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 } 432 ?> 433 <?=html_btn(index,$ID,'x',array('do' => 'index'))?> 434 <a href="#top"><input type="button" class="button" value="<?=$lang['btn_top']?>" /></a> 435 </div> 436 </div> 437 </div> 438 <?@include("includes/footer.html")?> 439 </div> 440 </body> 441 </html> 442<? 443} 444 445/** 446 * Print the table of contents 447 * 448 * @author Andreas Gohr <andi@splitbrain.org> 449 */ 450function html_toc($toc){ 451 global $lang; 452 $ret = ''; 453 $ret .= '<div class="toc">'; 454 $ret .= '<div class="tocheader">'; 455 $ret .= $lang['toc']; 456 $ret .= ' <script type="text/javascript">'; 457 $ret .= 'showTocToggle("+","-")'; 458 $ret .= '</script>'; 459 $ret .= '</div>'; 460 $ret .= '<div id="tocinside">'; 461 $ret .= html_buildlist($toc,'toc','html_list_toc'); 462 $ret .= '</div>'; 463 $ret .= '</div>'; 464 return $ret; 465} 466 467/** 468 * TOC item formatter 469 * 470 * User function for html_buildlist() 471 * 472 * @author Andreas Gohr <andi@splitbrain.org> 473 */ 474function html_list_toc($item){ 475 $ret = ''; 476 $ret .= '<a href="#'.$item['id'].'" class="toc">'; 477 $ret .= $item['name']; 478 $ret .= '</a>'; 479 return $ret; 480} 481 482/** 483 * show a wiki page 484 * 485 * @author Andreas Gohr <andi@splitbrain.org> 486 */ 487function html_show($text=''){ 488 global $ID; 489 global $REV; 490 global $HIGH; 491 //disable section editing for old revisions or in preview 492 if($text || $REV){ 493 global $parser; 494 $parser['secedit'] = false; 495 } 496 497 if ($text){ 498 //PreviewHeader 499 print parsedLocale('preview'); 500 print '<div class="preview">'; 501 print html_secedit(parse($text),false); 502 print '</div>'; 503 }else{ 504 if ($REV) print parsedLocale('showrev'); 505 $html = parsedWiki($ID,$REV,true); 506 $html = html_secedit($html); 507 print html_hilight($html,$HIGH); 508 } 509} 510 511/** 512 * Highlights searchqueries in HTML code 513 * 514 * @author Andreas Gohr <andi@splitbrain.org> 515 */ 516function html_hilight($html,$query){ 517 $queries = preg_split ("/\s/",$query,-1,PREG_SPLIT_NO_EMPTY); 518 foreach ($queries as $q){ 519 $q = preg_quote($q,'/'); 520 $html = preg_replace("/((<[^>]*)|$q)/ie", '"\2"=="\1"? "\1":"<span class=\"search_hit\">\1</span>"', $html); 521 } 522 return $html; 523} 524 525/** 526 * Run a search and display the result 527 * 528 * @author Andreas Gohr <andi@splitbrain.org> 529 */ 530function html_search(){ 531 require_once(DOKU_INC.'inc/search.php'); 532 global $conf; 533 global $QUERY; 534 global $ID; 535 global $lang; 536 537 print parsedLocale('searchpage'); 538 flush(); 539 540 //show progressbar 541 print '<div align="center">'; 542 print '<script language="JavaScript" type="text/javascript">'; 543 print 'showLoadBar();'; 544 print '</script>'; 545 print '<br /></div>'; 546 547 //do quick pagesearch 548 $data = array(); 549 search($data,$conf['datadir'],'search_pagename',array(query => cleanID($QUERY))); 550 if(count($data)){ 551 sort($data); 552 print '<div class="search_quickresult">'; 553 print '<b>'.$lang[quickhits].':</b><br />'; 554 foreach($data as $row){ 555 print '<div class="search_quickhits">'; 556 print html_wikilink(':'.$row['id'],$row['id']); 557 print '</div> '; 558 } 559 //clear float (see http://www.complexspiral.com/publications/containing-floats/) 560 print '<div class="clearer"> </div>'; 561 print '</div>'; 562 } 563 flush(); 564 565 //do fulltext search 566 $data = array(); 567 search($data,$conf['datadir'],'search_fulltext',array(query => utf8_strtolower($QUERY))); 568 if(count($data)){ 569 usort($data,'sort_search_fulltext'); 570 foreach($data as $row){ 571 print '<div class="search_result">'; 572 print html_wikilink(':'.$row['id'],$row['id'],$QUERY); 573 print ': <span class="search_cnt">'.$row['count'].' '.$lang['hits'].'</span><br />'; 574 print '<div class="search_snippet">'.$row['snippet'].'</div>'; 575 print '</div>'; 576 } 577 }else{ 578 print '<div align="center">'.$lang['nothingfound'].'</div>'; 579 } 580 581 //hide progressbar 582 print '<script language="JavaScript" type="text/javascript">'; 583 print 'hideLoadBar();'; 584 print '</script>'; 585} 586 587/** 588 * Display error on locked pages 589 * 590 * @author Andreas Gohr <andi@splitbrain.org> 591 */ 592function html_locked($ip){ 593 global $ID; 594 global $conf; 595 global $lang; 596 597 $locktime = filemtime(wikiFN($ID).'.lock'); 598 $expire = @date($conf['dformat'], $locktime + $conf['locktime'] ); 599 $min = round(($conf['locktime'] - (time() - $locktime) )/60); 600 601 print parsedLocale('locked'); 602 print '<ul>'; 603 print '<li><b>'.$lang['lockedby'].':</b> '.$ip.'</li>'; 604 print '<li><b>'.$lang['lockexpire'].':</b> '.$expire.' ('.$min.' min)</li>'; 605 print '</ul>'; 606} 607 608/** 609 * list old revisions 610 * 611 * @author Andreas Gohr <andi@splitbrain.org> 612 */ 613function html_revisions(){ 614 global $ID; 615 global $INFO; 616 global $conf; 617 global $lang; 618 $revisions = getRevisions($ID); 619 $date = @date($conf['dformat'],$INFO['lastmod']); 620 621 print parsedLocale('revisions'); 622 print '<ul>'; 623 if($INFO['exists']){ 624 print '<li>'; 625 print $date.' <a class="wikilink1" href="'.wl($ID).'">'.$ID.'</a> '; 626 627 print $INFO['sum']; 628 print ' <span class="user">('; 629 print $INFO['ip']; 630 if($INFO['user']) print ' '.$INFO['user']; 631 print ')</span> '; 632 633 print '('.$lang['current'].')'; 634 print '</li>'; 635 } 636 637 foreach($revisions as $rev){ 638 $date = date($conf['dformat'],$rev); 639 $info = getRevisionInfo($ID,$rev); 640 641 print '<li>'; 642 print $date.' <a class="wikilink1" href="'.wl($ID,"rev=$rev").'">'.$ID.'</a> '; 643 print $info['sum']; 644 print ' <span class="user">('; 645 print $info['ip']; 646 if($info['user']) print ' '.$info['user']; 647 print ')</span> '; 648 649 print '<a href="'.wl($ID,"rev=$rev,do=diff").'">'; 650 print '<img src="'.DOKU_BASE.'images/diff.png" border="0" width="15" height="11" title="'.$lang['diff'].'" />'; 651 print '</a>'; 652 print '</li>'; 653 } 654 print '</ul>'; 655} 656 657/** 658 * display recent changes 659 * 660 * @author Andreas Gohr <andi@splitbrain.org> 661 */ 662function html_recent(){ 663 global $conf; 664 $recents = getRecents(0,true); 665 666 print parsedLocale('recent'); 667 print '<ul>'; 668 foreach(array_keys($recents) as $id){ 669 $date = date($conf['dformat'],$recents[$id]['date']); 670 print '<li>'; 671 print $date.' '.html_wikilink($id,$id); 672 print ' '.htmlspecialchars($recents[$id]['sum']); 673 print ' <span class="user">('; 674 print $recents[$id]['ip']; 675 if($recents[$id]['user']) print ' '.$recents[$id]['user']; 676 print ')</span>'; 677 print '</li>'; 678 } 679 print '</ul>'; 680} 681 682/** 683 * Display page index 684 * 685 * @author Andreas Gohr <andi@splitbrain.org> 686 */ 687function html_index($ns){ 688 require_once(DOKU_INC.'inc/search.php'); 689 global $conf; 690 global $ID; 691 $dir = $conf['datadir']; 692 $ns = cleanID($ns); 693 if(empty($ns)){ 694 $ns = dirname(str_replace(':','/',$ID)); 695 if($ns == '.') $ns =''; 696 } 697 $ns = str_replace(':','/',$ns); 698 699 print parsedLocale('index'); 700 701 $data = array(); 702 search($data,$conf['datadir'],'search_index',array('ns' => $ns)); 703 print html_buildlist($data,'idx','html_list_index','html_li_index'); 704} 705 706/** 707 * Index item formatter 708 * 709 * User function for html_buildlist() 710 * 711 * @author Andreas Gohr <andi@splitbrain.org> 712 */ 713function html_list_index($item){ 714 $ret = ''; 715 $base = ':'.$item['id']; 716 $base = substr($base,strrpos($base,':')+1); 717 if($item['type']=='d'){ 718 $ret .= '<a href="'.wl($ID,'idx='.$item['id']).'" class="idx_dir">'; 719 $ret .= $base; 720 $ret .= '</a>'; 721 }else{ 722 $ret .= html_wikilink(':'.$item['id']); 723 } 724 return $ret; 725} 726 727/** 728 * Index List item 729 * 730 * This user function is used in html_build_lidt to build the 731 * <li> tags for namespaces when displaying the page index 732 * it gives different classes to opened or closed "folders" 733 * 734 * @author Andreas Gohr <andi@splitbrain.org> 735 */ 736function html_li_index($item){ 737 if($item['type'] == "f"){ 738 return '<li class="level'.$item['level'].'">'; 739 }elseif($item['open']){ 740 return '<li class="open">'; 741 }else{ 742 return '<li class="closed">'; 743 } 744} 745 746/** 747 * Default List item 748 * 749 * @author Andreas Gohr <andi@splitbrain.org> 750 */ 751function html_li_default($item){ 752 return '<li class="level'.$item['level'].'">'; 753} 754 755/** 756 * Build an unordered list 757 * 758 * Build an unordered list from the given $data array 759 * Each item in the array has to have a 'level' property 760 * the item itself gets printed by the given $func user 761 * function. The second and optional function is used to 762 * print the <li> tag. Both user function need to accept 763 * a single item. 764 * 765 * @author Andreas Gohr <andi@splitbrain.org> 766 */ 767function html_buildlist($data,$class,$func,$lifunc='html_li_default'){ 768 $level = 0; 769 $opens = 0; 770 $ret = ''; 771 772 foreach ($data as $item){ 773 774 if( $item['level'] > $level ){ 775 //open new list 776 for($i=0; $i<($item['level'] - $level); $i++){ 777 if ($i) $ret .= "<li class=\"clear\">\n"; 778 $ret .= "\n<ul class=\"$class\">\n"; 779 } 780 }elseif( $item['level'] < $level ){ 781 //close last item 782 $ret .= "</li>\n"; 783 for ($i=0; $i<($level - $item['level']); $i++){ 784 //close higher lists 785 $ret .= "</ul>\n</li>\n"; 786 } 787 }else{ 788 //close last item 789 $ret .= "</li>\n"; 790 } 791 792 //remember current level 793 $level = $item['level']; 794 795 //print item 796 $ret .= $lifunc($item); //user function 797 $ret .= '<span class="li">'; 798 $ret .= $func($item); //user function 799 $ret .= '</span>'; 800 } 801 802 //close remaining items and lists 803 for ($i=0; $i < $level; $i++){ 804 $ret .= "</li></ul>\n"; 805 } 806 807 return $ret; 808} 809 810/** 811 * display backlinks 812 * 813 * @author Andreas Gohr <andi@splitbrain.org> 814 */ 815function html_backlinks(){ 816 require_once(DOKU_INC.'inc/search.php'); 817 global $ID; 818 global $conf; 819 820 if(preg_match('#^(.*):(.*)$#',$ID,$matches)){ 821 $opts['ns'] = $matches[1]; 822 $opts['name'] = $matches[2]; 823 }else{ 824 $opts['ns'] = ''; 825 $opts['name'] = $ID; 826 } 827 828 print parsedLocale('backlinks'); 829 830 $data = array(); 831 search($data,$conf['datadir'],'search_backlinks',$opts); 832 sort($data); 833 834 print '<ul class="idx">'; 835 foreach($data as $row){ 836 print '<li>'; 837 print html_wikilink(':'.$row['id'],$row['id']); 838 print '</li>'; 839 } 840 print '</ul>'; 841} 842 843/** 844 * show diff 845 * 846 * @author Andreas Gohr <andi@splitbrain.org> 847 */ 848function html_diff($text='',$intro=true){ 849 require_once(DOKU_INC.'inc/DifferenceEngine.php'); 850 global $ID; 851 global $REV; 852 global $lang; 853 global $conf; 854 if($text){ 855 $df = new Diff(split("\n",htmlspecialchars(rawWiki($ID,''))), 856 split("\n",htmlspecialchars(cleanText($text)))); 857 $left = '<a class="wikilink1" href="'.wl($ID).'">'. 858 $ID.' '.date($conf['dformat'],@filemtime(wikiFN($ID))).'</a>'. 859 $lang['current']; 860 $right = $lang['yours']; 861 }else{ 862 $df = new Diff(split("\n",htmlspecialchars(rawWiki($ID,$REV))), 863 split("\n",htmlspecialchars(rawWiki($ID,'')))); 864 $left = '<a class="wikilink1" href="'.wl($ID,"rev=$REV").'">'. 865 $ID.' '.date($conf['dformat'],$REV).'</a>'; 866 $right = '<a class="wikilink1" href="'.wl($ID).'">'. 867 $ID.' '.date($conf['dformat'],@filemtime(wikiFN($ID))).'</a> '. 868 $lang['current']; 869 } 870 $tdf = new TableDiffFormatter(); 871 if($intro) print parsedLocale('diff'); 872 ?> 873 <table class="diff" width="100%"> 874 <tr> 875 <td colspan="2" width="50%" class="diff-header"> 876 <?=$left?> 877 </td> 878 <td colspan="2" width="50%" class="diff-header"> 879 <?=$right?> 880 </td> 881 </tr> 882 <?=$tdf->format($df)?> 883 </table> 884 <? 885} 886 887/** 888 * show warning on conflict detection 889 * 890 * @author Andreas Gohr <andi@splitbrain.org> 891 */ 892function html_conflict($text,$summary){ 893 global $ID; 894 global $lang; 895 896 print parsedLocale('conflict'); 897 ?> 898 <form name="editform" method="post" action="<?=script()?>" accept-charset="<?=$lang['encoding']?>"> 899 <input type="hidden" name="id" value="<?=$ID?>" /> 900 <input type="hidden" name="wikitext" value="<?=formText($text)?>" /> 901 <input type="hidden" name="summary" value="<?=formText($summary)?>" /> 902 903 <div align="center"> 904 <input class="button" type="submit" name="do" value="<?=$lang['btn_save']?>" accesskey="s" title="[ALT+S]" /> 905 <input class="button" type="submit" name="do" value="<?=$lang['btn_cancel']?>" /> 906 </div> 907 </form> 908 <br /><br /><br /><br /> 909 <? 910} 911 912/** 913 * Prints the global message array 914 * 915 * @author Andreas Gohr <andi@splitbrain.org> 916 */ 917function html_msgarea(){ 918 global $MSG; 919 920 if(!isset($MSG)) return; 921 922 foreach($MSG as $msg){ 923 print '<div class="'.$msg['lvl'].'">'; 924 print $msg['msg']; 925 print '</div>'; 926 } 927} 928 929/** 930 * Prints the registration form 931 * 932 * @author Andreas Gohr <andi@splitbrain.org> 933 */ 934function html_register(){ 935 global $lang; 936 global $ID; 937 938 print parsedLocale('register'); 939?> 940 <div align="center"> 941 <form name="register" method="post" action="<?=wl($ID)?>" accept-charset="<?=$lang['encoding']?>"> 942 <input type="hidden" name="do" value="register" /> 943 <input type="hidden" name="save" value="1" /> 944 <fieldset> 945 <legend><?=$lang['register']?></legend> 946 <label> 947 <?=$lang['user']?> 948 <input type="text" name="login" class="edit" size="50" value="<?=formText($_POST['login'])?>" /> 949 </label><br /> 950 <label> 951 <?=$lang['fullname']?> 952 <input type="text" name="fullname" class="edit" size="50" value="<?=formText($_POST['fullname'])?>" /> 953 </label><br /> 954 <label> 955 <?=$lang['email']?> 956 <input type="text" name="email" class="edit" size="50" value="<?=formText($_POST['email'])?>" /> 957 </label><br /> 958 <input type="submit" class="button" value="<?=$lang['register']?>" /> 959 </fieldset> 960 </form> 961 </div> 962<? 963} 964 965/** 966 * This displays the edit form (lots of logic included) 967 * 968 * @author Andreas Gohr <andi@splitbrain.org> 969 */ 970function html_edit($text=null,$include='edit'){ //FIXME: include needed? 971 global $ID; 972 global $REV; 973 global $DATE; 974 global $RANGE; 975 global $PRE; 976 global $SUF; 977 global $INFO; 978 global $SUM; 979 global $lang; 980 global $conf; 981 982 //check for create permissions first 983 if(!$INFO['exists'] && !html_acl(AUTH_CREATE)) return; 984 985 //set summary default 986 if(!$SUM){ 987 if($REV){ 988 $SUM = $lang['restored']; 989 }elseif(!$INFO['exists']){ 990 $SUM = $lang['created']; 991 } 992 } 993 994 //no text? Load it! 995 if(!isset($text)){ 996 $pr = false; //no preview mode 997 if($RANGE){ 998 list($PRE,$text,$SUF) = rawWikiSlices($RANGE,$ID,$REV); 999 }else{ 1000 $text = rawWiki($ID,$REV); 1001 } 1002 }else{ 1003 $pr = true; //preview mode 1004 } 1005 1006 $wr = $INFO['writable']; 1007 if($wr){ 1008 if ($REV) print parsedLocale('editrev'); 1009 print parsedLocale($include); 1010 }else{ 1011 print parsedLocale('read'); 1012 $ro='readonly="readonly"'; 1013 } 1014 if(!$DATE) $DATE = $INFO['lastmod']; 1015?> 1016 <form name="editform" method="post" action="<?=script()?>" accept-charset="<?=$lang['encoding']?>" onsubmit="return svchk()"> 1017 <input type="hidden" name="id" value="<?=$ID?>" /> 1018 <input type="hidden" name="rev" value="<?=$REV?>" /> 1019 <input type="hidden" name="date" value="<?=$DATE?>" /> 1020 <input type="hidden" name="prefix" value="<?=formText($PRE)?>" /> 1021 <input type="hidden" name="suffix" value="<?=formText($SUF)?>" /> 1022 <table style="width:99%"> 1023 <tr> 1024 <td class="toolbar" colspan="3"> 1025 <?if($wr){?> 1026 <script language="JavaScript" type="text/javascript"> 1027 <?/* sets changed to true when previewed */?> 1028 textChanged = <? ($pr) ? print 'true' : print 'false' ?>; 1029 1030 formatButton('images/bold.png','<?=$lang['qb_bold']?>','**','**','<?=$lang['qb_bold']?>','b'); 1031 formatButton('images/italic.png','<?=$lang['qb_italic']?>',"\/\/","\/\/",'<?=$lang['qb_italic']?>','i'); 1032 formatButton('images/underline.png','<?=$lang['qb_underl']?>','__','__','<?=$lang['qb_underl']?>','u'); 1033 formatButton('images/code.png','<?=$lang['qb_code']?>','\'\'','\'\'','<?=$lang['qb_code']?>','c'); 1034 1035 formatButton('images/fonth1.png','<?=$lang['qb_h1']?>','====== ',' ======\n','<?=$lang['qb_h1']?>','1'); 1036 formatButton('images/fonth2.png','<?=$lang['qb_h2']?>','===== ',' =====\n','<?=$lang['qb_h2']?>','2'); 1037 formatButton('images/fonth3.png','<?=$lang['qb_h3']?>','==== ',' ====\n','<?=$lang['qb_h3']?>','3'); 1038 formatButton('images/fonth4.png','<?=$lang['qb_h4']?>','=== ',' ===\n','<?=$lang['qb_h4']?>','4'); 1039 formatButton('images/fonth5.png','<?=$lang['qb_h5']?>','== ',' ==\n','<?=$lang['qb_h5']?>','5'); 1040 1041 formatButton('images/link.png','<?=$lang['qb_link']?>','[[',']]','<?=$lang['qb_link']?>','l'); 1042 formatButton('images/extlink.png','<?=$lang['qb_extlink']?>','[[',']]','http://www.example.com|<?=$lang['qb_extlink']?>'); 1043 1044 formatButton('images/list.png','<?=$lang['qb_ol']?>',' - ','\n','<?=$lang['qb_ol']?>'); 1045 formatButton('images/list_ul.png','<?=$lang['qb_ul']?>',' * ','\n','<?=$lang['qb_ul']?>'); 1046 1047 insertButton('images/rule.png','<?=$lang['qb_hr']?>','----\n'); 1048 mediaButton('images/image.png','<?=$lang['qb_media']?>','m','<?=$INFO['namespace']?>'); 1049 1050 <? 1051 if($conf['useacl'] && $_SERVER['REMOTE_USER']){ 1052 echo "insertButton('images/sig.png','".$lang['qb_sig']."','".html_signature()."','y');"; 1053 } 1054 ?> 1055 </script> 1056 <?}?> 1057 </td> 1058 </tr> 1059 <tr> 1060 <td colspan="3"> 1061 <textarea name="wikitext" id="wikitext" <?=$ro?> cols="80" rows="10" class="edit" onchange="textChanged = true;" onkeyup="summaryCheck();" tabindex="1"><?="\n".formText($text)?></textarea> 1062 </td> 1063 </tr> 1064 <tr> 1065 <td> 1066 <?if($wr){?> 1067 <input class="button" type="submit" name="do" value="<?=$lang['btn_save']?>" accesskey="s" title="[ALT+S]" onclick="textChanged=false" onkeypress="textChanged=false" tabindex="3" /> 1068 <input class="button" type="submit" name="do" value="<?=$lang['btn_preview']?>" accesskey="p" title="[ALT+P]" onclick="textChanged=false" onkeypress="textChanged=false" tabindex="4" /> 1069 <input class="button" type="submit" name="do" value="<?=$lang['btn_cancel']?>" tabindex="5" /> 1070 <?}?> 1071 </td> 1072 <td> 1073 <?if($wr){?> 1074 <?=$lang['summary']?>: 1075 <input type="text" class="edit" name="summary" id="summary" size="50" onkeyup="summaryCheck();" value="<?=formText($SUM)?>" tabindex="2" /> 1076 <?}?> 1077 </td> 1078 <td align="right"> 1079 <script type="text/javascript"> 1080 showSizeCtl(); 1081 <?if($wr){?> 1082 init_locktimer(<?=$conf['locktime']-60?>,'<?=$lang['willexpire']?>'); 1083 document.editform.wikitext.focus(); 1084 <?}?> 1085 </script> 1086 </td> 1087 </tr> 1088 </table> 1089 </form> 1090<? 1091} 1092 1093/** 1094 * prepares the signature string as configured in the config 1095 * 1096 * @author Andreas Gohr <andi@splitbrain.org> 1097 */ 1098function html_signature(){ 1099 global $conf; 1100 global $INFO; 1101 1102 $sig = $conf['signature']; 1103 $sig = strftime($sig); 1104 $sig = str_replace('@USER@',$_SERVER['REMOTE_USER'],$sig); 1105 $sig = str_replace('@NAME@',$INFO['userinfo']['name'],$sig); 1106 $sig = str_replace('@MAIL@',$INFO['userinfo']['mail'],$sig); 1107 $sig = str_replace('@DATE@',date($conf['dformat']),$sig); 1108 return $sig; 1109} 1110 1111/** 1112 * prints some debug info 1113 * 1114 * @author Andreas Gohr <andi@splitbrain.org> 1115 */ 1116function html_debug(){ 1117 global $conf; 1118 global $lang; 1119 //remove sensitive data 1120 $cnf = $conf; 1121 $cnf['auth']='***'; 1122 $cnf['notify']='***'; 1123 1124 print '<html><body>'; 1125 1126 print '<p>When reporting bugs please send all the following '; 1127 print 'output as a mail to andi@splitbrain.org '; 1128 print 'The best way to do this is to save this page in your browser</p>'; 1129 1130 print '<b>$_SERVER:</b><pre>'; 1131 print_r($_SERVER); 1132 print '</pre>'; 1133 1134 print '<b>$conf:</b><pre>'; 1135 print_r($cnf); 1136 print '</pre>'; 1137 1138 print '<b>DOKU_BASE:</b><pre>'; 1139 print DOKU_BASE; 1140 print '</pre>'; 1141 1142 print '<b>abs DOKU_BASE:</b><pre>'; 1143 print DOKU_URL; 1144 print '</pre>'; 1145 1146 print '<b>rel DOKU_BASE:</b><pre>'; 1147 print dirname($_SERVER['PHP_SELF']).'/'; 1148 print '</pre>'; 1149 1150 print '<b>PHP Version:</b><pre>'; 1151 print phpversion(); 1152 print '</pre>'; 1153 1154 print '<b>locale:</b><pre>'; 1155 print setlocale(LC_ALL,0); 1156 print '</pre>'; 1157 1158 print '<b>encoding:</b><pre>'; 1159 print $lang['encoding']; 1160 print '</pre>'; 1161 1162 print '<b>Environment:</b><pre>'; 1163 print_r($_ENV); 1164 print '</pre>'; 1165 1166 print '<b>PHP settings:</b><pre>'; 1167 $inis = ini_get_all(); 1168 print_r($inis); 1169 print '</pre>'; 1170 1171 print '</body></html>'; 1172} 1173 1174?> 1175