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 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); 10 require_once(DOKU_INC.'inc/format.php'); 11 12/** 13 * Convenience function to quickly build a wikilink 14 * 15 * @author Andreas Gohr <andi@splitbrain.org> 16 */ 17function html_wikilink($url,$name='',$search=''){ 18 global $conf; 19 $link = array(); 20 $link['url'] = $url; 21 $link['name'] = $name; 22 $link = format_link_wiki($link); 23 24 if($search){ 25 ($conf['userewrite']) ? $link['url'].='?s=' : $link['url'].='&s='; 26 $link['url'] .= urlencode($search); 27 } 28 29 return format_link_build($link); 30} 31 32/** 33 * The loginform 34 * 35 * @author Andreas Gohr <andi@splitbrain.org> 36 */ 37function html_login(){ 38 global $lang; 39 global $conf; 40 global $ID; 41 42 print parsedLocale('login'); 43 ?> 44 <div align="center"> 45 <form action="<?=script()?>" accept-charset="<?=$lang['encoding']?>" method="post"> 46 <fieldset> 47 <legend><?=$lang['btn_login']?></legend> 48 <input type="hidden" name="id" value="<?=$ID?>" /> 49 <input type="hidden" name="do" value="login" /> 50 <label> 51 <span><?=$lang['user']?></span> 52 <input type="text" name="u" value="<?=formText($_REQUEST['u'])?>" class="edit" /> 53 </label><br /> 54 <label> 55 <span><?=$lang['pass']?></span> 56 <input type="password" name="p" class="edit" /> 57 </label><br /> 58 <input type="submit" value="<?=$lang['btn_login']?>" class="button" /> 59 <label for="remember" class="simple"> 60 <input type="checkbox" name="r" id="remember" value="1" /> 61 <span><?=$lang['remember']?></span> 62 </label> 63 </fieldset> 64 </form> 65 <? 66 if($conf['openregister']){ 67 print '<p>'; 68 print $lang['reghere']; 69 print ': <a href="'.wl($ID,'do=register').'" class="wikilink1">'.$lang['register'].'</a>'; 70 print '</p>'; 71 } 72 ?> 73 </div> 74 <? 75 if(@file_exists('includes/login.txt')){ 76 print io_cacheParse('includes/login.txt'); 77 } 78} 79 80/** 81 * shows the edit/source/show button dependent on current mode 82 * 83 * @author Andreas Gohr <andi@splitbrain.org> 84 */ 85function html_editbutton(){ 86 global $ID; 87 global $REV; 88 global $ACT; 89 global $INFO; 90 91 if($ACT == 'show' || $ACT == 'search'){ 92 if($INFO['writable']){ 93 if($INFO['exists']){ 94 $r = html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post'); 95 }else{ 96 $r = html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post'); 97 } 98 }else{ 99 $r = html_btn('source',$ID,'v',array('do' => 'edit','rev' => $REV),'post'); 100 } 101 }else{ 102 $r = html_btn('show',$ID,'v',array('do' => 'show')); 103 } 104 return $r; 105} 106 107/** 108 * prints a section editing button 109 * 110 * @author Andreas Gohr <andi@splitbrain.org> 111 */ 112function html_secedit_button($section,$p){ 113 global $ID; 114 global $lang; 115 $secedit = ''; 116 if($p) $secedit .= "</p>\n"; 117 $secedit .= '<div class="secedit">'; 118 $secedit .= html_btn('secedit',$ID,'', 119 array('do' => 'edit', 120 'lines' => "$section"), 121 'post'); 122 $secedit .= '</div>'; 123 if($p) $secedit .= "\n<p>"; 124 return $secedit; 125} 126 127/** 128 * inserts section edit buttons if wanted or removes the markers 129 * 130 * @author Andreas Gohr <andi@splitbrain.org> 131 */ 132function html_secedit($text,$show=true){ 133 global $INFO; 134 if($INFO['writable'] && $show){ 135 $text = preg_replace('#<!-- SECTION \[(\d+-\d+)\] -->#e', 136 "html_secedit_button('\\1',true)", 137 $text); 138 $text = preg_replace('#<!-- SECTION \[(\d+-)\] -->#e', 139 "html_secedit_button('\\1',false)", 140 $text); 141 }else{ 142 $text = preg_replace('#<!-- SECTION \[(\d*-\d*)\] -->#e','',$text); 143 } 144 return $text; 145} 146 147/** 148 * displays the breadcrumbs trace 149 * 150 * @deprecated 151 * @author Andreas Gohr <andi@splitbrain.org> 152 */ 153function html_breadcrumbs(){ 154 global $lang; 155 global $conf; 156 157 //check if enabled 158 if(!$conf['breadcrumbs']) return; 159 160 $crumbs = breadcrumbs(); //setup crumb trace 161 print '<div class="breadcrumbs">'; 162 print $lang['breadcrumb'].':'; 163 foreach ($crumbs as $crumb){ 164 print ' » '; 165 print '<a href="'.wl($crumb).'" class="breadcrumbs" onclick="return svchk()" onkeypress="return svchk()" title="'.$crumb.'">'.noNS($crumb).'</a>'; 166 } 167 print '</div>'; 168} 169 170/** 171 * display the HTML head and metadata 172 * 173 * @deprecated -> tpl_metaheaders() 174 * @author Andreas Gohr <andi@splitbrain.org> 175 */ 176function html_head(){ 177 global $ID; 178 global $ACT; 179 global $INFO; 180 global $REV; 181 global $conf; 182 global $lang; 183 184 //print '<'.'?xml version="1.0"?'.">\n"; 185 print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'; 186 print ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'; 187 print "\n"; 188?> 189 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?=$conf['lang']?>" lang="<?=$conf['lang']?>" dir="ltr"> 190 <head> 191 <title><?=$ID?> [<?=$conf['title']?>]</title> 192 <meta http-equiv="Content-Type" content="text/html; charset=<?=$lang['encoding']?>" /> 193 <meta name="generator" content="DokuWiki <?=getVersion()?>" /> 194 <link rel="stylesheet" media="screen" type="text/css" href="<?=DOKU_BASE?>style.css" /> 195 <link rel="stylesheet" media="print" type="text/css" href="<?=DOKU_BASE?>print.css" /> 196 <link rel="shortcut icon" href="<?=DOKU_BASE?>images/favicon.ico" /> 197 <link rel="start" href="<?=wl()?>" /> 198 <link rel="contents" href="<?=wl($ID,'do=index')?>" title="<?=$lang['index']?>" /> 199 <link rel="alternate" type="application/rss+xml" title="Recent Changes" href="<?=DOKU_BASE?>feed.php" /> 200 <link rel="alternate" type="application/rss+xml" title="Current Namespace" href="<?=DOKU_BASE?>feed.php?mode=list&ns=<?=$INFO['namespace']?>" /> 201 <link rel="alternate" type="text/html" title="Plain HTML" href="<?=wl($ID,'do=export_html')?>" /> 202 <link rel="alternate" type="text/plain" title="Wiki Markup" href="<?=wl($ID, 'do=export_raw')?>" /> 203<? 204 if( ($ACT=='show' || $ACT=='export_html') && !$REV){ 205 if($INFO['exists']){ 206 print ' <meta name="robots" content="index,follow" />'."\n"; 207 print ' <meta name="date" content="'.date('Y-m-d\TH:i:sO',$INFO['lastmod']).'" />'."\n"; 208 }else{ 209 print ' <meta name="robots" content="noindex,follow" />'."\n"; 210 } 211 }else{ 212 print ' <meta name="robots" content="noindex,nofollow" />'."\n"; 213 } 214?> 215 216 <script language="JavaScript" type="text/javascript"> 217 var alertText = '<?=$lang['qb_alert']?>'; 218 var notSavedYet = '<?=$lang['notsavedyet']?>'; 219 var DOKU_BASE = '<?=DOKU_BASE?>'; 220 </script> 221 <script language="JavaScript" type="text/javascript" src="<?=DOKU_BASE?>script.js"></script> 222 223 <!--[if gte IE 5]> 224 <style type="text/css"> 225 /* that IE 5+ conditional comment makes this only visible in IE 5+ */ 226 img { behavior: url("<?=DOKU_BASE?>pngbehavior.htc"); } /* IE bugfix for transparent PNGs */ 227 </style> 228 <![endif]--> 229 230 <?@include("includes/meta.html")?> 231 </head> 232<? 233} 234 235/** 236 * Just the back to top button (in it's own form) 237 * 238 * @author Andreas Gohr <andi@splitbrain.org> 239 */ 240function html_topbtn(){ 241 global $lang; 242 243 $ret = ''; 244 $ret .= '<form class="button" method="get" action="#top" onsubmit="return svchk()">'; 245 $ret .= '<input type="submit" value="'.htmlspecialchars($lang['btn_top']).'" class="button" '; 246 $ret .= '</form>'; 247 return $ret; 248} 249 250/** 251 * Displays a button (using it's own form) 252 * 253 * @author Andreas Gohr <andi@splitbrain.org> 254 */ 255function html_btn($name,$id,$akey,$params,$method='get'){ 256 global $conf; 257 global $lang; 258 259 $label = $lang['btn_'.$name]; 260 261 $ret = ''; 262 263 //filter id (without urlencoding) 264 $id = idfilter($id,false); 265 266 //make nice URLs even for buttons 267 if(!$conf['userewrite']){ 268 $script = DOKU_BASE.DOKU_SCRIPT; 269 $params['id'] = $id; 270 }else{ 271 $script = DOKU_BASE.$id; 272 } 273 274 $ret .= '<form class="button" method="'.$method.'" action="'.$script.'" onsubmit="return svchk()">'; 275 276 reset($params); 277 while (list($key, $val) = each($params)) { 278 $ret .= '<input type="hidden" name="'.$key.'" '; 279 $ret .= 'value="'.htmlspecialchars($val).'" />'; 280 } 281 282 $ret .= '<input type="submit" value="'.htmlspecialchars($label).'" class="button" '; 283 if($akey){ 284 $ret .= 'title="ALT+'.strtoupper($akey).'" '; 285 $ret .= 'accesskey="'.$akey.'" '; 286 } 287 $ret .= '/>'; 288 $ret .= '</form>'; 289 290 return $ret; 291} 292 293/** 294 * Check for the given permission or prints an error 295 * 296 * @deprecated 297 * @author Andreas Gohr <andi@splitbrain.org> 298 */ 299function html_acl($perm){ 300 global $INFO; 301 if($INFO['perm'] >= $perm) return true; 302 303 print parsedLocale('denied'); 304 return false; 305} 306 307/** 308 * Displays the overall page header and calls html_head() 309 * 310 * @author Andreas Gohr <andi@splitbrain.org> 311 */ 312function html_header(){ 313 global $ID; 314 global $REV; 315 global $lang; 316 global $conf; 317 html_head(); 318?> 319<body> 320 <div class="all"> 321 <? 322 @include("includes/topheader.html"); 323 html_msgarea(); 324 ?> 325 <div class="stylehead"> 326 <div class="header"> 327 <div class="pagename"> 328 [[<a href="<?=wl($ID,'do=backlink')?>" onclick="return svchk()" onkeypress="return svchk()"><?=$ID?></a>]] 329 </div> 330 <div class="logo"> 331 <a href="<?=wl()?>" name="top" accesskey="h" title="[ALT+H]" onclick="return svchk()" onkeypress="return svchk()"><?=$conf['title']?></a> 332 </div> 333 </div> 334 <?@include("includes/header.html")?> 335 336 <div class="bar" id="bar_top"> 337 <div class="bar-left" id="bar_topleft"> 338 <?=html_editbutton()?> 339 <?=html_btn(revs,$ID,'o',array('do' => 'revisions'))?> 340 </div> 341 342 <div class="bar-right" id="bar_topright"> 343 <?=html_btn(recent,'','r',array('do' => 'recent'))?> 344 <form action="<?=wl()?>" accept-charset="<?=$lang['encoding']?>"> 345 <input type="hidden" name="do" value="search" /> 346 <input type="text" accesskey="f" name="id" class="edit" /> 347 <input type="submit" value="<?=$lang['btn_search']?>" class="button" /> 348 </form> 349 </div> 350 </div> 351 352 <? 353 flush(); 354 html_breadcrumbs(); 355 @include("includes/pageheader.html"); 356 ?> 357 </div> 358 <div class="page"> 359 <!-- wikipage start --> 360<? 361} 362 363/** 364 * display document and user info 365 * 366 * Displays some Metadata like who's logged in and the last modified 367 * date - do not confuse this with the HTML meta header. 368 * 369 * @author Andreas Gohr <andi@splitbrain.org> 370 */ 371function html_metainfo(){ 372 global $conf; 373 global $lang; 374 global $INFO; 375 global $REV; 376 377 $fn = $INFO['filepath']; 378 if(!$conf['fullpath']){ 379 if($REV){ 380 $fn = str_replace(realpath($conf['olddir']).DIRECTORY_SEPARATOR,'',$fn); 381 }else{ 382 $fn = str_replace(realpath($conf['datadir']).DIRECTORY_SEPARATOR,'',$fn); 383 } 384 } 385 $date = date($conf['dformat'],$INFO['lastmod']); 386 387 print '<div class="meta">'; 388 if($_SERVER['REMOTE_USER']){ 389 print '<div class="user">'; 390 print $lang['loggedinas'].': '.$_SERVER['REMOTE_USER']; 391 print '</div>'; 392 } 393 print ' '; 394 if($INFO['exists']){ 395 print $fn; 396 print ' · '; 397 print $lang['lastmod']; 398 print ': '; 399 print $date; 400 if($INFO['editor']){ 401 print ' '.$lang['by'].' '; 402 print $INFO['editor']; 403 } 404 if($INFO['locked']){ 405 print ' · '; 406 print $lang['lockedby']; 407 print ': '; 408 print $INFO['locked']; 409 } 410 } 411 print '</div>'; 412} 413 414/** 415 * Diplay the overall footer 416 * 417 * @author Andreas Gohr <andi@splitbrain.org> 418 */ 419function html_footer(){ 420 global $ID; 421 global $REV; 422 global $INFO; 423 global $lang; 424 global $conf; 425?> 426 <!-- wikipage stop --> 427 </div> 428 <div class="clearer"> </div> 429 <div class="stylefoot"> 430 <? 431 flush(); 432 @include("includes/pagefooter.html"); 433 html_metainfo(); 434 ?> 435 <div class="bar" id="bar_bottom"> 436 <div class="bar-left" id="bar_bottomleft"> 437 <?=html_editbutton()?> 438 <?=html_btn(revs,$ID,'o',array('do' => 'revisions'))?> 439 </div> 440 441 <div class="bar-right" id="bar_bottomright"> 442 <? 443 if($conf['useacl']){ 444 if($_SERVER['REMOTE_USER']){ 445 print html_btn('logout',$ID,'',array('do' => 'logout',)); 446 }else{ 447 print html_btn('login',$ID,'',array('do' => 'login')); 448 } 449 #//acl-admin button 450 #if($INFO['perm'] == AUTH_GRANT){ 451 # print html_btn('acl_admin',$ID,'',array('do' => 'acl_admin')); 452 #} 453 } 454 ?> 455 <?=html_btn(index,$ID,'x',array('do' => 'index'))?> 456 <a href="#top"><input type="button" class="button" value="<?=$lang['btn_top']?>" /></a> 457 </div> 458 </div> 459 </div> 460 <?@include("includes/footer.html")?> 461 </div> 462 </body> 463 </html> 464<? 465} 466 467/** 468 * Print the table of contents 469 * 470 * @author Andreas Gohr <andi@splitbrain.org> 471 */ 472function html_toc($toc){ 473 global $lang; 474 $ret = ''; 475 $ret .= '<div class="toc">'; 476 $ret .= '<div class="tocheader">'; 477 $ret .= $lang['toc']; 478 $ret .= ' <script type="text/javascript">'; 479 $ret .= 'showTocToggle("+","-")'; 480 $ret .= '</script>'; 481 $ret .= '</div>'; 482 $ret .= '<div id="tocinside">'; 483 $ret .= html_buildlist($toc,'toc','html_list_toc'); 484 $ret .= '</div>'; 485 $ret .= '</div>'; 486 return $ret; 487} 488 489/** 490 * TOC item formatter 491 * 492 * User function for html_buildlist() 493 * 494 * @author Andreas Gohr <andi@splitbrain.org> 495 */ 496function html_list_toc($item){ 497 $ret = ''; 498 $ret .= '<a href="#'.$item['id'].'" class="toc">'; 499 $ret .= $item['name']; 500 $ret .= '</a>'; 501 return $ret; 502} 503 504/** 505 * show a wiki page 506 * 507 * @author Andreas Gohr <andi@splitbrain.org> 508 */ 509function html_show($text=''){ 510 global $ID; 511 global $REV; 512 global $HIGH; 513 //disable section editing for old revisions or in preview 514 if($text || $REV){ 515 global $parser; 516 $parser['secedit'] = false; 517 } 518 519 if ($text){ 520 //PreviewHeader 521 print parsedLocale('preview'); 522 print '<div class="preview">'; 523 print html_secedit(parse($text),false); 524 print '</div>'; 525 }else{ 526 if ($REV) print parsedLocale('showrev'); 527 $html = parsedWiki($ID,$REV,true); 528 $html = html_secedit($html); 529 print html_hilight($html,$HIGH); 530 } 531} 532 533/** 534 * Highlights searchqueries in HTML code 535 * 536 * @author Andreas Gohr <andi@splitbrain.org> 537 */ 538function html_hilight($html,$query){ 539 $queries = preg_split ("/\s/",$query,-1,PREG_SPLIT_NO_EMPTY); 540 foreach ($queries as $q){ 541 $q = preg_quote($q,'/'); 542 $html = preg_replace("/((<[^>]*)|$q)/ie", '"\2"=="\1"? "\1":"<span class=\"search_hit\">\1</span>"', $html); 543 } 544 return $html; 545} 546 547/** 548 * Run a search and display the result 549 * 550 * @author Andreas Gohr <andi@splitbrain.org> 551 */ 552function html_search(){ 553 require_once(DOKU_INC.'inc/search.php'); 554 global $conf; 555 global $QUERY; 556 global $ID; 557 global $lang; 558 559 print parsedLocale('searchpage'); 560 flush(); 561 562 //show progressbar 563 print '<div align="center">'; 564 print '<script language="JavaScript" type="text/javascript">'; 565 print 'showLoadBar();'; 566 print '</script>'; 567 print '<br /></div>'; 568 569 //do quick pagesearch 570 $data = array(); 571 search($data,$conf['datadir'],'search_pagename',array(query => cleanID($QUERY))); 572 if(count($data)){ 573 sort($data); 574 print '<div class="search_quickresult">'; 575 print '<b>'.$lang[quickhits].':</b><br />'; 576 foreach($data as $row){ 577 print '<div class="search_quickhits">'; 578 print html_wikilink(':'.$row['id'],$row['id']); 579 print '</div> '; 580 } 581 //clear float (see http://www.complexspiral.com/publications/containing-floats/) 582 print '<div class="clearer"> </div>'; 583 print '</div>'; 584 } 585 flush(); 586 587 //do fulltext search 588 $data = array(); 589 search($data,$conf['datadir'],'search_fulltext',array(query => utf8_strtolower($QUERY))); 590 if(count($data)){ 591 usort($data,'sort_search_fulltext'); 592 foreach($data as $row){ 593 print '<div class="search_result">'; 594 print html_wikilink(':'.$row['id'],$row['id'],$QUERY); 595 print ': <span class="search_cnt">'.$row['count'].' '.$lang['hits'].'</span><br />'; 596 print '<div class="search_snippet">'.$row['snippet'].'</div>'; 597 print '</div>'; 598 } 599 }else{ 600 print '<div class="nothing">'.$lang['nothingfound'].'</div>'; 601 } 602 603 //hide progressbar 604 print '<script language="JavaScript" type="text/javascript">'; 605 print 'hideLoadBar();'; 606 print '</script>'; 607} 608 609/** 610 * Display error on locked pages 611 * 612 * @author Andreas Gohr <andi@splitbrain.org> 613 */ 614function html_locked($ip){ 615 global $ID; 616 global $conf; 617 global $lang; 618 619 $locktime = filemtime(wikiFN($ID).'.lock'); 620 $expire = @date($conf['dformat'], $locktime + $conf['locktime'] ); 621 $min = round(($conf['locktime'] - (time() - $locktime) )/60); 622 623 print parsedLocale('locked'); 624 print '<ul>'; 625 print '<li><b>'.$lang['lockedby'].':</b> '.$ip.'</li>'; 626 print '<li><b>'.$lang['lockexpire'].':</b> '.$expire.' ('.$min.' min)</li>'; 627 print '</ul>'; 628} 629 630/** 631 * list old revisions 632 * 633 * @author Andreas Gohr <andi@splitbrain.org> 634 */ 635function html_revisions(){ 636 global $ID; 637 global $INFO; 638 global $conf; 639 global $lang; 640 $revisions = getRevisions($ID); 641 $date = @date($conf['dformat'],$INFO['lastmod']); 642 643 print parsedLocale('revisions'); 644 print '<ul>'; 645 if($INFO['exists']){ 646 print '<li>'; 647 print $date.' <a class="wikilink1" href="'.wl($ID).'">'.$ID.'</a> '; 648 649 print $INFO['sum']; 650 print ' <span class="user">('; 651 print $INFO['ip']; 652 if($INFO['user']) print ' '.$INFO['user']; 653 print ')</span> '; 654 655 print '('.$lang['current'].')'; 656 print '</li>'; 657 } 658 659 foreach($revisions as $rev){ 660 $date = date($conf['dformat'],$rev); 661 $info = getRevisionInfo($ID,$rev); 662 663 print '<li>'; 664 print $date.' <a class="wikilink1" href="'.wl($ID,"rev=$rev").'">'.$ID.'</a> '; 665 print $info['sum']; 666 print ' <span class="user">('; 667 print $info['ip']; 668 if($info['user']) print ' '.$info['user']; 669 print ')</span> '; 670 671 print '<a href="'.wl($ID,"rev=$rev,do=diff").'">'; 672 print '<img src="'.DOKU_BASE.'images/diff.png" border="0" width="15" height="11" title="'.$lang['diff'].'" />'; 673 print '</a>'; 674 print '</li>'; 675 } 676 print '</ul>'; 677} 678 679/** 680 * display recent changes 681 * 682 * @author Andreas Gohr <andi@splitbrain.org> 683 */ 684function html_recent(){ 685 global $conf; 686 $recents = getRecents(0,true); 687 688 print parsedLocale('recent'); 689 print '<ul>'; 690 foreach(array_keys($recents) as $id){ 691 $date = date($conf['dformat'],$recents[$id]['date']); 692 print '<li>'; 693 print $date.' '.html_wikilink($id,$id); 694 print ' '.htmlspecialchars($recents[$id]['sum']); 695 print ' <span class="user">('; 696 print $recents[$id]['ip']; 697 if($recents[$id]['user']) print ' '.$recents[$id]['user']; 698 print ')</span>'; 699 print '</li>'; 700 } 701 print '</ul>'; 702} 703 704/** 705 * Display page index 706 * 707 * @author Andreas Gohr <andi@splitbrain.org> 708 */ 709function html_index($ns){ 710 require_once(DOKU_INC.'inc/search.php'); 711 global $conf; 712 global $ID; 713 $dir = $conf['datadir']; 714 $ns = cleanID($ns); 715 if(empty($ns)){ 716 $ns = dirname(str_replace(':','/',$ID)); 717 if($ns == '.') $ns =''; 718 } 719 $ns = utf8_encodeFN(str_replace(':','/',$ns)); 720 721 print parsedLocale('index'); 722 723 $data = array(); 724 search($data,$conf['datadir'],'search_index',array('ns' => $ns)); 725 print html_buildlist($data,'idx','html_list_index','html_li_index'); 726} 727 728/** 729 * Index item formatter 730 * 731 * User function for html_buildlist() 732 * 733 * @author Andreas Gohr <andi@splitbrain.org> 734 */ 735function html_list_index($item){ 736 $ret = ''; 737 $base = ':'.$item['id']; 738 $base = substr($base,strrpos($base,':')+1); 739 if($item['type']=='d'){ 740 $ret .= '<a href="'.wl($ID,'idx='.$item['id']).'" class="idx_dir">'; 741 $ret .= $base; 742 $ret .= '</a>'; 743 }else{ 744 $ret .= html_wikilink(':'.$item['id']); 745 } 746 return $ret; 747} 748 749/** 750 * Index List item 751 * 752 * This user function is used in html_build_lidt to build the 753 * <li> tags for namespaces when displaying the page index 754 * it gives different classes to opened or closed "folders" 755 * 756 * @author Andreas Gohr <andi@splitbrain.org> 757 */ 758function html_li_index($item){ 759 if($item['type'] == "f"){ 760 return '<li class="level'.$item['level'].'">'; 761 }elseif($item['open']){ 762 return '<li class="open">'; 763 }else{ 764 return '<li class="closed">'; 765 } 766} 767 768/** 769 * Default List item 770 * 771 * @author Andreas Gohr <andi@splitbrain.org> 772 */ 773function html_li_default($item){ 774 return '<li class="level'.$item['level'].'">'; 775} 776 777/** 778 * Build an unordered list 779 * 780 * Build an unordered list from the given $data array 781 * Each item in the array has to have a 'level' property 782 * the item itself gets printed by the given $func user 783 * function. The second and optional function is used to 784 * print the <li> tag. Both user function need to accept 785 * a single item. 786 * 787 * @author Andreas Gohr <andi@splitbrain.org> 788 */ 789function html_buildlist($data,$class,$func,$lifunc='html_li_default'){ 790 $level = 0; 791 $opens = 0; 792 $ret = ''; 793 794 foreach ($data as $item){ 795 796 if( $item['level'] > $level ){ 797 //open new list 798 for($i=0; $i<($item['level'] - $level); $i++){ 799 if ($i) $ret .= "<li class=\"clear\">\n"; 800 $ret .= "\n<ul class=\"$class\">\n"; 801 } 802 }elseif( $item['level'] < $level ){ 803 //close last item 804 $ret .= "</li>\n"; 805 for ($i=0; $i<($level - $item['level']); $i++){ 806 //close higher lists 807 $ret .= "</ul>\n</li>\n"; 808 } 809 }else{ 810 //close last item 811 $ret .= "</li>\n"; 812 } 813 814 //remember current level 815 $level = $item['level']; 816 817 //print item 818 $ret .= $lifunc($item); //user function 819 $ret .= '<span class="li">'; 820 $ret .= $func($item); //user function 821 $ret .= '</span>'; 822 } 823 824 //close remaining items and lists 825 for ($i=0; $i < $level; $i++){ 826 $ret .= "</li></ul>\n"; 827 } 828 829 return $ret; 830} 831 832/** 833 * display backlinks 834 * 835 * @author Andreas Gohr <andi@splitbrain.org> 836 */ 837function html_backlinks(){ 838 require_once(DOKU_INC.'inc/search.php'); 839 global $ID; 840 global $conf; 841 842 if(preg_match('#^(.*):(.*)$#',$ID,$matches)){ 843 $opts['ns'] = $matches[1]; 844 $opts['name'] = $matches[2]; 845 }else{ 846 $opts['ns'] = ''; 847 $opts['name'] = $ID; 848 } 849 850 print parsedLocale('backlinks'); 851 852 $data = array(); 853 search($data,$conf['datadir'],'search_backlinks',$opts); 854 sort($data); 855 856 print '<ul class="idx">'; 857 foreach($data as $row){ 858 print '<li>'; 859 print html_wikilink(':'.$row['id'],$row['id']); 860 print '</li>'; 861 } 862 print '</ul>'; 863} 864 865/** 866 * show diff 867 * 868 * @author Andreas Gohr <andi@splitbrain.org> 869 */ 870function html_diff($text='',$intro=true){ 871 require_once(DOKU_INC.'inc/DifferenceEngine.php'); 872 global $ID; 873 global $REV; 874 global $lang; 875 global $conf; 876 if($text){ 877 $df = new Diff(split("\n",htmlspecialchars(rawWiki($ID,''))), 878 split("\n",htmlspecialchars(cleanText($text)))); 879 $left = '<a class="wikilink1" href="'.wl($ID).'">'. 880 $ID.' '.date($conf['dformat'],@filemtime(wikiFN($ID))).'</a>'. 881 $lang['current']; 882 $right = $lang['yours']; 883 }else{ 884 $df = new Diff(split("\n",htmlspecialchars(rawWiki($ID,$REV))), 885 split("\n",htmlspecialchars(rawWiki($ID,'')))); 886 $left = '<a class="wikilink1" href="'.wl($ID,"rev=$REV").'">'. 887 $ID.' '.date($conf['dformat'],$REV).'</a>'; 888 $right = '<a class="wikilink1" href="'.wl($ID).'">'. 889 $ID.' '.date($conf['dformat'],@filemtime(wikiFN($ID))).'</a> '. 890 $lang['current']; 891 } 892 $tdf = new TableDiffFormatter(); 893 if($intro) print parsedLocale('diff'); 894 ?> 895 <table class="diff" width="100%"> 896 <tr> 897 <td colspan="2" width="50%" class="diff-header"> 898 <?=$left?> 899 </td> 900 <td colspan="2" width="50%" class="diff-header"> 901 <?=$right?> 902 </td> 903 </tr> 904 <?=$tdf->format($df)?> 905 </table> 906 <? 907} 908 909/** 910 * show warning on conflict detection 911 * 912 * @author Andreas Gohr <andi@splitbrain.org> 913 */ 914function html_conflict($text,$summary){ 915 global $ID; 916 global $lang; 917 918 print parsedLocale('conflict'); 919 ?> 920 <form name="editform" method="post" action="<?=script()?>" accept-charset="<?=$lang['encoding']?>"> 921 <input type="hidden" name="id" value="<?=$ID?>" /> 922 <input type="hidden" name="wikitext" value="<?=formText($text)?>" /> 923 <input type="hidden" name="summary" value="<?=formText($summary)?>" /> 924 925 <div align="center"> 926 <input class="button" type="submit" name="do" value="<?=$lang['btn_save']?>" accesskey="s" title="[ALT+S]" /> 927 <input class="button" type="submit" name="do" value="<?=$lang['btn_cancel']?>" /> 928 </div> 929 </form> 930 <br /><br /><br /><br /> 931 <? 932} 933 934/** 935 * Prints the global message array 936 * 937 * @author Andreas Gohr <andi@splitbrain.org> 938 */ 939function html_msgarea(){ 940 global $MSG; 941 942 if(!isset($MSG)) return; 943 944 foreach($MSG as $msg){ 945 print '<div class="'.$msg['lvl'].'">'; 946 print $msg['msg']; 947 print '</div>'; 948 } 949} 950 951/** 952 * Prints the registration form 953 * 954 * @author Andreas Gohr <andi@splitbrain.org> 955 */ 956function html_register(){ 957 global $lang; 958 global $ID; 959 960 print parsedLocale('register'); 961?> 962 <div align="center"> 963 <form name="register" method="post" action="<?=wl($ID)?>" accept-charset="<?=$lang['encoding']?>"> 964 <input type="hidden" name="do" value="register" /> 965 <input type="hidden" name="save" value="1" /> 966 <fieldset> 967 <legend><?=$lang['register']?></legend> 968 <label> 969 <?=$lang['user']?> 970 <input type="text" name="login" class="edit" size="50" value="<?=formText($_POST['login'])?>" /> 971 </label><br /> 972 <label> 973 <?=$lang['fullname']?> 974 <input type="text" name="fullname" class="edit" size="50" value="<?=formText($_POST['fullname'])?>" /> 975 </label><br /> 976 <label> 977 <?=$lang['email']?> 978 <input type="text" name="email" class="edit" size="50" value="<?=formText($_POST['email'])?>" /> 979 </label><br /> 980 <input type="submit" class="button" value="<?=$lang['register']?>" /> 981 </fieldset> 982 </form> 983 </div> 984<? 985} 986 987/** 988 * This displays the edit form (lots of logic included) 989 * 990 * @author Andreas Gohr <andi@splitbrain.org> 991 */ 992function html_edit($text=null,$include='edit'){ //FIXME: include needed? 993 global $ID; 994 global $REV; 995 global $DATE; 996 global $RANGE; 997 global $PRE; 998 global $SUF; 999 global $INFO; 1000 global $SUM; 1001 global $lang; 1002 global $conf; 1003 1004 //check for create permissions first 1005 if(!$INFO['exists'] && !html_acl(AUTH_CREATE)) return; 1006 1007 //set summary default 1008 if(!$SUM){ 1009 if($REV){ 1010 $SUM = $lang['restored']; 1011 }elseif(!$INFO['exists']){ 1012 $SUM = $lang['created']; 1013 } 1014 } 1015 1016 //no text? Load it! 1017 if(!isset($text)){ 1018 $pr = false; //no preview mode 1019 if($RANGE){ 1020 list($PRE,$text,$SUF) = rawWikiSlices($RANGE,$ID,$REV); 1021 }else{ 1022 $text = rawWiki($ID,$REV); 1023 } 1024 }else{ 1025 $pr = true; //preview mode 1026 } 1027 1028 $wr = $INFO['writable']; 1029 if($wr){ 1030 if ($REV) print parsedLocale('editrev'); 1031 print parsedLocale($include); 1032 }else{ 1033 print parsedLocale('read'); 1034 $ro='readonly="readonly"'; 1035 } 1036 if(!$DATE) $DATE = $INFO['lastmod']; 1037?> 1038 <form name="editform" method="post" action="<?=script()?>" accept-charset="<?=$lang['encoding']?>" onsubmit="return svchk()"> 1039 <input type="hidden" name="id" value="<?=$ID?>" /> 1040 <input type="hidden" name="rev" value="<?=$REV?>" /> 1041 <input type="hidden" name="date" value="<?=$DATE?>" /> 1042 <input type="hidden" name="prefix" value="<?=formText($PRE)?>" /> 1043 <input type="hidden" name="suffix" value="<?=formText($SUF)?>" /> 1044 <table style="width:99%"> 1045 <tr> 1046 <td class="toolbar" colspan="3"> 1047 <?if($wr){?> 1048 <script language="JavaScript" type="text/javascript"> 1049 <?/* sets changed to true when previewed */?> 1050 textChanged = <? ($pr) ? print 'true' : print 'false' ?>; 1051 1052 formatButton('images/bold.png','<?=$lang['qb_bold']?>','**','**','<?=$lang['qb_bold']?>','b'); 1053 formatButton('images/italic.png','<?=$lang['qb_italic']?>',"\/\/","\/\/",'<?=$lang['qb_italic']?>','i'); 1054 formatButton('images/underline.png','<?=$lang['qb_underl']?>','__','__','<?=$lang['qb_underl']?>','u'); 1055 formatButton('images/code.png','<?=$lang['qb_code']?>','\'\'','\'\'','<?=$lang['qb_code']?>','c'); 1056 1057 formatButton('images/fonth1.png','<?=$lang['qb_h1']?>','====== ',' ======\n','<?=$lang['qb_h1']?>','1'); 1058 formatButton('images/fonth2.png','<?=$lang['qb_h2']?>','===== ',' =====\n','<?=$lang['qb_h2']?>','2'); 1059 formatButton('images/fonth3.png','<?=$lang['qb_h3']?>','==== ',' ====\n','<?=$lang['qb_h3']?>','3'); 1060 formatButton('images/fonth4.png','<?=$lang['qb_h4']?>','=== ',' ===\n','<?=$lang['qb_h4']?>','4'); 1061 formatButton('images/fonth5.png','<?=$lang['qb_h5']?>','== ',' ==\n','<?=$lang['qb_h5']?>','5'); 1062 1063 formatButton('images/link.png','<?=$lang['qb_link']?>','[[',']]','<?=$lang['qb_link']?>','l'); 1064 formatButton('images/extlink.png','<?=$lang['qb_extlink']?>','[[',']]','http://www.example.com|<?=$lang['qb_extlink']?>'); 1065 1066 formatButton('images/list.png','<?=$lang['qb_ol']?>',' - ','\n','<?=$lang['qb_ol']?>'); 1067 formatButton('images/list_ul.png','<?=$lang['qb_ul']?>',' * ','\n','<?=$lang['qb_ul']?>'); 1068 1069 insertButton('images/rule.png','<?=$lang['qb_hr']?>','----\n'); 1070 mediaButton('images/image.png','<?=$lang['qb_media']?>','m','<?=$INFO['namespace']?>'); 1071 1072 <? 1073 if($conf['useacl'] && $_SERVER['REMOTE_USER']){ 1074 echo "insertButton('images/sig.png','".$lang['qb_sig']."','".html_signature()."','y');"; 1075 } 1076 ?> 1077 </script> 1078 <?}?> 1079 </td> 1080 </tr> 1081 <tr> 1082 <td colspan="3"> 1083 <textarea name="wikitext" id="wikitext" <?=$ro?> cols="80" rows="10" class="edit" onchange="textChanged = true;" onkeyup="summaryCheck();" tabindex="1"><?="\n".formText($text)?></textarea> 1084 </td> 1085 </tr> 1086 <tr> 1087 <td> 1088 <?if($wr){?> 1089 <input class="button" type="submit" name="do" value="<?=$lang['btn_save']?>" accesskey="s" title="[ALT+S]" onclick="textChanged=false" onkeypress="textChanged=false" tabindex="3" /> 1090 <input class="button" type="submit" name="do" value="<?=$lang['btn_preview']?>" accesskey="p" title="[ALT+P]" onclick="textChanged=false" onkeypress="textChanged=false" tabindex="4" /> 1091 <input class="button" type="submit" name="do" value="<?=$lang['btn_cancel']?>" tabindex="5" /> 1092 <?}?> 1093 </td> 1094 <td> 1095 <?if($wr){?> 1096 <?=$lang['summary']?>: 1097 <input type="text" class="edit" name="summary" id="summary" size="50" onkeyup="summaryCheck();" value="<?=formText($SUM)?>" tabindex="2" /> 1098 <?}?> 1099 </td> 1100 <td align="right"> 1101 <script type="text/javascript"> 1102 showSizeCtl(); 1103 <?if($wr){?> 1104 init_locktimer(<?=$conf['locktime']-60?>,'<?=$lang['willexpire']?>'); 1105 document.editform.wikitext.focus(); 1106 <?}?> 1107 </script> 1108 </td> 1109 </tr> 1110 </table> 1111 </form> 1112<? 1113} 1114 1115/** 1116 * prepares the signature string as configured in the config 1117 * 1118 * @author Andreas Gohr <andi@splitbrain.org> 1119 */ 1120function html_signature(){ 1121 global $conf; 1122 global $INFO; 1123 1124 $sig = $conf['signature']; 1125 $sig = strftime($sig); 1126 $sig = str_replace('@USER@',$_SERVER['REMOTE_USER'],$sig); 1127 $sig = str_replace('@NAME@',$INFO['userinfo']['name'],$sig); 1128 $sig = str_replace('@MAIL@',$INFO['userinfo']['mail'],$sig); 1129 $sig = str_replace('@DATE@',date($conf['dformat']),$sig); 1130 return $sig; 1131} 1132 1133/** 1134 * prints some debug info 1135 * 1136 * @author Andreas Gohr <andi@splitbrain.org> 1137 */ 1138function html_debug(){ 1139 global $conf; 1140 global $lang; 1141 //remove sensitive data 1142 $cnf = $conf; 1143 $cnf['auth']='***'; 1144 $cnf['notify']='***'; 1145 $cnf['ftp']='***'; 1146 1147 print '<html><body>'; 1148 1149 print '<p>When reporting bugs please send all the following '; 1150 print 'output as a mail to andi@splitbrain.org '; 1151 print 'The best way to do this is to save this page in your browser</p>'; 1152 1153 print '<b>$_SERVER:</b><pre>'; 1154 print_r($_SERVER); 1155 print '</pre>'; 1156 1157 print '<b>$conf:</b><pre>'; 1158 print_r($cnf); 1159 print '</pre>'; 1160 1161 print '<b>DOKU_BASE:</b><pre>'; 1162 print DOKU_BASE; 1163 print '</pre>'; 1164 1165 print '<b>abs DOKU_BASE:</b><pre>'; 1166 print DOKU_URL; 1167 print '</pre>'; 1168 1169 print '<b>rel DOKU_BASE:</b><pre>'; 1170 print dirname($_SERVER['PHP_SELF']).'/'; 1171 print '</pre>'; 1172 1173 print '<b>PHP Version:</b><pre>'; 1174 print phpversion(); 1175 print '</pre>'; 1176 1177 print '<b>locale:</b><pre>'; 1178 print setlocale(LC_ALL,0); 1179 print '</pre>'; 1180 1181 print '<b>encoding:</b><pre>'; 1182 print $lang['encoding']; 1183 print '</pre>'; 1184 1185 print '<b>Environment:</b><pre>'; 1186 print_r($_ENV); 1187 print '</pre>'; 1188 1189 print '<b>PHP settings:</b><pre>'; 1190 $inis = ini_get_all(); 1191 print_r($inis); 1192 print '</pre>'; 1193 1194 print '</body></html>'; 1195} 1196 1197/** 1198 * prints the acl-admin form(s) 1199 * 1200 * @author Frank Schubert <frank@schokilade.de> 1201 */ 1202function html_acl_admin(){ 1203 global $lang; 1204 global $ID; 1205 global $INFO; 1206 1207 print parsedLocale('acl_admin'); 1208?> 1209 <fieldset style="float:left; text-align:left; white-space:nowrap; width:320px;"> 1210 <legend><?=$lang['acl_admin']?></legend> 1211 1212 <form name="acl_admin_add" method="post" action="<?=wl($ID)?>" accept-charset="<?=$lang['encoding']?>"> 1213 <input type="hidden" name="do" value="acl_admin_add" /> 1214 <input type="hidden" name="save" value="1" /> 1215 <table> 1216 <tr> 1217 <td><?=$lang['acl_user']?></td> 1218 <td><input type="text" name="acl_user" class="edit" size="20" value="" /></td> 1219 </tr><tr> 1220 <td><?=$lang['acl_scope']?></td> 1221 <td><select name="acl_scope" id="acl_scope" class="edit" size="1" onChange="checkAclLevel();"> 1222 <option value="">(<?=$lang['acl_input_request']?>)</option> 1223 <option><?=$ID?></option> 1224 <?php if( ($ns=getNS($ID)) != NULL) {?> 1225 <option><?=$ns?>:*</option> 1226 <?php }else{ ?> 1227 <option>*</option> 1228 <?php } ?> 1229 </select></td> 1230 </tr><tr> 1231 <td style="vertical-align:top"><?=$lang['acl_level']?></td> 1232 <td> 1233 <input type="checkbox" name="acl_checkbox[1]" value="on" checked="checked" /><?=$lang['acl_read']?><br /> 1234 <input type="checkbox" name="acl_checkbox[2]" value="on" /><?=$lang['acl_edit']?><br /> 1235 <input type="checkbox" name="acl_checkbox[4]" value="on" /><?=$lang['acl_create']?><br /> 1236 <input type="checkbox" name="acl_checkbox[8]" value="on" /><?=$lang['acl_upload']?> 1237 </td> 1238 </tr><tr> 1239 <td></td> 1240 <td><input type="submit" class="button" value="<?=$lang['acl_commit']?>" /></td> 1241 </tr> 1242 </table> 1243 </form> 1244 </fieldset> 1245 1246 <div style="float:right;"> 1247 <fieldset> 1248 <legend><?=$lang['acl_current']?></legend> 1249 <div style="text-align:left"> 1250 <?php 1251 $acl_config=get_acl_config($ID); 1252 foreach($acl_config as $pagename => $value){ 1253 if($pagename != '*') { 1254 $ID_cur=$pagename; 1255 while(($piece=getNS($ID_cur)) !== false){ 1256 $url="<a href='".wl($piece,'do=acl_admin')."'>".noNS($piece)."</a>:".$url;; 1257 $ID_cur=$piece; 1258 } 1259 $url.="<a href='".wl($pagename,'do=acl_admin')."'>".noNS($pagename)."</a>"; 1260 print $url; 1261 $url=''; 1262 }else{ 1263 print $pagename; 1264 } ?> 1265 <table class="inline"> 1266 <tr> 1267 <th class="inline"></th> 1268 <th class="inline">name</th> 1269 <th class="inline">R</th> 1270 <th class="inline">W</th> 1271 <th class="inline">C</th> 1272 <th class="inline">U</th> 1273 <th class="inline">UPDATE</th> 1274 <th class="inline">DELETE</th> 1275 </tr> 1276 <?php 1277 foreach($value as $conf){ 1278 ?> 1279 <tr> 1280 <!-- user/group --> 1281 <td class="inline"> 1282 <?php 1283 $group = false; 1284 if(substr($conf[0],0,1)=="@"){ 1285 print $lang['acl_group']; 1286 $group = true; 1287 }else{ 1288 print $lang['acl_user']; 1289 } 1290 ?> 1291 </td> 1292 <td class="inline"> 1293 <!-- name --> 1294 <?php 1295 if($group) { print substr($conf[0],1); } else { print $conf[0]; } 1296 ?> 1297 </td> 1298 <form name="acl_admin_change" method="post" action="<?=wl($ID)?>" accept-charset="<?=$lang['encoding']?>"> 1299 <?php 1300 // read,write,create,upload 1301 $acl_nums=array(1,2,4,8); 1302 foreach($acl_nums as $num){ 1303 ?><td class="inline"> 1304 <input type="hidden" name="do" value="acl_admin_change" /> 1305 <input type="hidden" name="save" value="1" /> 1306 <input type="hidden" name="acl_scope" value='<?=urlencode($pagename)?>' /> 1307 <input type="hidden" name="acl_user" value='<?=urlencode($conf[0])?>' /> 1308 <input type="hidden" name="acl_level" value='<?=$conf[1]?>' /> 1309 <input type="checkbox" name="acl_checkbox[<?=$num?>]" value="on"<?php 1310 if($conf[1]>=$num) { 1311 ?> checked="checked"<?php 1312 } 1313 ?> /></td><?php 1314 } 1315 ?> 1316 <td class="inline"><input type="submit" class="button" value="update"></td> 1317 </form> 1318 <td class="inline"> 1319 <!-- delete form --> 1320 <form name="acl_admin_del" method="post" action="<?=wl($ID)?>" accept-charset="<?=$lang['encoding']?>"> 1321 <input type="hidden" name="do" value="acl_admin_del" /> 1322 <input type="hidden" name="save" value="1" /> 1323 <input type="hidden" name="acl_scope" value='<?=urlencode($pagename);?>' /> 1324 <input type="hidden" name="acl_user" value='<?=urlencode($conf[0])?>' /> 1325 <input type="hidden" name="acl_level" value='<?=$conf[1]?>' /> 1326 <input type="submit" class="button" value='DEL' onClick="return window.confirm('<?=$lang['acl_confirm_delete']?>');" /> 1327 </form> 1328 </td> 1329 </tr> 1330 <?php 1331 } 1332 ?></table><?php 1333 } 1334 ?> 1335 </div> 1336 </fieldset> 1337 </div> 1338<? 1339} 1340?> 1341