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