1<?php 2/** 3 * Initialize some defaults needed for DokuWiki 4 */ 5 6// start timing Dokuwiki execution 7function delta_time($start=0) { 8 list($usec, $sec) = explode(" ", microtime()); 9 return ((float)$usec+(float)$sec)-((float)$start); 10} 11define('DOKU_START_TIME', delta_time()); 12 13global $config_cascade; 14$config_cascade = ''; 15 16// if available load a preload config file 17$preload = fullpath(dirname(__FILE__)).'/preload.php'; 18if (@file_exists($preload)) include($preload); 19 20// define the include path 21if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../').'/'); 22 23// define config path (packagers may want to change this to /etc/dokuwiki/) 24if(!defined('DOKU_CONF')) define('DOKU_CONF',DOKU_INC.'conf/'); 25 26// check for error reporting override or set error reporting to sane values 27if (!defined('DOKU_E_LEVEL') && @file_exists(DOKU_CONF.'report_e_all')) { 28 define('DOKU_E_LEVEL', E_ALL); 29} 30if (!defined('DOKU_E_LEVEL')) { 31 if(defined('E_DEPRECATED')){ // since php 5.3 32 error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED); 33 }else{ 34 error_reporting(E_ALL ^ E_NOTICE); 35 } 36} else { 37 error_reporting(DOKU_E_LEVEL); 38} 39 40// init memory caches 41global $cache_revinfo; 42 $cache_revinfo = array(); 43global $cache_wikifn; 44 $cache_wikifn = array(); 45global $cache_cleanid; 46 $cache_cleanid = array(); 47global $cache_authname; 48 $cache_authname = array(); 49global $cache_metadata; 50 $cache_metadata = array(); 51 52//set the configuration cascade - but only if its not already been set in preload.php 53if (empty($config_cascade)) { 54 $config_cascade = array( 55 'main' => array( 56 'default' => array(DOKU_CONF.'dokuwiki.php'), 57 'local' => array(DOKU_CONF.'local.php'), 58 'protected' => array(DOKU_CONF.'local.protected.php'), 59 ), 60 'acronyms' => array( 61 'default' => array(DOKU_CONF.'acronyms.conf'), 62 'local' => array(DOKU_CONF.'acronyms.local.conf'), 63 ), 64 'entities' => array( 65 'default' => array(DOKU_CONF.'entities.conf'), 66 'local' => array(DOKU_CONF.'entities.local.conf'), 67 ), 68 'interwiki' => array( 69 'default' => array(DOKU_CONF.'interwiki.conf'), 70 'local' => array(DOKU_CONF.'interwiki.local.conf'), 71 ), 72 'license' => array( 73 'default' => array(DOKU_CONF.'license.php'), 74 'local' => array(DOKU_CONF.'license.local.php'), 75 ), 76 'mediameta' => array( 77 'default' => array(DOKU_CONF.'mediameta.php'), 78 'local' => array(DOKU_CONF.'mediameta.local.php'), 79 ), 80 'mime' => array( 81 'default' => array(DOKU_CONF.'mime.conf'), 82 'local' => array(DOKU_CONF.'mime.local.conf'), 83 ), 84 'scheme' => array( 85 'default' => array(DOKU_CONF.'scheme.conf'), 86 'local' => array(DOKU_CONF.'scheme.local.conf'), 87 ), 88 'smileys' => array( 89 'default' => array(DOKU_CONF.'smileys.conf'), 90 'local' => array(DOKU_CONF.'smileys.local.conf'), 91 ), 92 'wordblock' => array( 93 'default' => array(DOKU_CONF.'wordblock.conf'), 94 'local' => array(DOKU_CONF.'wordblock.local.conf'), 95 ), 96 ); 97} 98 99//prepare config array() 100global $conf; 101$conf = array(); 102 103// load the global config file(s) 104foreach (array('default','local','protected') as $config_group) { 105 if (empty($config_cascade['main'][$config_group])) continue; 106 foreach ($config_cascade['main'][$config_group] as $config_file) { 107 if (@file_exists($config_file)) { 108 include($config_file); 109 } 110 } 111} 112 113//prepare language array 114global $lang; 115$lang = array(); 116 117//load the language files 118require_once(DOKU_INC.'inc/lang/en/lang.php'); 119if ( $conf['lang'] && $conf['lang'] != 'en' ) { 120 require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php'); 121} 122 123//prepare license array() 124global $license; 125$license = array(); 126 127// load the license file(s) 128foreach (array('default','local') as $config_group) { 129 if (empty($config_cascade['license'][$config_group])) continue; 130 foreach ($config_cascade['license'][$config_group] as $config_file) { 131 if(@file_exists($config_file)){ 132 include($config_file); 133 } 134 } 135} 136 137// set timezone (as in pre 5.3.0 days) 138date_default_timezone_set(@date_default_timezone_get()); 139 140// define baseURL 141if(!defined('DOKU_REL')) define('DOKU_REL',getBaseURL(false)); 142if(!defined('DOKU_URL')) define('DOKU_URL',getBaseURL(true)); 143if(!defined('DOKU_BASE')){ 144 if($conf['canonical']){ 145 define('DOKU_BASE',DOKU_URL); 146 }else{ 147 define('DOKU_BASE',DOKU_REL); 148 } 149} 150 151// define whitespace 152if(!defined('DOKU_LF')) define ('DOKU_LF',"\n"); 153if(!defined('DOKU_TAB')) define ('DOKU_TAB',"\t"); 154 155// define cookie and session id, append server port when securecookie is configured FS#1664 156if (!defined('DOKU_COOKIE')) define('DOKU_COOKIE', 'DW'.md5(DOKU_REL.(($conf['securecookie'])?$_SERVER['SERVER_PORT']:''))); 157 158// define Plugin dir 159if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 160 161// define main script 162if(!defined('DOKU_SCRIPT')) define('DOKU_SCRIPT','doku.php'); 163 164// define Template baseURL 165if(!defined('DOKU_TPL')) define('DOKU_TPL', 166 DOKU_BASE.'lib/tpl/'.$conf['template'].'/'); 167 168// define real Template directory 169if(!defined('DOKU_TPLINC')) define('DOKU_TPLINC', 170 DOKU_INC.'lib/tpl/'.$conf['template'].'/'); 171 172// make session rewrites XHTML compliant 173@ini_set('arg_separator.output', '&'); 174 175// make sure global zlib does not interfere FS#1132 176@ini_set('zlib.output_compression', 'off'); 177 178// increase PCRE backtrack limit 179@ini_set('pcre.backtrack_limit', '20971520'); 180 181// enable gzip compression if supported 182$conf['gzip_output'] &= (strpos($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip') !== false); 183if ($conf['gzip_output'] && 184 !defined('DOKU_DISABLE_GZIP_OUTPUT') && 185 function_exists('ob_gzhandler')) { 186 ob_start('ob_gzhandler'); 187} 188 189// init session 190if (!headers_sent() && !defined('NOSESSION')){ 191 session_name("DokuWiki"); 192 if (version_compare(PHP_VERSION, '5.2.0', '>')) { 193 session_set_cookie_params(0,DOKU_REL,'',($conf['securecookie'] && is_ssl()),true); 194 }else{ 195 session_set_cookie_params(0,DOKU_REL,'',($conf['securecookie'] && is_ssl())); 196 } 197 session_start(); 198 199 // load left over messages 200 if(isset($_SESSION[DOKU_COOKIE]['msg'])){ 201 $MSG = $_SESSION[DOKU_COOKIE]['msg']; 202 unset($_SESSION[DOKU_COOKIE]['msg']); 203 } 204} 205 206// kill magic quotes 207if (get_magic_quotes_gpc() && !defined('MAGIC_QUOTES_STRIPPED')) { 208 if (!empty($_GET)) remove_magic_quotes($_GET); 209 if (!empty($_POST)) remove_magic_quotes($_POST); 210 if (!empty($_COOKIE)) remove_magic_quotes($_COOKIE); 211 if (!empty($_REQUEST)) remove_magic_quotes($_REQUEST); 212 @ini_set('magic_quotes_gpc', 0); 213 define('MAGIC_QUOTES_STRIPPED',1); 214} 215@set_magic_quotes_runtime(0); 216@ini_set('magic_quotes_sybase',0); 217 218// don't let cookies ever interfere with request vars 219$_REQUEST = array_merge($_GET,$_POST); 220 221// we don't want a purge URL to be digged 222if(isset($_REQUEST['purge']) && $_SERVER['HTTP_REFERER']) unset($_REQUEST['purge']); 223 224// disable gzip if not available 225if($conf['compression'] == 'bz2' && !function_exists('bzopen')){ 226 $conf['compression'] = 'gz'; 227} 228if($conf['compression'] == 'gz' && !function_exists('gzopen')){ 229 $conf['compression'] = 0; 230} 231 232// fix dateformat for upgraders 233if(strpos($conf['dformat'],'%') === false){ 234 $conf['dformat'] = '%Y/%m/%d %H:%M'; 235} 236 237// precalculate file creation modes 238init_creationmodes(); 239 240// make real paths and check them 241init_paths(); 242init_files(); 243 244// automatic upgrade to script versions of certain files 245scriptify(DOKU_CONF.'users.auth'); 246scriptify(DOKU_CONF.'acl.auth'); 247 248 249/** 250 * Checks paths from config file 251 */ 252function init_paths(){ 253 global $conf; 254 255 $paths = array('datadir' => 'pages', 256 'olddir' => 'attic', 257 'mediadir' => 'media', 258 'metadir' => 'meta', 259 'cachedir' => 'cache', 260 'indexdir' => 'index', 261 'lockdir' => 'locks', 262 'tmpdir' => 'tmp'); 263 264 foreach($paths as $c => $p){ 265 if(empty($conf[$c])) $conf[$c] = $conf['savedir'].'/'.$p; 266 $conf[$c] = init_path($conf[$c]); 267 if(empty($conf[$c])) nice_die("The $c ('$p') does not exist, isn't accessible or writable. 268 You should check your config and permission settings. 269 Or maybe you want to <a href=\"install.php\">run the 270 installer</a>?"); 271 } 272 273 // path to old changelog only needed for upgrading 274 $conf['changelog_old'] = init_path((isset($conf['changelog']))?($conf['changelog']):($conf['savedir'].'/changes.log')); 275 if ($conf['changelog_old']=='') { unset($conf['changelog_old']); } 276 // hardcoded changelog because it is now a cache that lives in meta 277 $conf['changelog'] = $conf['metadir'].'/_dokuwiki.changes'; 278 $conf['media_changelog'] = $conf['metadir'].'/_media.changes'; 279} 280 281/** 282 * Checks the existance of certain files and creates them if missing. 283 */ 284function init_files(){ 285 global $conf; 286 287 $files = array( $conf['indexdir'].'/page.idx'); 288 289 foreach($files as $file){ 290 if(!@file_exists($file)){ 291 $fh = @fopen($file,'a'); 292 if($fh){ 293 fclose($fh); 294 if($conf['fperm']) chmod($file, $conf['fperm']); 295 }else{ 296 nice_die("$file is not writable. Check your permissions settings!"); 297 } 298 } 299 } 300} 301 302/** 303 * Returns absolute path 304 * 305 * This tries the given path first, then checks in DOKU_INC. 306 * Check for accessability on directories as well. 307 * 308 * @author Andreas Gohr <andi@splitbrain.org> 309 */ 310function init_path($path){ 311 // check existance 312 $p = fullpath($path); 313 if(!@file_exists($p)){ 314 $p = fullpath(DOKU_INC.$path); 315 if(!@file_exists($p)){ 316 return ''; 317 } 318 } 319 320 // check writability 321 if(!@is_writable($p)){ 322 return ''; 323 } 324 325 // check accessability (execute bit) for directories 326 if(@is_dir($p) && !@file_exists("$p/.")){ 327 return ''; 328 } 329 330 return $p; 331} 332 333/** 334 * Sets the internal config values fperm and dperm which, when set, 335 * will be used to change the permission of a newly created dir or 336 * file with chmod. Considers the influence of the system's umask 337 * setting the values only if needed. 338 */ 339function init_creationmodes(){ 340 global $conf; 341 342 // Legacy support for old umask/dmask scheme 343 unset($conf['dmask']); 344 unset($conf['fmask']); 345 unset($conf['umask']); 346 unset($conf['fperm']); 347 unset($conf['dperm']); 348 349 // get system umask, fallback to 0 if none available 350 $umask = @umask(); 351 if(!$umask) $umask = 0000; 352 353 // check what is set automatically by the system on file creation 354 // and set the fperm param if it's not what we want 355 $auto_fmode = 0666 & ~$umask; 356 if($auto_fmode != $conf['fmode']) $conf['fperm'] = $conf['fmode']; 357 358 // check what is set automatically by the system on file creation 359 // and set the dperm param if it's not what we want 360 $auto_dmode = $conf['dmode'] & ~$umask; 361 if($auto_dmode != $conf['dmode']) $conf['dperm'] = $conf['dmode']; 362} 363 364/** 365 * remove magic quotes recursivly 366 * 367 * @author Andreas Gohr <andi@splitbrain.org> 368 */ 369function remove_magic_quotes(&$array) { 370 foreach (array_keys($array) as $key) { 371 // handle magic quotes in keynames (breaks order) 372 $sk = stripslashes($key); 373 if($sk != $key){ 374 $array[$sk] = $array[$key]; 375 unset($array[$key]); 376 $key = $sk; 377 } 378 379 // do recursion if needed 380 if (is_array($array[$key])) { 381 remove_magic_quotes($array[$key]); 382 }else { 383 $array[$key] = stripslashes($array[$key]); 384 } 385 } 386} 387 388/** 389 * Returns the full absolute URL to the directory where 390 * DokuWiki is installed in (includes a trailing slash) 391 * 392 * @author Andreas Gohr <andi@splitbrain.org> 393 */ 394function getBaseURL($abs=null){ 395 global $conf; 396 //if canonical url enabled always return absolute 397 if(is_null($abs)) $abs = $conf['canonical']; 398 399 if($conf['basedir']){ 400 $dir = $conf['basedir']; 401 }elseif(substr($_SERVER['SCRIPT_NAME'],-4) == '.php'){ 402 $dir = dirname($_SERVER['SCRIPT_NAME']); 403 }elseif(substr($_SERVER['PHP_SELF'],-4) == '.php'){ 404 $dir = dirname($_SERVER['PHP_SELF']); 405 }elseif($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']){ 406 $dir = preg_replace ('/^'.preg_quote($_SERVER['DOCUMENT_ROOT'],'/').'/','', 407 $_SERVER['SCRIPT_FILENAME']); 408 $dir = dirname('/'.$dir); 409 }else{ 410 $dir = '.'; //probably wrong 411 } 412 413 $dir = str_replace('\\','/',$dir); // bugfix for weird WIN behaviour 414 $dir = preg_replace('#//+#','/',"/$dir/"); // ensure leading and trailing slashes 415 416 //handle script in lib/exe dir 417 $dir = preg_replace('!lib/exe/$!','',$dir); 418 419 //handle script in lib/plugins dir 420 $dir = preg_replace('!lib/plugins/.*$!','',$dir); 421 422 //finish here for relative URLs 423 if(!$abs) return $dir; 424 425 //use config option if available, trim any slash from end of baseurl to avoid multiple consecutive slashes in the path 426 if($conf['baseurl']) return rtrim($conf['baseurl'],'/').$dir; 427 428 //split hostheader into host and port 429 $addr = explode(':',$_SERVER['HTTP_HOST']); 430 $host = $addr[0]; 431 $port = ''; 432 if (isset($addr[1])) { 433 $port = $addr[1]; 434 } elseif (isset($_SERVER['SERVER_PORT'])) { 435 $port = $_SERVER['SERVER_PORT']; 436 } 437 if(!is_ssl()){ 438 $proto = 'http://'; 439 if ($port == '80') { 440 $port = ''; 441 } 442 }else{ 443 $proto = 'https://'; 444 if ($port == '443') { 445 $port = ''; 446 } 447 } 448 449 if($port !== '') $port = ':'.$port; 450 451 return $proto.$host.$port.$dir; 452} 453 454/** 455 * Check if accessed via HTTPS 456 * 457 * Apache leaves ,$_SERVER['HTTPS'] empty when not available, IIS sets it to 'off'. 458 * 'false' and 'disabled' are just guessing 459 * 460 * @returns bool true when SSL is active 461 */ 462function is_ssl(){ 463 if (!isset($_SERVER['HTTPS']) || 464 preg_match('/^(|off|false|disabled)$/i',$_SERVER['HTTPS'])){ 465 return false; 466 }else{ 467 return true; 468 } 469} 470 471/** 472 * Append a PHP extension to a given file and adds an exit call 473 * 474 * This is used to migrate some old configfiles. An added PHP extension 475 * ensures the contents are not shown to webusers even if .htaccess files 476 * do not work 477 * 478 * @author Jan Decaluwe <jan@jandecaluwe.com> 479 */ 480function scriptify($file) { 481 // checks 482 if (!is_readable($file)) { 483 return; 484 } 485 $fn = $file.'.php'; 486 if (@file_exists($fn)) { 487 return; 488 } 489 $fh = fopen($fn, 'w'); 490 if (!$fh) { 491 nice_die($fn.' is not writable. Check your permission settings!'); 492 } 493 // write php exit hack first 494 fwrite($fh, "# $fn\n"); 495 fwrite($fh, '# <?php exit()?>'."\n"); 496 fwrite($fh, "# Don't modify the lines above\n"); 497 fwrite($fh, "#\n"); 498 // copy existing lines 499 $lines = file($file); 500 foreach ($lines as $line){ 501 fwrite($fh, $line); 502 } 503 fclose($fh); 504 //try to rename the old file 505 io_rename($file,"$file.old"); 506} 507 508/** 509 * print a nice message even if no styles are loaded yet. 510 */ 511function nice_die($msg){ 512 echo<<<EOT 513<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 514 "http://www.w3.org/TR/html4/loose.dtd"> 515<html> 516<head><title>DokuWiki Setup Error</title></head> 517<body style="font-family: Arial, sans-serif"> 518 <div style="width:60%; margin: auto; background-color: #fcc; 519 border: 1px solid #faa; padding: 0.5em 1em;"> 520 <h1 style="font-size: 120%">DokuWiki Setup Error</h1> 521 <p>$msg</p> 522 </div> 523</body> 524</html> 525EOT; 526 exit; 527} 528 529 530/** 531 * A realpath() replacement 532 * 533 * This function behaves similar to PHP's realpath() but does not resolve 534 * symlinks or accesses upper directories 535 * 536 * @author Andreas Gohr <andi@splitbrain.org> 537 * @author <richpageau at yahoo dot co dot uk> 538 * @link http://de3.php.net/manual/en/function.realpath.php#75992 539 */ 540function fullpath($path,$exists=false){ 541 static $run = 0; 542 $root = ''; 543 $iswin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' || @$GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']); 544 545 // find the (indestructable) root of the path - keeps windows stuff intact 546 if($path{0} == '/'){ 547 $root = '/'; 548 }elseif($iswin){ 549 // match drive letter and UNC paths 550 if(preg_match('!^([a-zA-z]:)(.*)!',$path,$match)){ 551 $root = $match[1].'/'; 552 $path = $match[2]; 553 }else if(preg_match('!^(\\\\\\\\[^\\\\/]+\\\\[^\\\\/]+[\\\\/])(.*)!',$path,$match)){ 554 $root = $match[1]; 555 $path = $match[2]; 556 } 557 } 558 $path = str_replace('\\','/',$path); 559 560 // if the given path wasn't absolute already, prepend the script path and retry 561 if(!$root){ 562 $base = dirname($_SERVER['SCRIPT_FILENAME']); 563 $path = $base.'/'.$path; 564 if($run == 0){ // avoid endless recursion when base isn't absolute for some reason 565 $run++; 566 return fullpath($path,$exists); 567 } 568 } 569 $run = 0; 570 571 // canonicalize 572 $path=explode('/', $path); 573 $newpath=array(); 574 foreach($path as $p) { 575 if ($p === '' || $p === '.') continue; 576 if ($p==='..') { 577 array_pop($newpath); 578 continue; 579 } 580 array_push($newpath, $p); 581 } 582 $finalpath = $root.implode('/', $newpath); 583 584 // check for existance when needed (except when unit testing) 585 if($exists && !defined('DOKU_UNITTEST') && !@file_exists($finalpath)) { 586 return false; 587 } 588 return $finalpath; 589} 590 591 592 593