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