[ Index ]
 

Code source de DokuWiki 2006-11-06

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/inc/ -> common.php (source)

   1  <?php
   2  /**
   3   * Common DokuWiki functions
   4   *
   5   * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
   6   * @author     Andreas Gohr <andi@splitbrain.org>
   7   */
   8  
   9  if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
  10  require_once(DOKU_CONF.'dokuwiki.php');
  11  require_once (DOKU_INC.'inc/io.php');
  12  require_once (DOKU_INC.'inc/changelog.php');
  13  require_once (DOKU_INC.'inc/utf8.php');
  14  require_once (DOKU_INC.'inc/mail.php');
  15  require_once (DOKU_INC.'inc/parserutils.php');
  16  require_once (DOKU_INC.'inc/infoutils.php');
  17  
  18  /**
  19   * These constants are used with the recents function
  20   */
  21  define('RECENTS_SKIP_DELETED',2);
  22  define('RECENTS_SKIP_MINORS',4);
  23  define('RECENTS_SKIP_SUBSPACES',8);
  24  
  25  /**
  26   * Wrapper around htmlspecialchars()
  27   *
  28   * @author Andreas Gohr <andi@splitbrain.org>
  29   * @see    htmlspecialchars()
  30   */
  31  function hsc($string){
  32    return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
  33  }
  34  
  35  /**
  36   * print a newline terminated string
  37   *
  38   * You can give an indention as optional parameter
  39   *
  40   * @author Andreas Gohr <andi@splitbrain.org>
  41   */
  42  function ptln($string,$intend=0){
  43    for($i=0; $i<$intend; $i++) print ' ';
  44    echo "$string\n";
  45  }
  46  
  47  /**
  48   * strips control characters (<32) from the given string
  49   *
  50   * @author Andreas Gohr <andi@splitbrain.org>
  51   */
  52  function stripctl($string){
  53    return preg_replace('/[\x00-\x1F]+/s','',$string);
  54  }
  55  
  56  /**
  57   * Return info about the current document as associative
  58   * array.
  59   *
  60   * @author Andreas Gohr <andi@splitbrain.org>
  61   */
  62  function pageinfo(){
  63    global $ID;
  64    global $REV;
  65    global $USERINFO;
  66    global $conf;
  67  
  68    // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml
  69    // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary
  70    $info['id'] = $ID;
  71    $info['rev'] = $REV;
  72  
  73    if($_SERVER['REMOTE_USER']){
  74      $info['userinfo']   = $USERINFO;
  75      $info['perm']       = auth_quickaclcheck($ID);
  76      $info['subscribed'] = is_subscribed($ID,$_SERVER['REMOTE_USER']);
  77      $info['client']     = $_SERVER['REMOTE_USER'];
  78  
  79      // if some outside auth were used only REMOTE_USER is set
  80      if(!$info['userinfo']['name']){
  81        $info['userinfo']['name'] = $_SERVER['REMOTE_USER'];
  82      }
  83  
  84    }else{
  85      $info['perm']       = auth_aclcheck($ID,'',null);
  86      $info['subscribed'] = false;
  87      $info['client']     = clientIP(true);
  88    }
  89  
  90    $info['namespace'] = getNS($ID);
  91    $info['locked']    = checklock($ID);
  92    $info['filepath']  = realpath(wikiFN($ID));
  93    $info['exists']    = @file_exists($info['filepath']);
  94    if($REV){
  95      //check if current revision was meant
  96      if($info['exists'] && (@filemtime($info['filepath'])==$REV)){
  97        $REV = '';
  98      }else{
  99        //really use old revision
 100        $info['filepath'] = realpath(wikiFN($ID,$REV));
 101        $info['exists']   = @file_exists($info['filepath']);
 102      }
 103    }
 104    $info['rev'] = $REV;
 105    if($info['exists']){
 106      $info['writable'] = (is_writable($info['filepath']) &&
 107                           ($info['perm'] >= AUTH_EDIT));
 108    }else{
 109      $info['writable'] = ($info['perm'] >= AUTH_CREATE);
 110    }
 111    $info['editable']  = ($info['writable'] && empty($info['lock']));
 112    $info['lastmod']   = @filemtime($info['filepath']);
 113  
 114    //load page meta data
 115    $info['meta'] = p_get_metadata($ID);
 116  
 117    //who's the editor
 118    if($REV){
 119      $revinfo = getRevisionInfo($ID, $REV, 1024);
 120    }else{
 121      $revinfo = isset($info['meta']['last_change']) ? $info['meta']['last_change'] : getRevisionInfo($ID,$info['lastmod'],1024);
 122    }
 123  
 124    $info['ip']     = $revinfo['ip'];
 125    $info['user']   = $revinfo['user'];
 126    $info['sum']    = $revinfo['sum'];
 127    // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID.
 128    // Use $INFO['meta']['last_change']['type']==='e' in place of $info['minor'].
 129  
 130    if($revinfo['user']){
 131      $info['editor'] = $revinfo['user'];
 132    }else{
 133      $info['editor'] = $revinfo['ip'];
 134    }
 135  
 136    // draft
 137    $draft = getCacheName($info['client'].$ID,'.draft');
 138    if(@file_exists($draft)){
 139      if(@filemtime($draft) < @filemtime(wikiFN($ID))){
 140        // remove stale draft
 141        @unlink($draft);
 142      }else{
 143        $info['draft'] = $draft;
 144      }
 145    }
 146  
 147    return $info;
 148  }
 149  
 150  /**
 151   * Build an string of URL parameters
 152   *
 153   * @author Andreas Gohr
 154   */
 155  function buildURLparams($params, $sep='&amp;'){
 156    $url = '';
 157    $amp = false;
 158    foreach($params as $key => $val){
 159      if($amp) $url .= $sep;
 160  
 161      $url .= $key.'=';
 162      $url .= rawurlencode($val);
 163      $amp = true;
 164    }
 165    return $url;
 166  }
 167  
 168  /**
 169   * Build an string of html tag attributes
 170   *
 171   * Skips keys starting with '_', values get HTML encoded
 172   *
 173   * @author Andreas Gohr
 174   */
 175  function buildAttributes($params){
 176    $url = '';
 177    foreach($params as $key => $val){
 178      if($key{0} == '_') continue;
 179  
 180      $url .= $key.'="';
 181      $url .= htmlspecialchars ($val);
 182      $url .= '" ';
 183    }
 184    return $url;
 185  }
 186  
 187  
 188  /**
 189   * This builds the breadcrumb trail and returns it as array
 190   *
 191   * @author Andreas Gohr <andi@splitbrain.org>
 192   */
 193  function breadcrumbs(){
 194    // we prepare the breadcrumbs early for quick session closing
 195    static $crumbs = null;
 196    if($crumbs != null) return $crumbs;
 197  
 198    global $ID;
 199    global $ACT;
 200    global $conf;
 201    $crumbs = $_SESSION[DOKU_COOKIE]['bc'];
 202  
 203    //first visit?
 204    if (!is_array($crumbs)){
 205      $crumbs = array();
 206    }
 207    //we only save on show and existing wiki documents
 208    $file = wikiFN($ID);
 209    if($ACT != 'show' || !@file_exists($file)){
 210      $_SESSION[DOKU_COOKIE]['bc'] = $crumbs;
 211      return $crumbs;
 212    }
 213  
 214    // page names
 215    $name = noNS($ID);
 216    if ($conf['useheading']) {
 217      // get page title
 218      $title = p_get_first_heading($ID);
 219      if ($title) {
 220        $name = $title;
 221      }
 222    }
 223  
 224    //remove ID from array
 225    if (isset($crumbs[$ID])) {
 226      unset($crumbs[$ID]);
 227    }
 228  
 229    //add to array
 230    $crumbs[$ID] = $name;
 231    //reduce size
 232    while(count($crumbs) > $conf['breadcrumbs']){
 233      array_shift($crumbs);
 234    }
 235    //save to session
 236    $_SESSION[DOKU_COOKIE]['bc'] = $crumbs;
 237    return $crumbs;
 238  }
 239  
 240  /**
 241   * Filter for page IDs
 242   *
 243   * This is run on a ID before it is outputted somewhere
 244   * currently used to replace the colon with something else
 245   * on Windows systems and to have proper URL encoding
 246   *
 247   * Urlencoding is ommitted when the second parameter is false
 248   *
 249   * @author Andreas Gohr <andi@splitbrain.org>
 250   */
 251  function idfilter($id,$ue=true){
 252    global $conf;
 253    if ($conf['useslash'] && $conf['userewrite']){
 254      $id = strtr($id,':','/');
 255    }elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' &&
 256        $conf['userewrite']) {
 257      $id = strtr($id,':',';');
 258    }
 259    if($ue){
 260      $id = rawurlencode($id);
 261      $id = str_replace('%3A',':',$id); //keep as colon
 262      $id = str_replace('%2F','/',$id); //keep as slash
 263    }
 264    return $id;
 265  }
 266  
 267  /**
 268   * This builds a link to a wikipage
 269   *
 270   * It handles URL rewriting and adds additional parameter if
 271   * given in $more
 272   *
 273   * @author Andreas Gohr <andi@splitbrain.org>
 274   */
 275  function wl($id='',$more='',$abs=false,$sep='&amp;'){
 276    global $conf;
 277    if(is_array($more)){
 278      $more = buildURLparams($more,$sep);
 279    }else{
 280      $more = str_replace(',',$sep,$more);
 281    }
 282  
 283    $id    = idfilter($id);
 284    if($abs){
 285      $xlink = DOKU_URL;
 286    }else{
 287      $xlink = DOKU_BASE;
 288    }
 289  
 290    if($conf['userewrite'] == 2){
 291      $xlink .= DOKU_SCRIPT.'/'.$id;
 292      if($more) $xlink .= '?'.$more;
 293    }elseif($conf['userewrite']){
 294      $xlink .= $id;
 295      if($more) $xlink .= '?'.$more;
 296    }else{
 297      $xlink .= DOKU_SCRIPT.'?id='.$id;
 298      if($more) $xlink .= $sep.$more;
 299    }
 300  
 301    return $xlink;
 302  }
 303  
 304  /**
 305   * This builds a link to an alternate page format
 306   *
 307   * Handles URL rewriting if enabled. Follows the style of wl().
 308   *
 309   * @author Ben Coburn <btcoburn@silicodon.net>
 310   */
 311  function exportlink($id='',$format='raw',$more='',$abs=false,$sep='&amp;'){
 312    global $conf;
 313    if(is_array($more)){
 314      $more = buildURLparams($more,$sep);
 315    }else{
 316      $more = str_replace(',',$sep,$more);
 317    }
 318  
 319    $format = rawurlencode($format);
 320    $id = idfilter($id);
 321    if($abs){
 322      $xlink = DOKU_URL;
 323    }else{
 324      $xlink = DOKU_BASE;
 325    }
 326  
 327    if($conf['userewrite'] == 2){
 328      $xlink .= DOKU_SCRIPT.'/'.$id.'?do=export_'.$format;
 329      if($more) $xlink .= $sep.$more;
 330    }elseif($conf['userewrite'] == 1){
 331      $xlink .= '_export/'.$format.'/'.$id;
 332      if($more) $xlink .= '?'.$more;
 333    }else{
 334      $xlink .= DOKU_SCRIPT.'?do=export_'.$format.$sep.'id='.$id;
 335      if($more) $xlink .= $sep.$more;
 336    }
 337  
 338    return $xlink;
 339  }
 340  
 341  /**
 342   * Build a link to a media file
 343   *
 344   * Will return a link to the detail page if $direct is false
 345   */
 346  function ml($id='',$more='',$direct=true,$sep='&amp;'){
 347    global $conf;
 348    if(is_array($more)){
 349      $more = buildURLparams($more,$sep);
 350    }else{
 351      $more = str_replace(',',$sep,$more);
 352    }
 353  
 354    $xlink = DOKU_BASE;
 355  
 356    // external URLs are always direct without rewriting
 357    if(preg_match('#^(https?|ftp)://#i',$id)){
 358      $xlink .= 'lib/exe/fetch.php';
 359      if($more){
 360        $xlink .= '?'.$more;
 361        $xlink .= $sep.'media='.rawurlencode($id);
 362      }else{
 363        $xlink .= '?media='.rawurlencode($id);
 364      }
 365      return $xlink;
 366    }
 367  
 368    $id = idfilter($id);
 369  
 370    // decide on scriptname
 371    if($direct){
 372      if($conf['userewrite'] == 1){
 373        $script = '_media';
 374      }else{
 375        $script = 'lib/exe/fetch.php';
 376      }
 377    }else{
 378      if($conf['userewrite'] == 1){
 379        $script = '_detail';
 380      }else{
 381        $script = 'lib/exe/detail.php';
 382      }
 383    }
 384  
 385    // build URL based on rewrite mode
 386     if($conf['userewrite']){
 387       $xlink .= $script.'/'.$id;
 388       if($more) $xlink .= '?'.$more;
 389     }else{
 390       if($more){
 391         $xlink .= $script.'?'.$more;
 392         $xlink .= $sep.'media='.$id;
 393       }else{
 394         $xlink .= $script.'?media='.$id;
 395       }
 396     }
 397  
 398    return $xlink;
 399  }
 400  
 401  
 402  
 403  /**
 404   * Just builds a link to a script
 405   *
 406   * @todo   maybe obsolete
 407   * @author Andreas Gohr <andi@splitbrain.org>
 408   */
 409  function script($script='doku.php'){
 410  #  $link = getBaseURL();
 411  #  $link .= $script;
 412  #  return $link;
 413    return DOKU_BASE.DOKU_SCRIPT;
 414  }
 415  
 416  /**
 417   * Spamcheck against wordlist
 418   *
 419   * Checks the wikitext against a list of blocked expressions
 420   * returns true if the text contains any bad words
 421   *
 422   * @author Andreas Gohr <andi@splitbrain.org>
 423   */
 424  function checkwordblock(){
 425    global $TEXT;
 426    global $conf;
 427  
 428    if(!$conf['usewordblock']) return false;
 429  
 430    // we prepare the text a tiny bit to prevent spammers circumventing URL checks
 431    $text = preg_replace('!(\b)(www\.[\w.:?\-;,]+?\.[\w.:?\-;,]+?[\w/\#~:.?+=&%@\!\-.:?\-;,]+?)([.:?\-;,]*[^\w/\#~:.?+=&%@\!\-.:?\-;,])!i','\1http://\2 \2\3',$TEXT);
 432  
 433    $wordblocks = getWordblocks();
 434    //how many lines to read at once (to work around some PCRE limits)
 435    if(version_compare(phpversion(),'4.3.0','<')){
 436      //old versions of PCRE define a maximum of parenthesises even if no
 437      //backreferences are used - the maximum is 99
 438      //this is very bad performancewise and may even be too high still
 439      $chunksize = 40;
 440    }else{
 441      //read file in chunks of 200 - this should work around the
 442      //MAX_PATTERN_SIZE in modern PCRE
 443      $chunksize = 200;
 444    }
 445    while($blocks = array_splice($wordblocks,0,$chunksize)){
 446      $re = array();
 447      #build regexp from blocks
 448      foreach($blocks as $block){
 449        $block = preg_replace('/#.*$/','',$block);
 450        $block = trim($block);
 451        if(empty($block)) continue;
 452        $re[]  = $block;
 453      }
 454      if(preg_match('#('.join('|',$re).')#si',$text, $match=array())) {
 455        return true;
 456      }
 457    }
 458    return false;
 459  }
 460  
 461  /**
 462   * Return the IP of the client
 463   *
 464   * Honours X-Forwarded-For and X-Real-IP Proxy Headers
 465   *
 466   * It returns a comma separated list of IPs if the above mentioned
 467   * headers are set. If the single parameter is set, it tries to return
 468   * a routable public address, prefering the ones suplied in the X
 469   * headers
 470   *
 471   * @param  boolean $single If set only a single IP is returned
 472   * @author Andreas Gohr <andi@splitbrain.org>
 473   */
 474  function clientIP($single=false){
 475    $ip = array();
 476    $ip[] = $_SERVER['REMOTE_ADDR'];
 477    if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
 478      $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']));
 479    if(!empty($_SERVER['HTTP_X_REAL_IP']))
 480      $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_REAL_IP']));
 481  
 482    // remove any non-IP stuff
 483    $cnt = count($ip);
 484    $match = array();
 485    for($i=0; $i<$cnt; $i++){
 486      if(preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/',$ip[$i],$match)) {
 487        $ip[$i] = $match[0];
 488      } else {
 489        $ip[$i] = '';
 490      }
 491      if(empty($ip[$i])) unset($ip[$i]);
 492    }
 493    $ip = array_values(array_unique($ip));
 494    if(!$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP
 495  
 496    if(!$single) return join(',',$ip);
 497  
 498    // decide which IP to use, trying to avoid local addresses
 499    $ip = array_reverse($ip);
 500    foreach($ip as $i){
 501      if(preg_match('/^(127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$i)){
 502        continue;
 503      }else{
 504        return $i;
 505      }
 506    }
 507    // still here? just use the first (last) address
 508    return $ip[0];
 509  }
 510  
 511  /**
 512   * Checks if a given page is currently locked.
 513   *
 514   * removes stale lockfiles
 515   *
 516   * @author Andreas Gohr <andi@splitbrain.org>
 517   */
 518  function checklock($id){
 519    global $conf;
 520    $lock = wikiLockFN($id);
 521  
 522    //no lockfile
 523    if(!@file_exists($lock)) return false;
 524  
 525    //lockfile expired
 526    if((time() - filemtime($lock)) > $conf['locktime']){
 527      @unlink($lock);
 528      return false;
 529    }
 530  
 531    //my own lock
 532    $ip = io_readFile($lock);
 533    if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
 534      return false;
 535    }
 536  
 537    return $ip;
 538  }
 539  
 540  /**
 541   * Lock a page for editing
 542   *
 543   * @author Andreas Gohr <andi@splitbrain.org>
 544   */
 545  function lock($id){
 546    $lock = wikiLockFN($id);
 547    if($_SERVER['REMOTE_USER']){
 548      io_saveFile($lock,$_SERVER['REMOTE_USER']);
 549    }else{
 550      io_saveFile($lock,clientIP());
 551    }
 552  }
 553  
 554  /**
 555   * Unlock a page if it was locked by the user
 556   *
 557   * @author Andreas Gohr <andi@splitbrain.org>
 558   * @return bool true if a lock was removed
 559   */
 560  function unlock($id){
 561    $lock = wikiLockFN($id);
 562    if(@file_exists($lock)){
 563      $ip = io_readFile($lock);
 564      if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
 565        @unlink($lock);
 566        return true;
 567      }
 568    }
 569    return false;
 570  }
 571  
 572  /**
 573   * convert line ending to unix format
 574   *
 575   * @see    formText() for 2crlf conversion
 576   * @author Andreas Gohr <andi@splitbrain.org>
 577   */
 578  function cleanText($text){
 579    $text = preg_replace("/(\015\012)|(\015)/","\012",$text);
 580    return $text;
 581  }
 582  
 583  /**
 584   * Prepares text for print in Webforms by encoding special chars.
 585   * It also converts line endings to Windows format which is
 586   * pseudo standard for webforms.
 587   *
 588   * @see    cleanText() for 2unix conversion
 589   * @author Andreas Gohr <andi@splitbrain.org>
 590   */
 591  function formText($text){
 592    $text = preg_replace("/\012/","\015\012",$text);
 593    return htmlspecialchars($text);
 594  }
 595  
 596  /**
 597   * Returns the specified local text in raw format
 598   *
 599   * @author Andreas Gohr <andi@splitbrain.org>
 600   */
 601  function rawLocale($id){
 602    return io_readFile(localeFN($id));
 603  }
 604  
 605  /**
 606   * Returns the raw WikiText
 607   *
 608   * @author Andreas Gohr <andi@splitbrain.org>
 609   */
 610  function rawWiki($id,$rev=''){
 611    return io_readWikiPage(wikiFN($id, $rev), $id, $rev);
 612  }
 613  
 614  /**
 615   * Returns the pagetemplate contents for the ID's namespace
 616   *
 617   * @author Andreas Gohr <andi@splitbrain.org>
 618   */
 619  function pageTemplate($data){
 620    $id = $data[0];
 621    global $conf;
 622    global $INFO;
 623    $tpl = io_readFile(dirname(wikiFN($id)).'/_template.txt');
 624    $tpl = str_replace('@ID@',$id,$tpl);
 625    $tpl = str_replace('@NS@',getNS($id),$tpl);
 626    $tpl = str_replace('@PAGE@',strtr(noNS($id),'_',' '),$tpl);
 627    $tpl = str_replace('@USER@',$_SERVER['REMOTE_USER'],$tpl);
 628    $tpl = str_replace('@NAME@',$INFO['userinfo']['name'],$tpl);
 629    $tpl = str_replace('@MAIL@',$INFO['userinfo']['mail'],$tpl);
 630    $tpl = str_replace('@DATE@',date($conf['dformat']),$tpl);
 631    return $tpl;
 632  }
 633  
 634  
 635  /**
 636   * Returns the raw Wiki Text in three slices.
 637   *
 638   * The range parameter needs to have the form "from-to"
 639   * and gives the range of the section in bytes - no
 640   * UTF-8 awareness is needed.
 641   * The returned order is prefix, section and suffix.
 642   *
 643   * @author Andreas Gohr <andi@splitbrain.org>
 644   */
 645  function rawWikiSlices($range,$id,$rev=''){
 646    list($from,$to) = split('-',$range,2);
 647    $text = io_readWikiPage(wikiFN($id, $rev), $id, $rev);
 648    if(!$from) $from = 0;
 649    if(!$to)   $to   = strlen($text)+1;
 650  
 651    $slices[0] = substr($text,0,$from-1);
 652    $slices[1] = substr($text,$from-1,$to-$from);
 653    $slices[2] = substr($text,$to);
 654  
 655    return $slices;
 656  }
 657  
 658  /**
 659   * Joins wiki text slices
 660   *
 661   * function to join the text slices with correct lineendings again.
 662   * When the pretty parameter is set to true it adds additional empty
 663   * lines between sections if needed (used on saving).
 664   *
 665   * @author Andreas Gohr <andi@splitbrain.org>
 666   */
 667  function con($pre,$text,$suf,$pretty=false){
 668  
 669    if($pretty){
 670      if($pre && substr($pre,-1) != "\n") $pre .= "\n";
 671      if($suf && substr($text,-1) != "\n") $text .= "\n";
 672    }
 673  
 674    if($pre) $pre .= "\n";
 675    if($suf) $text .= "\n";
 676    return $pre.$text.$suf;
 677  }
 678  
 679  /**
 680   * Saves a wikitext by calling io_writeWikiPage.
 681   * Also directs changelog and attic updates.
 682   *
 683   * @author Andreas Gohr <andi@splitbrain.org>
 684   * @author Ben Coburn <btcoburn@silicodon.net>
 685   */
 686  function saveWikiText($id,$text,$summary,$minor=false){
 687    /* Note to developers:
 688       This code is subtle and delicate. Test the behavior of
 689       the attic and changelog with dokuwiki and external edits
 690       after any changes. External edits change the wiki page
 691       directly without using php or dokuwiki.
 692    */
 693    global $conf;
 694    global $lang;
 695    global $REV;
 696    // ignore if no changes were made
 697    if($text == rawWiki($id,'')){
 698      return;
 699    }
 700  
 701    $file = wikiFN($id);
 702    $old = @filemtime($file); // from page
 703    $wasRemoved = empty($text);
 704    $wasCreated = !@file_exists($file);
 705    $wasReverted = ($REV==true);
 706    $newRev = false;
 707    $oldRev = getRevisions($id, -1, 1, 1024); // from changelog
 708    $oldRev = (int)(empty($oldRev)?0:$oldRev[0]);
 709    if(!@file_exists(wikiFN($id, $old)) && @file_exists($file) && $old>=$oldRev) {
 710      // add old revision to the attic if missing
 711      saveOldRevision($id);
 712      // add a changelog entry if this edit came from outside dokuwiki
 713      if ($old>$oldRev) {
 714        addLogEntry($old, $id);
 715        // send notify mails
 716        notify($id,'admin',$oldRev,'',false);
 717        notify($id,'subscribers',$oldRev,'',false);
 718        // remove soon to be stale instructions
 719        $cache = new cache_instructions($id, $file);
 720        $cache->removeCache();
 721      }
 722    }
 723  
 724    if ($wasRemoved){
 725      // pre-save deleted revision
 726      @touch($file);
 727      clearstatcache();
 728      $newRev = saveOldRevision($id);
 729      // remove empty file
 730      @unlink($file);
 731      // remove old meta info...
 732      $mfiles = metaFiles($id);
 733      $changelog = metaFN($id, '.changes');
 734      foreach ($mfiles as $mfile) {
 735        // but keep per-page changelog to preserve page history
 736        if (@file_exists($mfile) && $mfile!==$changelog) { @unlink($mfile); }
 737      }
 738      $del = true;
 739      // autoset summary on deletion
 740      if(empty($summary)) $summary = $lang['deleted'];
 741      // remove empty namespaces
 742      io_sweepNS($id, 'datadir');
 743      io_sweepNS($id, 'mediadir');
 744    }else{
 745      // save file (namespace dir is created in io_writeWikiPage)
 746      io_writeWikiPage($file, $text, $id);
 747      // pre-save the revision, to keep the attic in sync
 748      $newRev = saveOldRevision($id);
 749      $del = false;
 750    }
 751  
 752    // select changelog line type
 753    $extra = '';
 754    $type = 'E';
 755    if ($wasReverted) {
 756      $type = 'R';
 757      $extra = $REV;
 758    }
 759    else if ($wasCreated) { $type = 'C'; }
 760    else if ($wasRemoved) { $type = 'D'; }
 761    else if ($minor && $conf['useacl'] && $_SERVER['REMOTE_USER']) { $type = 'e'; } //minor edits only for logged in users
 762  
 763    addLogEntry($newRev, $id, $type, $summary, $extra);
 764    // send notify mails
 765    notify($id,'admin',$old,$summary,$minor);
 766    notify($id,'subscribers',$old,$summary,$minor);
 767  
 768    // update the purgefile (timestamp of the last time anything within the wiki was changed)
 769    io_saveFile($conf['cachedir'].'/purgefile',time());
 770  }
 771  
 772  /**
 773   * moves the current version to the attic and returns its
 774   * revision date
 775   *
 776   * @author Andreas Gohr <andi@splitbrain.org>
 777   */
 778  function saveOldRevision($id){
 779    global $conf;
 780    $oldf = wikiFN($id);
 781    if(!@file_exists($oldf)) return '';
 782    $date = filemtime($oldf);
 783    $newf = wikiFN($id,$date);
 784    io_writeWikiPage($newf, rawWiki($id), $id, $date);
 785    return $date;
 786  }
 787  
 788  /**
 789   * Sends a notify mail on page change
 790   *
 791   * @param  string  $id       The changed page
 792   * @param  string  $who      Who to notify (admin|subscribers)
 793   * @param  int     $rev      Old page revision
 794   * @param  string  $summary  What changed
 795   * @param  boolean $minor    Is this a minor edit?
 796   * @param  array   $replace  Additional string substitutions, @KEY@ to be replaced by value
 797   *
 798   * @author Andreas Gohr <andi@splitbrain.org>
 799   */
 800  function notify($id,$who,$rev='',$summary='',$minor=false,$replace=array()){
 801    global $lang;
 802    global $conf;
 803  
 804    // decide if there is something to do
 805    if($who == 'admin'){
 806      if(empty($conf['notify'])) return; //notify enabled?
 807      $text = rawLocale('mailtext');
 808      $to   = $conf['notify'];
 809      $bcc  = '';
 810    }elseif($who == 'subscribers'){
 811      if(!$conf['subscribers']) return; //subscribers enabled?
 812      if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return; //skip minors
 813      $bcc  = subscriber_addresslist($id);
 814      if(empty($bcc)) return;
 815      $to   = '';
 816      $text = rawLocale('subscribermail');
 817    }elseif($who == 'register'){
 818      if(empty($conf['registernotify'])) return;
 819      $text = rawLocale('registermail');
 820      $to   = $conf['registernotify'];
 821      $bcc  = '';
 822    }else{
 823      return; //just to be safe
 824    }
 825  
 826    $text = str_replace('@DATE@',date($conf['dformat']),$text);
 827    $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text);
 828    $text = str_replace('@IPADDRESS@',$_SERVER['REMOTE_ADDR'],$text);
 829    $text = str_replace('@HOSTNAME@',gethostbyaddr($_SERVER['REMOTE_ADDR']),$text);
 830    $text = str_replace('@NEWPAGE@',wl($id,'',true),$text);
 831    $text = str_replace('@PAGE@',$id,$text);
 832    $text = str_replace('@TITLE@',$conf['title'],$text);
 833    $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text);
 834    $text = str_replace('@SUMMARY@',$summary,$text);
 835    $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text);
 836  
 837    foreach ($replace as $key => $substitution) {
 838      $text = str_replace('@'.strtoupper($key).'@',$substitution, $text);
 839    }
 840  
 841    if($who == 'register'){
 842      $subject = $lang['mail_new_user'].' '.$summary;
 843    }elseif($rev){
 844      $subject = $lang['mail_changed'].' '.$id;
 845      $text = str_replace('@OLDPAGE@',wl($id,"rev=$rev",true),$text);
 846      require_once (DOKU_INC.'inc/DifferenceEngine.php');
 847      $df  = new Diff(split("\n",rawWiki($id,$rev)),
 848                      split("\n",rawWiki($id)));
 849      $dformat = new UnifiedDiffFormatter();
 850      $diff    = $dformat->format($df);
 851    }else{
 852      $subject=$lang['mail_newpage'].' '.$id;
 853      $text = str_replace('@OLDPAGE@','none',$text);
 854      $diff = rawWiki($id);
 855    }
 856    $text = str_replace('@DIFF@',$diff,$text);
 857    $subject = '['.$conf['title'].'] '.$subject;
 858  
 859    mail_send($to,$subject,$text,$conf['mailfrom'],'',$bcc);
 860  }
 861  
 862  /**
 863   * extracts the query from a google referer
 864   *
 865   * @todo   should be more generic and support yahoo et al
 866   * @author Andreas Gohr <andi@splitbrain.org>
 867   */
 868  function getGoogleQuery(){
 869    $url = parse_url($_SERVER['HTTP_REFERER']);
 870    if(!$url) return '';
 871  
 872    if(!preg_match("#google\.#i",$url['host'])) return '';
 873    $query = array();
 874    parse_str($url['query'],$query);
 875  
 876    return $query['q'];
 877  }
 878  
 879  /**
 880   * Try to set correct locale
 881   *
 882   * @deprecated No longer used
 883   * @author     Andreas Gohr <andi@splitbrain.org>
 884   */
 885  function setCorrectLocale(){
 886    global $conf;
 887    global $lang;
 888  
 889    $enc = strtoupper($lang['encoding']);
 890    foreach ($lang['locales'] as $loc){
 891      //try locale
 892      if(@setlocale(LC_ALL,$loc)) return;
 893      //try loceale with encoding
 894      if(@setlocale(LC_ALL,"$loc.$enc")) return;
 895    }
 896    //still here? try to set from environment
 897    @setlocale(LC_ALL,"");
 898  }
 899  
 900  /**
 901   * Return the human readable size of a file
 902   *
 903   * @param       int    $size   A file size
 904   * @param       int    $dec    A number of decimal places
 905   * @author      Martin Benjamin <b.martin@cybernet.ch>
 906   * @author      Aidan Lister <aidan@php.net>
 907   * @version     1.0.0
 908   */
 909  function filesize_h($size, $dec = 1){
 910    $sizes = array('B', 'KB', 'MB', 'GB');
 911    $count = count($sizes);
 912    $i = 0;
 913  
 914    while ($size >= 1024 && ($i < $count - 1)) {
 915      $size /= 1024;
 916      $i++;
 917    }
 918  
 919    return round($size, $dec) . ' ' . $sizes[$i];
 920  }
 921  
 922  /**
 923   * return an obfuscated email address in line with $conf['mailguard'] setting
 924   *
 925   * @author Harry Fuecks <hfuecks@gmail.com>
 926   * @author Christopher Smith <chris@jalakai.co.uk>
 927   */
 928  function obfuscate($email) {
 929    global $conf;
 930  
 931    switch ($conf['mailguard']) {
 932      case 'visible' :
 933        $obfuscate = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
 934        return strtr($email, $obfuscate);
 935  
 936      case 'hex' :
 937        $encode = '';
 938        for ($x=0; $x < strlen($email); $x++) $encode .= '&#x' . bin2hex($email{$x}).';';
 939        return $encode;
 940  
 941      case 'none' :
 942      default :
 943        return $email;
 944    }
 945  }
 946  
 947  /**
 948   * Let us know if a user is tracking a page
 949   *
 950   * @author Andreas Gohr <andi@splitbrain.org>
 951   */
 952  function is_subscribed($id,$uid){
 953    $file=metaFN($id,'.mlist');
 954    if (@file_exists($file)) {
 955      $mlist = file($file);
 956      $pos = array_search($uid."\n",$mlist);
 957      return is_int($pos);
 958    }
 959  
 960    return false;
 961  }
 962  
 963  /**
 964   * Return a string with the email addresses of all the
 965   * users subscribed to a page
 966   *
 967   * @author Steven Danz <steven-danz@kc.rr.com>
 968   */
 969  function subscriber_addresslist($id){
 970    global $conf;
 971    global $auth;
 972  
 973    $emails = '';
 974  
 975    if (!$conf['subscribers']) return;
 976  
 977    $mlist = array();
 978    $file=metaFN($id,'.mlist');
 979    if (@file_exists($file)) {
 980      $mlist = file($file);
 981    }
 982    if(count($mlist) > 0) {
 983      foreach ($mlist as $who) {
 984        $who = rtrim($who);
 985        $info = $auth->getUserData($who);
 986        $level = auth_aclcheck($id,$who,$info['grps']);
 987        if ($level >= AUTH_READ) {
 988          if (strcasecmp($info['mail'],$conf['notify']) != 0) {
 989            if (empty($emails)) {
 990              $emails = $info['mail'];
 991            } else {
 992              $emails = "$emails,".$info['mail'];
 993            }
 994          }
 995        }
 996      }
 997    }
 998  
 999    return $emails;
1000  }
1001  
1002  /**
1003   * Removes quoting backslashes
1004   *
1005   * @author Andreas Gohr <andi@splitbrain.org>
1006   */
1007  function unslash($string,$char="'"){
1008    return str_replace('\\'.$char,$char,$string);
1009  }
1010  
1011  //Setup VIM: ex: et ts=2 enc=utf-8 :


Généré le : Tue Apr 3 20:47:31 2007 par Balluche grâce à PHPXref 0.7