You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1070 lines
27 KiB

  1. <?php
  2. /**
  3. * HTML output functions
  4. *
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Andreas Gohr <andi@splitbrain.org>
  7. */
  8. use dokuwiki\Ui\MediaRevisions;
  9. use dokuwiki\Form\Form;
  10. use dokuwiki\Action\Denied;
  11. use dokuwiki\Action\Locked;
  12. use dokuwiki\ChangeLog\PageChangeLog;
  13. use dokuwiki\Extension\AuthPlugin;
  14. use dokuwiki\Extension\Event;
  15. use dokuwiki\Ui\Backlinks;
  16. use dokuwiki\Ui\Editor;
  17. use dokuwiki\Ui\Index;
  18. use dokuwiki\Ui\Login;
  19. use dokuwiki\Ui\PageConflict;
  20. use dokuwiki\Ui\PageDiff;
  21. use dokuwiki\Ui\PageDraft;
  22. use dokuwiki\Ui\PageRevisions;
  23. use dokuwiki\Ui\PageView;
  24. use dokuwiki\Ui\Recent;
  25. use dokuwiki\Ui\UserProfile;
  26. use dokuwiki\Ui\UserRegister;
  27. use dokuwiki\Ui\UserResendPwd;
  28. use dokuwiki\Utf8\Clean;
  29. if (!defined('SEC_EDIT_PATTERN')) {
  30. define('SEC_EDIT_PATTERN', '#<!-- EDIT({.*?}) -->#');
  31. }
  32. /**
  33. * Convenience function to quickly build a wikilink
  34. *
  35. * @author Andreas Gohr <andi@splitbrain.org>
  36. * @param string $id id of the target page
  37. * @param string $name the name of the link, i.e. the text that is displayed
  38. * @param string|array $search search string(s) that shall be highlighted in the target page
  39. * @return string the HTML code of the link
  40. */
  41. function html_wikilink($id, $name = null, $search = '')
  42. {
  43. /** @var Doku_Renderer_xhtml $xhtml_renderer */
  44. static $xhtml_renderer = null;
  45. if (is_null($xhtml_renderer)) {
  46. $xhtml_renderer = p_get_renderer('xhtml');
  47. }
  48. return $xhtml_renderer->internallink($id, $name, $search, true, 'navigation');
  49. }
  50. /**
  51. * The loginform
  52. *
  53. * @author Andreas Gohr <andi@splitbrain.org>
  54. *
  55. * @param bool $svg Whether to show svg icons in the register and resendpwd links or not
  56. * @deprecated 2020-07-18
  57. */
  58. function html_login($svg = false)
  59. {
  60. dbg_deprecated(Login::class . '::show()');
  61. (new Login($svg))->show();
  62. }
  63. /**
  64. * Denied page content
  65. *
  66. * @deprecated 2020-07-18 not called anymore, see inc/Action/Denied::tplContent()
  67. */
  68. function html_denied()
  69. {
  70. dbg_deprecated(Denied::class . '::showBanner()');
  71. (new Denied())->showBanner();
  72. }
  73. /**
  74. * inserts section edit buttons if wanted or removes the markers
  75. *
  76. * @author Andreas Gohr <andi@splitbrain.org>
  77. *
  78. * @param string $text
  79. * @param bool $show show section edit buttons?
  80. * @return string
  81. */
  82. function html_secedit($text, $show = true)
  83. {
  84. global $INFO;
  85. if ((isset($INFO) && !$INFO['writable']) || !$show || (isset($INFO) && $INFO['rev'])) {
  86. return preg_replace(SEC_EDIT_PATTERN, '', $text);
  87. }
  88. return preg_replace_callback(
  89. SEC_EDIT_PATTERN,
  90. 'html_secedit_button',
  91. $text
  92. );
  93. }
  94. /**
  95. * prepares section edit button data for event triggering
  96. * used as a callback in html_secedit
  97. *
  98. * @author Andreas Gohr <andi@splitbrain.org>
  99. *
  100. * @param array $matches matches with regexp
  101. * @return string
  102. * @triggers HTML_SECEDIT_BUTTON
  103. */
  104. function html_secedit_button($matches)
  105. {
  106. $json = htmlspecialchars_decode($matches[1], ENT_QUOTES);
  107. try {
  108. $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
  109. } catch (JsonException $e) {
  110. return '';
  111. }
  112. $data['target'] = strtolower($data['target']);
  113. $data['hid'] = strtolower($data['hid'] ?? '');
  114. return Event::createAndTrigger(
  115. 'HTML_SECEDIT_BUTTON',
  116. $data,
  117. 'html_secedit_get_button'
  118. );
  119. }
  120. /**
  121. * prints a section editing button
  122. * used as default action form HTML_SECEDIT_BUTTON
  123. *
  124. * @author Adrian Lang <lang@cosmocode.de>
  125. *
  126. * @param array $data name, section id and target
  127. * @return string html
  128. */
  129. function html_secedit_get_button($data)
  130. {
  131. global $ID;
  132. global $INFO;
  133. if (!isset($data['name']) || $data['name'] === '') return '';
  134. $name = $data['name'];
  135. unset($data['name']);
  136. $secid = $data['secid'];
  137. unset($data['secid']);
  138. $params = array_merge(
  139. ['do' => 'edit', 'rev' => $INFO['lastmod'], 'summary' => '[' . $name . '] '],
  140. $data
  141. );
  142. $html = '<div class="secedit editbutton_' . $data['target'] . ' editbutton_' . $secid . '">';
  143. $html .= html_btn('secedit', $ID, '', $params, 'post', $name);
  144. $html .= '</div>';
  145. return $html;
  146. }
  147. /**
  148. * Just the back to top button (in its own form)
  149. *
  150. * @author Andreas Gohr <andi@splitbrain.org>
  151. *
  152. * @return string html
  153. */
  154. function html_topbtn()
  155. {
  156. global $lang;
  157. return '<a class="nolink" href="#dokuwiki__top">'
  158. . '<button class="button" onclick="window.scrollTo(0, 0)" title="' . $lang['btn_top'] . '">'
  159. . $lang['btn_top']
  160. . '</button></a>';
  161. }
  162. /**
  163. * Displays a button (using its own form)
  164. * If tooltip exists, the access key tooltip is replaced.
  165. *
  166. * @author Andreas Gohr <andi@splitbrain.org>
  167. *
  168. * @param string $name
  169. * @param string $id
  170. * @param string $akey access key
  171. * @param string[] $params key-value pairs added as hidden inputs
  172. * @param string $method
  173. * @param string $tooltip
  174. * @param bool|string $label label text, false: lookup btn_$name in localization
  175. * @param string $svg (optional) svg code, inserted into the button
  176. * @return string
  177. */
  178. function html_btn($name, $id, $akey, $params, $method = 'get', $tooltip = '', $label = false, $svg = null)
  179. {
  180. global $conf;
  181. global $lang;
  182. if (!$label)
  183. $label = $lang['btn_' . $name];
  184. //filter id (without urlencoding)
  185. $id = idfilter($id, false);
  186. //make nice URLs even for buttons
  187. if ($conf['userewrite'] == 2) {
  188. $script = DOKU_BASE . DOKU_SCRIPT . '/' . $id;
  189. } elseif ($conf['userewrite']) {
  190. $script = DOKU_BASE . $id;
  191. } else {
  192. $script = DOKU_BASE . DOKU_SCRIPT;
  193. $params['id'] = $id;
  194. }
  195. $html = '<form class="button btn_' . $name . '" method="' . $method . '" action="' . $script . '"><div class="no">';
  196. if (is_array($params)) {
  197. foreach ($params as $key => $val) {
  198. $html .= '<input type="hidden" name="' . $key . '" value="' . hsc($val) . '" />';
  199. }
  200. }
  201. $tip = empty($tooltip) ? hsc($label) : hsc($tooltip);
  202. $html .= '<button type="submit" ';
  203. if ($akey) {
  204. $tip .= ' [' . strtoupper($akey) . ']';
  205. $html .= 'accesskey="' . $akey . '" ';
  206. }
  207. $html .= 'title="' . $tip . '">';
  208. if ($svg) {
  209. $html .= '<span>' . hsc($label) . '</span>' . inlineSVG($svg);
  210. } else {
  211. $html .= hsc($label);
  212. }
  213. $html .= '</button>';
  214. $html .= '</div></form>';
  215. return $html;
  216. }
  217. /**
  218. * show a revision warning
  219. *
  220. * @author Szymon Olewniczak <dokuwiki@imz.re>
  221. * @deprecated 2020-07-18
  222. */
  223. function html_showrev()
  224. {
  225. dbg_deprecated(PageView::class . '::showrev()');
  226. }
  227. /**
  228. * Show a wiki page
  229. *
  230. * @author Andreas Gohr <andi@splitbrain.org>
  231. *
  232. * @param null|string $txt wiki text or null for showing $ID
  233. * @deprecated 2020-07-18
  234. */
  235. function html_show($txt = null)
  236. {
  237. dbg_deprecated(PageView::class . '::show()');
  238. (new PageView($txt))->show();
  239. }
  240. /**
  241. * ask the user about how to handle an exisiting draft
  242. *
  243. * @author Andreas Gohr <andi@splitbrain.org>
  244. * @deprecated 2020-07-18
  245. */
  246. function html_draft()
  247. {
  248. dbg_deprecated(PageDraft::class . '::show()');
  249. (new PageDraft())->show();
  250. }
  251. /**
  252. * Highlights searchqueries in HTML code
  253. *
  254. * @author Andreas Gohr <andi@splitbrain.org>
  255. * @author Harry Fuecks <hfuecks@gmail.com>
  256. *
  257. * @param string $html
  258. * @param array|string $phrases
  259. * @return string html
  260. */
  261. function html_hilight($html, $phrases)
  262. {
  263. $phrases = (array) $phrases;
  264. $phrases = array_map('preg_quote_cb', $phrases);
  265. $phrases = array_map('ft_snippet_re_preprocess', $phrases);
  266. $phrases = array_filter($phrases);
  267. $regex = implode('|', $phrases);
  268. if ($regex === '') return $html;
  269. if (!Clean::isUtf8($regex)) return $html;
  270. return @preg_replace_callback("/((<[^>]*)|$regex)/ui", function ($match) {
  271. $hlight = unslash($match[0]);
  272. if (!isset($match[2])) {
  273. $hlight = '<span class="search_hit">' . $hlight . '</span>';
  274. }
  275. return $hlight;
  276. }, $html);
  277. }
  278. /**
  279. * Display error on locked pages
  280. *
  281. * @author Andreas Gohr <andi@splitbrain.org>
  282. * @deprecated 2020-07-18 not called anymore, see inc/Action/Locked::tplContent()
  283. */
  284. function html_locked()
  285. {
  286. dbg_deprecated(Locked::class . '::showBanner()');
  287. (new Locked())->showBanner();
  288. }
  289. /**
  290. * list old revisions
  291. *
  292. * @author Andreas Gohr <andi@splitbrain.org>
  293. * @author Ben Coburn <btcoburn@silicodon.net>
  294. * @author Kate Arzamastseva <pshns@ukr.net>
  295. *
  296. * @param int $first skip the first n changelog lines
  297. * @param string $media_id id of media, or empty for current page
  298. * @deprecated 2020-07-18
  299. */
  300. function html_revisions($first = -1, $media_id = '')
  301. {
  302. dbg_deprecated(PageRevisions::class . '::show()');
  303. if ($media_id) {
  304. (new MediaRevisions($media_id))->show($first);
  305. } else {
  306. global $INFO;
  307. (new PageRevisions($INFO['id']))->show($first);
  308. }
  309. }
  310. /**
  311. * display recent changes
  312. *
  313. * @author Andreas Gohr <andi@splitbrain.org>
  314. * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  315. * @author Ben Coburn <btcoburn@silicodon.net>
  316. * @author Kate Arzamastseva <pshns@ukr.net>
  317. *
  318. * @param int $first
  319. * @param string $show_changes
  320. * @deprecated 2020-07-18
  321. */
  322. function html_recent($first = 0, $show_changes = 'both')
  323. {
  324. dbg_deprecated(Recent::class . '::show()');
  325. (new Recent($first, $show_changes))->show();
  326. }
  327. /**
  328. * Display page index
  329. *
  330. * @author Andreas Gohr <andi@splitbrain.org>
  331. *
  332. * @param string $ns
  333. * @deprecated 2020-07-18
  334. */
  335. function html_index($ns)
  336. {
  337. dbg_deprecated(Index::class . '::show()');
  338. (new Index($ns))->show();
  339. }
  340. /**
  341. * Index tree item formatter for html_buildlist()
  342. *
  343. * User function for html_buildlist()
  344. *
  345. * @author Andreas Gohr <andi@splitbrain.org>
  346. *
  347. * @param array $item
  348. * @return string
  349. * @deprecated 2020-07-18
  350. */
  351. function html_list_index($item)
  352. {
  353. dbg_deprecated(Index::class . '::formatListItem()');
  354. return (new Index())->formatListItem($item);
  355. }
  356. /**
  357. * Index list item formatter for html_buildlist()
  358. *
  359. * This user function is used in html_buildlist to build the
  360. * <li> tags for namespaces when displaying the page index
  361. * it gives different classes to opened or closed "folders"
  362. *
  363. * @author Andreas Gohr <andi@splitbrain.org>
  364. *
  365. * @param array $item
  366. * @return string html
  367. * @deprecated 2020-07-18
  368. */
  369. function html_li_index($item)
  370. {
  371. dbg_deprecated(Index::class . '::tagListItem()');
  372. return (new Index())->tagListItem($item);
  373. }
  374. /**
  375. * Default list item formatter for html_buildlist()
  376. *
  377. * @author Andreas Gohr <andi@splitbrain.org>
  378. *
  379. * @param array $item
  380. * @return string html
  381. * @deprecated 2020-07-18
  382. */
  383. function html_li_default($item)
  384. {
  385. return '<li class="level' . $item['level'] . '">';
  386. }
  387. /**
  388. * Build an unordered list
  389. *
  390. * Build an unordered list from the given $data array
  391. * Each item in the array has to have a 'level' property
  392. * the item itself gets printed by the given $func user
  393. * function. The second and optional function is used to
  394. * print the <li> tag. Both user function need to accept
  395. * a single item.
  396. *
  397. * Both user functions can be given as array to point to
  398. * a member of an object.
  399. *
  400. * @author Andreas Gohr <andi@splitbrain.org>
  401. *
  402. * @param array $data array with item arrays
  403. * @param string $class class of ul wrapper
  404. * @param callable $func callback to print an list item
  405. * @param callable $lifunc (optional) callback to the opening li tag
  406. * @param bool $forcewrapper (optional) Trigger building a wrapper ul if the first level is
  407. * 0 (we have a root object) or 1 (just the root content)
  408. * @return string html of an unordered list
  409. */
  410. function html_buildlist($data, $class, $func, $lifunc = null, $forcewrapper = false)
  411. {
  412. if ($data === []) {
  413. return '';
  414. }
  415. $firstElement = reset($data);
  416. $start_level = $firstElement['level'];
  417. $level = $start_level;
  418. $html = '';
  419. $open = 0;
  420. // set callback function to build the <li> tag, formerly defined as html_li_default()
  421. if (!is_callable($lifunc)) {
  422. $lifunc = static fn($item) => '<li class="level' . $item['level'] . '">';
  423. }
  424. foreach ($data as $item) {
  425. if ($item['level'] > $level) {
  426. //open new list
  427. for ($i = 0; $i < ($item['level'] - $level); $i++) {
  428. if ($i) $html .= '<li class="clear">';
  429. $html .= "\n" . '<ul class="' . $class . '">' . "\n";
  430. $open++;
  431. }
  432. $level = $item['level'];
  433. } elseif ($item['level'] < $level) {
  434. //close last item
  435. $html .= '</li>' . "\n";
  436. while ($level > $item['level'] && $open > 0) {
  437. //close higher lists
  438. $html .= '</ul>' . "\n" . '</li>' . "\n";
  439. $level--;
  440. $open--;
  441. }
  442. } elseif ($html !== '') {
  443. //close previous item
  444. $html .= '</li>' . "\n";
  445. }
  446. //print item
  447. $html .= call_user_func($lifunc, $item);
  448. $html .= '<div class="li">';
  449. $html .= call_user_func($func, $item);
  450. $html .= '</div>';
  451. }
  452. //close remaining items and lists
  453. $html .= '</li>' . "\n";
  454. while ($open-- > 0) {
  455. $html .= '</ul></li>' . "\n";
  456. }
  457. if ($forcewrapper || $start_level < 2) {
  458. // Trigger building a wrapper ul if the first level is
  459. // 0 (we have a root object) or 1 (just the root content)
  460. $html = "\n" . '<ul class="' . $class . '">' . "\n" . $html . '</ul>' . "\n";
  461. }
  462. return $html;
  463. }
  464. /**
  465. * display backlinks
  466. *
  467. * @author Andreas Gohr <andi@splitbrain.org>
  468. * @author Michael Klier <chi@chimeric.de>
  469. * @deprecated 2020-07-18
  470. */
  471. function html_backlinks()
  472. {
  473. dbg_deprecated(Backlinks::class . '::show()');
  474. (new Backlinks())->show();
  475. }
  476. /**
  477. * Get header of diff HTML
  478. *
  479. * @param string $l_rev Left revisions
  480. * @param string $r_rev Right revision
  481. * @param string $id Page id, if null $ID is used
  482. * @param bool $media If it is for media files
  483. * @param bool $inline Return the header on a single line
  484. * @return string[] HTML snippets for diff header
  485. * @deprecated 2020-07-18
  486. */
  487. function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = false)
  488. {
  489. dbg_deprecated('see ' . PageDiff::class . '::buildDiffHead()');
  490. return ['', '', '', ''];
  491. }
  492. /**
  493. * Show diff
  494. * between current page version and provided $text
  495. * or between the revisions provided via GET or POST
  496. *
  497. * @author Andreas Gohr <andi@splitbrain.org>
  498. * @param string $text when non-empty: compare with this text with most current version
  499. * @param bool $intro display the intro text
  500. * @param string $type type of the diff (inline or sidebyside)
  501. * @deprecated 2020-07-18
  502. */
  503. function html_diff($text = '', $intro = true, $type = null)
  504. {
  505. dbg_deprecated(PageDiff::class . '::show()');
  506. global $INFO;
  507. (new PageDiff($INFO['id']))->compareWith($text)->preference([
  508. 'showIntro' => $intro,
  509. 'difftype' => $type,
  510. ])->show();
  511. }
  512. /**
  513. * Create html for revision navigation
  514. *
  515. * @param PageChangeLog $pagelog changelog object of current page
  516. * @param string $type inline vs sidebyside
  517. * @param int $l_rev left revision timestamp
  518. * @param int $r_rev right revision timestamp
  519. * @return string[] html of left and right navigation elements
  520. * @deprecated 2020-07-18
  521. */
  522. function html_diff_navigation($pagelog, $type, $l_rev, $r_rev)
  523. {
  524. dbg_deprecated('see ' . PageDiff::class . '::buildRevisionsNavigation()');
  525. return ['', ''];
  526. }
  527. /**
  528. * Create html link to a diff defined by two revisions
  529. *
  530. * @param string $difftype display type
  531. * @param string $linktype
  532. * @param int $lrev oldest revision
  533. * @param int $rrev newest revision or null for diff with current revision
  534. * @return string html of link to a diff
  535. * @deprecated 2020-07-18
  536. */
  537. function html_diff_navigationlink($difftype, $linktype, $lrev, $rrev = null)
  538. {
  539. dbg_deprecated('see ' . PageDiff::class . '::diffViewlink()');
  540. return '';
  541. }
  542. /**
  543. * Insert soft breaks in diff html
  544. *
  545. * @param string $diffhtml
  546. * @return string
  547. * @deprecated 2020-07-18
  548. */
  549. function html_insert_softbreaks($diffhtml)
  550. {
  551. dbg_deprecated(PageDiff::class . '::insertSoftbreaks()');
  552. return (new PageDiff())->insertSoftbreaks($diffhtml);
  553. }
  554. /**
  555. * show warning on conflict detection
  556. *
  557. * @author Andreas Gohr <andi@splitbrain.org>
  558. *
  559. * @param string $text
  560. * @param string $summary
  561. * @deprecated 2020-07-18
  562. */
  563. function html_conflict($text, $summary)
  564. {
  565. dbg_deprecated(PageConflict::class . '::show()');
  566. (new PageConflict($text, $summary))->show();
  567. }
  568. /**
  569. * Prints the global message array
  570. *
  571. * @author Andreas Gohr <andi@splitbrain.org>
  572. */
  573. function html_msgarea()
  574. {
  575. global $MSG, $MSG_shown;
  576. /** @var array $MSG */
  577. // store if the global $MSG has already been shown and thus HTML output has been started
  578. $MSG_shown = true;
  579. if (!isset($MSG)) return;
  580. $shown = [];
  581. foreach ($MSG as $msg) {
  582. $hash = md5($msg['msg']);
  583. if (isset($shown[$hash])) continue; // skip double messages
  584. if (info_msg_allowed($msg)) {
  585. echo '<div class="' . $msg['lvl'] . '">';
  586. echo $msg['msg'];
  587. echo '</div>';
  588. }
  589. $shown[$hash] = 1;
  590. }
  591. unset($GLOBALS['MSG']);
  592. }
  593. /**
  594. * Prints the registration form
  595. *
  596. * @author Andreas Gohr <andi@splitbrain.org>
  597. * @deprecated 2020-07-18
  598. */
  599. function html_register()
  600. {
  601. dbg_deprecated(UserRegister::class . '::show()');
  602. (new UserRegister())->show();
  603. }
  604. /**
  605. * Print the update profile form
  606. *
  607. * @author Christopher Smith <chris@jalakai.co.uk>
  608. * @author Andreas Gohr <andi@splitbrain.org>
  609. * @deprecated 2020-07-18
  610. */
  611. function html_updateprofile()
  612. {
  613. dbg_deprecated(UserProfile::class . '::show()');
  614. (new UserProfile())->show();
  615. }
  616. /**
  617. * Preprocess edit form data
  618. *
  619. * @author Andreas Gohr <andi@splitbrain.org>
  620. *
  621. * @deprecated 2020-07-18
  622. */
  623. function html_edit()
  624. {
  625. dbg_deprecated(Editor::class . '::show()');
  626. (new Editor())->show();
  627. }
  628. /**
  629. * Display the default edit form
  630. *
  631. * Is the default action for HTML_EDIT_FORMSELECTION.
  632. *
  633. * @param array $param
  634. * @deprecated 2020-07-18
  635. */
  636. function html_edit_form($param)
  637. {
  638. dbg_deprecated(Editor::class . '::addTextarea()');
  639. (new Editor())->addTextarea($param);
  640. }
  641. /**
  642. * prints some debug info
  643. *
  644. * @author Andreas Gohr <andi@splitbrain.org>
  645. */
  646. function html_debug()
  647. {
  648. global $conf;
  649. global $lang;
  650. /** @var AuthPlugin $auth */
  651. global $auth;
  652. global $INFO;
  653. //remove sensitive data
  654. $cnf = $conf;
  655. debug_guard($cnf);
  656. $nfo = $INFO;
  657. debug_guard($nfo);
  658. $ses = $_SESSION;
  659. debug_guard($ses);
  660. echo '<html><body>';
  661. echo '<p>When reporting bugs please send all the following ';
  662. echo 'output as a mail to andi@splitbrain.org ';
  663. echo 'The best way to do this is to save this page in your browser</p>';
  664. echo '<b>$INFO:</b><pre>';
  665. print_r($nfo);
  666. echo '</pre>';
  667. echo '<b>$_SERVER:</b><pre>';
  668. print_r($_SERVER);
  669. echo '</pre>';
  670. echo '<b>$conf:</b><pre>';
  671. print_r($cnf);
  672. echo '</pre>';
  673. echo '<b>DOKU_BASE:</b><pre>';
  674. echo DOKU_BASE;
  675. echo '</pre>';
  676. echo '<b>abs DOKU_BASE:</b><pre>';
  677. echo DOKU_URL;
  678. echo '</pre>';
  679. echo '<b>rel DOKU_BASE:</b><pre>';
  680. echo dirname($_SERVER['PHP_SELF']) . '/';
  681. echo '</pre>';
  682. echo '<b>PHP Version:</b><pre>';
  683. echo phpversion();
  684. echo '</pre>';
  685. echo '<b>locale:</b><pre>';
  686. echo setlocale(LC_ALL, 0);
  687. echo '</pre>';
  688. echo '<b>encoding:</b><pre>';
  689. echo $lang['encoding'];
  690. echo '</pre>';
  691. if ($auth instanceof AuthPlugin) {
  692. echo '<b>Auth backend capabilities:</b><pre>';
  693. foreach ($auth->getCapabilities() as $cando) {
  694. echo ' ' . str_pad($cando, 16) . ' => ' . (int)$auth->canDo($cando) . DOKU_LF;
  695. }
  696. echo '</pre>';
  697. }
  698. echo '<b>$_SESSION:</b><pre>';
  699. print_r($ses);
  700. echo '</pre>';
  701. echo '<b>Environment:</b><pre>';
  702. print_r($_ENV);
  703. echo '</pre>';
  704. echo '<b>PHP settings:</b><pre>';
  705. $inis = ini_get_all();
  706. print_r($inis);
  707. echo '</pre>';
  708. if (function_exists('apache_get_version')) {
  709. $apache = [];
  710. $apache['version'] = apache_get_version();
  711. if (function_exists('apache_get_modules')) {
  712. $apache['modules'] = apache_get_modules();
  713. }
  714. echo '<b>Apache</b><pre>';
  715. print_r($apache);
  716. echo '</pre>';
  717. }
  718. echo '</body></html>';
  719. }
  720. /**
  721. * Form to request a new password for an existing account
  722. *
  723. * @author Benoit Chesneau <benoit@bchesneau.info>
  724. * @author Andreas Gohr <gohr@cosmocode.de>
  725. * @deprecated 2020-07-18
  726. */
  727. function html_resendpwd()
  728. {
  729. dbg_deprecated(UserResendPwd::class . '::show()');
  730. (new UserResendPwd())->show();
  731. }
  732. /**
  733. * Return the TOC rendered to XHTML
  734. *
  735. * @author Andreas Gohr <andi@splitbrain.org>
  736. *
  737. * @param array $toc
  738. * @return string html
  739. */
  740. function html_TOC($toc)
  741. {
  742. if ($toc === []) return '';
  743. global $lang;
  744. $out = '<!-- TOC START -->' . DOKU_LF;
  745. $out .= '<div id="dw__toc" class="dw__toc">' . DOKU_LF;
  746. $out .= '<h3 class="toggle">';
  747. $out .= $lang['toc'];
  748. $out .= '</h3>' . DOKU_LF;
  749. $out .= '<div>' . DOKU_LF;
  750. $out .= html_buildlist($toc, 'toc', 'html_list_toc', null, true);
  751. $out .= '</div>' . DOKU_LF . '</div>' . DOKU_LF;
  752. $out .= '<!-- TOC END -->' . DOKU_LF;
  753. return $out;
  754. }
  755. /**
  756. * Callback for html_buildlist
  757. *
  758. * @param array $item
  759. * @return string html
  760. */
  761. function html_list_toc($item)
  762. {
  763. if (isset($item['hid'])) {
  764. $link = '#' . $item['hid'];
  765. } else {
  766. $link = $item['link'];
  767. }
  768. return '<a href="' . $link . '">' . hsc($item['title']) . '</a>';
  769. }
  770. /**
  771. * Helper function to build TOC items
  772. *
  773. * Returns an array ready to be added to a TOC array
  774. *
  775. * @param string $link - where to link (if $hash set to '#' it's a local anchor)
  776. * @param string $text - what to display in the TOC
  777. * @param int $level - nesting level
  778. * @param string $hash - is prepended to the given $link, set blank if you want full links
  779. * @return array the toc item
  780. */
  781. function html_mktocitem($link, $text, $level, $hash = '#')
  782. {
  783. return [
  784. 'link' => $hash . $link,
  785. 'title' => $text,
  786. 'type' => 'ul',
  787. 'level' => $level
  788. ];
  789. }
  790. /**
  791. * Output a Doku_Form object.
  792. * Triggers an event with the form name: HTML_{$name}FORM_OUTPUT
  793. *
  794. * @author Tom N Harris <tnharris@whoopdedo.org>
  795. *
  796. * @param string $name The name of the form
  797. * @param Doku_Form $form The form
  798. * @return void
  799. * @deprecated 2020-07-18
  800. */
  801. function html_form($name, $form)
  802. {
  803. dbg_deprecated('use dokuwiki\Form\Form instead of Doku_Form');
  804. // Safety check in case the caller forgets.
  805. $form->endFieldset();
  806. Event::createAndTrigger('HTML_' . strtoupper($name) . 'FORM_OUTPUT', $form, 'html_form_output', false);
  807. }
  808. /**
  809. * Form print function.
  810. * Just calls printForm() on the form object.
  811. *
  812. * @param Doku_Form $form The form
  813. * @return void
  814. * @deprecated 2020-07-18
  815. */
  816. function html_form_output($form)
  817. {
  818. dbg_deprecated('use ' . Form::class . '::toHTML()');
  819. $form->printForm();
  820. }
  821. /**
  822. * Embed a flash object in HTML
  823. *
  824. * This will create the needed HTML to embed a flash movie in a cross browser
  825. * compatble way using valid XHTML
  826. *
  827. * The parameters $params, $flashvars and $atts need to be associative arrays.
  828. * No escaping needs to be done for them. The alternative content *has* to be
  829. * escaped because it is used as is. If no alternative content is given
  830. * $lang['noflash'] is used.
  831. *
  832. * @author Andreas Gohr <andi@splitbrain.org>
  833. * @link http://latrine.dgx.cz/how-to-correctly-insert-a-flash-into-xhtml
  834. *
  835. * @param string $swf - the SWF movie to embed
  836. * @param int $width - width of the flash movie in pixels
  837. * @param int $height - height of the flash movie in pixels
  838. * @param array $params - additional parameters (<param>)
  839. * @param array $flashvars - parameters to be passed in the flashvar parameter
  840. * @param array $atts - additional attributes for the <object> tag
  841. * @param string $alt - alternative content (is NOT automatically escaped!)
  842. * @return string - the XHTML markup
  843. */
  844. function html_flashobject($swf, $width, $height, $params = null, $flashvars = null, $atts = null, $alt = '')
  845. {
  846. global $lang;
  847. $out = '';
  848. // prepare the object attributes
  849. if (is_null($atts)) $atts = [];
  850. $atts['width'] = (int) $width;
  851. $atts['height'] = (int) $height;
  852. if (!$atts['width']) $atts['width'] = 425;
  853. if (!$atts['height']) $atts['height'] = 350;
  854. // add object attributes for standard compliant browsers
  855. $std = $atts;
  856. $std['type'] = 'application/x-shockwave-flash';
  857. $std['data'] = $swf;
  858. // add object attributes for IE
  859. $ie = $atts;
  860. $ie['classid'] = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
  861. // open object (with conditional comments)
  862. $out .= '<!--[if !IE]> -->' . NL;
  863. $out .= '<object ' . buildAttributes($std) . '>' . NL;
  864. $out .= '<!-- <![endif]-->' . NL;
  865. $out .= '<!--[if IE]>' . NL;
  866. $out .= '<object ' . buildAttributes($ie) . '>' . NL;
  867. $out .= ' <param name="movie" value="' . hsc($swf) . '" />' . NL;
  868. $out .= '<!--><!-- -->' . NL;
  869. // print params
  870. if (is_array($params)) foreach ($params as $key => $val) {
  871. $out .= ' <param name="' . hsc($key) . '" value="' . hsc($val) . '" />' . NL;
  872. }
  873. // add flashvars
  874. if (is_array($flashvars)) {
  875. $out .= ' <param name="FlashVars" value="' . buildURLparams($flashvars) . '" />' . NL;
  876. }
  877. // alternative content
  878. if ($alt) {
  879. $out .= $alt . NL;
  880. } else {
  881. $out .= $lang['noflash'] . NL;
  882. }
  883. // finish
  884. $out .= '</object>' . NL;
  885. $out .= '<!-- <![endif]-->' . NL;
  886. return $out;
  887. }
  888. /**
  889. * Prints HTML code for the given tab structure
  890. *
  891. * @param array $tabs tab structure
  892. * @param string $current_tab the current tab id
  893. * @return void
  894. */
  895. function html_tabs($tabs, $current_tab = null)
  896. {
  897. echo '<ul class="tabs">' . NL;
  898. foreach ($tabs as $id => $tab) {
  899. html_tab($tab['href'], $tab['caption'], $id === $current_tab);
  900. }
  901. echo '</ul>' . NL;
  902. }
  903. /**
  904. * Prints a single tab
  905. *
  906. * @author Kate Arzamastseva <pshns@ukr.net>
  907. * @author Adrian Lang <mail@adrianlang.de>
  908. *
  909. * @param string $href - tab href
  910. * @param string $caption - tab caption
  911. * @param boolean $selected - is tab selected
  912. * @return void
  913. */
  914. function html_tab($href, $caption, $selected = false)
  915. {
  916. $tab = '<li>';
  917. if ($selected) {
  918. $tab .= '<strong>';
  919. } else {
  920. $tab .= '<a href="' . hsc($href) . '">';
  921. }
  922. $tab .= hsc($caption)
  923. . '</' . ($selected ? 'strong' : 'a') . '>'
  924. . '</li>' . NL;
  925. echo $tab;
  926. }
  927. /**
  928. * Display size change
  929. *
  930. * @param int $sizechange - size of change in Bytes
  931. * @param Doku_Form $form - (optional) form to add elements to
  932. * @return void|string
  933. */
  934. function html_sizechange($sizechange, $form = null)
  935. {
  936. if (isset($sizechange)) {
  937. $class = 'sizechange';
  938. $value = filesize_h(abs($sizechange));
  939. if ($sizechange > 0) {
  940. $class .= ' positive';
  941. $value = '+' . $value;
  942. } elseif ($sizechange < 0) {
  943. $class .= ' negative';
  944. $value = '-' . $value;
  945. } else {
  946. $value = '±' . $value;
  947. }
  948. if (!isset($form)) {
  949. return '<span class="' . $class . '">' . $value . '</span>';
  950. } else { // Doku_Form
  951. $form->addElement(form_makeOpenTag('span', ['class' => $class]));
  952. $form->addElement($value);
  953. $form->addElement(form_makeCloseTag('span'));
  954. }
  955. }
  956. }