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