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