[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ -> html.php (source)

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