1ed7b5f09Sandi<?php 215fae107Sandi/** 315fae107Sandi * Common DokuWiki functions 415fae107Sandi * 515fae107Sandi * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 715fae107Sandi */ 815fae107Sandi 9ed7b5f09Sandiif(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); 10e7cb32dcSAndreas Gohrrequire_once(DOKU_CONF.'dokuwiki.php'); 11ed7b5f09Sandirequire_once(DOKU_INC.'inc/io.php'); 127d559c7fSBen Coburnrequire_once(DOKU_INC.'inc/changelog.php'); 13ed7b5f09Sandirequire_once(DOKU_INC.'inc/utf8.php'); 14ed7b5f09Sandirequire_once(DOKU_INC.'inc/mail.php'); 15c112d578Sandirequire_once(DOKU_INC.'inc/parserutils.php'); 16c29dc6e4SAndreas Gohrrequire_once(DOKU_INC.'inc/infoutils.php'); 17f3f0262cSandi 18f3f0262cSandi/** 19b6912aeaSAndreas Gohr * These constants are used with the recents function 20b6912aeaSAndreas Gohr */ 21b6912aeaSAndreas Gohrdefine('RECENTS_SKIP_DELETED',2); 22b6912aeaSAndreas Gohrdefine('RECENTS_SKIP_MINORS',4); 23b6912aeaSAndreas Gohrdefine('RECENTS_SKIP_SUBSPACES',8); 24b6912aeaSAndreas Gohr 25b6912aeaSAndreas Gohr/** 26d5197206Schris * Wrapper around htmlspecialchars() 27d5197206Schris * 28d5197206Schris * @author Andreas Gohr <andi@splitbrain.org> 29d5197206Schris * @see htmlspecialchars() 30d5197206Schris */ 31d5197206Schrisfunction hsc($string){ 32d5197206Schris return htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); 33d5197206Schris} 34d5197206Schris 35d5197206Schris/** 36d5197206Schris * print a newline terminated string 37d5197206Schris * 38d5197206Schris * You can give an indention as optional parameter 39d5197206Schris * 40d5197206Schris * @author Andreas Gohr <andi@splitbrain.org> 41d5197206Schris */ 42d5197206Schrisfunction ptln($string,$intend=0){ 43d5197206Schris for($i=0; $i<$intend; $i++) print ' '; 4402b0b681SAndreas Gohr echo "$string\n"; 4502b0b681SAndreas Gohr} 4602b0b681SAndreas Gohr 4702b0b681SAndreas Gohr/** 4802b0b681SAndreas Gohr * strips control characters (<32) from the given string 4902b0b681SAndreas Gohr * 5002b0b681SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 5102b0b681SAndreas Gohr */ 5202b0b681SAndreas Gohrfunction stripctl($string){ 5302b0b681SAndreas Gohr return preg_replace('/[\x00-\x1F]+/s','',$string); 54d5197206Schris} 55d5197206Schris 56d5197206Schris/** 5715fae107Sandi * Return info about the current document as associative 58f3f0262cSandi * array. 5915fae107Sandi * 6015fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 61f3f0262cSandi */ 62f3f0262cSandifunction pageinfo(){ 63f3f0262cSandi global $ID; 64f3f0262cSandi global $REV; 65f3f0262cSandi global $USERINFO; 66f3f0262cSandi global $conf; 67f3f0262cSandi 686afe8dcaSchris // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml 696afe8dcaSchris // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary 706afe8dcaSchris $info['id'] = $ID; 716afe8dcaSchris $info['rev'] = $REV; 726afe8dcaSchris 73f3f0262cSandi if($_SERVER['REMOTE_USER']){ 74f3f0262cSandi $info['userinfo'] = $USERINFO; 75f3f0262cSandi $info['perm'] = auth_quickaclcheck($ID); 761380fc45SAndreas Gohr $info['subscribed'] = is_subscribed($ID,$_SERVER['REMOTE_USER']); 77ee4c4a1bSAndreas Gohr $info['client'] = $_SERVER['REMOTE_USER']; 7817ee7f66SAndreas Gohr 7917ee7f66SAndreas Gohr // if some outside auth were used only REMOTE_USER is set 8017ee7f66SAndreas Gohr if(!$info['userinfo']['name']){ 8117ee7f66SAndreas Gohr $info['userinfo']['name'] = $_SERVER['REMOTE_USER']; 8217ee7f66SAndreas Gohr } 83ee4c4a1bSAndreas Gohr 84f3f0262cSandi }else{ 85f3f0262cSandi $info['perm'] = auth_aclcheck($ID,'',null); 861380fc45SAndreas Gohr $info['subscribed'] = false; 87ee4c4a1bSAndreas Gohr $info['client'] = clientIP(true); 88f3f0262cSandi } 89f3f0262cSandi 90f3f0262cSandi $info['namespace'] = getNS($ID); 91f3f0262cSandi $info['locked'] = checklock($ID); 92*2ca9d91cSBen Coburn $info['filepath'] = realpath(wikiFN($ID)); 93*2ca9d91cSBen Coburn $info['exists'] = @file_exists($info['filepath']); 94*2ca9d91cSBen Coburn if($REV){ 95*2ca9d91cSBen Coburn //check if current revision was meant 96*2ca9d91cSBen Coburn if($info['exists'] && (@filemtime($info['filepath'])==$REV)){ 97*2ca9d91cSBen Coburn $REV = ''; 98*2ca9d91cSBen Coburn }else{ 99*2ca9d91cSBen Coburn //really use old revision 100f3f0262cSandi $info['filepath'] = realpath(wikiFN($ID,$REV)); 101f3f0262cSandi $info['exists'] = @file_exists($info['filepath']); 102f3f0262cSandi } 103f3f0262cSandi } 104c112d578Sandi $info['rev'] = $REV; 105f3f0262cSandi if($info['exists']){ 106f3f0262cSandi $info['writable'] = (is_writable($info['filepath']) && 107f3f0262cSandi ($info['perm'] >= AUTH_EDIT)); 108f3f0262cSandi }else{ 109f3f0262cSandi $info['writable'] = ($info['perm'] >= AUTH_CREATE); 110f3f0262cSandi } 111f3f0262cSandi $info['editable'] = ($info['writable'] && empty($info['lock'])); 112f3f0262cSandi $info['lastmod'] = @filemtime($info['filepath']); 113f3f0262cSandi 11471726d78SBen Coburn //load page meta data 11571726d78SBen Coburn $info['meta'] = p_get_metadata($ID); 11671726d78SBen Coburn 117652610a2Sandi //who's the editor 118652610a2Sandi if($REV){ 11971726d78SBen Coburn $revinfo = getRevisionInfo($ID, $REV, 1024); 120652610a2Sandi }else{ 121bb4866bdSchris $revinfo = isset($info['meta']['last_change']) ? $info['meta']['last_change'] : getRevisionInfo($ID,$info['lastmod'],1024); 122652610a2Sandi } 123bb4866bdSchris 124652610a2Sandi $info['ip'] = $revinfo['ip']; 125652610a2Sandi $info['user'] = $revinfo['user']; 126652610a2Sandi $info['sum'] = $revinfo['sum']; 12771726d78SBen Coburn // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID. 12871726d78SBen Coburn // Use $INFO['meta']['last_change']['type']==='e' in place of $info['minor']. 12959f257aeSchris 13088f522e9Sandi if($revinfo['user']){ 13188f522e9Sandi $info['editor'] = $revinfo['user']; 13288f522e9Sandi }else{ 13388f522e9Sandi $info['editor'] = $revinfo['ip']; 13488f522e9Sandi } 135652610a2Sandi 136ee4c4a1bSAndreas Gohr // draft 137ee4c4a1bSAndreas Gohr $draft = getCacheName($info['client'].$ID,'.draft'); 138ee4c4a1bSAndreas Gohr if(@file_exists($draft)){ 139ee4c4a1bSAndreas Gohr if(@filemtime($draft) < @filemtime(wikiFN($ID))){ 140ee4c4a1bSAndreas Gohr // remove stale draft 141ee4c4a1bSAndreas Gohr @unlink($draft); 142ee4c4a1bSAndreas Gohr }else{ 143ee4c4a1bSAndreas Gohr $info['draft'] = $draft; 144ee4c4a1bSAndreas Gohr } 145ee4c4a1bSAndreas Gohr } 146ee4c4a1bSAndreas Gohr 147f3f0262cSandi return $info; 148f3f0262cSandi} 149f3f0262cSandi 150f3f0262cSandi/** 1512684e50aSAndreas Gohr * Build an string of URL parameters 1522684e50aSAndreas Gohr * 1532684e50aSAndreas Gohr * @author Andreas Gohr 1542684e50aSAndreas Gohr */ 155b174aeaeSchrisfunction buildURLparams($params, $sep='&'){ 1562684e50aSAndreas Gohr $url = ''; 1572684e50aSAndreas Gohr $amp = false; 1582684e50aSAndreas Gohr foreach($params as $key => $val){ 159b174aeaeSchris if($amp) $url .= $sep; 1602684e50aSAndreas Gohr 1612684e50aSAndreas Gohr $url .= $key.'='; 162b6c6979fSAndreas Gohr $url .= rawurlencode($val); 1632684e50aSAndreas Gohr $amp = true; 1642684e50aSAndreas Gohr } 1652684e50aSAndreas Gohr return $url; 1662684e50aSAndreas Gohr} 1672684e50aSAndreas Gohr 1682684e50aSAndreas Gohr/** 1692684e50aSAndreas Gohr * Build an string of html tag attributes 1702684e50aSAndreas Gohr * 1717bff22c0SAndreas Gohr * Skips keys starting with '_', values get HTML encoded 1727bff22c0SAndreas Gohr * 1732684e50aSAndreas Gohr * @author Andreas Gohr 1742684e50aSAndreas Gohr */ 1752684e50aSAndreas Gohrfunction buildAttributes($params){ 1762684e50aSAndreas Gohr $url = ''; 1772684e50aSAndreas Gohr foreach($params as $key => $val){ 1787bff22c0SAndreas Gohr if($key{0} == '_') continue; 1797bff22c0SAndreas Gohr 1802684e50aSAndreas Gohr $url .= $key.'="'; 1812684e50aSAndreas Gohr $url .= htmlspecialchars ($val); 1822684e50aSAndreas Gohr $url .= '" '; 1832684e50aSAndreas Gohr } 1842684e50aSAndreas Gohr return $url; 1852684e50aSAndreas Gohr} 1862684e50aSAndreas Gohr 1872684e50aSAndreas Gohr 1882684e50aSAndreas Gohr/** 18915fae107Sandi * This builds the breadcrumb trail and returns it as array 19015fae107Sandi * 19115fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 192f3f0262cSandi */ 193f3f0262cSandifunction breadcrumbs(){ 1948746e727Sandi // we prepare the breadcrumbs early for quick session closing 1958746e727Sandi static $crumbs = null; 1968746e727Sandi if($crumbs != null) return $crumbs; 1978746e727Sandi 198f3f0262cSandi global $ID; 199f3f0262cSandi global $ACT; 200f3f0262cSandi global $conf; 201e71ce681SAndreas Gohr $crumbs = $_SESSION[DOKU_COOKIE]['bc']; 202f3f0262cSandi 203f3f0262cSandi //first visit? 204f3f0262cSandi if (!is_array($crumbs)){ 205f3f0262cSandi $crumbs = array(); 206f3f0262cSandi } 207f3f0262cSandi //we only save on show and existing wiki documents 208a77f5846Sjan $file = wikiFN($ID); 209a77f5846Sjan if($ACT != 'show' || !@file_exists($file)){ 210e71ce681SAndreas Gohr $_SESSION[DOKU_COOKIE]['bc'] = $crumbs; 211f3f0262cSandi return $crumbs; 212f3f0262cSandi } 213a77f5846Sjan 214a77f5846Sjan // page names 215a77f5846Sjan $name = noNS($ID); 216a77f5846Sjan if ($conf['useheading']) { 217a77f5846Sjan // get page title 218bb0a59d4Sjan $title = p_get_first_heading($ID); 219a77f5846Sjan if ($title) { 220a77f5846Sjan $name = $title; 221a77f5846Sjan } 222a77f5846Sjan } 223a77f5846Sjan 224f3f0262cSandi //remove ID from array 225a77f5846Sjan if (isset($crumbs[$ID])) { 226a77f5846Sjan unset($crumbs[$ID]); 227f3f0262cSandi } 228f3f0262cSandi 229f3f0262cSandi //add to array 230a77f5846Sjan $crumbs[$ID] = $name; 231f3f0262cSandi //reduce size 232f3f0262cSandi while(count($crumbs) > $conf['breadcrumbs']){ 233f3f0262cSandi array_shift($crumbs); 234f3f0262cSandi } 235f3f0262cSandi //save to session 236e71ce681SAndreas Gohr $_SESSION[DOKU_COOKIE]['bc'] = $crumbs; 237f3f0262cSandi return $crumbs; 238f3f0262cSandi} 239f3f0262cSandi 240f3f0262cSandi/** 24115fae107Sandi * Filter for page IDs 24215fae107Sandi * 243f3f0262cSandi * This is run on a ID before it is outputted somewhere 244f3f0262cSandi * currently used to replace the colon with something else 245f3f0262cSandi * on Windows systems and to have proper URL encoding 24615fae107Sandi * 24749c713a3Sandi * Urlencoding is ommitted when the second parameter is false 24849c713a3Sandi * 24915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 250f3f0262cSandi */ 25149c713a3Sandifunction idfilter($id,$ue=true){ 252f3f0262cSandi global $conf; 253f3f0262cSandi if ($conf['useslash'] && $conf['userewrite']){ 254f3f0262cSandi $id = strtr($id,':','/'); 255f3f0262cSandi }elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && 256f3f0262cSandi $conf['userewrite']) { 257f3f0262cSandi $id = strtr($id,':',';'); 258f3f0262cSandi } 25949c713a3Sandi if($ue){ 260b6c6979fSAndreas Gohr $id = rawurlencode($id); 261f3f0262cSandi $id = str_replace('%3A',':',$id); //keep as colon 262f3f0262cSandi $id = str_replace('%2F','/',$id); //keep as slash 26349c713a3Sandi } 264f3f0262cSandi return $id; 265f3f0262cSandi} 266f3f0262cSandi 267f3f0262cSandi/** 268ed7b5f09Sandi * This builds a link to a wikipage 26915fae107Sandi * 2706c7843b5Sandi * It handles URL rewriting and adds additional parameter if 2716c7843b5Sandi * given in $more 2726c7843b5Sandi * 27315fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 274f3f0262cSandi */ 275b174aeaeSchrisfunction wl($id='',$more='',$abs=false,$sep='&'){ 276f3f0262cSandi global $conf; 2776de3759aSAndreas Gohr if(is_array($more)){ 278b174aeaeSchris $more = buildURLparams($more,$sep); 2796de3759aSAndreas Gohr }else{ 280b174aeaeSchris $more = str_replace(',',$sep,$more); 2816de3759aSAndreas Gohr } 282f3f0262cSandi 283f3f0262cSandi $id = idfilter($id); 284ed7b5f09Sandi if($abs){ 285ed7b5f09Sandi $xlink = DOKU_URL; 286ed7b5f09Sandi }else{ 287ed7b5f09Sandi $xlink = DOKU_BASE; 288ed7b5f09Sandi } 289f3f0262cSandi 2906c7843b5Sandi if($conf['userewrite'] == 2){ 2916c7843b5Sandi $xlink .= DOKU_SCRIPT.'/'.$id; 2926c7843b5Sandi if($more) $xlink .= '?'.$more; 2936c7843b5Sandi }elseif($conf['userewrite']){ 294f3f0262cSandi $xlink .= $id; 295f3f0262cSandi if($more) $xlink .= '?'.$more; 2966c7843b5Sandi }else{ 2976c7843b5Sandi $xlink .= DOKU_SCRIPT.'?id='.$id; 298b174aeaeSchris if($more) $xlink .= $sep.$more; 299f3f0262cSandi } 300f3f0262cSandi 301f3f0262cSandi return $xlink; 302f3f0262cSandi} 303f3f0262cSandi 304f3f0262cSandi/** 305f5c2808fSBen Coburn * This builds a link to an alternate page format 306f5c2808fSBen Coburn * 307f5c2808fSBen Coburn * Handles URL rewriting if enabled. Follows the style of wl(). 308f5c2808fSBen Coburn * 309f5c2808fSBen Coburn * @author Ben Coburn <btcoburn@silicodon.net> 310f5c2808fSBen Coburn */ 311f5c2808fSBen Coburnfunction exportlink($id='',$format='raw',$more='',$abs=false,$sep='&'){ 312f5c2808fSBen Coburn global $conf; 313f5c2808fSBen Coburn if(is_array($more)){ 314f5c2808fSBen Coburn $more = buildURLparams($more,$sep); 315f5c2808fSBen Coburn }else{ 316f5c2808fSBen Coburn $more = str_replace(',',$sep,$more); 317f5c2808fSBen Coburn } 318f5c2808fSBen Coburn 319f5c2808fSBen Coburn $format = rawurlencode($format); 320f5c2808fSBen Coburn $id = idfilter($id); 321f5c2808fSBen Coburn if($abs){ 322f5c2808fSBen Coburn $xlink = DOKU_URL; 323f5c2808fSBen Coburn }else{ 324f5c2808fSBen Coburn $xlink = DOKU_BASE; 325f5c2808fSBen Coburn } 326f5c2808fSBen Coburn 327f5c2808fSBen Coburn if($conf['userewrite'] == 2){ 328f5c2808fSBen Coburn $xlink .= DOKU_SCRIPT.'/'.$id.'?do=export_'.$format; 329f5c2808fSBen Coburn if($more) $xlink .= $sep.$more; 330f5c2808fSBen Coburn }elseif($conf['userewrite'] == 1){ 331f5c2808fSBen Coburn $xlink .= '_export/'.$format.'/'.$id; 332f5c2808fSBen Coburn if($more) $xlink .= '?'.$more; 333f5c2808fSBen Coburn }else{ 334f5c2808fSBen Coburn $xlink .= DOKU_SCRIPT.'?do=export_'.$format.$sep.'id='.$id; 335f5c2808fSBen Coburn if($more) $xlink .= $sep.$more; 336f5c2808fSBen Coburn } 337f5c2808fSBen Coburn 338f5c2808fSBen Coburn return $xlink; 339f5c2808fSBen Coburn} 340f5c2808fSBen Coburn 341f5c2808fSBen Coburn/** 3426de3759aSAndreas Gohr * Build a link to a media file 3436de3759aSAndreas Gohr * 3446de3759aSAndreas Gohr * Will return a link to the detail page if $direct is false 3456de3759aSAndreas Gohr */ 346b174aeaeSchrisfunction ml($id='',$more='',$direct=true,$sep='&'){ 3476de3759aSAndreas Gohr global $conf; 3486de3759aSAndreas Gohr if(is_array($more)){ 349b174aeaeSchris $more = buildURLparams($more,$sep); 3506de3759aSAndreas Gohr }else{ 351b174aeaeSchris $more = str_replace(',',$sep,$more); 3526de3759aSAndreas Gohr } 3536de3759aSAndreas Gohr 3546de3759aSAndreas Gohr $xlink = DOKU_BASE; 3556de3759aSAndreas Gohr 3566de3759aSAndreas Gohr // external URLs are always direct without rewriting 3576de3759aSAndreas Gohr if(preg_match('#^(https?|ftp)://#i',$id)){ 3586de3759aSAndreas Gohr $xlink .= 'lib/exe/fetch.php'; 3596de3759aSAndreas Gohr if($more){ 3606de3759aSAndreas Gohr $xlink .= '?'.$more; 361b174aeaeSchris $xlink .= $sep.'media='.rawurlencode($id); 3626de3759aSAndreas Gohr }else{ 363b6c6979fSAndreas Gohr $xlink .= '?media='.rawurlencode($id); 3646de3759aSAndreas Gohr } 3656de3759aSAndreas Gohr return $xlink; 3666de3759aSAndreas Gohr } 3676de3759aSAndreas Gohr 3686de3759aSAndreas Gohr $id = idfilter($id); 3696de3759aSAndreas Gohr 3706de3759aSAndreas Gohr // decide on scriptname 3716de3759aSAndreas Gohr if($direct){ 3726de3759aSAndreas Gohr if($conf['userewrite'] == 1){ 3736de3759aSAndreas Gohr $script = '_media'; 3746de3759aSAndreas Gohr }else{ 3756de3759aSAndreas Gohr $script = 'lib/exe/fetch.php'; 3766de3759aSAndreas Gohr } 3776de3759aSAndreas Gohr }else{ 3786de3759aSAndreas Gohr if($conf['userewrite'] == 1){ 3796de3759aSAndreas Gohr $script = '_detail'; 3806de3759aSAndreas Gohr }else{ 3816de3759aSAndreas Gohr $script = 'lib/exe/detail.php'; 3826de3759aSAndreas Gohr } 3836de3759aSAndreas Gohr } 3846de3759aSAndreas Gohr 3856de3759aSAndreas Gohr // build URL based on rewrite mode 3866de3759aSAndreas Gohr if($conf['userewrite']){ 3876de3759aSAndreas Gohr $xlink .= $script.'/'.$id; 3886de3759aSAndreas Gohr if($more) $xlink .= '?'.$more; 3896de3759aSAndreas Gohr }else{ 3906de3759aSAndreas Gohr if($more){ 391a99d3236SEsther Brunner $xlink .= $script.'?'.$more; 392b174aeaeSchris $xlink .= $sep.'media='.$id; 3936de3759aSAndreas Gohr }else{ 394a99d3236SEsther Brunner $xlink .= $script.'?media='.$id; 3956de3759aSAndreas Gohr } 3966de3759aSAndreas Gohr } 3976de3759aSAndreas Gohr 3986de3759aSAndreas Gohr return $xlink; 3996de3759aSAndreas Gohr} 4006de3759aSAndreas Gohr 4016de3759aSAndreas Gohr 4026de3759aSAndreas Gohr 4036de3759aSAndreas Gohr/** 404f3f0262cSandi * Just builds a link to a script 40515fae107Sandi * 406ed7b5f09Sandi * @todo maybe obsolete 40715fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 408f3f0262cSandi */ 409f3f0262cSandifunction script($script='doku.php'){ 410ed7b5f09Sandi# $link = getBaseURL(); 411ed7b5f09Sandi# $link .= $script; 412ed7b5f09Sandi# return $link; 413ed7b5f09Sandi return DOKU_BASE.DOKU_SCRIPT; 414f3f0262cSandi} 415f3f0262cSandi 416f3f0262cSandi/** 41715fae107Sandi * Spamcheck against wordlist 41815fae107Sandi * 419f3f0262cSandi * Checks the wikitext against a list of blocked expressions 420f3f0262cSandi * returns true if the text contains any bad words 42115fae107Sandi * 42215fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 423f3f0262cSandi */ 424f3f0262cSandifunction checkwordblock(){ 425f3f0262cSandi global $TEXT; 426f3f0262cSandi global $conf; 427f3f0262cSandi 428f3f0262cSandi if(!$conf['usewordblock']) return false; 429f3f0262cSandi 430041d1964SAndreas Gohr // we prepare the text a tiny bit to prevent spammers circumventing URL checks 431041d1964SAndreas Gohr $text = preg_replace('!(\b)(www\.[\w.:?\-;,]+?\.[\w.:?\-;,]+?[\w/\#~:.?+=&%@\!\-.:?\-;,]+?)([.:?\-;,]*[^\w/\#~:.?+=&%@\!\-.:?\-;,])!i','\1http://\2 \2\3',$TEXT); 432041d1964SAndreas Gohr 433b9ac8716Schris $wordblocks = getWordblocks(); 4343e2965d7Sandi //how many lines to read at once (to work around some PCRE limits) 4353e2965d7Sandi if(version_compare(phpversion(),'4.3.0','<')){ 4363e2965d7Sandi //old versions of PCRE define a maximum of parenthesises even if no 4373e2965d7Sandi //backreferences are used - the maximum is 99 4383e2965d7Sandi //this is very bad performancewise and may even be too high still 4393e2965d7Sandi $chunksize = 40; 4403e2965d7Sandi }else{ 441a51d08efSAndreas Gohr //read file in chunks of 200 - this should work around the 4423e2965d7Sandi //MAX_PATTERN_SIZE in modern PCRE 443a51d08efSAndreas Gohr $chunksize = 200; 4443e2965d7Sandi } 445b9ac8716Schris while($blocks = array_splice($wordblocks,0,$chunksize)){ 446f3f0262cSandi $re = array(); 447f3f0262cSandi #build regexp from blocks 448f3f0262cSandi foreach($blocks as $block){ 449f3f0262cSandi $block = preg_replace('/#.*$/','',$block); 450f3f0262cSandi $block = trim($block); 451f3f0262cSandi if(empty($block)) continue; 452f3f0262cSandi $re[] = $block; 453f3f0262cSandi } 454041d1964SAndreas Gohr if(preg_match('#('.join('|',$re).')#si',$text, $match=array())) { 455b9ac8716Schris return true; 456b9ac8716Schris } 457703f6fdeSandi } 458f3f0262cSandi return false; 459f3f0262cSandi} 460f3f0262cSandi 461f3f0262cSandi/** 46215fae107Sandi * Return the IP of the client 46315fae107Sandi * 4646d8affe6SAndreas Gohr * Honours X-Forwarded-For and X-Real-IP Proxy Headers 46515fae107Sandi * 4666d8affe6SAndreas Gohr * It returns a comma separated list of IPs if the above mentioned 4676d8affe6SAndreas Gohr * headers are set. If the single parameter is set, it tries to return 4686d8affe6SAndreas Gohr * a routable public address, prefering the ones suplied in the X 4696d8affe6SAndreas Gohr * headers 4706d8affe6SAndreas Gohr * 4716d8affe6SAndreas Gohr * @param boolean $single If set only a single IP is returned 47215fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 473f3f0262cSandi */ 4746d8affe6SAndreas Gohrfunction clientIP($single=false){ 4756d8affe6SAndreas Gohr $ip = array(); 4766d8affe6SAndreas Gohr $ip[] = $_SERVER['REMOTE_ADDR']; 477bb4866bdSchris if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) 4786d8affe6SAndreas Gohr $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_FORWARDED_FOR'])); 479bb4866bdSchris if(!empty($_SERVER['HTTP_X_REAL_IP'])) 4806d8affe6SAndreas Gohr $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_REAL_IP'])); 4816d8affe6SAndreas Gohr 4826d8affe6SAndreas Gohr // remove any non-IP stuff 4836d8affe6SAndreas Gohr $cnt = count($ip); 4844ff28443Schris $match = array(); 4856d8affe6SAndreas Gohr for($i=0; $i<$cnt; $i++){ 4864ff28443Schris if(preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/',$ip[$i],$match)) { 4874ff28443Schris $ip[$i] = $match[0]; 4884ff28443Schris } else { 4894ff28443Schris $ip[$i] = ''; 4904ff28443Schris } 4916d8affe6SAndreas Gohr if(empty($ip[$i])) unset($ip[$i]); 492f3f0262cSandi } 4936d8affe6SAndreas Gohr $ip = array_values(array_unique($ip)); 4946d8affe6SAndreas Gohr if(!$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP 4956d8affe6SAndreas Gohr 4966d8affe6SAndreas Gohr if(!$single) return join(',',$ip); 4976d8affe6SAndreas Gohr 4986d8affe6SAndreas Gohr // decide which IP to use, trying to avoid local addresses 4996d8affe6SAndreas Gohr $ip = array_reverse($ip); 5006d8affe6SAndreas Gohr foreach($ip as $i){ 5016d8affe6SAndreas Gohr if(preg_match('/^(127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$i)){ 5026d8affe6SAndreas Gohr continue; 5036d8affe6SAndreas Gohr }else{ 5046d8affe6SAndreas Gohr return $i; 5056d8affe6SAndreas Gohr } 5066d8affe6SAndreas Gohr } 5076d8affe6SAndreas Gohr // still here? just use the first (last) address 5086d8affe6SAndreas Gohr return $ip[0]; 509f3f0262cSandi} 510f3f0262cSandi 511f3f0262cSandi/** 51215fae107Sandi * Checks if a given page is currently locked. 51315fae107Sandi * 514f3f0262cSandi * removes stale lockfiles 51515fae107Sandi * 51615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 517f3f0262cSandi */ 518f3f0262cSandifunction checklock($id){ 519f3f0262cSandi global $conf; 520c9b4bd1eSBen Coburn $lock = wikiLockFN($id); 521f3f0262cSandi 522f3f0262cSandi //no lockfile 523f3f0262cSandi if(!@file_exists($lock)) return false; 524f3f0262cSandi 525f3f0262cSandi //lockfile expired 526f3f0262cSandi if((time() - filemtime($lock)) > $conf['locktime']){ 527d8186216SBen Coburn @unlink($lock); 528f3f0262cSandi return false; 529f3f0262cSandi } 530f3f0262cSandi 531f3f0262cSandi //my own lock 532f3f0262cSandi $ip = io_readFile($lock); 533f3f0262cSandi if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){ 534f3f0262cSandi return false; 535f3f0262cSandi } 536f3f0262cSandi 537f3f0262cSandi return $ip; 538f3f0262cSandi} 539f3f0262cSandi 540f3f0262cSandi/** 54115fae107Sandi * Lock a page for editing 54215fae107Sandi * 54315fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 544f3f0262cSandi */ 545f3f0262cSandifunction lock($id){ 546c9b4bd1eSBen Coburn $lock = wikiLockFN($id); 547f3f0262cSandi if($_SERVER['REMOTE_USER']){ 548f3f0262cSandi io_saveFile($lock,$_SERVER['REMOTE_USER']); 549f3f0262cSandi }else{ 550f3f0262cSandi io_saveFile($lock,clientIP()); 551f3f0262cSandi } 552f3f0262cSandi} 553f3f0262cSandi 554f3f0262cSandi/** 55515fae107Sandi * Unlock a page if it was locked by the user 556f3f0262cSandi * 55715fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 55815fae107Sandi * @return bool true if a lock was removed 559f3f0262cSandi */ 560f3f0262cSandifunction unlock($id){ 561c9b4bd1eSBen Coburn $lock = wikiLockFN($id); 562f3f0262cSandi if(@file_exists($lock)){ 563f3f0262cSandi $ip = io_readFile($lock); 564f3f0262cSandi if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){ 565f3f0262cSandi @unlink($lock); 566f3f0262cSandi return true; 567f3f0262cSandi } 568f3f0262cSandi } 569f3f0262cSandi return false; 570f3f0262cSandi} 571f3f0262cSandi 572f3f0262cSandi/** 573f3f0262cSandi * convert line ending to unix format 574f3f0262cSandi * 57515fae107Sandi * @see formText() for 2crlf conversion 57615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 577f3f0262cSandi */ 578f3f0262cSandifunction cleanText($text){ 579f3f0262cSandi $text = preg_replace("/(\015\012)|(\015)/","\012",$text); 580f3f0262cSandi return $text; 581f3f0262cSandi} 582f3f0262cSandi 583f3f0262cSandi/** 584f3f0262cSandi * Prepares text for print in Webforms by encoding special chars. 585f3f0262cSandi * It also converts line endings to Windows format which is 586f3f0262cSandi * pseudo standard for webforms. 587f3f0262cSandi * 58815fae107Sandi * @see cleanText() for 2unix conversion 58915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 590f3f0262cSandi */ 591f3f0262cSandifunction formText($text){ 592f3f0262cSandi $text = preg_replace("/\012/","\015\012",$text); 593f3f0262cSandi return htmlspecialchars($text); 594f3f0262cSandi} 595f3f0262cSandi 596f3f0262cSandi/** 59715fae107Sandi * Returns the specified local text in raw format 59815fae107Sandi * 59915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 600f3f0262cSandi */ 601f3f0262cSandifunction rawLocale($id){ 602f3f0262cSandi return io_readFile(localeFN($id)); 603f3f0262cSandi} 604f3f0262cSandi 605f3f0262cSandi/** 606f3f0262cSandi * Returns the raw WikiText 60715fae107Sandi * 60815fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 609f3f0262cSandi */ 610f3f0262cSandifunction rawWiki($id,$rev=''){ 611cc7d0c94SBen Coburn return io_readWikiPage(wikiFN($id, $rev), $id, $rev); 612f3f0262cSandi} 613f3f0262cSandi 614f3f0262cSandi/** 6157146cee2SAndreas Gohr * Returns the pagetemplate contents for the ID's namespace 6167146cee2SAndreas Gohr * 6177146cee2SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 6187146cee2SAndreas Gohr */ 619b7d5a5f0SAndreas Gohrfunction pageTemplate($data){ 620b7d5a5f0SAndreas Gohr $id = $data[0]; 621a15ce62dSEsther Brunner global $conf; 622a15ce62dSEsther Brunner global $INFO; 623a15ce62dSEsther Brunner $tpl = io_readFile(dirname(wikiFN($id)).'/_template.txt'); 624a15ce62dSEsther Brunner $tpl = str_replace('@ID@',$id,$tpl); 625a15ce62dSEsther Brunner $tpl = str_replace('@NS@',getNS($id),$tpl); 626a15ce62dSEsther Brunner $tpl = str_replace('@PAGE@',strtr(noNS($id),'_',' '),$tpl); 627a15ce62dSEsther Brunner $tpl = str_replace('@USER@',$_SERVER['REMOTE_USER'],$tpl); 628a15ce62dSEsther Brunner $tpl = str_replace('@NAME@',$INFO['userinfo']['name'],$tpl); 629a15ce62dSEsther Brunner $tpl = str_replace('@MAIL@',$INFO['userinfo']['mail'],$tpl); 630a15ce62dSEsther Brunner $tpl = str_replace('@DATE@',date($conf['dformat']),$tpl); 631a15ce62dSEsther Brunner return $tpl; 6327146cee2SAndreas Gohr} 6337146cee2SAndreas Gohr 6347146cee2SAndreas Gohr 6357146cee2SAndreas Gohr/** 63615fae107Sandi * Returns the raw Wiki Text in three slices. 63715fae107Sandi * 63815fae107Sandi * The range parameter needs to have the form "from-to" 63915cfe303Sandi * and gives the range of the section in bytes - no 64015cfe303Sandi * UTF-8 awareness is needed. 641f3f0262cSandi * The returned order is prefix, section and suffix. 64215fae107Sandi * 64315fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 644f3f0262cSandi */ 645f3f0262cSandifunction rawWikiSlices($range,$id,$rev=''){ 646f3f0262cSandi list($from,$to) = split('-',$range,2); 647cc7d0c94SBen Coburn $text = io_readWikiPage(wikiFN($id, $rev), $id, $rev); 648f3f0262cSandi if(!$from) $from = 0; 649c3d8e19bSandi if(!$to) $to = strlen($text)+1; 650f3f0262cSandi 65115cfe303Sandi $slices[0] = substr($text,0,$from-1); 65215cfe303Sandi $slices[1] = substr($text,$from-1,$to-$from); 65315cfe303Sandi $slices[2] = substr($text,$to); 654f3f0262cSandi 655f3f0262cSandi return $slices; 656f3f0262cSandi} 657f3f0262cSandi 658f3f0262cSandi/** 65915fae107Sandi * Joins wiki text slices 66015fae107Sandi * 661f3f0262cSandi * function to join the text slices with correct lineendings again. 662f3f0262cSandi * When the pretty parameter is set to true it adds additional empty 663f3f0262cSandi * lines between sections if needed (used on saving). 66415fae107Sandi * 66515fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 666f3f0262cSandi */ 667f3f0262cSandifunction con($pre,$text,$suf,$pretty=false){ 668f3f0262cSandi 669f3f0262cSandi if($pretty){ 670f3f0262cSandi if($pre && substr($pre,-1) != "\n") $pre .= "\n"; 671f3f0262cSandi if($suf && substr($text,-1) != "\n") $text .= "\n"; 672f3f0262cSandi } 673f3f0262cSandi 674f3f0262cSandi if($pre) $pre .= "\n"; 675f3f0262cSandi if($suf) $text .= "\n"; 676f3f0262cSandi return $pre.$text.$suf; 677f3f0262cSandi} 678f3f0262cSandi 679f3f0262cSandi/** 680a701424fSBen Coburn * Saves a wikitext by calling io_writeWikiPage. 681a701424fSBen Coburn * Also directs changelog and attic updates. 68215fae107Sandi * 68315fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 68471726d78SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net> 685f3f0262cSandi */ 686b6912aeaSAndreas Gohrfunction saveWikiText($id,$text,$summary,$minor=false){ 687a701424fSBen Coburn /* Note to developers: 688a701424fSBen Coburn This code is subtle and delicate. Test the behavior of 689a701424fSBen Coburn the attic and changelog with dokuwiki and external edits 690a701424fSBen Coburn after any changes. External edits change the wiki page 691a701424fSBen Coburn directly without using php or dokuwiki. 692a701424fSBen Coburn */ 693f3f0262cSandi global $conf; 694f3f0262cSandi global $lang; 69571726d78SBen Coburn global $REV; 696f3f0262cSandi // ignore if no changes were made 697f3f0262cSandi if($text == rawWiki($id,'')){ 698f3f0262cSandi return; 699f3f0262cSandi } 700f3f0262cSandi 701f3f0262cSandi $file = wikiFN($id); 702a701424fSBen Coburn $old = @filemtime($file); // from page 70371726d78SBen Coburn $wasRemoved = empty($text); 704d8186216SBen Coburn $wasCreated = !@file_exists($file); 70571726d78SBen Coburn $wasReverted = ($REV==true); 706e45b34cdSBen Coburn $newRev = false; 707a701424fSBen Coburn $oldRev = getRevisions($id, -1, 1, 1024); // from changelog 708a701424fSBen Coburn $oldRev = (int)(empty($oldRev)?0:$oldRev[0]); 709a701424fSBen Coburn if(!@file_exists(wikiFN($id, $old)) && @file_exists($file) && $old>=$oldRev) { 71046844156SBen Coburn // add old revision to the attic if missing 71146844156SBen Coburn saveOldRevision($id); 71246844156SBen Coburn // add a changelog entry if this edit came from outside dokuwiki 713a701424fSBen Coburn if ($old>$oldRev) { 71446844156SBen Coburn addLogEntry($old, $id); 71546844156SBen Coburn // send notify mails 71646844156SBen Coburn notify($id,'admin',$oldRev,'',false); 71746844156SBen Coburn notify($id,'subscribers',$oldRev,'',false); 71846844156SBen Coburn // remove soon to be stale instructions 71946844156SBen Coburn $cache = new cache_instructions($id, $file); 72046844156SBen Coburn $cache->removeCache(); 72146844156SBen Coburn } 72246844156SBen Coburn } 723f3f0262cSandi 72471726d78SBen Coburn if ($wasRemoved){ 725e45b34cdSBen Coburn // pre-save deleted revision 726e45b34cdSBen Coburn @touch($file); 72746844156SBen Coburn clearstatcache(); 728e45b34cdSBen Coburn $newRev = saveOldRevision($id); 729e1f3d9e1SEsther Brunner // remove empty file 730f3f0262cSandi @unlink($file); 73171726d78SBen Coburn // remove old meta info... 732e1f3d9e1SEsther Brunner $mfiles = metaFiles($id); 73371726d78SBen Coburn $changelog = metaFN($id, '.changes'); 734e1f3d9e1SEsther Brunner foreach ($mfiles as $mfile) { 73571726d78SBen Coburn // but keep per-page changelog to preserve page history 736d8186216SBen Coburn if (@file_exists($mfile) && $mfile!==$changelog) { @unlink($mfile); } 737b158d625SSteven Danz } 738f3f0262cSandi $del = true; 7393ce054b3Sandi // autoset summary on deletion 7403ce054b3Sandi if(empty($summary)) $summary = $lang['deleted']; 74153d6ccfeSandi // remove empty namespaces 742cc7d0c94SBen Coburn io_sweepNS($id, 'datadir'); 743cc7d0c94SBen Coburn io_sweepNS($id, 'mediadir'); 744f3f0262cSandi }else{ 745cc7d0c94SBen Coburn // save file (namespace dir is created in io_writeWikiPage) 746cc7d0c94SBen Coburn io_writeWikiPage($file, $text, $id); 74746844156SBen Coburn // pre-save the revision, to keep the attic in sync 74846844156SBen Coburn $newRev = saveOldRevision($id); 749f3f0262cSandi $del = false; 750f3f0262cSandi } 751f3f0262cSandi 75271726d78SBen Coburn // select changelog line type 75371726d78SBen Coburn $extra = ''; 75471726d78SBen Coburn $type = 'E'; 75571726d78SBen Coburn if ($wasReverted) { 75671726d78SBen Coburn $type = 'R'; 75771726d78SBen Coburn $extra = $REV; 75871726d78SBen Coburn } 75971726d78SBen Coburn else if ($wasCreated) { $type = 'C'; } 76071726d78SBen Coburn else if ($wasRemoved) { $type = 'D'; } 76171726d78SBen Coburn else if ($minor && $conf['useacl'] && $_SERVER['REMOTE_USER']) { $type = 'e'; } //minor edits only for logged in users 76271726d78SBen Coburn 763e45b34cdSBen Coburn addLogEntry($newRev, $id, $type, $summary, $extra); 76426a0801fSAndreas Gohr // send notify mails 76590033e9dSAndreas Gohr notify($id,'admin',$old,$summary,$minor); 76690033e9dSAndreas Gohr notify($id,'subscribers',$old,$summary,$minor); 767f3f0262cSandi 768ce6b63d9Schris // update the purgefile (timestamp of the last time anything within the wiki was changed) 76998407a7aSandi io_saveFile($conf['cachedir'].'/purgefile',time()); 770f3f0262cSandi} 771f3f0262cSandi 772f3f0262cSandi/** 773f3f0262cSandi * moves the current version to the attic and returns its 774f3f0262cSandi * revision date 77515fae107Sandi * 77615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 777f3f0262cSandi */ 778f3f0262cSandifunction saveOldRevision($id){ 779f3f0262cSandi global $conf; 780f3f0262cSandi $oldf = wikiFN($id); 781f3f0262cSandi if(!@file_exists($oldf)) return ''; 782f3f0262cSandi $date = filemtime($oldf); 783f3f0262cSandi $newf = wikiFN($id,$date); 784cc7d0c94SBen Coburn io_writeWikiPage($newf, rawWiki($id), $id, $date); 785f3f0262cSandi return $date; 786f3f0262cSandi} 787f3f0262cSandi 788f3f0262cSandi/** 78926a0801fSAndreas Gohr * Sends a notify mail on page change 79026a0801fSAndreas Gohr * 79126a0801fSAndreas Gohr * @param string $id The changed page 79226a0801fSAndreas Gohr * @param string $who Who to notify (admin|subscribers) 79326a0801fSAndreas Gohr * @param int $rev Old page revision 79426a0801fSAndreas Gohr * @param string $summary What changed 79590033e9dSAndreas Gohr * @param boolean $minor Is this a minor edit? 79602a498e7Schris * @param array $replace Additional string substitutions, @KEY@ to be replaced by value 79715fae107Sandi * 79815fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 799f3f0262cSandi */ 80002a498e7Schrisfunction notify($id,$who,$rev='',$summary='',$minor=false,$replace=array()){ 801f3f0262cSandi global $lang; 802f3f0262cSandi global $conf; 803b158d625SSteven Danz 80426a0801fSAndreas Gohr // decide if there is something to do 80526a0801fSAndreas Gohr if($who == 'admin'){ 80626a0801fSAndreas Gohr if(empty($conf['notify'])) return; //notify enabled? 807f3f0262cSandi $text = rawLocale('mailtext'); 80826a0801fSAndreas Gohr $to = $conf['notify']; 80926a0801fSAndreas Gohr $bcc = ''; 81026a0801fSAndreas Gohr }elseif($who == 'subscribers'){ 81126a0801fSAndreas Gohr if(!$conf['subscribers']) return; //subscribers enabled? 81290033e9dSAndreas Gohr if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return; //skip minors 81326a0801fSAndreas Gohr $bcc = subscriber_addresslist($id); 81426a0801fSAndreas Gohr if(empty($bcc)) return; 81526a0801fSAndreas Gohr $to = ''; 81626a0801fSAndreas Gohr $text = rawLocale('subscribermail'); 817a06e4bdbSSebastian Harl }elseif($who == 'register'){ 818a06e4bdbSSebastian Harl if(empty($conf['registernotify'])) return; 819a06e4bdbSSebastian Harl $text = rawLocale('registermail'); 820a06e4bdbSSebastian Harl $to = $conf['registernotify']; 821a06e4bdbSSebastian Harl $bcc = ''; 82226a0801fSAndreas Gohr }else{ 82326a0801fSAndreas Gohr return; //just to be safe 82426a0801fSAndreas Gohr } 82526a0801fSAndreas Gohr 826f3f0262cSandi $text = str_replace('@DATE@',date($conf['dformat']),$text); 827f3f0262cSandi $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text); 828f3f0262cSandi $text = str_replace('@IPADDRESS@',$_SERVER['REMOTE_ADDR'],$text); 829f3f0262cSandi $text = str_replace('@HOSTNAME@',gethostbyaddr($_SERVER['REMOTE_ADDR']),$text); 830ed7b5f09Sandi $text = str_replace('@NEWPAGE@',wl($id,'',true),$text); 83126a0801fSAndreas Gohr $text = str_replace('@PAGE@',$id,$text); 83226a0801fSAndreas Gohr $text = str_replace('@TITLE@',$conf['title'],$text); 833ed7b5f09Sandi $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text); 834f3f0262cSandi $text = str_replace('@SUMMARY@',$summary,$text); 8357a82afdcSandi $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text); 836f3f0262cSandi 83702a498e7Schris foreach ($replace as $key => $substitution) { 83802a498e7Schris $text = str_replace('@'.strtoupper($key).'@',$substitution, $text); 83902a498e7Schris } 84002a498e7Schris 841a06e4bdbSSebastian Harl if($who == 'register'){ 842a06e4bdbSSebastian Harl $subject = $lang['mail_new_user'].' '.$summary; 843a06e4bdbSSebastian Harl }elseif($rev){ 844f3f0262cSandi $subject = $lang['mail_changed'].' '.$id; 845ed7b5f09Sandi $text = str_replace('@OLDPAGE@',wl($id,"rev=$rev",true),$text); 846ccdfa6c0SAndreas Gohr require_once(DOKU_INC.'inc/DifferenceEngine.php'); 847f3f0262cSandi $df = new Diff(split("\n",rawWiki($id,$rev)), 848f3f0262cSandi split("\n",rawWiki($id))); 849f3f0262cSandi $dformat = new UnifiedDiffFormatter(); 850f3f0262cSandi $diff = $dformat->format($df); 851f3f0262cSandi }else{ 852f3f0262cSandi $subject=$lang['mail_newpage'].' '.$id; 853f3f0262cSandi $text = str_replace('@OLDPAGE@','none',$text); 854f3f0262cSandi $diff = rawWiki($id); 855f3f0262cSandi } 856f3f0262cSandi $text = str_replace('@DIFF@',$diff,$text); 857241f3a36Sandi $subject = '['.$conf['title'].'] '.$subject; 858f3f0262cSandi 85926a0801fSAndreas Gohr mail_send($to,$subject,$text,$conf['mailfrom'],'',$bcc); 860f3f0262cSandi} 861f3f0262cSandi 86215fae107Sandi/** 863f3f0262cSandi * extracts the query from a google referer 86415fae107Sandi * 8656b13307fSandi * @todo should be more generic and support yahoo et al 86615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 867f3f0262cSandi */ 868f3f0262cSandifunction getGoogleQuery(){ 869f3f0262cSandi $url = parse_url($_SERVER['HTTP_REFERER']); 8705c3f206fSandi if(!$url) return ''; 871f3f0262cSandi 872f3f0262cSandi if(!preg_match("#google\.#i",$url['host'])) return ''; 873f3f0262cSandi $query = array(); 874f3f0262cSandi parse_str($url['query'],$query); 875f3f0262cSandi 876f3f0262cSandi return $query['q']; 877f3f0262cSandi} 878f3f0262cSandi 879f3f0262cSandi/** 88015fae107Sandi * Try to set correct locale 88115fae107Sandi * 882095bfd5cSandi * @deprecated No longer used 88315fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 884f3f0262cSandi */ 885f3f0262cSandifunction setCorrectLocale(){ 886f3f0262cSandi global $conf; 887f3f0262cSandi global $lang; 888f3f0262cSandi 889f3f0262cSandi $enc = strtoupper($lang['encoding']); 890f3f0262cSandi foreach ($lang['locales'] as $loc){ 891f3f0262cSandi //try locale 892f3f0262cSandi if(@setlocale(LC_ALL,$loc)) return; 893f3f0262cSandi //try loceale with encoding 894f3f0262cSandi if(@setlocale(LC_ALL,"$loc.$enc")) return; 895f3f0262cSandi } 896f3f0262cSandi //still here? try to set from environment 897f3f0262cSandi @setlocale(LC_ALL,""); 898f3f0262cSandi} 899f3f0262cSandi 900f3f0262cSandi/** 901f3f0262cSandi * Return the human readable size of a file 902f3f0262cSandi * 903f3f0262cSandi * @param int $size A file size 904f3f0262cSandi * @param int $dec A number of decimal places 905f3f0262cSandi * @author Martin Benjamin <b.martin@cybernet.ch> 906f3f0262cSandi * @author Aidan Lister <aidan@php.net> 907f3f0262cSandi * @version 1.0.0 908f3f0262cSandi */ 909f31d5b73Sandifunction filesize_h($size, $dec = 1){ 910f3f0262cSandi $sizes = array('B', 'KB', 'MB', 'GB'); 911f3f0262cSandi $count = count($sizes); 912f3f0262cSandi $i = 0; 913f3f0262cSandi 914f3f0262cSandi while ($size >= 1024 && ($i < $count - 1)) { 915f3f0262cSandi $size /= 1024; 916f3f0262cSandi $i++; 917f3f0262cSandi } 918f3f0262cSandi 919f3f0262cSandi return round($size, $dec) . ' ' . $sizes[$i]; 920f3f0262cSandi} 921f3f0262cSandi 92215fae107Sandi/** 92300a7b5adSEsther Brunner * return an obfuscated email address in line with $conf['mailguard'] setting 92400a7b5adSEsther Brunner * 92500a7b5adSEsther Brunner * @author Harry Fuecks <hfuecks@gmail.com> 92600a7b5adSEsther Brunner * @author Christopher Smith <chris@jalakai.co.uk> 92700a7b5adSEsther Brunner */ 92800a7b5adSEsther Brunnerfunction obfuscate($email) { 92900a7b5adSEsther Brunner global $conf; 93000a7b5adSEsther Brunner 93100a7b5adSEsther Brunner switch ($conf['mailguard']) { 93200a7b5adSEsther Brunner case 'visible' : 93300a7b5adSEsther Brunner $obfuscate = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] '); 93400a7b5adSEsther Brunner return strtr($email, $obfuscate); 93500a7b5adSEsther Brunner 93600a7b5adSEsther Brunner case 'hex' : 93700a7b5adSEsther Brunner $encode = ''; 93800a7b5adSEsther Brunner for ($x=0; $x < strlen($email); $x++) $encode .= '&#x' . bin2hex($email{$x}).';'; 93900a7b5adSEsther Brunner return $encode; 94000a7b5adSEsther Brunner 94100a7b5adSEsther Brunner case 'none' : 94200a7b5adSEsther Brunner default : 94300a7b5adSEsther Brunner return $email; 94400a7b5adSEsther Brunner } 94500a7b5adSEsther Brunner} 94600a7b5adSEsther Brunner 94700a7b5adSEsther Brunner/** 948b158d625SSteven Danz * Let us know if a user is tracking a page 949b158d625SSteven Danz * 9501380fc45SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 951b158d625SSteven Danz */ 9521380fc45SAndreas Gohrfunction is_subscribed($id,$uid){ 9531380fc45SAndreas Gohr $file=metaFN($id,'.mlist'); 9541380fc45SAndreas Gohr if (@file_exists($file)) { 955b158d625SSteven Danz $mlist = file($file); 9561380fc45SAndreas Gohr $pos = array_search($uid."\n",$mlist); 9571380fc45SAndreas Gohr return is_int($pos); 958b158d625SSteven Danz } 9591380fc45SAndreas Gohr 960b158d625SSteven Danz return false; 961b158d625SSteven Danz} 962340756e4Sandi 963f9eb5648Ssteven-danz/** 964f9eb5648Ssteven-danz * Return a string with the email addresses of all the 965f9eb5648Ssteven-danz * users subscribed to a page 966f9eb5648Ssteven-danz * 96726a0801fSAndreas Gohr * @author Steven Danz <steven-danz@kc.rr.com> 968f9eb5648Ssteven-danz */ 969f9eb5648Ssteven-danzfunction subscriber_addresslist($id){ 970f9eb5648Ssteven-danz global $conf; 971cd52f92dSchris global $auth; 972f9eb5648Ssteven-danz 973f9eb5648Ssteven-danz $emails = ''; 974f9eb5648Ssteven-danz 97526a0801fSAndreas Gohr if (!$conf['subscribers']) return; 97626a0801fSAndreas Gohr 977f9eb5648Ssteven-danz $mlist = array(); 978f9eb5648Ssteven-danz $file=metaFN($id,'.mlist'); 979d8186216SBen Coburn if (@file_exists($file)) { 980f9eb5648Ssteven-danz $mlist = file($file); 981f9eb5648Ssteven-danz } 982f9eb5648Ssteven-danz if(count($mlist) > 0) { 983f9eb5648Ssteven-danz foreach ($mlist as $who) { 984f9eb5648Ssteven-danz $who = rtrim($who); 985cd52f92dSchris $info = $auth->getUserData($who); 986f9eb5648Ssteven-danz $level = auth_aclcheck($id,$who,$info['grps']); 987f9eb5648Ssteven-danz if ($level >= AUTH_READ) { 988f9eb5648Ssteven-danz if (strcasecmp($info['mail'],$conf['notify']) != 0) { 989f9eb5648Ssteven-danz if (empty($emails)) { 990f9eb5648Ssteven-danz $emails = $info['mail']; 991f9eb5648Ssteven-danz } else { 992f9eb5648Ssteven-danz $emails = "$emails,".$info['mail']; 993f9eb5648Ssteven-danz } 994f9eb5648Ssteven-danz } 995f9eb5648Ssteven-danz } 996f9eb5648Ssteven-danz } 997f9eb5648Ssteven-danz } 998f9eb5648Ssteven-danz 999f9eb5648Ssteven-danz return $emails; 1000f9eb5648Ssteven-danz} 1001f9eb5648Ssteven-danz 100289541d4bSAndreas Gohr/** 100389541d4bSAndreas Gohr * Removes quoting backslashes 100489541d4bSAndreas Gohr * 100589541d4bSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 100689541d4bSAndreas Gohr */ 100789541d4bSAndreas Gohrfunction unslash($string,$char="'"){ 100889541d4bSAndreas Gohr return str_replace('\\'.$char,$char,$string); 100989541d4bSAndreas Gohr} 101089541d4bSAndreas Gohr 1011340756e4Sandi//Setup VIM: ex: et ts=2 enc=utf-8 : 1012