xref: /dokuwiki/inc/common.php (revision f3f0262c480d7e509b008d37c90aed884532bba8)
1<?
2require_once("conf/dokuwiki.php");
3require_once("inc/io.php");
4
5//set up error reporting to sane values
6error_reporting(E_ALL ^ E_NOTICE);
7
8//make session rewrites XHTML compliant
9ini_set('arg_separator.output', '&amp;');
10
11//init session
12session_name("DokuWiki");
13session_start();
14
15//kill magic quotes
16if (get_magic_quotes_gpc()) {
17  if (!empty($_GET))    remove_magic_quotes($_GET);
18  if (!empty($_POST))   remove_magic_quotes($_POST);
19  if (!empty($_COOKIE)) remove_magic_quotes($_COOKIE);
20  if (!empty($_REQUEST)) remove_magic_quotes($_REQUEST);
21  if (!empty($_SESSION)) remove_magic_quotes($_SESSION);
22  ini_set('magic_quotes_gpc', 0);
23}
24set_magic_quotes_runtime(0);
25ini_set('magic_quotes_sybase',0);
26
27function remove_magic_quotes(&$array) {
28  foreach (array_keys($array) as $key) {
29    if (is_array($array[$key])) {
30      remove_magic_quotes($array[$key]);
31    }else {
32      $array[$key] = stripslashes($array[$key]);
33    }
34  }
35}
36
37//disable gzip if not available
38if($conf['usegzip'] && !function_exists('gzopen')){
39  $conf['usegzip'] = 0;
40}
41
42/* ---------------------------------------------------------------------------------- */
43
44/**
45 * This returns the full absolute URL to the directory where
46 * DokuWiki is installed in (includes a trailing slash)
47 */
48function getBaseURL($abs=false){
49  global $conf;
50  //if canonical url enabled always return absolute
51  if($conf['canonical']) $abs = true;
52
53  //relative URLs are easy
54  if(!$abs){
55    $dir = dirname($_SERVER['PHP_SELF']).'/';
56    $dir = preg_replace('#//#','/',$dir);
57    $dir = preg_replace('#\/$#','/',$dir); #bugfix for weird WIN behaviour
58    return $dir;
59  }
60
61  $port = ':'.$_SERVER['SERVER_PORT'];
62  //remove port from hostheader as sent by IE
63  $host = preg_replace('/:.*$/','',$_SERVER['HTTP_HOST']);
64
65  // see if HTTPS is enabled - apache leaves this empty when not available,
66  // IIS sets it to 'off', 'false' and 'disabled' are just guessing
67  if (preg_match('/^(|off|false|disabled)$/i',$_SERVER['HTTPS'])){
68    $proto = 'http://';
69    if ($_SERVER['SERVER_PORT'] == '80') {
70      $port='';
71    }
72  }else{
73    $proto = 'https://';
74    if ($_SERVER['SERVER_PORT'] == '443') {
75      $port='';
76    }
77  }
78  $dir = (dirname($_SERVER['PHP_SELF'])).'/';
79  $dir = preg_replace('#//#','/',$dir);
80  $dir = preg_replace('#\/$#','/',$dir); #bugfix for weird WIN behaviour
81
82  return $proto.$host.$port.$dir;
83}
84
85/**
86 * Returns info about the current document as associative
87 * array.
88 */
89function pageinfo(){
90  global $ID;
91  global $REV;
92  global $USERINFO;
93  global $conf;
94
95  if($_SERVER['REMOTE_USER']){
96    $info['user']     = $_SERVER['REMOTE_USER'];
97    $info['userinfo'] = $USERINFO;
98    $info['perm']     = auth_quickaclcheck($ID);
99  }else{
100    $info['user']     = '';
101    $info['perm']     = auth_aclcheck($ID,'',null);
102  }
103
104  $info['namespace'] = getNS($ID);
105  $info['locked']    = checklock($ID);
106  $info['filepath']  = realpath(wikiFN($ID,$REV));
107  $info['exists']    = @file_exists($info['filepath']);
108  if($REV && !$info['exists']){
109    //check if current revision was meant
110    $cur = wikiFN($ID);
111    if(@file_exists($cur) && (@filemtime($cur) == $REV)){
112      $info['filepath'] = realpath($cur);
113      $info['exists']   = true;
114      $REV = '';
115    }
116  }
117  if($info['exists']){
118    $info['writable'] = (is_writable($info['filepath']) &&
119                         ($info['perm'] >= AUTH_EDIT));
120  }else{
121    $info['writable'] = ($info['perm'] >= AUTH_CREATE);
122  }
123  $info['editable']  = ($info['writable'] && empty($info['lock']));
124  $info['lastmod']   = @filemtime($info['filepath']);
125
126  return $info;
127}
128
129/**
130 * adds a message to the global message array
131 *
132 * Levels can be:
133 *
134 * -1 error
135 *  0 info
136 *  1 success
137 */
138function msg($message,$lvl=0){
139  global $MSG;
140  $errors[-1] = 'error';
141  $errors[0]  = 'info';
142  $errors[1]  = 'success';
143
144  if(!isset($MSG)) $MSG = array();
145  $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message);
146}
147
148/**
149 * This builds the breadcrumbstrail and returns it as array
150 */
151function breadcrumbs(){
152  global $ID;
153  global $ACT;
154  global $conf;
155  $crumbs = $_SESSION[$conf['title']]['bc'];
156
157  //first visit?
158  if (!is_array($crumbs)){
159    $crumbs = array();
160  }
161  //we only save on show and existing wiki documents
162  if($ACT != 'show' || !@file_exists(wikiFN($ID))){
163    $_SESSION[$conf['title']]['bc'] = $crumbs;
164    return $crumbs;
165  }
166  //remove ID from array
167  $pos = array_search($ID,$crumbs);
168  if($pos !== false && $pos !== null){
169    array_splice($crumbs,$pos,1);
170  }
171
172  //add to array
173  $crumbs[] =$ID;
174  //reduce size
175  while(count($crumbs) > $conf['breadcrumbs']){
176    array_shift($crumbs);
177  }
178  //save to session
179  $_SESSION[$conf['title']]['bc'] = $crumbs;
180  return $crumbs;
181}
182
183/**
184 * This is run on a ID before it is outputted somewhere
185 * currently used to replace the colon with something else
186 * on Windows systems and to have proper URL encoding
187 */
188function idfilter($id){
189  global $conf;
190  if ($conf['useslash'] && $conf['userewrite']){
191    $id = strtr($id,':','/');
192  }elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' &&
193      $conf['userewrite']) {
194    $id = strtr($id,':',';');
195  }
196  $id = urlencode($id);
197  $id = str_replace('%3A',':',$id); //keep as colon
198  $id = str_replace('%2F','/',$id); //keep as slash
199  return $id;
200}
201
202/**
203 * This builds a link to a wikipage (using getBaseURL)
204 */
205function wl($id='',$more='',$script='doku.php',$canonical=false){
206  global $conf;
207  $more = str_replace(',','&amp;',$more);
208
209  $id    = idfilter($id);
210  $xlink = getBaseURL($canonical);
211
212  if(!$conf['userewrite']){
213    $xlink .= $script;
214    $xlink .= '?id='.$id;
215    if($more) $xlink .= '&amp;'.$more;
216  }else{
217    $xlink .= $id;
218    if($more) $xlink .= '?'.$more;
219  }
220
221  return $xlink;
222}
223
224/**
225 * Just builds a link to a script
226 */
227function script($script='doku.php'){
228  $link = getBaseURL();
229  $link .= $script;
230  return $link;
231}
232
233/**
234 * Return namespacepart of a wiki ID
235 */
236function getNS($id){
237 if(strpos($id,':')!==false){
238   return substr($id,0,strrpos($id,':'));
239 }
240 return false;
241}
242
243/**
244 * Returns the id without the namespace
245 */
246function noNS($id){
247  return preg_replace('/.*:/','',$id);
248}
249
250/**
251 * Checks the wikitext against a list of blocked expressions
252 * returns true if the text contains any bad words
253 */
254function checkwordblock(){
255  global $TEXT;
256  global $conf;
257
258  if(!$conf['usewordblock']) return false;
259
260  $blocks = file('conf/wordblock.conf');
261  $re = array();
262  #build regexp from blocks
263  foreach($blocks as $block){
264    $block = preg_replace('/#.*$/','',$block);
265    $block = trim($block);
266    if(empty($block)) continue;
267    $re[]  = $block;
268  }
269  if(preg_match('#('.join('|',$re).')#si',$TEXT)) return true;
270  return false;
271}
272
273/**
274 * Returns the IP of the client including X-Forwarded-For
275 * Proxy Headers
276 */
277function clientIP(){
278  $my = $_SERVER['REMOTE_ADDR'];
279  if($_SERVER['HTTP_X_FORWARDED_FOR']){
280    $my .= ' ('.$_SERVER['HTTP_X_FORWARDED_FOR'].')';
281  }
282  return $my;
283}
284
285/**
286 * Checks if a given page is currently locked by anyone for editing.
287 * removes stale lockfiles
288 */
289function checklock($id){
290  global $conf;
291  $lock = wikiFN($id).'.lock';
292
293  //no lockfile
294  if(!@file_exists($lock)) return false;
295
296  //lockfile expired
297  if((time() - filemtime($lock)) > $conf['locktime']){
298    unlink($lock);
299    return false;
300  }
301
302  //my own lock
303  $ip = io_readFile($lock);
304  if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
305    return false;
306  }
307
308  return $ip;
309}
310
311/**
312 * Locks a page for editing
313 */
314function lock($id){
315  $lock = wikiFN($id).'.lock';
316  if($_SERVER['REMOTE_USER']){
317    io_saveFile($lock,$_SERVER['REMOTE_USER']);
318  }else{
319    io_saveFile($lock,clientIP());
320  }
321}
322
323/**
324 * Unlocks a page if it was locked by the user
325 *
326 * return true if a lock was removed
327 */
328function unlock($id){
329  $lock = wikiFN($id).'.lock';
330  if(@file_exists($lock)){
331    $ip = io_readFile($lock);
332    if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
333      @unlink($lock);
334      return true;
335    }
336  }
337  return false;
338}
339
340/**
341 * Cleans a given ID to only use allowed characters. Accented characters are
342 * converted to unaccented ones
343 */
344function cleanID($id){
345  global $conf;
346  global $lang;
347  $id = trim($id);
348  $id = strtolower($id);
349
350  //alternative namespace seperator
351  $id = strtr($id,';',':');
352  $id = strtr($id,'/',':');
353
354  if(!$conf['localnames']){
355    if($lang['encoding'] == 'iso-8859-15'){
356      // replace accented chars with unaccented ones
357      // this may look strange on your terminal - just don't touch
358      $id = strtr(
359      strtr($id,
360       '������������������������������������������������������',
361       'szszyaaaaaceeeeiiiinooooouuuyaaaaaceeeeiiiinooooouuuyy'),
362       array('�' => 'th', '�' => 'th', '�' => 'dh', '�' => 'dh', '�' => 'ss',
363             '�' => 'oe', '�' => 'oe', '�' => 'ae', '�' => 'ae', '�' => 'u',
364             '�' => 'ue', '�' => 'oe', '�' => 'ae', '�' => 'ue', '�' => '�',
365             '�' => 'ae'));
366    }
367    $WORD = 'a-z';
368  }else{
369    $WORD = '\w';
370  }
371
372  //special chars left will be converted to _
373  $id = preg_replace('#[^'.$WORD.'0-9:\-\.]#','_',$id);
374  $id = preg_replace('#__#','_',$id);
375  $id = preg_replace('#:+#',':',$id);
376  $id = trim($id,':._-');
377  $id = preg_replace('#:[:\._\-]+#',':',$id);
378
379  return($id);
380}
381
382/**
383 * returns the full path to the datafile specified by ID and
384 * optional revision
385 */
386function wikiFN($id,$rev=''){
387  global $conf;
388  $id = cleanID($id);
389  $id = str_replace(':','/',$id);
390  if(empty($rev)){
391    return $conf['datadir'].'/'.$id.'.txt';
392  }else{
393    $fn = $conf['olddir'].'/'.$id.'.'.$rev.'.txt';
394    if(!$conf['usegzip'] || @file_exists($fn)){
395      //return plaintext if exists or gzip is disabled
396      return $fn;
397    }else{
398      return $fn.'.gz';
399    }
400  }
401}
402
403/**
404 * Returns the full filepath to a localized textfile if local
405 * version isn't found the english one is returned
406 */
407function localeFN($id){
408  global $conf;
409  $file = './lang/'.$conf['lang'].'/'.$id.'.txt';
410  if(!@file_exists($file)){
411    //fall back to english
412    $file = './lang/en/'.$id.'.txt';
413  }
414  return cleanText($file);
415}
416
417/**
418 * convert line ending to unix format
419 *
420 * @see: formText() for 2crlf conversion
421 */
422function cleanText($text){
423  $text = preg_replace("/(\015\012)|(\015)/","\012",$text);
424  return $text;
425}
426
427/**
428 * Prepares text for print in Webforms by encoding special chars.
429 * It also converts line endings to Windows format which is
430 * pseudo standard for webforms.
431 *
432 * @see: cleanText() for 2unix conversion
433 */
434function formText($text){
435  $text = preg_replace("/\012/","\015\012",$text);
436  return htmlspecialchars($text);
437}
438
439/**
440 * Returns the specified textfile in parsed format
441 */
442function parsedLocale($id){
443  //disable section editing
444  global $parser;
445  $se = $parser['secedit'];
446  $parser['secedit'] = false;
447  //fetch parsed locale
448  $html = io_cacheParse(localeFN($id));
449  //reset section editing
450  $parser['secedit'] = $se;
451  return $html;
452}
453
454/**
455 * Returns the specified textfile in parsed format
456 */
457function rawLocale($id){
458  return io_readFile(localeFN($id));
459}
460
461
462/**
463 * Returns the parsed Wikitext for the given id and revision. If $excuse
464 * is true an explanation is returned if the file wasn't found
465 */
466function parsedWiki($id,$rev='',$excuse=true){
467  $file = wikiFN($id,$rev);
468  $ret  = '';
469
470  //ensure $id is in global $ID (needed for parsing)
471  global $ID;
472  $ID = $id;
473
474  if($rev){
475    if(@file_exists($file)){
476      $ret = parse(io_readFile($file));
477    }elseif($excuse){
478      $ret = parsedLocale('norev');
479    }
480  }else{
481    if(@file_exists($file)){
482      $ret = io_cacheParse($file);
483    }elseif($excuse){
484      $ret = parsedLocale('newpage');
485    }
486  }
487  return $ret;
488}
489
490/**
491 * Returns the raw WikiText
492 */
493function rawWiki($id,$rev=''){
494  return io_readFile(wikiFN($id,$rev));
495}
496
497/**
498 * Returns the raw Wiki Text in three slices. The range parameter
499 * Need to have the form "from-to" and gives the range of the section.
500 * The returned order is prefix, section and suffix.
501 */
502function rawWikiSlices($range,$id,$rev=''){
503  list($from,$to) = split('-',$range,2);
504  $text = io_readFile(wikiFN($id,$rev));
505  $text = split("\n",$text);
506  if(!$from) $from = 0;
507  if(!$to)   $to   = count($text);
508
509  $slices[0] = join("\n",array_slice($text,0,$from));
510  $slices[1] = join("\n",array_slice($text,$from,$to + 1  - $from));
511  $slices[2] = join("\n",array_slice($text,$to+1));
512
513  return $slices;
514}
515
516/**
517 * function to join the text slices with correct lineendings again.
518 * When the pretty parameter is set to true it adds additional empty
519 * lines between sections if needed (used on saving).
520 */
521function con($pre,$text,$suf,$pretty=false){
522
523  if($pretty){
524    if($pre && substr($pre,-1) != "\n") $pre .= "\n";
525    if($suf && substr($text,-1) != "\n") $text .= "\n";
526  }
527
528  if($pre) $pre .= "\n";
529  if($suf) $text .= "\n";
530  return $pre.$text.$suf;
531}
532
533/**
534 * little function to print the content of a var
535 */
536function dbg($msg,$hidden=false){
537  (!$hidden) ? print '<pre class="dbg">' : print "<!--\n";
538  print_r($msg);
539  (!$hidden) ? print '</pre>' : print "\n-->";
540}
541
542/**
543 * Add's an entry to the changelog
544 */
545function addLogEntry($id,$summary=""){
546  global $conf;
547  $id     = cleanID($id);
548  $date   = time();
549  $remote = $_SERVER['REMOTE_ADDR'];
550  $user   = $_SERVER['REMOTE_USER'];
551
552  $logline = join("\t",array($date,$remote,$id,$user,$summary))."\n";
553
554  $fh = fopen($conf['changelog'],'a');
555  if($fh){
556    fwrite($fh,$logline);
557    fclose($fh);
558  }
559}
560
561/**
562 * returns an array of recently changed files using the
563 * changelog
564 */
565function getRecents($num=0,$incdel=false){
566  global $conf;
567  $recent = array();
568  if(!$num) $num = $conf['recent'];
569
570  $loglines = file($conf['changelog']);
571  rsort($loglines); //reverse sort on timestamp
572
573  foreach ($loglines as $line){
574    $line = rtrim($line);        //remove newline
575    if(empty($line)) continue;   //skip empty lines
576    $info = split("\t",$line);   //split into parts
577    //add id if not in yet and file still exists and is allowed to read
578    if(!$recent[$info[2]] &&
579       (@file_exists(wikiFN($info[2])) || $incdel) &&
580       (auth_quickaclcheck($info[2]) >= AUTH_READ)
581      ){
582      $recent[$info[2]]['date'] = $info[0];
583      $recent[$info[2]]['ip']   = $info[1];
584      $recent[$info[2]]['user'] = $info[3];
585      $recent[$info[2]]['sum']  = $info[4];
586      $recent[$info[2]]['del']  = !@file_exists(wikiFN($info[2]));
587    }
588    if(count($recent) >= $num){
589      break; //finish if enough items found
590    }
591  }
592  return $recent;
593}
594
595/**
596 * Saves a wikitext by calling io_saveFile
597 */
598function saveWikiText($id,$text,$summary){
599  global $conf;
600  global $lang;
601  umask($conf['umask']);
602  // ignore if no changes were made
603  if($text == rawWiki($id,'')){
604    return;
605  }
606
607  $file = wikiFN($id);
608  $old  = saveOldRevision($id);
609
610  if (empty($text)){
611    // remove empty files
612    @unlink($file);
613    $del = true;
614    $summary = $lang['deleted']; //autoset summary on deletion
615  }else{
616    // save file (datadir is created in io_saveFile)
617    io_saveFile($file,$text);
618    $del = false;
619  }
620
621  addLogEntry($id,$summary);
622  notify($id,$old,$summary);
623
624  //purge cache on add by updating the purgefile
625  if($conf['purgeonadd'] && (!$old || $del)){
626    io_saveFile($conf['datadir'].'/.cache/purgefile',time());
627  }
628}
629
630/**
631 * moves the current version to the attic and returns its
632 * revision date
633 */
634function saveOldRevision($id){
635	global $conf;
636  umask($conf['umask']);
637  $oldf = wikiFN($id);
638  if(!@file_exists($oldf)) return '';
639  $date = filemtime($oldf);
640  $newf = wikiFN($id,$date);
641  if(substr($newf,-3)=='.gz'){
642    io_saveFile($newf,rawWiki($id));
643  }else{
644    io_makeFileDir($newf);
645    copy($oldf, $newf);
646  }
647  return $date;
648}
649
650/**
651 * Sends a notify mail to the wikiadmin when a page was
652 * changed
653 */
654function notify($id,$rev="",$summary=""){
655  global $lang;
656  global $conf;
657  $hdrs ='';
658  if(empty($conf['notify'])) return; //notify enabled?
659
660  $text = rawLocale('mailtext');
661  $text = str_replace('@DATE@',date($conf['dformat']),$text);
662  $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text);
663  $text = str_replace('@IPADDRESS@',$_SERVER['REMOTE_ADDR'],$text);
664  $text = str_replace('@HOSTNAME@',gethostbyaddr($_SERVER['REMOTE_ADDR']),$text);
665  $text = str_replace('@NEWPAGE@',wl($id,'','',true),$text);
666  $text = str_replace('@DOKUWIKIURL@',getBaseURL(true),$text);
667  $text = str_replace('@SUMMARY@',$summary,$text);
668
669  if($rev){
670    $subject = $lang['mail_changed'].' '.$id;
671    $text = str_replace('@OLDPAGE@',wl($id,"rev=$rev",'',true),$text);
672    require_once("inc/DifferenceEngine.php");
673    $df  = new Diff(split("\n",rawWiki($id,$rev)),
674                    split("\n",rawWiki($id)));
675    $dformat = new UnifiedDiffFormatter();
676    $diff    = $dformat->format($df);
677  }else{
678    $subject=$lang['mail_newpage'].' '.$id;
679    $text = str_replace('@OLDPAGE@','none',$text);
680    $diff = rawWiki($id);
681  }
682  $text = str_replace('@DIFF@',$diff,$text);
683
684  if (!empty($conf['mailfrom'])) {
685    $hdrs = 'From: '.$conf['mailfrom']."\n";
686  }
687  @mail($conf['notify'],$subject,$text,$hdrs);
688}
689
690function getRevisions($id){
691  $revd = dirname(wikiFN($id,'foo'));
692  $revs = array();
693  $clid = cleanID($id);
694  if(strrpos($clid,':')) $clid = substr($clid,strrpos($clid,':')+1); //remove path
695
696  if (is_dir($revd) && $dh = opendir($revd)) {
697    while (($file = readdir($dh)) !== false) {
698      if (is_dir($revd.'/'.$file)) continue;
699      if (preg_match('/^'.$clid.'\.(\d+)\.txt(\.gz)?$/',$file,$match)){
700        $revs[]=$match[1];
701      }
702    }
703    closedir($dh);
704  }
705  rsort($revs);
706  return $revs;
707}
708
709/**
710 * downloads a file from the net and saves it to the given location
711 */
712function download($url,$file){
713  $fp = @fopen($url,"rb");
714  if(!$fp) return false;
715
716  while(!feof($fp)){
717    $cont.= fread($fp,1024);
718  }
719  fclose($fp);
720
721  $fp2 = @fopen($file,"w");
722  if(!$fp2) return false;
723  fwrite($fp2,$cont);
724  fclose($fp2);
725  return true;
726}
727
728/**
729 * extracts the query from a google referer
730 */
731function getGoogleQuery(){
732  $url = parse_url($_SERVER['HTTP_REFERER']);
733
734  if(!preg_match("#google\.#i",$url['host'])) return '';
735  $query = array();
736  parse_str($url['query'],$query);
737
738  return $query['q'];
739}
740
741/**
742 * This function tries the locales given in the
743 * language file
744 */
745function setCorrectLocale(){
746  global $conf;
747  global $lang;
748
749  $enc = strtoupper($lang['encoding']);
750  foreach ($lang['locales'] as $loc){
751    //try locale
752    if(@setlocale(LC_ALL,$loc)) return;
753    //try loceale with encoding
754    if(@setlocale(LC_ALL,"$loc.$enc")) return;
755  }
756  //still here? try to set from environment
757  @setlocale(LC_ALL,"");
758}
759
760/**
761* Return the human readable size of a file
762*
763* @param       int    $size   A file size
764* @param       int    $dec    A number of decimal places
765* @author      Martin Benjamin <b.martin@cybernet.ch>
766* @author      Aidan Lister <aidan@php.net>
767* @version     1.0.0
768*/
769function filesize_h($size, $dec = 1)
770{
771  $sizes = array('B', 'KB', 'MB', 'GB');
772  $count = count($sizes);
773  $i = 0;
774
775  while ($size >= 1024 && ($i < $count - 1)) {
776    $size /= 1024;
777    $i++;
778  }
779
780  return round($size, $dec) . ' ' . $sizes[$i];
781}
782
783function check(){
784  global $conf;
785  global $INFO;
786
787  if(is_writable($conf['changelog'])){
788    msg('Changelog is writable',1);
789  }else{
790    msg('Changelog is not writable',-1);
791  }
792
793  if(is_writable($conf['datadir'])){
794    msg('Datadir is writable',1);
795  }else{
796    msg('Datadir is not writable',-1);
797  }
798
799  if(is_writable($conf['olddir'])){
800    msg('Attic is writable',1);
801  }else{
802    msg('Attic is not writable',-1);
803  }
804
805  if(is_writable($conf['mediadir'])){
806    msg('Mediadir is writable',1);
807  }else{
808    msg('Mediadir is not writable',-1);
809  }
810
811  if(is_writable('conf/users.auth')){
812    msg('conf/users.auth is writable',1);
813  }else{
814    msg('conf/users.auth is not writable',0);
815  }
816
817  msg('Your current permission for this page is '.$INFO['perm'],0);
818
819  if(is_writable($INFO['filepath'])){
820    msg('The current page is writable by the webserver',0);
821  }else{
822    msg('The current page is not writable by the webserver',0);
823  }
824
825  if($INFO['writable']){
826    msg('The current page is writable by you',0);
827  }else{
828    msg('The current page is not writable you',0);
829  }
830}
831?>
832