From 49eb6e38061d744f4a35b78082dce49fa35f79c8 Mon Sep 17 00:00:00 2001
From: Andreas Gohr <andi@splitbrain.org>
Date: Fri, 15 Jan 2010 19:50:13 +0100
Subject: [PATCH] some more coding standard compliance updates

---
 feed.php             |    2 +-
 inc/HTTPClient.php   |    1 -
 inc/IXR_Library.php  |   15 +-
 inc/TarLib.class.php | 1547 ++++++++++++++++++------------------
 inc/actions.php      |  830 +++++++++----------
 inc/cache.php        |  448 +++++------
 inc/changelog.php    |  611 +++++++-------
 inc/cliopts.php      |   37 +-
 inc/common.php       | 1792 +++++++++++++++++++++---------------------
 inc/confutils.php    |  297 +++----
 inc/events.php       |  320 ++++----
 inc/form.php         |    4 +-
 inc/fulltext.php     |  178 ++---
 install.php          |   25 +-
 14 files changed, 3027 insertions(+), 3080 deletions(-)

diff --git a/feed.php b/feed.php
index e7ea5808c..0ad1c2c30 100644
--- a/feed.php
+++ b/feed.php
@@ -25,7 +25,7 @@ $opt = rss_parseOptions();
 // the feed is dynamic - we need a cache for each combo
 // (but most people just use the default feed so it's still effective)
 $cache = getCacheName(join('',array_values($opt)).$_SERVER['REMOTE_USER'],'.feed');
-$key   = join('', array_values($opt)) . $_SERVER['REMOTE_USER']; 
+$key   = join('', array_values($opt)) . $_SERVER['REMOTE_USER'];
 $cache = new cache($key, '.feed');
 
 // prepare cache depends
diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index 578d7e7cd..c88d1c45d 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -279,7 +279,6 @@ class HTTPClient {
             $written += $ret;
         }
 
-
         // read headers from socket
         $r_headers = '';
         do{
diff --git a/inc/IXR_Library.php b/inc/IXR_Library.php
index 2752e31f2..25d1066b0 100644
--- a/inc/IXR_Library.php
+++ b/inc/IXR_Library.php
@@ -300,7 +300,7 @@ class IXR_Server {
         if (!$data) {
             global $HTTP_RAW_POST_DATA;
             if (!$HTTP_RAW_POST_DATA) {
-               die('XML-RPC server accepts POST requests only.');
+                die('XML-RPC server accepts POST requests only.');
             }
             $data = $HTTP_RAW_POST_DATA;
         }
@@ -342,14 +342,13 @@ EOD;
         $method = $this->callbacks[$methodname];
         // Perform the callback and send the response
 
-# Removed for DokuWiki to have a more consistent interface
-#        if (count($args) == 1) {
-#            // If only one paramater just send that instead of the whole array
-#            $args = $args[0];
-#        }
+        # Removed for DokuWiki to have a more consistent interface
+        #        if (count($args) == 1) {
+        #            // If only one paramater just send that instead of the whole array
+        #            $args = $args[0];
+        #        }
 
-
-# Adjusted for DokuWiki to use call_user_func_array
+        # Adjusted for DokuWiki to use call_user_func_array
 
         // args need to be an array
         $args = (array) $args;
diff --git a/inc/TarLib.class.php b/inc/TarLib.class.php
index ab802163b..3c1827554 100644
--- a/inc/TarLib.class.php
+++ b/inc/TarLib.class.php
@@ -59,860 +59,803 @@ define('ARCHIVE_DYNAMIC',0);
 define('ARCHIVE_RENAMECOMP',5);
 define('COMPRESS_DETECT',-1);
 
-class TarLib
-{
-  var $_comptype;
-  var $_compzlevel;
-  var $_fp;
-  var $_memdat;
-  var $_nomf;
-  var $_result;
-  var $_initerror;
-
-  /**
-   * constructor, initialize the class
-   *
-   * The constructor initialize the variables and prepare the class for the
-   * archive, and return the object created. Note that you can use multiple
-   * instances of the MaxgTar class, if you call this function another time and
-   * store the object in an other variable.
-   *
-   * In fact, MaxgTar accepts the following arguments (all are optional) :
-   *
-   * filename can be either a file name (absolute or relative). In this
-   * case, it can be used both for reading and writing. You can also open
-   * remote archive if you add a protocole name at the beginning of the file
-   * (ie https://host.dom/archive.tar.gz), but for reading only and if the
-   * directive allow_url_fopen is enabled in PHP.INI (this can be checked with
-   * TarInfo()). If you pass a file that doesn't exist, the script
-   * will try to create it. If the archive already exists and contains files,
-   * you can use Add() to append files.But by default this parameter
-   * is ARCHIVE_DYNAMIC (write only) so the archive is created in memory and
-   * can be sent to a file [writeArchive()] or to the client
-   * [sendClient()]
-   *
-   * compression_type should be a constant that represents a type of
-   * compression, or its integer value. The different values are described in
-   * the constants.
-   *
-   * compression_level is an integer between 1 and 9 (by default) an
-   * represent the GZIP or BZIP compression level.  1 produce fast compression,
-   * and 9 produce smaller files. See the RFC 1952 for more infos.
-   */
-  function tarlib($p_filen = ARCHIVE_DYNAMIC , $p_comptype = COMPRESS_AUTO, $p_complevel = 9)
-  {
-    $this->_initerror = 0;
-    $this->_nomf = $p_filen; $flag=0;
-    if($p_comptype && $p_comptype % 5 == 0){$p_comptype /= ARCHIVE_RENAMECOMP; $flag=1;}
-
-    if($p_complevel > 0 && $p_complevel <= 9) $this->_compzlevel = $p_complevel;
-    else $p_complevel = 9;
-
-    if($p_comptype == COMPRESS_DETECT)
-    {
-      if(strtolower(substr($p_filen,-3)) == '.gz') $p_comptype = COMPRESS_GZIP;
-      elseif(strtolower(substr($p_filen,-4)) == '.bz2') $p_comptype = COMPRESS_BZIP;
-      else $p_comptype = COMPRESS_NONE;
-    }
+class TarLib {
+    var $_comptype;
+    var $_compzlevel;
+    var $_fp;
+    var $_memdat;
+    var $_nomf;
+    var $_result;
+    var $_initerror;
+
+    /**
+     * constructor, initialize the class
+     *
+     * The constructor initialize the variables and prepare the class for the
+     * archive, and return the object created. Note that you can use multiple
+     * instances of the MaxgTar class, if you call this function another time and
+     * store the object in an other variable.
+     *
+     * In fact, MaxgTar accepts the following arguments (all are optional) :
+     *
+     * filename can be either a file name (absolute or relative). In this
+     * case, it can be used both for reading and writing. You can also open
+     * remote archive if you add a protocole name at the beginning of the file
+     * (ie https://host.dom/archive.tar.gz), but for reading only and if the
+     * directive allow_url_fopen is enabled in PHP.INI (this can be checked with
+     * TarInfo()). If you pass a file that doesn't exist, the script
+     * will try to create it. If the archive already exists and contains files,
+     * you can use Add() to append files.But by default this parameter
+     * is ARCHIVE_DYNAMIC (write only) so the archive is created in memory and
+     * can be sent to a file [writeArchive()] or to the client
+     * [sendClient()]
+     *
+     * compression_type should be a constant that represents a type of
+     * compression, or its integer value. The different values are described in
+     * the constants.
+     *
+     * compression_level is an integer between 1 and 9 (by default) an
+     * represent the GZIP or BZIP compression level.  1 produce fast compression,
+     * and 9 produce smaller files. See the RFC 1952 for more infos.
+     */
+    function tarlib($p_filen = ARCHIVE_DYNAMIC , $p_comptype = COMPRESS_AUTO, $p_complevel = 9) {
+        $this->_initerror = 0;
+        $this->_nomf = $p_filen;
+        $flag=0;
+        if($p_comptype && $p_comptype % 5 == 0){
+            $p_comptype /= ARCHIVE_RENAMECOMP;
+            $flag=1;
+        }
 
-    switch($p_comptype)
-    {
-      case COMPRESS_GZIP:
-        if(!extension_loaded('zlib')) $this->_initerror = -1;
-        $this->_comptype = COMPRESS_GZIP;
-      break;
-
-      case COMPRESS_BZIP:
-        if(!extension_loaded('bz2')) $this->_inierror = -2;
-        $this->_comptype = COMPRESS_BZIP;
-      break;
-
-      case COMPRESS_AUTO:
-        if(extension_loaded('zlib'))
-          $this->_comptype = COMPRESS_GZIP;
-        elseif(extension_loaded('bz2'))
-          $this->_comptype = COMPRESS_BZIP;
-        else
-          $this->_comptype = COMPRESS_NONE;
-      break;
+        if($p_complevel > 0 && $p_complevel <= 9) $this->_compzlevel = $p_complevel;
+        else $p_complevel = 9;
 
-      default:
-        $this->_comptype = COMPRESS_NONE;
+        if($p_comptype == COMPRESS_DETECT) {
+            if(strtolower(substr($p_filen,-3)) == '.gz') $p_comptype = COMPRESS_GZIP;
+            elseif(strtolower(substr($p_filen,-4)) == '.bz2') $p_comptype = COMPRESS_BZIP;
+            else $p_comptype = COMPRESS_NONE;
+        }
+
+        switch($p_comptype) {
+            case COMPRESS_GZIP:
+                if(!extension_loaded('zlib')) $this->_initerror = -1;
+                $this->_comptype = COMPRESS_GZIP;
+                break;
+
+            case COMPRESS_BZIP:
+                if(!extension_loaded('bz2')) $this->_inierror = -2;
+                $this->_comptype = COMPRESS_BZIP;
+                break;
+
+            case COMPRESS_AUTO:
+                if(extension_loaded('zlib'))
+                    $this->_comptype = COMPRESS_GZIP;
+                elseif(extension_loaded('bz2'))
+                    $this->_comptype = COMPRESS_BZIP;
+                else
+                    $this->_comptype = COMPRESS_NONE;
+                break;
+
+            default:
+                $this->_comptype = COMPRESS_NONE;
+        }
+
+        if($this->_init_error < 0) $this->_comptype = COMPRESS_NONE;
+
+        if($flag) $this->_nomf.= '.'.$this->getCompression(1);
+        $this->_result = true;
     }
 
-    if($this->_init_error < 0) $this->_comptype = COMPRESS_NONE;
-
-    if($flag) $this->_nomf.= '.'.$this->getCompression(1);
-    $this->_result = true;
-  }
-
-  /**
-   * Recycle a TAR object.
-   *
-   * This function does exactly the same as TarLib (constructor), except it
-   * returns a status code.
-   */
-  function setArchive($p_name='', $p_comp = COMPRESS_AUTO, $p_level=9)
-  {
-    $this->_CompTar();
-    $this->TarLib($p_name, $p_comp, $p_level);
-    return $this->_result;
-  }
-
-  /**
-   * Get the compression used to generate the archive
-   *
-   * This is a very useful function when you're using dynamical archives.
-   * Besides, if you let the script chose which compression to use, you'll have
-   * a problem when you'll want to send it to the client if you don't know
-   * which compression was used.
-   *
-   * There are two ways to call this function : if you call it without argument
-   * or with FALSE, it will return the compression constants, explained on the
-   * MaxgTar Constants.  If you call it with GetExtension on TRUE it will
-   * return the extension without starting dot (ie "tar" or "tar.bz2" or
-   * "tar.gz")
-   *
-   * NOTE: This can be done with the flag ARCHIVE_RENAMECOMP, see the
-   * MaxgTar Constants
-   */
-  function getCompression($ext = false)
-  {
-    $exts = Array('tar','tar.gz','tar.bz2');
-    if($ext) return $exts[$this->_comptype];
-    return $this->_comptype;
-  }
-
-  /**
-   * Change the compression mode.
-   *
-   * This function will change the compression methode to read or write
-   * the archive. See the MaxgTar Constants to see which constants you can use.
-   * It may look strange, but it returns the GZIP compression level.
-   */
-  function setCompression($p_comp = COMPRESS_AUTO)
-  {
-    $this->setArchive($this->_nomf, $p_comp, $this->_compzlevel);
-    return $this->_compzlevel;
-  }
-
-  /**
-   * Returns the compressed dynamic archive.
-   *
-   * When you're working with dynamic archives, use this function to grab
-   * the final compressed archive in a string ready to be put in a SQL table or
-   * in a file.
-   */
-  function getDynamicArchive()
-  {
-    return $this->_encode($this->_memdat);
-  }
-
-  /**
-   * Write a dynamical archive into a file
-   *
-   * This function attempts to write a dynamicaly-genrated archive into
-   * TargetFile on the webserver.  It returns a TarErrorStr() status
-   * code.
-   *
-   * To know the extension to add to the file if you're using AUTO_DETECT
-   * compression, you can use getCompression().
-   */
-  function writeArchive($p_archive) {
-    if(!$this->_memdat) return -7;
-    $fp = @fopen($p_archive, 'wb');
-    if(!$fp) return -6;
-
-    fwrite($fp, $this->_memdat);
-    fclose($fp);
-
-    return true;
-  }
-
-  /**
-   * Send a TAR archive to the client browser.
-   *
-   * This function will send an archive to the client, and return a status
-   * code, but can behave differently depending on the arguments you give. All
-   * arguments are optional.
-   *
-   * ClientName is used to specify the archive name to give to the browser. If
-   * you don't give one, it will send the constructor filename or return an
-   * error code in case of dynamical archive.
-   *
-   * FileName is optional and used to send a specific archive. Leave it blank
-   * to send dynamical archives or the current working archive.
-   *
-   * If SendHeaders is enabled (by default), the library will send the HTTP
-   * headers itself before it sends the contents. This headers are :
-   * Content-Type, Content-Disposition, Content-Length and Accept-Range.
-   *
-   * Please note that this function DOES NOT stops the script so don't forget
-   * to exit() to avoid your script sending other data and corrupt the archive.
-   * Another note : for AUTO_DETECT dynamical archives you can know the
-   * extension to add to the name with getCompression()
-   */
-  function sendClient($name = '', $archive = '', $headers = true)
-  {
-    if(!$name && !$this->_nomf) return -9;
-    if(!$archive && !$this->_memdat) return -10;
-    if(!$name) $name = basename($this->_nomf);
-
-    if($archive){ if(!file_exists($archive)) return -11; }
-    else $decoded = $this->getDynamicArchive();
-
-    if($headers)
-    {
-      header('Content-Type: application/x-gtar');
-      header('Content-Disposition: attachment; filename='.basename($name));
-      header('Accept-Ranges: bytes');
-      header('Content-Length: '.($archive ? filesize($archive) : strlen($decoded)));
+    /**
+     * Recycle a TAR object.
+     *
+     * This function does exactly the same as TarLib (constructor), except it
+     * returns a status code.
+     */
+    function setArchive($p_name='', $p_comp = COMPRESS_AUTO, $p_level=9) {
+        $this->_CompTar();
+        $this->TarLib($p_name, $p_comp, $p_level);
+        return $this->_result;
     }
 
-    if($archive)
-    {
-      $fp = @fopen($archive,'rb');
-      if(!$fp) return -4;
+    /**
+     * Get the compression used to generate the archive
+     *
+     * This is a very useful function when you're using dynamical archives.
+     * Besides, if you let the script chose which compression to use, you'll have
+     * a problem when you'll want to send it to the client if you don't know
+     * which compression was used.
+     *
+     * There are two ways to call this function : if you call it without argument
+     * or with FALSE, it will return the compression constants, explained on the
+     * MaxgTar Constants.  If you call it with GetExtension on TRUE it will
+     * return the extension without starting dot (ie "tar" or "tar.bz2" or
+     * "tar.gz")
+     *
+     * NOTE: This can be done with the flag ARCHIVE_RENAMECOMP, see the
+     * MaxgTar Constants
+     */
+    function getCompression($ext = false) {
+        $exts = Array('tar','tar.gz','tar.bz2');
+        if($ext) return $exts[$this->_comptype];
+        return $this->_comptype;
+    }
 
-      while(!feof($fp)) echo fread($fp,2048);
+    /**
+     * Change the compression mode.
+     *
+     * This function will change the compression methode to read or write
+     * the archive. See the MaxgTar Constants to see which constants you can use.
+     * It may look strange, but it returns the GZIP compression level.
+     */
+    function setCompression($p_comp = COMPRESS_AUTO) {
+        $this->setArchive($this->_nomf, $p_comp, $this->_compzlevel);
+        return $this->_compzlevel;
     }
-    else
-    {
-      echo $decoded;
+
+    /**
+     * Returns the compressed dynamic archive.
+     *
+     * When you're working with dynamic archives, use this function to grab
+     * the final compressed archive in a string ready to be put in a SQL table or
+     * in a file.
+     */
+    function getDynamicArchive() {
+        return $this->_encode($this->_memdat);
     }
 
-    return true;
-  }
-
-  /**
-   * Extract part or totality of the archive.
-   *
-   * This function can extract files from an archive, and returns then a
-   * status codes that can be converted with TarErrorStr() into a
-   * human readable message.
-   *
-   * Only the first argument is required, What and it can be either the
-   * constant FULL_ARCHIVE or an indexed array containing each file you want to
-   * extract.
-   *
-   * To contains the target folder to extract the archive. It is optional and
-   * the default value is '.' which means the current folder. If the target
-   * folder doesn't exist, the script attempts to create it and give it
-   * permissions 0777 by default.
-   *
-   * RemovePath is very usefull when you want to extract files from a subfoler
-   * in the archive to a root folder. For instance, if you have a file in the
-   * archive called some/sub/folder/test.txt and you want to extract it to the
-   * script folder, you can call Extract with To = '.' and RemovePath =
-   * 'some/sub/folder/'
-   *
-   * FileMode is optional and its default value is 0755. It is in fact the UNIX
-   * permission in octal mode (prefixed with a 0) that will be given on each
-   * extracted file.
-   */
-  function Extract($p_what = FULL_ARCHIVE, $p_to = '.', $p_remdir='', $p_mode = 0755)
-  {
-    if(!$this->_OpenRead()) return -4;
-//  if(!@is_dir($p_to)) if(!@mkdir($p_to, 0777)) return -8;   --CS
-    if(!@is_dir($p_to)) if(!$this->_dirApp($p_to)) return -8;   //--CS (route through correct dir fn)
-
-    $ok = $this->_extractList($p_to, $p_what, $p_remdir, $p_mode);
-    $this->_CompTar();
-
-    return $ok;
-  }
-
-  /**
-   * Create a new package with the given files
-   *
-   * This function will attempt to create a new archive with global headers
-   * then add the given files into.  If the archive is a real file, the
-   * contents are written directly into the file, if it is a dynamic archive
-   * contents are only stored in memory. This function should not be used to
-   * add files to an existing archive, you should use Add() instead.
-   *
-   * The FileList actually supports three different modes :
-   *
-   * - You can pass a string containing filenames separated by pipes '|'.
-   *   In this case the file are read from the webserver filesystem and the
-   *   root folder is the folder where the script using the MaxgTar is called.
-   *
-   * - You can also give a unidimensional indexed array containing the
-   *   filenames. The behaviour for the content reading is the same that a
-   *   '|'ed string.
-   *
-   * - The more useful usage is to pass bidimensional arrays, where the
-   *   first element contains the filename and the second contains the file
-   *   contents. You can even add empty folders to the package if the filename
-   *   has a leading '/'. Once again, have a look at the exemples to understand
-   *   better.
-   *
-   * Note you can also give arrays with both dynamic contents and static files.
-   *
-   * The optional parameter RemovePath can be used to delete a part of the tree
-   * of the filename you're adding, for instance if you're adding in the root
-   * of a package a file that is stored somewhere in the server tree.
-   *
-   * On the contrary the parameter AddPath can be used to add a prefix folder
-   * to the file you store. Note also that the RemovePath is applied before the
-   * AddPath is added, so it HAS a sense to use both parameters together.
-   */
-  function Create($p_filelist,$p_add='',$p_rem='')
-  {
-    if(!$fl = $this->_fetchFilelist($p_filelist)) return -5;
-    if(!$this->_OpenWrite()) return -6;
-
-    $ok = $this->_addFileList($fl,$p_add,$p_rem);
-
-    if($ok) $this->_writeFooter();
-    else{ $this->_CompTar(); @unlink($this->_nomf); }
-
-    return $ok;
-  }
-
-  /**
-   * Add files to an existing package.
-   *
-   * This function does exactly the same than Create() exept it
-   * will append the given files at the end of the archive.  Please not the is
-   * safe to call Add() on a newly created archive whereas the
-   * contrary will fail !
-   *
-   * This function returns a status code, you can use TarErrorStr() on
-   * it to get the human-readable description of the error.
-   */
-  function Add($p_filelist, $p_add = '', $p_rem = '') { if (($this->_nomf
-!= ARCHIVE_DYNAMIC && @is_file($this->_nomf)) || ($this->_nomf ==
-ARCHIVE_DYNAMIC && !$this->_memdat)) return $this->Create($p_filelist,
-$p_add, $p_rem);
-
-    if(!$fl = $this->_fetchFilelist($p_filelist)) return -5;
-    return $this->_append($fl, $p_add, $p_rem);
-  }
-
-  /**
-   * Read the contents of a TAR archive
-   *
-   * This function attempts to get the list of the files stored in the
-   * archive, and return either an error code or an indexed array of
-   * associative array containing for each file the following informations :
-   *
-   * checksum    Tar Checksum of the file
-   * filename    The full name of the stored file (up to 100 c.)
-   * mode        UNIX permissions in DECIMAL, not octal
-   * uid         The Owner ID
-   * gid         The Group ID
-   * size        Uncompressed filesize
-   * mtime       Timestamp of last modification
-   * typeflag    Empty for files, set for folders
-   * link        For the links, did you guess it ?
-   * uname       Owner name
-   * gname       Group name
-   */
-  function ListContents()
-  {
-    if(!$this->_nomf) return -3;
-    if(!$this->_OpenRead()) return -4;
-
-    $result = Array();
-
-    while ($dat = $this->_read(512))
-    {
-      $dat = $this->_readHeader($dat);
-      if(!is_array($dat)) continue;
-
-      $this->_seek(ceil($dat['size']/512)*512,1);
-      $result[] = $dat;
+    /**
+     * Write a dynamical archive into a file
+     *
+     * This function attempts to write a dynamicaly-genrated archive into
+     * TargetFile on the webserver.  It returns a TarErrorStr() status
+     * code.
+     *
+     * To know the extension to add to the file if you're using AUTO_DETECT
+     * compression, you can use getCompression().
+     */
+    function writeArchive($p_archive) {
+        if(!$this->_memdat) return -7;
+        $fp = @fopen($p_archive, 'wb');
+        if(!$fp) return -6;
+
+        fwrite($fp, $this->_memdat);
+        fclose($fp);
+
+        return true;
     }
 
-    return  $result;
-  }
-
-  /**
-   * Convert a status code into a human readable message
-   *
-   * Some MaxgTar functions like Create(), Add() ... return numerical
-   * status code.  You can pass them to this function to grab their english
-   * equivalent.
-   */
-  function TarErrorStr($i)
-  {
-    $ecodes = Array(
-         1 => true,
-         0 => "Undocumented error",
-        -1 => "Can't use COMPRESS_GZIP compression : ZLIB extensions are not loaded !",
-        -2 => "Can't use COMPRESS_BZIP compression : BZ2 extensions are not loaded !",
-        -3 => "You must set a archive file to read the contents !",
-        -4 => "Can't open the archive file for read !",
-        -5 => "Invalide file list !",
-        -6 => "Can't open the archive in write mode !",
-        -7 => "There is no ARCHIVE_DYNAMIC to write !",
-        -8 => "Can't create the directory to extract files !",
-        -9 => "Please pass a archive name to send if you made created an ARCHIVE_DYNAMIC !",
-       -10 => "You didn't pass an archive filename and there is no stored ARCHIVE_DYNAMIC !",
-       -11 => "Given archive doesn't exist !"
-    );
-
-    return isset($ecodes[$i]) ? $ecodes[$i] : $ecodes[0];
-  }
-
-  /**
-   * Display informations about the MaxgTar Class.
-   *
-   * This function will display vaious informations about the server
-   * MaxgTar is running on.
-   *
-   * The optional parameter DispHeaders is used to generate a full page with
-   * HTML headers (TRUE by default) or just the table with the informations
-   * (FALSE).  Note that the HTML page generated is verified compatible XHTML
-   * 1.0, but not HTML 4.0 compatible.
-   */
-  function TarInfo($headers = true)
-  {
-    if($headers)
-    {
-    ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
-
-<head>
-  <title>MaxgComp TAR</title>
-  <style type="text/css">
-   body{margin: 20px;}
-   body,td{font-size:10pt;font-family: arial;}
-  </style>
-  <meta name="Author" content="The Maxg Network, http://maxg.info" />
-  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-</head>
-
-<body bgcolor="#EFEFEF">
-<?php
+    /**
+     * Send a TAR archive to the client browser.
+     *
+     * This function will send an archive to the client, and return a status
+     * code, but can behave differently depending on the arguments you give. All
+     * arguments are optional.
+     *
+     * ClientName is used to specify the archive name to give to the browser. If
+     * you don't give one, it will send the constructor filename or return an
+     * error code in case of dynamical archive.
+     *
+     * FileName is optional and used to send a specific archive. Leave it blank
+     * to send dynamical archives or the current working archive.
+     *
+     * If SendHeaders is enabled (by default), the library will send the HTTP
+     * headers itself before it sends the contents. This headers are :
+     * Content-Type, Content-Disposition, Content-Length and Accept-Range.
+     *
+     * Please note that this function DOES NOT stops the script so don't forget
+     * to exit() to avoid your script sending other data and corrupt the archive.
+     * Another note : for AUTO_DETECT dynamical archives you can know the
+     * extension to add to the name with getCompression()
+     */
+    function sendClient($name = '', $archive = '', $headers = true) {
+        if(!$name && !$this->_nomf) return -9;
+        if(!$archive && !$this->_memdat) return -10;
+        if(!$name) $name = basename($this->_nomf);
+
+        if($archive){ if(!file_exists($archive)) return -11; }
+        else $decoded = $this->getDynamicArchive();
+
+        if($headers) {
+            header('Content-Type: application/x-gtar');
+            header('Content-Disposition: attachment; filename='.basename($name));
+            header('Accept-Ranges: bytes');
+            header('Content-Length: '.($archive ? filesize($archive) : strlen($decoded)));
+        }
+
+        if($archive) {
+            $fp = @fopen($archive,'rb');
+            if(!$fp) return -4;
+
+            while(!feof($fp)) echo fread($fp,2048);
+        } else {
+            echo $decoded;
+        }
+
+        return true;
     }
-?>
-<table border="0" align="center" width="500" cellspacing="4" cellpadding="5" style="border:1px dotted black;">
-<tr>
-  <td align="center" bgcolor="#DFDFEF" colspan="3" style="font-size:15pt;font-color:#330000;border:1px solid black;">MaxgComp TAR</td>
-</tr>
-<tr>
-  <td colspan="2" bgcolor="#EFEFFE" style="border:1px solid black;">This software was created by the Maxg Network, <a href="http://maxg.info" target="_blank" style="text-decoration:none;color:#333366;">http://maxg.info</a>
-   <br />It is distributed under the GNU <a href="http://www.gnu.org/copyleft/lesser.html" target="_blank" style="text-decoration:none;color:#333366;">Lesser General Public License</a>
-   <br />You can find the documentation of this class <a href="http://docs.maxg.info" target="_blank" style="text-decoration:none;color:#333366;">here</a></td>
-   <td width="60" bgcolor="#EFEFFE" style="border:1px solid black;" align="center"><img src="http://img.maxg.info/menu/tar.gif" border="0" alt="MaxgComp TAR" /></td>
-</tr>
-<tr>
-  <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">MaxgComp TAR version</td>
-  <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=TARLIB_VERSION?></td>
-</tr>
-<tr>
-  <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">ZLIB extensions</td>
-  <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=(extension_loaded('zlib') ? '<b>Yes</b>' : '<i>No</i>')?></td>
-</tr>
-<tr>
-  <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">BZ2 extensions</td>
-  <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=(extension_loaded('bz2') ? '<b>Yes</b>' : '<i>No</i>')?></td>
-</tr>
-<tr>
-  <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">Allow URL fopen</td>
-  <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=(ini_get('allow_url_fopen') ? '<b>Yes</b>' : '<i>No</i>')?></td>
-</tr>
-<tr>
-  <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">Time limit</td>
-  <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=ini_get('max_execution_time')?></td>
-</tr>
-<tr>
-  <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">PHP Version</td>
-  <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=phpversion()?></td>
-</tr>
-<tr>
-  <td colspan="3" align="center" bgcolor="#EFEFFE" style="border:1px solid black;">
-    <i>Special thanks to &laquo; Vincent Blavet &raquo; for his PEAR::Archive_Tar class</i>
-  </td>
-</tr>
-</table>
-<?php
-    if($headers) echo '</body></html>';
-  }
-
-  function _seek($p_flen, $tell=0)
-  {
-    if($this->_nomf === ARCHIVE_DYNAMIC)
-      $this->_memdat=substr($this->_memdat,0,($tell ? strlen($this->_memdat) : 0) + $p_flen);
-    elseif($this->_comptype == COMPRESS_GZIP)
-      @gzseek($this->_fp, ($tell ? @gztell($this->_fp) : 0)+$p_flen);
-    elseif($this->_comptype == COMPRESS_BZIP)
-      @fseek($this->_fp, ($tell ? @ftell($this->_fp) : 0)+$p_flen);
-    else
-      @fseek($this->_fp, ($tell ? @ftell($this->_fp) : 0)+$p_flen);
-  }
-
-  function _OpenRead()
-  {
-    if($this->_comptype == COMPRESS_GZIP)
-      $this->_fp = @gzopen($this->_nomf, 'rb');
-    elseif($this->_comptype == COMPRESS_BZIP)
-      $this->_fp = @bzopen($this->_nomf, 'rb');
-    else
-      $this->_fp = @fopen($this->_nomf, 'rb');
-
-    return ($this->_fp ? true : false);
-  }
-
-  function _OpenWrite($add = 'w')
-  {
-    if($this->_nomf === ARCHIVE_DYNAMIC) return true;
-
-    if($this->_comptype == COMPRESS_GZIP)
-      $this->_fp = @gzopen($this->_nomf, $add.'b'.$this->_compzlevel);
-    elseif($this->_comptype == COMPRESS_BZIP)
-      $this->_fp = @bzopen($this->_nomf, $add.'b');
-    else
-      $this->_fp = @fopen($this->_nomf, $add.'b');
-
-    return ($this->_fp ? true : false);
-  }
-
-  function _CompTar()
-  {
-    if($this->_nomf === ARCHIVE_DYNAMIC || !$this->_fp) return;
-
-    if($this->_comptype == COMPRESS_GZIP) @gzclose($this->_fp);
-    elseif($this->_comptype == COMPRESS_BZIP) @bzclose($this->_fp);
-    else @fclose($this->_fp);
-  }
-
-  function _read($p_len)
-  {
-    if($this->_comptype == COMPRESS_GZIP)
-      return @gzread($this->_fp,$p_len);
-    elseif($this->_comptype == COMPRESS_BZIP)
-      return @bzread($this->_fp,$p_len);
-    else
-      return @fread($this->_fp,$p_len);
-  }
-
-  function _write($p_data)
-  {
-    if($this->_nomf === ARCHIVE_DYNAMIC) $this->_memdat .= $p_data;
-    elseif($this->_comptype == COMPRESS_GZIP)
-      return @gzwrite($this->_fp,$p_data);
-
-    elseif($this->_comptype == COMPRESS_BZIP)
-      return @bzwrite($this->_fp,$p_data);
-
-    else
-      return @fwrite($this->_fp,$p_data);
-  }
-
-  function _encode($p_dat)
-  {
-    if($this->_comptype == COMPRESS_GZIP)
-      return gzencode($p_dat, $this->_compzlevel);
-    elseif($this->_comptype == COMPRESS_BZIP)
-      return bzcompress($p_dat, $this->_compzlevel);
-    else return $p_dat;
-  }
-
-  function _readHeader($p_dat)
-  {
-    if (!$p_dat || strlen($p_dat) != 512) return false;
-
-    for ($i=0, $chks=0; $i<148; $i++)
-      $chks += ord($p_dat[$i]);
-
-    for ($i=156,$chks+=256; $i<512; $i++)
-      $chks += ord($p_dat[$i]);
-
-    $headers = @unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $p_dat);
-    if(!$headers) return false;
-
-    $return['checksum'] = OctDec(trim($headers['checksum']));
-    if ($return['checksum'] != $chks) return false;
-
-    $return['filename'] = trim($headers['filename']);
-    $return['mode'] = OctDec(trim($headers['mode']));
-    $return['uid'] = OctDec(trim($headers['uid']));
-    $return['gid'] = OctDec(trim($headers['gid']));
-    $return['size'] = OctDec(trim($headers['size']));
-    $return['mtime'] = OctDec(trim($headers['mtime']));
-    $return['typeflag'] = $headers['typeflag'];
-    $return['link'] = trim($headers['link']);
-    $return['uname'] = trim($headers['uname']);
-    $return['gname'] = trim($headers['gname']);
-
-    return $return;
-  }
-
-  function _fetchFilelist($p_filelist)
-  {
-    if(!$p_filelist || (is_array($p_filelist) && !@count($p_filelist))) return false;
-
-    if(is_string($p_filelist))
-    {
-        $p_filelist = explode('|',$p_filelist);
-        if(!is_array($p_filelist)) $p_filelist = Array($p_filelist);
+
+    /**
+     * Extract part or totality of the archive.
+     *
+     * This function can extract files from an archive, and returns then a
+     * status codes that can be converted with TarErrorStr() into a
+     * human readable message.
+     *
+     * Only the first argument is required, What and it can be either the
+     * constant FULL_ARCHIVE or an indexed array containing each file you want to
+     * extract.
+     *
+     * To contains the target folder to extract the archive. It is optional and
+     * the default value is '.' which means the current folder. If the target
+     * folder doesn't exist, the script attempts to create it and give it
+     * permissions 0777 by default.
+     *
+     * RemovePath is very usefull when you want to extract files from a subfoler
+     * in the archive to a root folder. For instance, if you have a file in the
+     * archive called some/sub/folder/test.txt and you want to extract it to the
+     * script folder, you can call Extract with To = '.' and RemovePath =
+     * 'some/sub/folder/'
+     *
+     * FileMode is optional and its default value is 0755. It is in fact the UNIX
+     * permission in octal mode (prefixed with a 0) that will be given on each
+     * extracted file.
+     */
+    function Extract($p_what = FULL_ARCHIVE, $p_to = '.', $p_remdir='', $p_mode = 0755) {
+        if(!$this->_OpenRead()) return -4;
+        //  if(!@is_dir($p_to)) if(!@mkdir($p_to, 0777)) return -8;   --CS
+        if(!@is_dir($p_to)) if(!$this->_dirApp($p_to)) return -8;   //--CS (route through correct dir fn)
+
+        $ok = $this->_extractList($p_to, $p_what, $p_remdir, $p_mode);
+        $this->_CompTar();
+
+        return $ok;
     }
 
-    return $p_filelist;
-  }
+    /**
+     * Create a new package with the given files
+     *
+     * This function will attempt to create a new archive with global headers
+     * then add the given files into.  If the archive is a real file, the
+     * contents are written directly into the file, if it is a dynamic archive
+     * contents are only stored in memory. This function should not be used to
+     * add files to an existing archive, you should use Add() instead.
+     *
+     * The FileList actually supports three different modes :
+     *
+     * - You can pass a string containing filenames separated by pipes '|'.
+     *   In this case the file are read from the webserver filesystem and the
+     *   root folder is the folder where the script using the MaxgTar is called.
+     *
+     * - You can also give a unidimensional indexed array containing the
+     *   filenames. The behaviour for the content reading is the same that a
+     *   '|'ed string.
+     *
+     * - The more useful usage is to pass bidimensional arrays, where the
+     *   first element contains the filename and the second contains the file
+     *   contents. You can even add empty folders to the package if the filename
+     *   has a leading '/'. Once again, have a look at the exemples to understand
+     *   better.
+     *
+     * Note you can also give arrays with both dynamic contents and static files.
+     *
+     * The optional parameter RemovePath can be used to delete a part of the tree
+     * of the filename you're adding, for instance if you're adding in the root
+     * of a package a file that is stored somewhere in the server tree.
+     *
+     * On the contrary the parameter AddPath can be used to add a prefix folder
+     * to the file you store. Note also that the RemovePath is applied before the
+     * AddPath is added, so it HAS a sense to use both parameters together.
+     */
+    function Create($p_filelist,$p_add='',$p_rem='') {
+        if(!$fl = $this->_fetchFilelist($p_filelist)) return -5;
+        if(!$this->_OpenWrite()) return -6;
+
+        $ok = $this->_addFileList($fl,$p_add,$p_rem);
+
+        if($ok){
+            $this->_writeFooter();
+        }else{
+            $this->_CompTar();
+            @unlink($this->_nomf);
+        }
 
-  function _addFileList($p_fl, $p_addir, $p_remdir)
-  {
-    foreach($p_fl as $file)
-    {
-      if(($file == $this->_nomf && $this->_nomf != ARCHIVE_DYNAMIC) || !$file || (!file_exists($file) && !is_array($file)))
-        continue;
+        return $ok;
+    }
 
-      if (!$this->_addFile($file, $p_addir, $p_remdir))
-        continue;
+    /**
+     * Add files to an existing package.
+     *
+     * This function does exactly the same than Create() exept it
+     * will append the given files at the end of the archive.  Please not the is
+     * safe to call Add() on a newly created archive whereas the
+     * contrary will fail !
+     *
+     * This function returns a status code, you can use TarErrorStr() on
+     * it to get the human-readable description of the error.
+     */
+    function Add($p_filelist, $p_add = '', $p_rem = '') {
+        if (($this->_nomf != ARCHIVE_DYNAMIC && @is_file($this->_nomf)) ||
+            ($this->_nomf == ARCHIVE_DYNAMIC && !$this->_memdat)){
+             return $this->Create($p_filelist, $p_add, $p_rem);
+        }
 
-      if (@is_dir($file))
-      {
-        $d = @opendir($file);
+        if(!$fl = $this->_fetchFilelist($p_filelist)) return -5;
+        return $this->_append($fl, $p_add, $p_rem);
+    }
 
-        if(!$d) continue;
-        readdir($d); readdir($d);
+    /**
+     * Read the contents of a TAR archive
+     *
+     * This function attempts to get the list of the files stored in the
+     * archive, and return either an error code or an indexed array of
+     * associative array containing for each file the following informations :
+     *
+     * checksum    Tar Checksum of the file
+     * filename    The full name of the stored file (up to 100 c.)
+     * mode        UNIX permissions in DECIMAL, not octal
+     * uid         The Owner ID
+     * gid         The Group ID
+     * size        Uncompressed filesize
+     * mtime       Timestamp of last modification
+     * typeflag    Empty for files, set for folders
+     * link        For the links, did you guess it ?
+     * uname       Owner name
+     * gname       Group name
+     */
+    function ListContents() {
+        if(!$this->_nomf) return -3;
+        if(!$this->_OpenRead()) return -4;
+
+        $result = Array();
+
+        while ($dat = $this->_read(512)) {
+            $dat = $this->_readHeader($dat);
+            if(!is_array($dat)) continue;
+
+            $this->_seek(ceil($dat['size']/512)*512,1);
+            $result[] = $dat;
+        }
+
+        return  $result;
+    }
 
-        while($f = readdir($d))
-        {
-          if($file != ".") $tmplist[0] = "$file/$f";
-          else $tmplist[0] = $d;
+    /**
+     * Convert a status code into a human readable message
+     *
+     * Some MaxgTar functions like Create(), Add() ... return numerical
+     * status code.  You can pass them to this function to grab their english
+     * equivalent.
+     */
+    function TarErrorStr($i) {
+        $ecodes = Array(
+                1 => true,
+                0 => "Undocumented error",
+                -1 => "Can't use COMPRESS_GZIP compression : ZLIB extensions are not loaded !",
+                -2 => "Can't use COMPRESS_BZIP compression : BZ2 extensions are not loaded !",
+                -3 => "You must set a archive file to read the contents !",
+                -4 => "Can't open the archive file for read !",
+                -5 => "Invalide file list !",
+                -6 => "Can't open the archive in write mode !",
+                -7 => "There is no ARCHIVE_DYNAMIC to write !",
+                -8 => "Can't create the directory to extract files !",
+                -9 => "Please pass a archive name to send if you made created an ARCHIVE_DYNAMIC !",
+                -10 => "You didn't pass an archive filename and there is no stored ARCHIVE_DYNAMIC !",
+                -11 => "Given archive doesn't exist !"
+                );
+
+        return isset($ecodes[$i]) ? $ecodes[$i] : $ecodes[0];
+    }
 
-          $this->_addFileList($tmplist, $p_addir, $p_remdir);
+    /**
+     * Display informations about the MaxgTar Class.
+     *
+     * This function will display vaious informations about the server
+     * MaxgTar is running on.
+     *
+     * The optional parameter DispHeaders is used to generate a full page with
+     * HTML headers (TRUE by default) or just the table with the informations
+     * (FALSE).  Note that the HTML page generated is verified compatible XHTML
+     * 1.0, but not HTML 4.0 compatible.
+     */
+    function TarInfo($headers = true) {
+        if($headers) {
+            ?>
+                <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+                <html>
+
+                <head>
+                <title>MaxgComp TAR</title>
+                <style type="text/css">
+                body{margin: 20px;}
+            body,td{font-size:10pt;font-family: arial;}
+            </style>
+                <meta name="Author" content="The Maxg Network, http://maxg.info" />
+                <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+                </head>
+
+                <body bgcolor="#EFEFEF">
+                <?php
         }
+        ?>
+            <table border="0" align="center" width="500" cellspacing="4" cellpadding="5" style="border:1px dotted black;">
+            <tr>
+            <td align="center" bgcolor="#DFDFEF" colspan="3" style="font-size:15pt;font-color:#330000;border:1px solid black;">MaxgComp TAR</td>
+            </tr>
+            <tr>
+            <td colspan="2" bgcolor="#EFEFFE" style="border:1px solid black;">This software was created by the Maxg Network, <a href="http://maxg.info" target="_blank" style="text-decoration:none;color:#333366;">http://maxg.info</a>
+            <br />It is distributed under the GNU <a href="http://www.gnu.org/copyleft/lesser.html" target="_blank" style="text-decoration:none;color:#333366;">Lesser General Public License</a>
+            <br />You can find the documentation of this class <a href="http://docs.maxg.info" target="_blank" style="text-decoration:none;color:#333366;">here</a></td>
+            <td width="60" bgcolor="#EFEFFE" style="border:1px solid black;" align="center"><img src="http://img.maxg.info/menu/tar.gif" border="0" alt="MaxgComp TAR" /></td>
+            </tr>
+            <tr>
+            <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">MaxgComp TAR version</td>
+            <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=TARLIB_VERSION?></td>
+            </tr>
+            <tr>
+            <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">ZLIB extensions</td>
+            <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=(extension_loaded('zlib') ? '<b>Yes</b>' : '<i>No</i>')?></td>
+            </tr>
+            <tr>
+            <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">BZ2 extensions</td>
+            <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=(extension_loaded('bz2') ? '<b>Yes</b>' : '<i>No</i>')?></td>
+            </tr>
+            <tr>
+            <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">Allow URL fopen</td>
+            <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=(ini_get('allow_url_fopen') ? '<b>Yes</b>' : '<i>No</i>')?></td>
+            </tr>
+            <tr>
+            <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">Time limit</td>
+            <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=ini_get('max_execution_time')?></td>
+            </tr>
+            <tr>
+            <td width="50%" align="center" style="border:1px solid black;" bgcolor="#DFDFEF">PHP Version</td>
+            <td colspan="2" align="center" bgcolor="#EFEFFE" style="border:1px solid black;"><?=phpversion()?></td>
+            </tr>
+            <tr>
+            <td colspan="3" align="center" bgcolor="#EFEFFE" style="border:1px solid black;">
+            <i>Special thanks to &laquo; Vincent Blavet &raquo; for his PEAR::Archive_Tar class</i>
+            </td>
+            </tr>
+            </table>
+            <?php
+            if($headers) echo '</body></html>';
+    }
 
-        closedir($d); unset($tmplist,$f);
-      }
+    function _seek($p_flen, $tell=0) {
+        if($this->_nomf === ARCHIVE_DYNAMIC)
+            $this->_memdat=substr($this->_memdat,0,($tell ? strlen($this->_memdat) : 0) + $p_flen);
+        elseif($this->_comptype == COMPRESS_GZIP)
+            @gzseek($this->_fp, ($tell ? @gztell($this->_fp) : 0)+$p_flen);
+        elseif($this->_comptype == COMPRESS_BZIP)
+            @fseek($this->_fp, ($tell ? @ftell($this->_fp) : 0)+$p_flen);
+        else
+            @fseek($this->_fp, ($tell ? @ftell($this->_fp) : 0)+$p_flen);
     }
-    return true;
-  }
 
-  function _addFile($p_fn, $p_addir = '', $p_remdir = '')
-  {
-    if(is_array($p_fn)) list($p_fn, $data) = $p_fn;
-    $sname = $p_fn;
+    function _OpenRead() {
+        if($this->_comptype == COMPRESS_GZIP)
+            $this->_fp = @gzopen($this->_nomf, 'rb');
+        elseif($this->_comptype == COMPRESS_BZIP)
+            $this->_fp = @bzopen($this->_nomf, 'rb');
+        else
+            $this->_fp = @fopen($this->_nomf, 'rb');
+
+        return ($this->_fp ? true : false);
+    }
 
-    if($p_remdir)
-    {
-        if(substr($p_remdir,-1) != '/') $p_remdir .= "/";
+    function _OpenWrite($add = 'w') {
+        if($this->_nomf === ARCHIVE_DYNAMIC) return true;
+
+        if($this->_comptype == COMPRESS_GZIP)
+            $this->_fp = @gzopen($this->_nomf, $add.'b'.$this->_compzlevel);
+        elseif($this->_comptype == COMPRESS_BZIP)
+            $this->_fp = @bzopen($this->_nomf, $add.'b');
+        else
+            $this->_fp = @fopen($this->_nomf, $add.'b');
 
-        if(substr($sname, 0, strlen($p_remdir)) == $p_remdir)
-          $sname = substr($sname, strlen($p_remdir));
+        return ($this->_fp ? true : false);
     }
 
-    if($p_addir) $sname = $p_addir.(substr($p_addir,-1) == '/' ? '' : "/").$sname;
+    function _CompTar() {
+        if($this->_nomf === ARCHIVE_DYNAMIC || !$this->_fp) return;
 
-    if(strlen($sname) > 99) return;
+        if($this->_comptype == COMPRESS_GZIP) @gzclose($this->_fp);
+        elseif($this->_comptype == COMPRESS_BZIP) @bzclose($this->_fp);
+        else @fclose($this->_fp);
+    }
+
+    function _read($p_len) {
+        if($this->_comptype == COMPRESS_GZIP)
+            return @gzread($this->_fp,$p_len);
+        elseif($this->_comptype == COMPRESS_BZIP)
+            return @bzread($this->_fp,$p_len);
+        else
+            return @fread($this->_fp,$p_len);
+    }
+
+    function _write($p_data) {
+        if($this->_nomf === ARCHIVE_DYNAMIC) $this->_memdat .= $p_data;
+        elseif($this->_comptype == COMPRESS_GZIP)
+            return @gzwrite($this->_fp,$p_data);
 
-    if(@is_dir($p_fn))
-    {
-      if(!$this->_writeFileHeader($p_fn, $sname)) return false;
+        elseif($this->_comptype == COMPRESS_BZIP)
+            return @bzwrite($this->_fp,$p_data);
+
+        else
+            return @fwrite($this->_fp,$p_data);
     }
-    else
-    {
-     if(!$data)
-     {
-      $fp = fopen($p_fn, 'rb');
-      if(!$fp) return false;
-     }
-
-     if(!$this->_writeFileHeader($p_fn, $sname, ($data ? strlen($data) : false))) return false;
-
-     if(!$data)
-     {
-      while(!feof($fp))
-      {
-        $packed = pack("a512", fread($fp,512));
-        $this->_write($packed);
-      }
-      fclose($fp);
-     }
-     else
-     {
-      for($s = 0; $s < strlen($data); $s += 512)
-        $this->_write(pack("a512",substr($data,$s,512)));
-     }
+
+    function _encode($p_dat) {
+        if($this->_comptype == COMPRESS_GZIP)
+            return gzencode($p_dat, $this->_compzlevel);
+        elseif($this->_comptype == COMPRESS_BZIP)
+            return bzcompress($p_dat, $this->_compzlevel);
+        else return $p_dat;
     }
 
-    return true;
-  }
-
-  function _writeFileHeader($p_file, $p_sname, $p_data=false)
-  {
-   if(!$p_data)
-   {
-    if (!$p_sname) $p_sname = $p_file;
-    $p_sname = $this->_pathTrans($p_sname);
-
-    $h_info = stat($p_file);
-    $h[0] = sprintf("%6s ", DecOct($h_info[4]));
-    $h[] = sprintf("%6s ", DecOct($h_info[5]));
-    $h[] = sprintf("%6s ", DecOct(fileperms($p_file)));
-    clearstatcache();
-    $h[] = sprintf("%11s ", DecOct(filesize($p_file)));
-    $h[] = sprintf("%11s", DecOct(filemtime($p_file)));
-
-    $dir = @is_dir($p_file) ? '5' : '';
-   }
-   else
-   {
-    $dir = '';
-    $p_data = sprintf("%11s ", DecOct($p_data));
-    $time = sprintf("%11s ", DecOct(time()));
-    $h = Array("     0 ","     0 "," 40777 ",$p_data,$time);
-   }
-
-    $data_first = pack("a100a8a8a8a12A12", $p_sname, $h[2], $h[0], $h[1], $h[3], $h[4]);
-    $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $dir, '', '', '', '', '', '', '', '', "");
-
-     for ($i=0,$chks=0; $i<148; $i++)
-       $chks += ord($data_first[$i]);
-
-     for ($i=156, $chks+=256, $j=0; $i<512; $i++, $j++)
-       $chks += ord($data_last[$j]);
-
-     $this->_write($data_first);
-
-     $chks = pack("a8",sprintf("%6s ", DecOct($chks)));
-     $this->_write($chks.$data_last);
-
-     return true;
-  }
-
-  function _append($p_filelist, $p_addir="", $p_remdir="")
-  {
-    if(!$this->_fp) if(!$this->_OpenWrite('a')) return -6;
-
-    if($this->_nomf == ARCHIVE_DYNAMIC)
-    {
-      $s = strlen($this->_memdat);
-      $this->_memdat = substr($this->_memdat,0,-512);
+    function _readHeader($p_dat) {
+        if (!$p_dat || strlen($p_dat) != 512) return false;
+
+        for ($i=0, $chks=0; $i<148; $i++)
+            $chks += ord($p_dat[$i]);
+
+        for ($i=156,$chks+=256; $i<512; $i++)
+            $chks += ord($p_dat[$i]);
+
+        $headers = @unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $p_dat);
+        if(!$headers) return false;
+
+        $return['checksum'] = OctDec(trim($headers['checksum']));
+        if ($return['checksum'] != $chks) return false;
+
+        $return['filename'] = trim($headers['filename']);
+        $return['mode'] = OctDec(trim($headers['mode']));
+        $return['uid'] = OctDec(trim($headers['uid']));
+        $return['gid'] = OctDec(trim($headers['gid']));
+        $return['size'] = OctDec(trim($headers['size']));
+        $return['mtime'] = OctDec(trim($headers['mtime']));
+        $return['typeflag'] = $headers['typeflag'];
+        $return['link'] = trim($headers['link']);
+        $return['uname'] = trim($headers['uname']);
+        $return['gname'] = trim($headers['gname']);
+
+        return $return;
     }
-    else
-    {
-      $s = filesize($this->_nomf);
-      $this->_seek($s-512);
+
+    function _fetchFilelist($p_filelist) {
+        if(!$p_filelist || (is_array($p_filelist) && !@count($p_filelist))) return false;
+
+        if(is_string($p_filelist)) {
+            $p_filelist = explode('|',$p_filelist);
+            if(!is_array($p_filelist)) $p_filelist = Array($p_filelist);
+        }
+
+        return $p_filelist;
     }
 
-    $ok = $this->_addFileList($p_filelist, $p_addir, $p_remdir);
-    $this->_writeFooter();
-
-    return $ok;
-  }
-
-  function _pathTrans($p_dir)
-  {
-    if ($p_dir)
-    {
-      $subf = explode("/", $p_dir); $r='';
-
-      for ($i=count($subf)-1; $i>=0; $i--)
-      {
-        if ($subf[$i] == ".") {}
-        else if ($subf[$i] == "..") $i--;
-        else if (!$subf[$i] && $i!=count($subf)-1 && $i) {}
-        else $r = $subf[$i].($i!=(count($subf)-1) ? "/".$r : "");
-      }
+    function _addFileList($p_fl, $p_addir, $p_remdir) {
+        foreach($p_fl as $file) {
+            if(($file == $this->_nomf && $this->_nomf != ARCHIVE_DYNAMIC) || !$file || (!file_exists($file) && !is_array($file)))
+                continue;
+
+            if (!$this->_addFile($file, $p_addir, $p_remdir))
+                continue;
+
+            if (@is_dir($file)) {
+                $d = @opendir($file);
+
+                if(!$d) continue;
+                readdir($d);
+                readdir($d);
+
+                while($f = readdir($d)) {
+                    if($file != ".") $tmplist[0] = "$file/$f";
+                    else $tmplist[0] = $d;
+
+                    $this->_addFileList($tmplist, $p_addir, $p_remdir);
+                }
+
+                closedir($d);
+                unset($tmplist,$f);
+            }
+        }
+        return true;
     }
-    return $r;
-  }
-
-  function _writeFooter()
-  {
-    $this->_write(pack("a512", ""));
-  }
-
-  function _extractList($p_to, $p_files, $p_remdir, $p_mode = 0755)
-  {
-    if (!$p_to || ($p_to[0]!="/"&&substr($p_to,0,3)!="../"&&substr($p_to,1,3)!=":\\"&&substr($p_to,1,2)!=":/")) /*" // <- PHP Coder bug */
-      $p_to = "./$p_to";
-
-    if ($p_remdir && substr($p_remdir,-1)!='/') $p_remdir .= '/';
-    $p_remdirs = strlen($p_remdir);
-    while($dat = $this->_read(512))
-    {
-      $headers = $this->_readHeader($dat);
-      if(!$headers['filename']) continue;
-
-      if($p_files == -1 || $p_files[0] == -1) $extract = true;
-      else
-      {
-        $extract = false;
-
-        foreach($p_files as $f)
-        {
-          if(substr($f,-1) == "/") {
-            if((strlen($headers['filename']) > strlen($f)) && (substr($headers['filename'],0,strlen($f))==$f)) {
-              $extract = true; break;
+
+    function _addFile($p_fn, $p_addir = '', $p_remdir = '') {
+        if(is_array($p_fn)) list($p_fn, $data) = $p_fn;
+        $sname = $p_fn;
+
+        if($p_remdir) {
+            if(substr($p_remdir,-1) != '/') $p_remdir .= "/";
+
+            if(substr($sname, 0, strlen($p_remdir)) == $p_remdir)
+                $sname = substr($sname, strlen($p_remdir));
+        }
+
+        if($p_addir) $sname = $p_addir.(substr($p_addir,-1) == '/' ? '' : "/").$sname;
+
+        if(strlen($sname) > 99) return;
+
+        if(@is_dir($p_fn)) {
+            if(!$this->_writeFileHeader($p_fn, $sname)) return false;
+        } else {
+            if(!$data) {
+                $fp = fopen($p_fn, 'rb');
+                if(!$fp) return false;
+            }
+
+            if(!$this->_writeFileHeader($p_fn, $sname, ($data ? strlen($data) : false))) return false;
+
+            if(!$data) {
+                while(!feof($fp)) {
+                    $packed = pack("a512", fread($fp,512));
+                    $this->_write($packed);
+                }
+                fclose($fp);
+            } else {
+                $len = strlen($data);
+                for($s = 0; $s < $len; $s += 512){
+                    $this->_write(pack("a512",substr($data,$s,512)));
+                }
             }
-          }
-          elseif($f == $headers['filename']) {
-            $extract = true; break;
-          }
         }
-      }
 
-      if ($extract)
-      {
-        $det[] = $headers;
-        if ($p_remdir && substr($headers['filename'],0,$p_remdirs)==$p_remdir)
-          $headers['filename'] = substr($headers['filename'],$p_remdirs);
+        return true;
+    }
+
+    function _writeFileHeader($p_file, $p_sname, $p_data=false) {
+        if(!$p_data) {
+            if (!$p_sname) $p_sname = $p_file;
+            $p_sname = $this->_pathTrans($p_sname);
+
+            $h_info = stat($p_file);
+            $h[0] = sprintf("%6s ", DecOct($h_info[4]));
+            $h[] = sprintf("%6s ", DecOct($h_info[5]));
+            $h[] = sprintf("%6s ", DecOct(fileperms($p_file)));
+            clearstatcache();
+            $h[] = sprintf("%11s ", DecOct(filesize($p_file)));
+            $h[] = sprintf("%11s", DecOct(filemtime($p_file)));
+
+            $dir = @is_dir($p_file) ? '5' : '';
+        } else {
+            $dir = '';
+            $p_data = sprintf("%11s ", DecOct($p_data));
+            $time = sprintf("%11s ", DecOct(time()));
+            $h = Array("     0 ","     0 "," 40777 ",$p_data,$time);
+        }
 
-        if($headers['filename'].'/' == $p_remdir && $headers['typeflag']=='5') continue;
+        $data_first = pack("a100a8a8a8a12A12", $p_sname, $h[2], $h[0], $h[1], $h[3], $h[4]);
+        $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $dir, '', '', '', '', '', '', '', '', "");
 
-        if ($p_to != "./" && $p_to != "/")
-        {
-          while($p_to{-1}=="/") $p_to = substr($p_to,0,-1);
+        for ($i=0,$chks=0; $i<148; $i++)
+            $chks += ord($data_first[$i]);
+
+        for ($i=156, $chks+=256, $j=0; $i<512; $i++, $j++)
+            $chks += ord($data_last[$j]);
+
+        $this->_write($data_first);
+
+        $chks = pack("a8",sprintf("%6s ", DecOct($chks)));
+        $this->_write($chks.$data_last);
+
+        return true;
+    }
 
-          if($headers['filename']{0} == "/")
-            $headers['filename'] = $p_to.$headers['filename'];
-          else
-            $headers['filename'] = $p_to."/".$headers['filename'];
+    function _append($p_filelist, $p_addir="", $p_remdir="") {
+        if(!$this->_fp) if(!$this->_OpenWrite('a')) return -6;
+
+        if($this->_nomf == ARCHIVE_DYNAMIC) {
+            $s = strlen($this->_memdat);
+            $this->_memdat = substr($this->_memdat,0,-512);
+        } else {
+            $s = filesize($this->_nomf);
+            $this->_seek($s-512);
         }
 
-        $ok = $this->_dirApp($headers['typeflag']=="5" ? $headers['filename'] : dirname($headers['filename']));
-        if($ok < 0) return $ok;
+        $ok = $this->_addFileList($p_filelist, $p_addir, $p_remdir);
+        $this->_writeFooter();
+
+        return $ok;
+    }
+
+    function _pathTrans($p_dir) {
+        if ($p_dir) {
+            $subf = explode("/", $p_dir);
+            $r='';
+
+            for ($i=count($subf)-1; $i>=0; $i--) {
+                if ($subf[$i] == ".") {
+                    # do nothing
+                } elseif ($subf[$i] == "..") {
+                    $i--;
+                } elseif (!$subf[$i] && $i!=count($subf)-1 && $i) {
+                    # do nothing
+                } else {
+                    $r = $subf[$i].($i!=(count($subf)-1) ? "/".$r : "");
+                }
+            }
+        }
+        return $r;
+    }
 
-        if (!$headers['typeflag'])
-        {
-          if (!$fp = @fopen($headers['filename'], "wb")) return -6;
-          $n = floor($headers['size']/512);
+    function _writeFooter() {
+        $this->_write(pack("a512", ""));
+    }
 
-          for ($i=0; $i<$n; $i++) fwrite($fp, $this->_read(512),512);
-          if (($headers['size'] % 512) != 0) fwrite($fp, $this->_read(512), $headers['size'] % 512);
+    function _extractList($p_to, $p_files, $p_remdir, $p_mode = 0755) {
+        if (!$p_to || ($p_to[0]!="/"&&substr($p_to,0,3)!="../"&&substr($p_to,1,3)!=":\\"&&substr($p_to,1,2)!=":/")) /*" // <- PHP Coder bug */
+            $p_to = "./$p_to";
+
+        if ($p_remdir && substr($p_remdir,-1)!='/') $p_remdir .= '/';
+        $p_remdirs = strlen($p_remdir);
+        while($dat = $this->_read(512)) {
+            $headers = $this->_readHeader($dat);
+            if(!$headers['filename']) continue;
+
+            if($p_files == -1 || $p_files[0] == -1){
+                $extract = true;
+            } else {
+                $extract = false;
+
+                foreach($p_files as $f) {
+                    if(substr($f,-1) == "/") {
+                        if((strlen($headers['filename']) > strlen($f)) && (substr($headers['filename'],0,strlen($f))==$f)) {
+                            $extract = true;
+                            break;
+                        }
+                    } elseif($f == $headers['filename']) {
+                        $extract = true;
+                        break;
+                    }
+                }
+            }
 
-          fclose($fp);
-          touch($headers['filename'], $headers['mtime']);
-          chmod($headers['filename'], $p_mode);
+            if ($extract) {
+                $det[] = $headers;
+                if ($p_remdir && substr($headers['filename'],0,$p_remdirs)==$p_remdir)
+                    $headers['filename'] = substr($headers['filename'],$p_remdirs);
+
+                if($headers['filename'].'/' == $p_remdir && $headers['typeflag']=='5') continue;
+
+                if ($p_to != "./" && $p_to != "/") {
+                    while($p_to{-1}=="/") $p_to = substr($p_to,0,-1);
+
+                    if($headers['filename']{0} == "/")
+                        $headers['filename'] = $p_to.$headers['filename'];
+                    else
+                        $headers['filename'] = $p_to."/".$headers['filename'];
+                }
+
+                $ok = $this->_dirApp($headers['typeflag']=="5" ? $headers['filename'] : dirname($headers['filename']));
+                if($ok < 0) return $ok;
+
+                if (!$headers['typeflag']) {
+                    if (!$fp = @fopen($headers['filename'], "wb")) return -6;
+                    $n = floor($headers['size']/512);
+
+                    for ($i=0; $i<$n; $i++){
+                        fwrite($fp, $this->_read(512),512);
+                    }
+                    if (($headers['size'] % 512) != 0) fwrite($fp, $this->_read(512), $headers['size'] % 512);
+
+                    fclose($fp);
+                    touch($headers['filename'], $headers['mtime']);
+                    chmod($headers['filename'], $p_mode);
+                } else {
+                    $this->_seek(ceil($headers['size']/512)*512,1);
+                }
+            }else $this->_seek(ceil($headers['size']/512)*512,1);
         }
-       else
-       {
-         $this->_seek(ceil($headers['size']/512)*512,1);
-       }
-      }else $this->_seek(ceil($headers['size']/512)*512,1);
+        return $det;
     }
-    return $det;
-  }
-
-function _dirApp($d)
-  {
-//  map to dokuwiki function (its more robust)
-    return io_mkdir_p($d);
-/*
-    $d = explode('/', $d);
-    $base = '';
-
-    foreach($d as $f)
-    {
-      if(!is_dir($base.$f))
-      {
-        $ok = @mkdir($base.$f, 0777);
-        if(!$ok) return false;
-      }
-      $base .= "$f/";
+
+    function _dirApp($d) {
+        //  map to dokuwiki function (its more robust)
+        return io_mkdir_p($d);
     }
-*/
-  }
 
 }
 
diff --git a/inc/actions.php b/inc/actions.php
index 27292e6f6..92f817133 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -18,149 +18,149 @@ require_once(DOKU_INC.'inc/template.php');
  * @triggers ACTION_HEADERS_SEND
  */
 function act_dispatch(){
-  global $INFO;
-  global $ACT;
-  global $ID;
-  global $QUERY;
-  global $lang;
-  global $conf;
-  global $license;
-
-  $preact = $ACT;
-
-  // give plugins an opportunity to process the action
-  $evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT);
-  if ($evt->advise_before()) {
-
-    //sanitize $ACT
-    $ACT = act_clean($ACT);
-
-    //check if searchword was given - else just show
-    $s = cleanID($QUERY);
-    if($ACT == 'search' && empty($s)){
-      $ACT = 'show';
-    }
+    global $INFO;
+    global $ACT;
+    global $ID;
+    global $QUERY;
+    global $lang;
+    global $conf;
+    global $license;
 
-    //login stuff
-    if(in_array($ACT,array('login','logout'))){
-        $ACT = act_auth($ACT);
-    }
+    $preact = $ACT;
 
-    //check if user is asking to (un)subscribe a page
-    if($ACT == 'subscribe' || $ACT == 'unsubscribe')
-      $ACT = act_subscription($ACT);
+    // give plugins an opportunity to process the action
+    $evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT);
+    if ($evt->advise_before()) {
 
-    //check if user is asking to (un)subscribe a namespace
-    if($ACT == 'subscribens' || $ACT == 'unsubscribens')
-      $ACT = act_subscriptionns($ACT);
+        //sanitize $ACT
+        $ACT = act_clean($ACT);
 
-    //check permissions
-    $ACT = act_permcheck($ACT);
+        //check if searchword was given - else just show
+        $s = cleanID($QUERY);
+        if($ACT == 'search' && empty($s)){
+            $ACT = 'show';
+        }
 
-    //register
-    $nil = array();
-    if($ACT == 'register' && $_POST['save'] && register()){
-      $ACT = 'login';
-    }
+        //login stuff
+        if(in_array($ACT,array('login','logout'))){
+            $ACT = act_auth($ACT);
+        }
 
-    if ($ACT == 'resendpwd' && act_resendpwd()) {
-      $ACT = 'login';
-    }
+        //check if user is asking to (un)subscribe a page
+        if($ACT == 'subscribe' || $ACT == 'unsubscribe')
+            $ACT = act_subscription($ACT);
+
+        //check if user is asking to (un)subscribe a namespace
+        if($ACT == 'subscribens' || $ACT == 'unsubscribens')
+            $ACT = act_subscriptionns($ACT);
 
-    //update user profile
-    if ($ACT == 'profile') {
-      if(!$_SERVER['REMOTE_USER']) {
-        $ACT = 'login';
-      } else {
-        if(updateprofile()) {
-          msg($lang['profchanged'],1);
-          $ACT = 'show';
+        //check permissions
+        $ACT = act_permcheck($ACT);
+
+        //register
+        $nil = array();
+        if($ACT == 'register' && $_POST['save'] && register()){
+            $ACT = 'login';
         }
-      }
-    }
 
-    //revert
-    if($ACT == 'revert'){
-      if(checkSecurityToken()){
-        $ACT = act_revert($ACT);
-      }else{
-        $ACT = 'show';
-      }
-    }
+        if ($ACT == 'resendpwd' && act_resendpwd()) {
+            $ACT = 'login';
+        }
 
-    //save
-    if($ACT == 'save'){
-      if(checkSecurityToken()){
-        $ACT = act_save($ACT);
-      }else{
-        $ACT = 'show';
-      }
-    }
+        //update user profile
+        if ($ACT == 'profile') {
+            if(!$_SERVER['REMOTE_USER']) {
+                $ACT = 'login';
+            } else {
+                if(updateprofile()) {
+                    msg($lang['profchanged'],1);
+                    $ACT = 'show';
+                }
+            }
+        }
 
-    //cancel conflicting edit
-    if($ACT == 'cancel')
-      $ACT = 'show';
+        //revert
+        if($ACT == 'revert'){
+            if(checkSecurityToken()){
+                $ACT = act_revert($ACT);
+            }else{
+                $ACT = 'show';
+            }
+        }
 
-    //draft deletion
-    if($ACT == 'draftdel')
-      $ACT = act_draftdel($ACT);
+        //save
+        if($ACT == 'save'){
+            if(checkSecurityToken()){
+                $ACT = act_save($ACT);
+            }else{
+                $ACT = 'show';
+            }
+        }
 
-    //draft saving on preview
-    if($ACT == 'preview')
-      $ACT = act_draftsave($ACT);
+        //cancel conflicting edit
+        if($ACT == 'cancel')
+            $ACT = 'show';
 
-    //edit
-    if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){
-      $ACT = act_edit($ACT);
-    }else{
-      unlock($ID); //try to unlock
-    }
+        //draft deletion
+        if($ACT == 'draftdel')
+            $ACT = act_draftdel($ACT);
 
-    //handle export
-    if(substr($ACT,0,7) == 'export_')
-      $ACT = act_export($ACT);
+        //draft saving on preview
+        if($ACT == 'preview')
+            $ACT = act_draftsave($ACT);
 
-    //display some infos
-    if($ACT == 'check'){
-      check();
-      $ACT = 'show';
-    }
+        //edit
+        if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){
+            $ACT = act_edit($ACT);
+        }else{
+            unlock($ID); //try to unlock
+        }
 
-    //handle admin tasks
-    if($ACT == 'admin'){
-      // retrieve admin plugin name from $_REQUEST['page']
-      if (!empty($_REQUEST['page'])) {
-          $pluginlist = plugin_list('admin');
-          if (in_array($_REQUEST['page'], $pluginlist)) {
-            // attempt to load the plugin
-            if ($plugin =& plugin_load('admin',$_REQUEST['page']) !== NULL)
-                $plugin->handle();
-          }
-      }
-    }
+        //handle export
+        if(substr($ACT,0,7) == 'export_')
+            $ACT = act_export($ACT);
 
-    // check permissions again - the action may have changed
-    $ACT = act_permcheck($ACT);
-  }  // end event ACTION_ACT_PREPROCESS default action
-  $evt->advise_after();
-  unset($evt);
+        //display some infos
+        if($ACT == 'check'){
+            check();
+            $ACT = 'show';
+        }
 
-  // when action 'show', the intial not 'show' and POST, do a redirect
-  if($ACT == 'show' && $preact != 'show' && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){
-    act_redirect($ID,$preact);
-  }
+        //handle admin tasks
+        if($ACT == 'admin'){
+            // retrieve admin plugin name from $_REQUEST['page']
+            if (!empty($_REQUEST['page'])) {
+                $pluginlist = plugin_list('admin');
+                if (in_array($_REQUEST['page'], $pluginlist)) {
+                    // attempt to load the plugin
+                    if ($plugin =& plugin_load('admin',$_REQUEST['page']) !== null)
+                        $plugin->handle();
+                }
+            }
+        }
+
+        // check permissions again - the action may have changed
+        $ACT = act_permcheck($ACT);
+    }  // end event ACTION_ACT_PREPROCESS default action
+    $evt->advise_after();
+    unset($evt);
+
+    // when action 'show', the intial not 'show' and POST, do a redirect
+    if($ACT == 'show' && $preact != 'show' && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){
+        act_redirect($ID,$preact);
+    }
 
-  //call template FIXME: all needed vars available?
-  $headers[] = 'Content-Type: text/html; charset=utf-8';
-  trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
+    //call template FIXME: all needed vars available?
+    $headers[] = 'Content-Type: text/html; charset=utf-8';
+    trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
 
-  include(template('main.php'));
-  // output for the commands is now handled in inc/templates.php
-  // in function tpl_content()
+    include(template('main.php'));
+    // output for the commands is now handled in inc/templates.php
+    // in function tpl_content()
 }
 
 function act_sendheaders($headers) {
-  foreach ($headers as $hdr) header($hdr);
+    foreach ($headers as $hdr) header($hdr);
 }
 
 /**
@@ -171,44 +171,44 @@ function act_sendheaders($headers) {
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function act_clean($act){
-  global $lang;
-  global $conf;
+    global $lang;
+    global $conf;
 
-  // check if the action was given as array key
-  if(is_array($act)){
-    list($act) = array_keys($act);
-  }
+    // check if the action was given as array key
+    if(is_array($act)){
+        list($act) = array_keys($act);
+    }
 
-  //remove all bad chars
-  $act = strtolower($act);
-  $act = preg_replace('/[^1-9a-z_]+/','',$act);
+    //remove all bad chars
+    $act = strtolower($act);
+    $act = preg_replace('/[^1-9a-z_]+/','',$act);
 
-  if($act == 'export_html') $act = 'export_xhtml';
-  if($act == 'export_htmlbody') $act = 'export_xhtmlbody';
+    if($act == 'export_html') $act = 'export_xhtml';
+    if($act == 'export_htmlbody') $act = 'export_xhtmlbody';
 
-  // check if action is disabled
-  if(!actionOK($act)){
-    msg('Command disabled: '.htmlspecialchars($act),-1);
-    return 'show';
-  }
+    // check if action is disabled
+    if(!actionOK($act)){
+        msg('Command disabled: '.htmlspecialchars($act),-1);
+        return 'show';
+    }
 
-  //disable all acl related commands if ACL is disabled
-  if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
-                                             'subscribe','unsubscribe','profile','revert',
-                                             'resendpwd','subscribens','unsubscribens',))){
-    msg('Command unavailable: '.htmlspecialchars($act),-1);
-    return 'show';
-  }
-
-  if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
-                          'preview','search','show','check','index','revisions',
-                          'diff','recent','backlink','admin','subscribe','revert',
-                          'unsubscribe','profile','resendpwd','recover','wordblock',
-                          'draftdel','subscribens','unsubscribens',)) && substr($act,0,7) != 'export_' ) {
-    msg('Command unknown: '.htmlspecialchars($act),-1);
-    return 'show';
-  }
-  return $act;
+    //disable all acl related commands if ACL is disabled
+    if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
+                    'subscribe','unsubscribe','profile','revert',
+                    'resendpwd','subscribens','unsubscribens',))){
+        msg('Command unavailable: '.htmlspecialchars($act),-1);
+        return 'show';
+    }
+
+    if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
+                    'preview','search','show','check','index','revisions',
+                    'diff','recent','backlink','admin','subscribe','revert',
+                    'unsubscribe','profile','resendpwd','recover','wordblock',
+                    'draftdel','subscribens','unsubscribens',)) && substr($act,0,7) != 'export_' ) {
+        msg('Command unknown: '.htmlspecialchars($act),-1);
+        return 'show';
+    }
+    return $act;
 }
 
 /**
@@ -217,44 +217,44 @@ function act_clean($act){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function act_permcheck($act){
-  global $INFO;
-  global $conf;
-
-  if(in_array($act,array('save','preview','edit','recover'))){
-    if($INFO['exists']){
-      if($act == 'edit'){
-        //the edit function will check again and do a source show
-        //when no AUTH_EDIT available
-        $permneed = AUTH_READ;
-      }else{
-        $permneed = AUTH_EDIT;
-      }
-    }else{
-      $permneed = AUTH_CREATE;
-    }
-  }elseif(in_array($act,array('login','search','recent','profile'))){
-    $permneed = AUTH_NONE;
-  }elseif($act == 'revert'){
-    $permneed = AUTH_ADMIN;
-    if($INFO['ismanager']) $permneed = AUTH_EDIT;
-  }elseif($act == 'register'){
-    $permneed = AUTH_NONE;
-  }elseif($act == 'resendpwd'){
-    $permneed = AUTH_NONE;
-  }elseif($act == 'admin'){
-    if($INFO['ismanager']){
-      // if the manager has the needed permissions for a certain admin
-      // action is checked later
-      $permneed = AUTH_READ;
+    global $INFO;
+    global $conf;
+
+    if(in_array($act,array('save','preview','edit','recover'))){
+        if($INFO['exists']){
+            if($act == 'edit'){
+                //the edit function will check again and do a source show
+                //when no AUTH_EDIT available
+                $permneed = AUTH_READ;
+            }else{
+                $permneed = AUTH_EDIT;
+            }
+        }else{
+            $permneed = AUTH_CREATE;
+        }
+    }elseif(in_array($act,array('login','search','recent','profile'))){
+        $permneed = AUTH_NONE;
+    }elseif($act == 'revert'){
+        $permneed = AUTH_ADMIN;
+        if($INFO['ismanager']) $permneed = AUTH_EDIT;
+    }elseif($act == 'register'){
+        $permneed = AUTH_NONE;
+    }elseif($act == 'resendpwd'){
+        $permneed = AUTH_NONE;
+    }elseif($act == 'admin'){
+        if($INFO['ismanager']){
+            // if the manager has the needed permissions for a certain admin
+            // action is checked later
+            $permneed = AUTH_READ;
+        }else{
+            $permneed = AUTH_ADMIN;
+        }
     }else{
-      $permneed = AUTH_ADMIN;
+        $permneed = AUTH_READ;
     }
-  }else{
-    $permneed = AUTH_READ;
-  }
-  if($INFO['perm'] >= $permneed) return $act;
+    if($INFO['perm'] >= $permneed) return $act;
 
-  return 'denied';
+    return 'denied';
 }
 
 /**
@@ -263,10 +263,10 @@ function act_permcheck($act){
  * Deletes the draft for the current page and user
  */
 function act_draftdel($act){
-  global $INFO;
-  @unlink($INFO['draft']);
-  $INFO['draft'] = null;
-  return 'show';
+    global $INFO;
+    @unlink($INFO['draft']);
+    $INFO['draft'] = null;
+    return 'show';
 }
 
 /**
@@ -275,23 +275,23 @@ function act_draftdel($act){
  * @todo this currently duplicates code from ajax.php :-/
  */
 function act_draftsave($act){
-  global $INFO;
-  global $ID;
-  global $conf;
-  if($conf['usedraft'] && $_POST['wikitext']){
-    $draft = array('id'     => $ID,
-                   'prefix' => $_POST['prefix'],
-                   'text'   => $_POST['wikitext'],
-                   'suffix' => $_POST['suffix'],
-                   'date'   => $_POST['date'],
-                   'client' => $INFO['client'],
-                  );
-    $cname = getCacheName($draft['client'].$ID,'.draft');
-    if(io_saveFile($cname,serialize($draft))){
-      $INFO['draft'] = $cname;
+    global $INFO;
+    global $ID;
+    global $conf;
+    if($conf['usedraft'] && $_POST['wikitext']){
+        $draft = array('id'     => $ID,
+                'prefix' => $_POST['prefix'],
+                'text'   => $_POST['wikitext'],
+                'suffix' => $_POST['suffix'],
+                'date'   => $_POST['date'],
+                'client' => $INFO['client'],
+                );
+        $cname = getCacheName($draft['client'].$ID,'.draft');
+        if(io_saveFile($cname,serialize($draft))){
+            $INFO['draft'] = $cname;
+        }
     }
-  }
-  return $act;
+    return $act;
 }
 
 /**
@@ -304,31 +304,31 @@ function act_draftsave($act){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function act_save($act){
-  global $ID;
-  global $DATE;
-  global $PRE;
-  global $TEXT;
-  global $SUF;
-  global $SUM;
-
-  //spam check
-  if(checkwordblock())
-    return 'wordblock';
-  //conflict check //FIXME use INFO
-  if($DATE != 0 && @filemtime(wikiFN($ID)) > $DATE )
-    return 'conflict';
-
-  //save it
-  saveWikiText($ID,con($PRE,$TEXT,$SUF,1),$SUM,$_REQUEST['minor']); //use pretty mode for con
-  //unlock it
-  unlock($ID);
-
-  //delete draft
-  act_draftdel($act);
-  session_write_close();
-
-  // when done, show page
-  return 'show';
+    global $ID;
+    global $DATE;
+    global $PRE;
+    global $TEXT;
+    global $SUF;
+    global $SUM;
+
+    //spam check
+    if(checkwordblock())
+        return 'wordblock';
+    //conflict check //FIXME use INFO
+    if($DATE != 0 && @filemtime(wikiFN($ID)) > $DATE )
+        return 'conflict';
+
+    //save it
+    saveWikiText($ID,con($PRE,$TEXT,$SUF,1),$SUM,$_REQUEST['minor']); //use pretty mode for con
+    //unlock it
+    unlock($ID);
+
+    //delete draft
+    act_draftdel($act);
+    session_write_close();
+
+    // when done, show page
+    return 'show';
 }
 
 /**
@@ -374,38 +374,38 @@ function act_revert($act){
  * Tries to add the section id as hash mark after section editing
  */
 function act_redirect($id,$preact){
-  global $PRE;
-  global $TEXT;
-  global $MSG;
-
-  //are there any undisplayed messages? keep them in session for display
-  //on the next page
-  if(isset($MSG) && count($MSG)){
-    //reopen session, store data and close session again
-    @session_start();
-    $_SESSION[DOKU_COOKIE]['msg'] = $MSG;
-    session_write_close();
-  }
-
-  $opts = array(
-    'id'       => $id,
-    'preact'   => $preact
-  );
-  //get section name when coming from section edit
-  if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
-    $check = false; //Byref
-    $opts['fragment'] = sectionID($match[0], $check);
-  }
-
-  trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
+    global $PRE;
+    global $TEXT;
+    global $MSG;
+
+    //are there any undisplayed messages? keep them in session for display
+    //on the next page
+    if(isset($MSG) && count($MSG)){
+        //reopen session, store data and close session again
+        @session_start();
+        $_SESSION[DOKU_COOKIE]['msg'] = $MSG;
+        session_write_close();
+    }
+
+    $opts = array(
+            'id'       => $id,
+            'preact'   => $preact
+            );
+    //get section name when coming from section edit
+    if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
+        $check = false; //Byref
+        $opts['fragment'] = sectionID($match[0], $check);
+    }
+
+    trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
 }
 
 function act_redirect_execute($opts){
-  $go = wl($opts['id'],'',true);
-  if(isset($opts['fragment'])) $go .= '#'.$opts['fragment'];
+    $go = wl($opts['id'],'',true);
+    if(isset($opts['fragment'])) $go .= '#'.$opts['fragment'];
 
-  //show it
-  send_redirect($go);
+    //show it
+    send_redirect($go);
 }
 
 /**
@@ -414,30 +414,30 @@ function act_redirect_execute($opts){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function act_auth($act){
-  global $ID;
-  global $INFO;
+    global $ID;
+    global $INFO;
 
-  //already logged in?
-  if(isset($_SERVER['REMOTE_USER']) && $act=='login'){
-    return 'show';
-  }
+    //already logged in?
+    if(isset($_SERVER['REMOTE_USER']) && $act=='login'){
+        return 'show';
+    }
 
-  //handle logout
-  if($act=='logout'){
-    $lockedby = checklock($ID); //page still locked?
-    if($lockedby == $_SERVER['REMOTE_USER'])
-      unlock($ID); //try to unlock
+    //handle logout
+    if($act=='logout'){
+        $lockedby = checklock($ID); //page still locked?
+        if($lockedby == $_SERVER['REMOTE_USER'])
+            unlock($ID); //try to unlock
 
-    // do the logout stuff
-    auth_logoff();
+        // do the logout stuff
+        auth_logoff();
 
-    // rebuild info array
-    $INFO = pageinfo();
+        // rebuild info array
+        $INFO = pageinfo();
 
-    act_redirect($ID,'login');
-  }
+        act_redirect($ID,'login');
+    }
 
-  return $act;
+    return $act;
 }
 
 /**
@@ -446,15 +446,15 @@ function act_auth($act){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function act_edit($act){
-  global $ID;
-  global $INFO;
+    global $ID;
+    global $INFO;
 
-  //check if locked by anyone - if not lock for my self
-  $lockedby = checklock($ID);
-  if($lockedby) return 'locked';
+    //check if locked by anyone - if not lock for my self
+    $lockedby = checklock($ID);
+    if($lockedby) return 'locked';
 
-  lock($ID);
-  return $act;
+    lock($ID);
+    return $act;
 }
 
 /**
@@ -472,81 +472,81 @@ function act_edit($act){
  * @author Michael Klier <chi@chimeric.de>
  */
 function act_export($act){
-  global $ID;
-  global $REV;
-  global $conf;
-  global $lang;
-
-  $pre = '';
-  $post = '';
-  $output = '';
-  $headers = array();
-
-  // search engines: never cache exported docs! (Google only currently)
-  $headers['X-Robots-Tag'] = 'noindex';
-
-  $mode = substr($act,7);
-  switch($mode) {
-    case 'raw':
-      $headers['Content-Type'] = 'text/plain; charset=utf-8';
-      $headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
-      $output = rawWiki($ID,$REV);
-      break;
-    case 'xhtml':
-      $pre .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' . DOKU_LF;
-      $pre .= ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . DOKU_LF;
-      $pre .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"' . DOKU_LF;
-      $pre .= ' lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">' . DOKU_LF;
-      $pre .= '<head>' . DOKU_LF;
-      $pre .= '  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . DOKU_LF;
-      $pre .= '  <title>'.$ID.'</title>' . DOKU_LF;
-
-      // get metaheaders
-      ob_start();
-      tpl_metaheaders();
-      $pre .= ob_get_clean();
-
-      $pre .= '</head>' . DOKU_LF;
-      $pre .= '<body>' . DOKU_LF;
-      $pre .= '<div class="dokuwiki export">' . DOKU_LF;
-
-      // get toc
-      $pre .= tpl_toc(true);
-
-      $headers['Content-Type'] = 'text/html; charset=utf-8';
-      $output = p_wiki_xhtml($ID,$REV,false);
-
-      $post .= '</div>' . DOKU_LF;
-      $post .= '</body>' . DOKU_LF;
-      $post .= '</html>' . DOKU_LF;
-      break;
-    case 'xhtmlbody':
-      $headers['Content-Type'] = 'text/html; charset=utf-8';
-      $output = p_wiki_xhtml($ID,$REV,false);
-      break;
-    default:
-      $output = p_cached_output(wikiFN($ID,$REV), $mode);
-      $headers = p_get_metadata($ID,"format $mode");
-      break;
-  }
-
-  // prepare event data
-  $data = array();
-  $data['id'] = $ID;
-  $data['mode'] = $mode;
-  $data['headers'] = $headers;
-  $data['output'] =& $output;
-
-  trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
-
-  if(!empty($data['output'])){
-    if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
-      header("$key: $val");
+    global $ID;
+    global $REV;
+    global $conf;
+    global $lang;
+
+    $pre = '';
+    $post = '';
+    $output = '';
+    $headers = array();
+
+    // search engines: never cache exported docs! (Google only currently)
+    $headers['X-Robots-Tag'] = 'noindex';
+
+    $mode = substr($act,7);
+    switch($mode) {
+        case 'raw':
+            $headers['Content-Type'] = 'text/plain; charset=utf-8';
+            $headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
+            $output = rawWiki($ID,$REV);
+            break;
+        case 'xhtml':
+            $pre .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' . DOKU_LF;
+            $pre .= ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . DOKU_LF;
+            $pre .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"' . DOKU_LF;
+            $pre .= ' lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">' . DOKU_LF;
+            $pre .= '<head>' . DOKU_LF;
+            $pre .= '  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . DOKU_LF;
+            $pre .= '  <title>'.$ID.'</title>' . DOKU_LF;
+
+            // get metaheaders
+            ob_start();
+            tpl_metaheaders();
+            $pre .= ob_get_clean();
+
+            $pre .= '</head>' . DOKU_LF;
+            $pre .= '<body>' . DOKU_LF;
+            $pre .= '<div class="dokuwiki export">' . DOKU_LF;
+
+            // get toc
+            $pre .= tpl_toc(true);
+
+            $headers['Content-Type'] = 'text/html; charset=utf-8';
+            $output = p_wiki_xhtml($ID,$REV,false);
+
+            $post .= '</div>' . DOKU_LF;
+            $post .= '</body>' . DOKU_LF;
+            $post .= '</html>' . DOKU_LF;
+            break;
+        case 'xhtmlbody':
+            $headers['Content-Type'] = 'text/html; charset=utf-8';
+            $output = p_wiki_xhtml($ID,$REV,false);
+            break;
+        default:
+            $output = p_cached_output(wikiFN($ID,$REV), $mode);
+            $headers = p_get_metadata($ID,"format $mode");
+            break;
     }
-    print $pre.$data['output'].$post;
-    exit;
-  }
-  return 'show';
+
+    // prepare event data
+    $data = array();
+    $data['id'] = $ID;
+    $data['mode'] = $mode;
+    $data['headers'] = $headers;
+    $data['output'] =& $output;
+
+    trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
+
+    if(!empty($data['output'])){
+        if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
+            header("$key: $val");
+        }
+        print $pre.$data['output'].$post;
+        exit;
+    }
+    return 'show';
 }
 
 /**
@@ -556,32 +556,32 @@ function act_export($act){
  * @todo   localize
  */
 function act_subscription($act){
-  global $ID;
-  global $INFO;
-  global $lang;
-
-  $file=metaFN($ID,'.mlist');
-  if ($act=='subscribe' && !$INFO['subscribed']){
-    if ($INFO['userinfo']['mail']){
-      if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
-        $INFO['subscribed'] = true;
-        msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
-      } else {
-        msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
-      }
-    } else {
-      msg($lang['subscribe_noaddress']);
-    }
-  } elseif ($act=='unsubscribe' && $INFO['subscribed']){
-    if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
-      $INFO['subscribed'] = false;
-      msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
-    } else {
-      msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
+    global $ID;
+    global $INFO;
+    global $lang;
+
+    $file=metaFN($ID,'.mlist');
+    if ($act=='subscribe' && !$INFO['subscribed']){
+        if ($INFO['userinfo']['mail']){
+            if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
+                $INFO['subscribed'] = true;
+                msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
+            } else {
+                msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
+            }
+        } else {
+            msg($lang['subscribe_noaddress']);
+        }
+    } elseif ($act=='unsubscribe' && $INFO['subscribed']){
+        if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
+            $INFO['subscribed'] = false;
+            msg(sprintf($lang[$act.'_success'], $INFO['userinfo']['name'], $ID),1);
+        } else {
+            msg(sprintf($lang[$act.'_error'], $INFO['userinfo']['name'], $ID),1);
+        }
     }
-  }
 
-  return 'show';
+    return 'show';
 }
 
 /**
@@ -589,42 +589,42 @@ function act_subscription($act){
  *
  */
 function act_subscriptionns($act){
-  global $ID;
-  global $INFO;
-  global $lang;
-
-  if(!getNS($ID)) {
-    $file = metaFN(getNS($ID),'.mlist');
-    $ns = "root";
-  } else {
-    $file = metaFN(getNS($ID),'/.mlist');
-    $ns = getNS($ID);
-  }
-
-  // reuse strings used to display the status of the subscribe action
-  $act_msg = rtrim($act, 'ns');
-
-  if ($act=='subscribens' && !$INFO['subscribedns']){
-    if ($INFO['userinfo']['mail']){
-      if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
-        $INFO['subscribedns'] = true;
-        msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
-      } else {
-        msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
-      }
+    global $ID;
+    global $INFO;
+    global $lang;
+
+    if(!getNS($ID)) {
+        $file = metaFN(getNS($ID),'.mlist');
+        $ns = "root";
     } else {
-      msg($lang['subscribe_noaddress']);
+        $file = metaFN(getNS($ID),'/.mlist');
+        $ns = getNS($ID);
     }
-  } elseif ($act=='unsubscribens' && $INFO['subscribedns']){
-    if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
-      $INFO['subscribedns'] = false;
-      msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
-    } else {
-      msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
+
+    // reuse strings used to display the status of the subscribe action
+    $act_msg = rtrim($act, 'ns');
+
+    if ($act=='subscribens' && !$INFO['subscribedns']){
+        if ($INFO['userinfo']['mail']){
+            if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
+                $INFO['subscribedns'] = true;
+                msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
+            } else {
+                msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
+            }
+        } else {
+            msg($lang['subscribe_noaddress']);
+        }
+    } elseif ($act=='unsubscribens' && $INFO['subscribedns']){
+        if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
+            $INFO['subscribedns'] = false;
+            msg(sprintf($lang[$act_msg.'_success'], $INFO['userinfo']['name'], $ns),1);
+        } else {
+            msg(sprintf($lang[$act_msg.'_error'], $INFO['userinfo']['name'], $ns),1);
+        }
     }
-  }
 
-  return 'show';
+    return 'show';
 }
 
 //Setup VIM: ex: et ts=2 enc=utf-8 :
diff --git a/inc/cache.php b/inc/cache.php
index 8e8adfd6d..2e22edfb1 100644
--- a/inc/cache.php
+++ b/inc/cache.php
@@ -12,281 +12,281 @@ require_once(DOKU_INC.'inc/pageutils.php');
 require_once(DOKU_INC.'inc/parserutils.php');
 
 class cache {
-  var $key = '';          // primary identifier for this item
-  var $ext = '';          // file ext for cache data, secondary identifier for this item
-  var $cache = '';        // cache file name
-  var $depends = array(); // array containing cache dependency information,
-                          //   used by _useCache to determine cache validity
-
-  var $_event = '';       // event to be triggered during useCache
-
-  function cache($key,$ext) {
-    $this->key = $key;
-    $this->ext = $ext;
-    $this->cache = getCacheName($key,$ext);
-  }
-
-  /**
-   * public method to determine whether the cache can be used
-   *
-   * to assist in cetralisation of event triggering and calculation of cache statistics,
-   * don't override this function override _useCache()
-   *
-   * @param  array   $depends   array of cache dependencies, support dependecies:
-   *                            'age'   => max age of the cache in seconds
-   *                            'files' => cache must be younger than mtime of each file
-   *                                       (nb. dependency passes if file doesn't exist)
-   *
-   * @return bool    true if cache can be used, false otherwise
-   */
-  function useCache($depends=array()) {
-    $this->depends = $depends;
-    $this->_addDependencies();
-
-    if ($this->_event) {
-      return $this->_stats(trigger_event($this->_event,$this,array($this,'_useCache')));
-    } else {
-      return $this->_stats($this->_useCache());
+    var $key = '';          // primary identifier for this item
+    var $ext = '';          // file ext for cache data, secondary identifier for this item
+    var $cache = '';        // cache file name
+    var $depends = array(); // array containing cache dependency information,
+    //   used by _useCache to determine cache validity
+
+    var $_event = '';       // event to be triggered during useCache
+
+    function cache($key,$ext) {
+        $this->key = $key;
+        $this->ext = $ext;
+        $this->cache = getCacheName($key,$ext);
     }
-  }
-
-  /**
-   * private method containing cache use decision logic
-   *
-   * this function processes the following keys in the depends array
-   *   purge - force a purge on any non empty value
-   *   age   - expire cache if older than age (seconds)
-   *   files - expire cache if any file in this array was updated more recently than the cache
-   *
-   * can be overridden
-   *
-   * @return bool               see useCache()
-   */
-  function _useCache() {
-
-    if (!empty($this->depends['purge'])) return false;              // purge requested?
-    if (!($this->_time = @filemtime($this->cache))) return false;   // cache exists?
-
-    // cache too old?
-    if (!empty($this->depends['age']) && ((time() - $this->_time) > $this->depends['age'])) return false;
-
-    if (!empty($this->depends['files'])) {
-      foreach ($this->depends['files'] as $file) {
-        if ($this->_time < @filemtime($file)) return false;         // cache older than files it depends on?
-      }
+
+    /**
+     * public method to determine whether the cache can be used
+     *
+     * to assist in cetralisation of event triggering and calculation of cache statistics,
+     * don't override this function override _useCache()
+     *
+     * @param  array   $depends   array of cache dependencies, support dependecies:
+     *                            'age'   => max age of the cache in seconds
+     *                            'files' => cache must be younger than mtime of each file
+     *                                       (nb. dependency passes if file doesn't exist)
+     *
+     * @return bool    true if cache can be used, false otherwise
+     */
+    function useCache($depends=array()) {
+        $this->depends = $depends;
+        $this->_addDependencies();
+
+        if ($this->_event) {
+            return $this->_stats(trigger_event($this->_event,$this,array($this,'_useCache')));
+        } else {
+            return $this->_stats($this->_useCache());
+        }
+    }
+
+    /**
+     * private method containing cache use decision logic
+     *
+     * this function processes the following keys in the depends array
+     *   purge - force a purge on any non empty value
+     *   age   - expire cache if older than age (seconds)
+     *   files - expire cache if any file in this array was updated more recently than the cache
+     *
+     * can be overridden
+     *
+     * @return bool               see useCache()
+     */
+    function _useCache() {
+
+        if (!empty($this->depends['purge'])) return false;              // purge requested?
+        if (!($this->_time = @filemtime($this->cache))) return false;   // cache exists?
+
+        // cache too old?
+        if (!empty($this->depends['age']) && ((time() - $this->_time) > $this->depends['age'])) return false;
+
+        if (!empty($this->depends['files'])) {
+            foreach ($this->depends['files'] as $file) {
+                if ($this->_time < @filemtime($file)) return false;         // cache older than files it depends on?
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * add dependencies to the depends array
+     *
+     * this method should only add dependencies,
+     * it should not remove any existing dependencies and
+     * it should only overwrite a dependency when the new value is more stringent than the old
+     */
+    function _addDependencies() {
+        if (isset($_REQUEST['purge'])) $this->depends['purge'] = true;   // purge requested
     }
 
-    return true;
-  }
-
-  /**
-   * add dependencies to the depends array
-   *
-   * this method should only add dependencies,
-   * it should not remove any existing dependencies and
-   * it should only overwrite a dependency when the new value is more stringent than the old
-   */
-  function _addDependencies() {
-    if (isset($_REQUEST['purge'])) $this->depends['purge'] = true;   // purge requested
-  }
-
-  /**
-   * retrieve the cached data
-   *
-   * @param   bool   $clean   true to clean line endings, false to leave line endings alone
-   * @return  string          cache contents
-   */
-  function retrieveCache($clean=true) {
-    return io_readFile($this->cache, $clean);
-  }
-
-  /**
-   * cache $data
-   *
-   * @param   string $data   the data to be cached
-   * @return  bool           true on success, false otherwise
-   */
-  function storeCache($data) {
-    return io_savefile($this->cache, $data);
-  }
-
-  /**
-   * remove any cached data associated with this cache instance
-   */
-  function removeCache() {
-    @unlink($this->cache);
-  }
-
-  /**
-   * Record cache hits statistics.
-   * (Only when debugging allowed, to reduce overhead.)
-   *
-   * @param    bool   $success   result of this cache use attempt
-   * @return   bool              pass-thru $success value
-   */
-  function _stats($success) {
-    global $conf;
-    static $stats = NULL;
-    static $file;
-
-    if (!$conf['allowdebug']) { return $success; }
-
-    if (is_null($stats)) {
-      $file = $conf['cachedir'].'/cache_stats.txt';
-      $lines = explode("\n",io_readFile($file));
-
-      foreach ($lines as $line) {
-        $i = strpos($line,',');
-        $stats[substr($line,0,$i)] = $line;
-      }
+    /**
+     * retrieve the cached data
+     *
+     * @param   bool   $clean   true to clean line endings, false to leave line endings alone
+     * @return  string          cache contents
+     */
+    function retrieveCache($clean=true) {
+        return io_readFile($this->cache, $clean);
     }
 
-    if (isset($stats[$this->ext])) {
-      list($ext,$count,$hits) = explode(',',$stats[$this->ext]);
-    } else {
-      $ext = $this->ext;
-      $count = 0;
-      $hits = 0;
+    /**
+     * cache $data
+     *
+     * @param   string $data   the data to be cached
+     * @return  bool           true on success, false otherwise
+     */
+    function storeCache($data) {
+        return io_savefile($this->cache, $data);
     }
 
-    $count++;
-    if ($success) $hits++;
-    $stats[$this->ext] = "$ext,$count,$hits";
+    /**
+     * remove any cached data associated with this cache instance
+     */
+    function removeCache() {
+        @unlink($this->cache);
+    }
+
+    /**
+     * Record cache hits statistics.
+     * (Only when debugging allowed, to reduce overhead.)
+     *
+     * @param    bool   $success   result of this cache use attempt
+     * @return   bool              pass-thru $success value
+     */
+    function _stats($success) {
+        global $conf;
+        static $stats = null;
+        static $file;
+
+        if (!$conf['allowdebug']) { return $success; }
+
+        if (is_null($stats)) {
+            $file = $conf['cachedir'].'/cache_stats.txt';
+            $lines = explode("\n",io_readFile($file));
+
+            foreach ($lines as $line) {
+                $i = strpos($line,',');
+                $stats[substr($line,0,$i)] = $line;
+            }
+        }
+
+        if (isset($stats[$this->ext])) {
+            list($ext,$count,$hits) = explode(',',$stats[$this->ext]);
+        } else {
+            $ext = $this->ext;
+            $count = 0;
+            $hits = 0;
+        }
+
+        $count++;
+        if ($success) $hits++;
+        $stats[$this->ext] = "$ext,$count,$hits";
 
-    io_saveFile($file,join("\n",$stats));
+        io_saveFile($file,join("\n",$stats));
 
-    return $success;
-  }
+        return $success;
+    }
 }
 
 class cache_parser extends cache {
 
-  var $file = '';       // source file for cache
-  var $mode = '';       // input mode (represents the processing the input file will undergo)
+    var $file = '';       // source file for cache
+    var $mode = '';       // input mode (represents the processing the input file will undergo)
 
-  var $_event = 'PARSER_CACHE_USE';
+    var $_event = 'PARSER_CACHE_USE';
 
-  function cache_parser($id, $file, $mode) {
-    if ($id) $this->page = $id;
-    $this->file = $file;
-    $this->mode = $mode;
+    function cache_parser($id, $file, $mode) {
+        if ($id) $this->page = $id;
+        $this->file = $file;
+        $this->mode = $mode;
 
-    parent::cache($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.'.$mode);
-  }
+        parent::cache($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.'.$mode);
+    }
 
-  function _useCache() {
+    function _useCache() {
 
-    if (!@file_exists($this->file)) return false;                   // source exists?
-    return parent::_useCache();
-  }
+        if (!@file_exists($this->file)) return false;                   // source exists?
+        return parent::_useCache();
+    }
 
-  function _addDependencies() {
-    global $conf, $config_cascade;
+    function _addDependencies() {
+        global $conf, $config_cascade;
 
-    $this->depends['age'] = isset($this->depends['age']) ?
-                   min($this->depends['age'],$conf['cachetime']) : $conf['cachetime'];
+        $this->depends['age'] = isset($this->depends['age']) ?
+            min($this->depends['age'],$conf['cachetime']) : $conf['cachetime'];
 
-    // parser cache file dependencies ...
-    $files = array($this->file,                                     // ... source
-                   DOKU_INC.'inc/parser/parser.php',                // ... parser
-                   DOKU_INC.'inc/parser/handler.php',               // ... handler
-             );
-    $files = array_merge($files, getConfigFiles('main'));           // ... wiki settings
+        // parser cache file dependencies ...
+        $files = array($this->file,                                     // ... source
+                DOKU_INC.'inc/parser/parser.php',                // ... parser
+                DOKU_INC.'inc/parser/handler.php',               // ... handler
+                );
+        $files = array_merge($files, getConfigFiles('main'));           // ... wiki settings
 
-    $this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
-    parent::_addDependencies();
-  }
+        $this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
+        parent::_addDependencies();
+    }
 
 }
 
 class cache_renderer extends cache_parser {
 
-  function useCache($depends=array()) {
-    $use = parent::useCache($depends);
+    function useCache($depends=array()) {
+        $use = parent::useCache($depends);
+
+        // meta data needs to be kept in step with the cache
+        if (!$use && isset($this->page)) {
+            p_set_metadata($this->page,array(),true);
+        }
 
-    // meta data needs to be kept in step with the cache
-    if (!$use && isset($this->page)) {
-      p_set_metadata($this->page,array(),true);
+        return $use;
     }
 
-    return $use;
-  }
+    function _useCache() {
+        global $conf;
 
-  function _useCache() {
-    global $conf;
+        if (!parent::_useCache()) return false;
 
-    if (!parent::_useCache()) return false;
+        if (!isset($this->page)) {
+            return true;
+        }
 
-    if (!isset($this->page)) {
-      return true;
-    }
+        // check current link existence is consistent with cache version
+        // first check the purgefile
+        // - if the cache is more recent than the purgefile we know no links can have been updated
+        if ($this->_time >= @filemtime($conf['cachedir'].'/purgefile')) {
+            return true;
+        }
 
-    // check current link existence is consistent with cache version
-    // first check the purgefile
-    // - if the cache is more recent than the purgefile we know no links can have been updated
-    if ($this->_time >= @filemtime($conf['cachedir'].'/purgefile')) {
-      return true;
-    }
+        // for wiki pages, check metadata dependencies
+        $metadata = p_get_metadata($this->page);
 
-    // for wiki pages, check metadata dependencies
-    $metadata = p_get_metadata($this->page);
+        if (!isset($metadata['relation']['references']) ||
+                empty($metadata['relation']['references'])) {
+            return true;
+        }
 
-    if (!isset($metadata['relation']['references']) ||
-         empty($metadata['relation']['references'])) {
-      return true;
-    }
+        foreach ($metadata['relation']['references'] as $id => $exists) {
+            if ($exists != page_exists($id,'',false)) return false;
+        }
 
-    foreach ($metadata['relation']['references'] as $id => $exists) {
-      if ($exists != page_exists($id,'',false)) return false;
+        return true;
     }
 
-    return true;
-  }
+    function _addDependencies() {
 
-  function _addDependencies() {
+        // renderer cache file dependencies ...
+        $files = array(
+                DOKU_INC.'inc/parser/'.$this->mode.'.php',       // ... the renderer
+                );
 
-    // renderer cache file dependencies ...
-    $files = array(
-                   DOKU_INC.'inc/parser/'.$this->mode.'.php',       // ... the renderer
-             );
+        // page implies metadata and possibly some other dependencies
+        if (isset($this->page)) {
 
-    // page implies metadata and possibly some other dependencies
-    if (isset($this->page)) {
+            $metafile = metaFN($this->page,'.meta');
+            if (@file_exists($metafile)) {
+                $files[] = $metafile;                                       // ... the page's own metadata
+                $files[] = DOKU_INC.'inc/parser/metadata.php';              // ... the metadata renderer
 
-      $metafile = metaFN($this->page,'.meta');
-      if (@file_exists($metafile)) {
-        $files[] = $metafile;                                       // ... the page's own metadata
-        $files[] = DOKU_INC.'inc/parser/metadata.php';              // ... the metadata renderer
+                $valid = p_get_metadata($this->page, 'date valid');
+                if (!empty($valid['age'])) {
+                    $this->depends['age'] = isset($this->depends['age']) ?
+                        min($this->depends['age'],$valid['age']) : $valid['age'];
+                }
 
-        $valid = p_get_metadata($this->page, 'date valid');
-        if (!empty($valid['age'])) {
-          $this->depends['age'] = isset($this->depends['age']) ?
-                   min($this->depends['age'],$valid['age']) : $valid['age'];
+            } else {
+                $this->depends['purge'] = true;                             // ... purging cache will generate metadata
+                return;
+            }
         }
 
-      } else {
-        $this->depends['purge'] = true;                             // ... purging cache will generate metadata
-        return;
-      }
+        $this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
+        parent::_addDependencies();
     }
-
-    $this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
-    parent::_addDependencies();
-  }
 }
 
 class cache_instructions extends cache_parser {
 
-  function cache_instructions($id, $file) {
-    parent::cache_parser($id, $file, 'i');
-  }
+    function cache_instructions($id, $file) {
+        parent::cache_parser($id, $file, 'i');
+    }
 
-  function retrieveCache($clean=true) {
-    $contents = io_readFile($this->cache, false);
-    return !empty($contents) ? unserialize($contents) : array();
-  }
+    function retrieveCache($clean=true) {
+        $contents = io_readFile($this->cache, false);
+        return !empty($contents) ? unserialize($contents) : array();
+    }
 
-  function storeCache($instructions) {
-    return io_savefile($this->cache,serialize($instructions));
-  }
+    function storeCache($instructions) {
+        return io_savefile($this->cache,serialize($instructions));
+    }
 }
diff --git a/inc/changelog.php b/inc/changelog.php
index bc2af2de3..d4130ac99 100644
--- a/inc/changelog.php
+++ b/inc/changelog.php
@@ -20,18 +20,18 @@ define('DOKU_CHANGE_TYPE_REVERT',       'R');
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function parseChangelogLine($line) {
-  $tmp = explode("\t", $line);
+    $tmp = explode("\t", $line);
     if ($tmp!==false && count($tmp)>1) {
-      $info = array();
-      $info['date']  = (int)$tmp[0]; // unix timestamp
-      $info['ip']    = $tmp[1]; // IPv4 address (127.0.0.1)
-      $info['type']  = $tmp[2]; // log line type
-      $info['id']    = $tmp[3]; // page id
-      $info['user']  = $tmp[4]; // user name
-      $info['sum']   = $tmp[5]; // edit summary (or action reason)
-      $info['extra'] = rtrim($tmp[6], "\n"); // extra data (varies by line type)
-      return $info;
-  } else { return false; }
+        $info = array();
+        $info['date']  = (int)$tmp[0]; // unix timestamp
+        $info['ip']    = $tmp[1]; // IPv4 address (127.0.0.1)
+        $info['type']  = $tmp[2]; // log line type
+        $info['id']    = $tmp[3]; // page id
+        $info['user']  = $tmp[4]; // user name
+        $info['sum']   = $tmp[5]; // edit summary (or action reason)
+        $info['extra'] = rtrim($tmp[6], "\n"); // extra data (varies by line type)
+        return $info;
+    } else { return false; }
 }
 
 /**
@@ -42,57 +42,57 @@ function parseChangelogLine($line) {
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null){
-  global $conf, $INFO;
-
-  // check for special flags as keys
-  if (!is_array($flags)) { $flags = array(); }
-  $flagExternalEdit = isset($flags['ExternalEdit']);
-
-  $id = cleanid($id);
-  $file = wikiFN($id);
-  $created = @filectime($file);
-  $minor = ($type===DOKU_CHANGE_TYPE_MINOR_EDIT);
-  $wasRemoved = ($type===DOKU_CHANGE_TYPE_DELETE);
-
-  if(!$date) $date = time(); //use current time if none supplied
-  $remote = (!$flagExternalEdit)?clientIP(true):'127.0.0.1';
-  $user   = (!$flagExternalEdit)?$_SERVER['REMOTE_USER']:'';
-
-  $strip = array("\t", "\n");
-  $logline = array(
-    'date'  => $date,
-    'ip'    => $remote,
-    'type'  => str_replace($strip, '', $type),
-    'id'    => $id,
-    'user'  => $user,
-    'sum'   => str_replace($strip, '', $summary),
-    'extra' => str_replace($strip, '', $extra)
-  );
-
-  // update metadata
-  if (!$wasRemoved) {
-    $oldmeta = p_read_metadata($id);
-    $meta    = array();
-    if (!$INFO['exists'] && empty($oldmeta['persistent']['date']['created'])){ // newly created
-      $meta['date']['created'] = $created;
-      if ($user) $meta['creator'] = $INFO['userinfo']['name'];
-    } elseif (!$INFO['exists'] && !empty($oldmeta['persistent']['date']['created'])) { // re-created / restored
-      $meta['date']['created']  = $oldmeta['persistent']['date']['created'];
-      $meta['date']['modified'] = $created; // use the files ctime here
-      $meta['creator'] = $oldmeta['persistent']['creator'];
-      if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
-    } elseif (!$minor) {   // non-minor modification
-      $meta['date']['modified'] = $date;
-      if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
+    global $conf, $INFO;
+
+    // check for special flags as keys
+    if (!is_array($flags)) { $flags = array(); }
+    $flagExternalEdit = isset($flags['ExternalEdit']);
+
+    $id = cleanid($id);
+    $file = wikiFN($id);
+    $created = @filectime($file);
+    $minor = ($type===DOKU_CHANGE_TYPE_MINOR_EDIT);
+    $wasRemoved = ($type===DOKU_CHANGE_TYPE_DELETE);
+
+    if(!$date) $date = time(); //use current time if none supplied
+    $remote = (!$flagExternalEdit)?clientIP(true):'127.0.0.1';
+    $user   = (!$flagExternalEdit)?$_SERVER['REMOTE_USER']:'';
+
+    $strip = array("\t", "\n");
+    $logline = array(
+            'date'  => $date,
+            'ip'    => $remote,
+            'type'  => str_replace($strip, '', $type),
+            'id'    => $id,
+            'user'  => $user,
+            'sum'   => str_replace($strip, '', $summary),
+            'extra' => str_replace($strip, '', $extra)
+            );
+
+    // update metadata
+    if (!$wasRemoved) {
+        $oldmeta = p_read_metadata($id);
+        $meta    = array();
+        if (!$INFO['exists'] && empty($oldmeta['persistent']['date']['created'])){ // newly created
+            $meta['date']['created'] = $created;
+            if ($user) $meta['creator'] = $INFO['userinfo']['name'];
+        } elseif (!$INFO['exists'] && !empty($oldmeta['persistent']['date']['created'])) { // re-created / restored
+            $meta['date']['created']  = $oldmeta['persistent']['date']['created'];
+            $meta['date']['modified'] = $created; // use the files ctime here
+            $meta['creator'] = $oldmeta['persistent']['creator'];
+            if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
+        } elseif (!$minor) {   // non-minor modification
+            $meta['date']['modified'] = $date;
+            if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
+        }
+        $meta['last_change'] = $logline;
+        p_set_metadata($id, $meta, true);
     }
-    $meta['last_change'] = $logline;
-    p_set_metadata($id, $meta, true);
-  }
-
-  // add changelog lines
-  $logline = implode("\t", $logline)."\n";
-  io_saveFile(metaFN($id,'.changes'),$logline,true); //page changelog
-  io_saveFile($conf['changelog'],$logline,true); //global changelog cache
+
+    // add changelog lines
+    $logline = implode("\t", $logline)."\n";
+    io_saveFile(metaFN($id,'.changes'),$logline,true); //page changelog
+    io_saveFile($conf['changelog'],$logline,true); //global changelog cache
 }
 
 /**
@@ -104,28 +104,28 @@ function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extr
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function addMediaLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null){
-  global $conf, $INFO;
-
-  $id = cleanid($id);
-
-  if(!$date) $date = time(); //use current time if none supplied
-  $remote = clientIP(true);
-  $user   = $_SERVER['REMOTE_USER'];
-
-  $strip = array("\t", "\n");
-  $logline = array(
-    'date'  => $date,
-    'ip'    => $remote,
-    'type'  => str_replace($strip, '', $type),
-    'id'    => $id,
-    'user'  => $user,
-    'sum'   => str_replace($strip, '', $summary),
-    'extra' => str_replace($strip, '', $extra)
-  );
-
-  // add changelog lines
-  $logline = implode("\t", $logline)."\n";
-  io_saveFile($conf['media_changelog'],$logline,true); //global media changelog cache
+    global $conf, $INFO;
+
+    $id = cleanid($id);
+
+    if(!$date) $date = time(); //use current time if none supplied
+    $remote = clientIP(true);
+    $user   = $_SERVER['REMOTE_USER'];
+
+    $strip = array("\t", "\n");
+    $logline = array(
+            'date'  => $date,
+            'ip'    => $remote,
+            'type'  => str_replace($strip, '', $type),
+            'id'    => $id,
+            'user'  => $user,
+            'sum'   => str_replace($strip, '', $summary),
+            'extra' => str_replace($strip, '', $extra)
+            );
+
+    // add changelog lines
+    $logline = implode("\t", $logline)."\n";
+    io_saveFile($conf['media_changelog'],$logline,true); //global media changelog cache
 }
 
 /**
@@ -148,35 +148,34 @@ function addMediaLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='',
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function getRecents($first,$num,$ns='',$flags=0){
-  global $conf;
-  $recent = array();
-  $count  = 0;
-
-  if(!$num)
-    return $recent;
+    global $conf;
+    $recent = array();
+    $count  = 0;
+
+    if(!$num)
+        return $recent;
+
+    // read all recent changes. (kept short)
+    if ($flags & RECENTS_MEDIA_CHANGES) {
+        $lines = @file($conf['media_changelog']);
+    } else {
+        $lines = @file($conf['changelog']);
+    }
 
-  // read all recent changes. (kept short)
-  if ($flags & RECENTS_MEDIA_CHANGES) {
-    $lines = @file($conf['media_changelog']);
-  } else {
-    $lines = @file($conf['changelog']);
-  }
-
-
-  // handle lines
-  $seen = array(); // caches seen lines, _handleRecent() skips them
-  for($i = count($lines)-1; $i >= 0; $i--){
-    $rec = _handleRecent($lines[$i], $ns, $flags, $seen);
-    if($rec !== false) {
-      if(--$first >= 0) continue; // skip first entries
-      $recent[] = $rec;
-      $count++;
-      // break when we have enough entries
-      if($count >= $num){ break; }
+    // handle lines
+    $seen = array(); // caches seen lines, _handleRecent() skips them
+    for($i = count($lines)-1; $i >= 0; $i--){
+        $rec = _handleRecent($lines[$i], $ns, $flags, $seen);
+        if($rec !== false) {
+            if(--$first >= 0) continue; // skip first entries
+            $recent[] = $rec;
+            $count++;
+            // break when we have enough entries
+            if($count >= $num){ break; }
+        }
     }
-  }
 
-  return $recent;
+    return $recent;
 }
 
 /**
@@ -200,39 +199,39 @@ function getRecents($first,$num,$ns='',$flags=0){
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function getRecentsSince($from,$to=null,$ns='',$flags=0){
-  global $conf;
-  $recent = array();
+    global $conf;
+    $recent = array();
 
-  if($to && $to < $from)
-    return $recent;
+    if($to && $to < $from)
+        return $recent;
+
+    // read all recent changes. (kept short)
+    if ($flags & RECENTS_MEDIA_CHANGES) {
+        $lines = @file($conf['media_changelog']);
+    } else {
+        $lines = @file($conf['changelog']);
+    }
 
-  // read all recent changes. (kept short)
-  if ($flags & RECENTS_MEDIA_CHANGES) {
-    $lines = @file($conf['media_changelog']);
-  } else {
-    $lines = @file($conf['changelog']);
-  }
-
-  // we start searching at the end of the list
-  $lines = array_reverse($lines);
-
-  // handle lines
-  $seen = array(); // caches seen lines, _handleRecent() skips them
-
-  foreach($lines as $line){
-    $rec = _handleRecent($line, $ns, $flags, $seen);
-    if($rec !== false) {
-      if ($rec['date'] >= $from) {
-        if (!$to || $rec['date'] <= $to) {
-          $recent[] = $rec;
+    // we start searching at the end of the list
+    $lines = array_reverse($lines);
+
+    // handle lines
+    $seen = array(); // caches seen lines, _handleRecent() skips them
+
+    foreach($lines as $line){
+        $rec = _handleRecent($line, $ns, $flags, $seen);
+        if($rec !== false) {
+            if ($rec['date'] >= $from) {
+                if (!$to || $rec['date'] <= $to) {
+                    $recent[] = $rec;
+                }
+            } else {
+                break;
+            }
         }
-      } else {
-        break;
-      }
     }
-  }
 
-  return array_reverse($recent);
+    return array_reverse($recent);
 }
 
 /**
@@ -245,39 +244,39 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function _handleRecent($line,$ns,$flags,&$seen){
-  if(empty($line)) return false;   //skip empty lines
+    if(empty($line)) return false;   //skip empty lines
 
-  // split the line into parts
-  $recent = parseChangelogLine($line);
-  if ($recent===false) { return false; }
+    // split the line into parts
+    $recent = parseChangelogLine($line);
+    if ($recent===false) { return false; }
 
-  // skip seen ones
-  if(isset($seen[$recent['id']])) return false;
+    // skip seen ones
+    if(isset($seen[$recent['id']])) return false;
 
-  // skip minors
-  if($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT && ($flags & RECENTS_SKIP_MINORS)) return false;
+    // skip minors
+    if($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT && ($flags & RECENTS_SKIP_MINORS)) return false;
 
-  // remember in seen to skip additional sights
-  $seen[$recent['id']] = 1;
+    // remember in seen to skip additional sights
+    $seen[$recent['id']] = 1;
 
-  // check if it's a hidden page
-  if(isHiddenPage($recent['id'])) return false;
+    // check if it's a hidden page
+    if(isHiddenPage($recent['id'])) return false;
 
-  // filter namespace
-  if (($ns) && (strpos($recent['id'],$ns.':') !== 0)) return false;
+    // filter namespace
+    if (($ns) && (strpos($recent['id'],$ns.':') !== 0)) return false;
 
-  // exclude subnamespaces
-  if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false;
+    // exclude subnamespaces
+    if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false;
 
-  // check ACL
-  $recent['perms'] = auth_quickaclcheck($recent['id']);
-  if ($recent['perms'] < AUTH_READ) return false;
+    // check ACL
+    $recent['perms'] = auth_quickaclcheck($recent['id']);
+    if ($recent['perms'] < AUTH_READ) return false;
 
-  // check existance
-  $fn = (($flags & RECENTS_MEDIA_CHANGES) ? mediaFN($recent['id']) : wikiFN($recent['id']));
-  if((!@file_exists($fn)) && ($flags & RECENTS_SKIP_DELETED)) return false;
+    // check existance
+    $fn = (($flags & RECENTS_MEDIA_CHANGES) ? mediaFN($recent['id']) : wikiFN($recent['id']));
+    if((!@file_exists($fn)) && ($flags & RECENTS_SKIP_DELETED)) return false;
 
-  return $recent;
+    return $recent;
 }
 
 /**
@@ -291,80 +290,80 @@ function _handleRecent($line,$ns,$flags,&$seen){
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function getRevisionInfo($id, $rev, $chunk_size=8192) {
-  global $cache_revinfo;
-  $cache =& $cache_revinfo;
-  if (!isset($cache[$id])) { $cache[$id] = array(); }
-  $rev = max($rev, 0);
-
-  // check if it's already in the memory cache
-  if (isset($cache[$id]) && isset($cache[$id][$rev])) {
-    return $cache[$id][$rev];
-  }
-
-  $file = metaFN($id, '.changes');
-  if (!@file_exists($file)) { return false; }
-  if (filesize($file)<$chunk_size || $chunk_size==0) {
-    // read whole file
-    $lines = file($file);
-    if ($lines===false) { return false; }
-  } else {
-    // read by chunk
-    $fp = fopen($file, 'rb'); // "file pointer"
-    if ($fp===false) { return false; }
-    $head = 0;
-    fseek($fp, 0, SEEK_END);
-    $tail = ftell($fp);
-    $finger = 0;
-    $finger_rev = 0;
-
-    // find chunk
-    while ($tail-$head>$chunk_size) {
-      $finger = $head+floor(($tail-$head)/2.0);
-      fseek($fp, $finger);
-      fgets($fp); // slip the finger forward to a new line
-      $finger = ftell($fp);
-      $tmp = fgets($fp); // then read at that location
-      $tmp = parseChangelogLine($tmp);
-      $finger_rev = $tmp['date'];
-      if ($finger==$head || $finger==$tail) { break; }
-      if ($finger_rev>$rev) {
-        $tail = $finger;
-      } else {
-        $head = $finger;
-      }
+    global $cache_revinfo;
+    $cache =& $cache_revinfo;
+    if (!isset($cache[$id])) { $cache[$id] = array(); }
+    $rev = max($rev, 0);
+
+    // check if it's already in the memory cache
+    if (isset($cache[$id]) && isset($cache[$id][$rev])) {
+        return $cache[$id][$rev];
     }
 
-    if ($tail-$head<1) {
-      // cound not find chunk, assume requested rev is missing
-      fclose($fp);
-      return false;
-    }
+    $file = metaFN($id, '.changes');
+    if (!@file_exists($file)) { return false; }
+    if (filesize($file)<$chunk_size || $chunk_size==0) {
+        // read whole file
+        $lines = file($file);
+        if ($lines===false) { return false; }
+    } else {
+        // read by chunk
+        $fp = fopen($file, 'rb'); // "file pointer"
+        if ($fp===false) { return false; }
+        $head = 0;
+        fseek($fp, 0, SEEK_END);
+        $tail = ftell($fp);
+        $finger = 0;
+        $finger_rev = 0;
+
+        // find chunk
+        while ($tail-$head>$chunk_size) {
+            $finger = $head+floor(($tail-$head)/2.0);
+            fseek($fp, $finger);
+            fgets($fp); // slip the finger forward to a new line
+            $finger = ftell($fp);
+            $tmp = fgets($fp); // then read at that location
+            $tmp = parseChangelogLine($tmp);
+            $finger_rev = $tmp['date'];
+            if ($finger==$head || $finger==$tail) { break; }
+            if ($finger_rev>$rev) {
+                $tail = $finger;
+            } else {
+                $head = $finger;
+            }
+        }
+
+        if ($tail-$head<1) {
+            // cound not find chunk, assume requested rev is missing
+            fclose($fp);
+            return false;
+        }
 
-    // read chunk
-    $chunk = '';
-    $chunk_size = max($tail-$head, 0); // found chunk size
-    $got = 0;
-    fseek($fp, $head);
-    while ($got<$chunk_size && !feof($fp)) {
-      $tmp = @fread($fp, max($chunk_size-$got, 0));
-      if ($tmp===false) { break; } //error state
-      $got += strlen($tmp);
-      $chunk .= $tmp;
+        // read chunk
+        $chunk = '';
+        $chunk_size = max($tail-$head, 0); // found chunk size
+        $got = 0;
+        fseek($fp, $head);
+        while ($got<$chunk_size && !feof($fp)) {
+            $tmp = @fread($fp, max($chunk_size-$got, 0));
+            if ($tmp===false) { break; } //error state
+            $got += strlen($tmp);
+            $chunk .= $tmp;
+        }
+        $lines = explode("\n", $chunk);
+        array_pop($lines); // remove trailing newline
+        fclose($fp);
     }
-    $lines = explode("\n", $chunk);
-    array_pop($lines); // remove trailing newline
-    fclose($fp);
-  }
-
-  // parse and cache changelog lines
-  foreach ($lines as $value) {
-    $tmp = parseChangelogLine($value);
-    if ($tmp!==false) {
-      $cache[$id][$tmp['date']] = $tmp;
+
+    // parse and cache changelog lines
+    foreach ($lines as $value) {
+        $tmp = parseChangelogLine($value);
+        if ($tmp!==false) {
+            $cache[$id][$tmp['date']] = $tmp;
+        }
     }
-  }
-  if (!isset($cache[$id][$rev])) { return false; }
-  return $cache[$id][$rev];
+    if (!isset($cache[$id][$rev])) { return false; }
+    return $cache[$id][$rev];
 }
 
 /**
@@ -388,87 +387,87 @@ function getRevisionInfo($id, $rev, $chunk_size=8192) {
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function getRevisions($id, $first, $num, $chunk_size=8192) {
-  global $cache_revinfo;
-  $cache =& $cache_revinfo;
-  if (!isset($cache[$id])) { $cache[$id] = array(); }
-
-  $revs = array();
-  $lines = array();
-  $count  = 0;
-  $file = metaFN($id, '.changes');
-  $num = max($num, 0);
-  $chunk_size = max($chunk_size, 0);
-  if ($first<0) { $first = 0; }
-  else if (@file_exists(wikiFN($id))) {
-     // skip current revision if the page exists
-    $first = max($first+1, 0);
-  }
-
-  if (!@file_exists($file)) { return $revs; }
-  if (filesize($file)<$chunk_size || $chunk_size==0) {
-    // read whole file
-    $lines = file($file);
-    if ($lines===false) { return $revs; }
-  } else {
-    // read chunks backwards
-    $fp = fopen($file, 'rb'); // "file pointer"
-    if ($fp===false) { return $revs; }
-    fseek($fp, 0, SEEK_END);
-    $tail = ftell($fp);
-
-    // chunk backwards
-    $finger = max($tail-$chunk_size, 0);
-    while ($count<$num+$first) {
-      fseek($fp, $finger);
-      if ($finger>0) {
-        fgets($fp); // slip the finger forward to a new line
-        $finger = ftell($fp);
-      }
-
-      // read chunk
-      if ($tail<=$finger) { break; }
-      $chunk = '';
-      $read_size = max($tail-$finger, 0); // found chunk size
-      $got = 0;
-      while ($got<$read_size && !feof($fp)) {
-        $tmp = @fread($fp, max($read_size-$got, 0));
-        if ($tmp===false) { break; } //error state
-        $got += strlen($tmp);
-        $chunk .= $tmp;
-      }
-      $tmp = explode("\n", $chunk);
-      array_pop($tmp); // remove trailing newline
-
-      // combine with previous chunk
-      $count += count($tmp);
-      $lines = array_merge($tmp, $lines);
-
-      // next chunk
-      if ($finger==0) { break; } // already read all the lines
-      else {
-        $tail = $finger;
+    global $cache_revinfo;
+    $cache =& $cache_revinfo;
+    if (!isset($cache[$id])) { $cache[$id] = array(); }
+
+    $revs = array();
+    $lines = array();
+    $count  = 0;
+    $file = metaFN($id, '.changes');
+    $num = max($num, 0);
+    $chunk_size = max($chunk_size, 0);
+    if ($first<0) { $first = 0; }
+    else if (@file_exists(wikiFN($id))) {
+        // skip current revision if the page exists
+        $first = max($first+1, 0);
+    }
+
+    if (!@file_exists($file)) { return $revs; }
+    if (filesize($file)<$chunk_size || $chunk_size==0) {
+        // read whole file
+        $lines = file($file);
+        if ($lines===false) { return $revs; }
+    } else {
+        // read chunks backwards
+        $fp = fopen($file, 'rb'); // "file pointer"
+        if ($fp===false) { return $revs; }
+        fseek($fp, 0, SEEK_END);
+        $tail = ftell($fp);
+
+        // chunk backwards
         $finger = max($tail-$chunk_size, 0);
-      }
+        while ($count<$num+$first) {
+            fseek($fp, $finger);
+            if ($finger>0) {
+                fgets($fp); // slip the finger forward to a new line
+                $finger = ftell($fp);
+            }
+
+            // read chunk
+            if ($tail<=$finger) { break; }
+            $chunk = '';
+            $read_size = max($tail-$finger, 0); // found chunk size
+            $got = 0;
+            while ($got<$read_size && !feof($fp)) {
+                $tmp = @fread($fp, max($read_size-$got, 0));
+                if ($tmp===false) { break; } //error state
+                $got += strlen($tmp);
+                $chunk .= $tmp;
+            }
+            $tmp = explode("\n", $chunk);
+            array_pop($tmp); // remove trailing newline
+
+            // combine with previous chunk
+            $count += count($tmp);
+            $lines = array_merge($tmp, $lines);
+
+            // next chunk
+            if ($finger==0) { break; } // already read all the lines
+            else {
+                $tail = $finger;
+                $finger = max($tail-$chunk_size, 0);
+            }
+        }
+        fclose($fp);
     }
-    fclose($fp);
-  }
-
-  // skip parsing extra lines
-  $num = max(min(count($lines)-$first, $num), 0);
-  if      ($first>0 && $num>0)  { $lines = array_slice($lines, max(count($lines)-$first-$num, 0), $num); }
-  else if ($first>0 && $num==0) { $lines = array_slice($lines, 0, max(count($lines)-$first, 0)); }
-  else if ($first==0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$num, 0)); }
-
-  // handle lines in reverse order
-  for ($i = count($lines)-1; $i >= 0; $i--) {
-    $tmp = parseChangelogLine($lines[$i]);
-    if ($tmp!==false) {
-      $cache[$id][$tmp['date']] = $tmp;
-      $revs[] = $tmp['date'];
+
+    // skip parsing extra lines
+    $num = max(min(count($lines)-$first, $num), 0);
+    if      ($first>0 && $num>0)  { $lines = array_slice($lines, max(count($lines)-$first-$num, 0), $num); }
+    else if ($first>0 && $num==0) { $lines = array_slice($lines, 0, max(count($lines)-$first, 0)); }
+    else if ($first==0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$num, 0)); }
+
+    // handle lines in reverse order
+    for ($i = count($lines)-1; $i >= 0; $i--) {
+        $tmp = parseChangelogLine($lines[$i]);
+        if ($tmp!==false) {
+            $cache[$id][$tmp['date']] = $tmp;
+            $revs[] = $tmp['date'];
+        }
     }
-  }
 
-  return $revs;
+    return $revs;
 }
 
 
diff --git a/inc/cliopts.php b/inc/cliopts.php
index a3698ab24..ede559a63 100644
--- a/inc/cliopts.php
+++ b/inc/cliopts.php
@@ -1,7 +1,7 @@
 <?php
 /**
-* Brutally chopped and modified from http://pear.php.net/package/Console_Getopts
-*/
+ * Brutally chopped and modified from http://pear.php.net/package/Console_Getopts
+ */
 // +----------------------------------------------------------------------+
 // | PHP Version 4                                                        |
 // +----------------------------------------------------------------------+
@@ -23,10 +23,10 @@
 
 //------------------------------------------------------------------------------
 /**
-* Sets up CLI environment based on SAPI and PHP version
-* Helps resolve some issues between the CGI and CLI SAPIs
-* as well is inconsistencies between PHP 4.3+ and older versions
-*/
+ * Sets up CLI environment based on SAPI and PHP version
+ * Helps resolve some issues between the CGI and CLI SAPIs
+ * as well is inconsistencies between PHP 4.3+ and older versions
+ */
 if (version_compare(phpversion(), '4.3.0', '<') || php_sapi_name() == 'cgi') {
     // Handle output buffering
     @ob_end_flush();
@@ -67,16 +67,16 @@ define('DOKU_CLI_OPTS_ARG_READ',5);//Could not read argv
  * @author Andrei Zmievski <andrei@php.net>
  *
  */
- class Doku_Cli_Opts {
+class Doku_Cli_Opts {
 
     /**
-    * <?php ?>
-    * @see http://www.sitepoint.com/article/php-command-line-1/3
-    * @param string executing file name - this MUST be passed the __FILE__ constant
-    * @param string short options
-    * @param array (optional) long options
-    * @return Doku_Cli_Opts_Container or Doku_Cli_Opts_Error
-    */
+     * <?php ?>
+     * @see http://www.sitepoint.com/article/php-command-line-1/3
+     * @param string executing file name - this MUST be passed the __FILE__ constant
+     * @param string short options
+     * @param array (optional) long options
+     * @return Doku_Cli_Opts_Container or Doku_Cli_Opts_Error
+     */
     function & getOptions($bin_file, $short_options, $long_options = null) {
         $args = Doku_Cli_Opts::readPHPArgv();
 
@@ -168,7 +168,8 @@ define('DOKU_CLI_OPTS_ARG_READ',5);//Could not read argv
     }
 
     function _parseShortOption($arg, $short_options, &$opts, &$args) {
-        for ($i = 0; $i < strlen($arg); $i++) {
+        $len = strlen($arg);
+        for ($i = 0; $i < $len; $i++) {
             $opt = $arg{$i};
             $opt_arg = null;
 
@@ -212,8 +213,9 @@ define('DOKU_CLI_OPTS_ARG_READ',5);//Could not read argv
     function _parseLongOption($arg, $long_options, &$opts, &$args) {
         @list($opt, $opt_arg) = explode('=', $arg);
         $opt_len = strlen($opt);
+        $opt_cnt = count($long_options);
 
-        for ($i = 0; $i < count($long_options); $i++) {
+        for ($i = 0; $i < $opt_cnt; $i++) {
             $long_opt  = $long_options[$i];
             $opt_start = substr($long_opt, 0, $opt_len);
 
@@ -226,7 +228,7 @@ define('DOKU_CLI_OPTS_ARG_READ',5);//Could not read argv
             /* Check that the options uniquely matches one of the allowed
                options. */
             if ($opt_rest != '' && $opt{0} != '=' &&
-                $i + 1 < count($long_options) &&
+                $i + 1 < $opt_cnt &&
                 $opt == substr($long_options[$i+1], 0, $opt_len)) {
                 return Doku_Cli_Opts::raiseError(
                     DOKU_CLI_OPTS_OPT_ABIGUOUS,
@@ -326,7 +328,6 @@ class Doku_Cli_Opts_Container {
             $this->options[$opt_name] = $option[1];
         }
 
-
         $this->args = $options[1];
     }
 
diff --git a/inc/common.php b/inc/common.php
index 321148c7a..85187f16d 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -29,7 +29,7 @@ define('RECENTS_MEDIA_CHANGES',16);
  * @see    htmlspecialchars()
  */
 function hsc($string){
-  return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
+    return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
 }
 
 /**
@@ -40,7 +40,7 @@ function hsc($string){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function ptln($string,$indent=0){
-  echo str_repeat(' ', $indent)."$string\n";
+    echo str_repeat(' ', $indent)."$string\n";
 }
 
 /**
@@ -49,7 +49,7 @@ function ptln($string,$indent=0){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function stripctl($string){
-  return preg_replace('/[\x00-\x1F]+/s','',$string);
+    return preg_replace('/[\x00-\x1F]+/s','',$string);
 }
 
 /**
@@ -61,21 +61,21 @@ function stripctl($string){
  * @return  string
  */
 function getSecurityToken(){
-  return md5(auth_cookiesalt().session_id());
+    return md5(auth_cookiesalt().session_id());
 }
 
 /**
  * Check the secret CSRF token
  */
 function checkSecurityToken($token=null){
-  if(!$_SERVER['REMOTE_USER']) return true; // no logged in user, no need for a check
+    if(!$_SERVER['REMOTE_USER']) return true; // no logged in user, no need for a check
 
-  if(is_null($token)) $token = $_REQUEST['sectok'];
-  if(getSecurityToken() != $token){
-    msg('Security Token did not match. Possible CSRF attack.',-1);
-    return false;
-  }
-  return true;
+    if(is_null($token)) $token = $_REQUEST['sectok'];
+    if(getSecurityToken() != $token){
+        msg('Security Token did not match. Possible CSRF attack.',-1);
+        return false;
+    }
+    return true;
 }
 
 /**
@@ -84,12 +84,12 @@ function checkSecurityToken($token=null){
  * @author  Andreas Gohr <andi@splitbrain.org>
  */
 function formSecurityToken($print=true){
-  $ret = '<div class="no"><input type="hidden" name="sectok" value="'.getSecurityToken().'" /></div>'."\n";
-  if($print){
-    echo $ret;
-  }else{
-    return $ret;
-  }
+    $ret = '<div class="no"><input type="hidden" name="sectok" value="'.getSecurityToken().'" /></div>'."\n";
+    if($print){
+        echo $ret;
+    }else{
+        return $ret;
+    }
 }
 
 /**
@@ -99,128 +99,128 @@ function formSecurityToken($print=true){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function pageinfo(){
-  global $ID;
-  global $REV;
-  global $RANGE;
-  global $USERINFO;
-  global $conf;
-  global $lang;
-
-  // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml
-  // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary
-  $info['id'] = $ID;
-  $info['rev'] = $REV;
+    global $ID;
+    global $REV;
+    global $RANGE;
+    global $USERINFO;
+    global $conf;
+    global $lang;
+
+    // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml
+    // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary
+    $info['id'] = $ID;
+    $info['rev'] = $REV;
 
     // set info about manager/admin status.
     $info['isadmin']   = false;
     $info['ismanager'] = false;
-  if(isset($_SERVER['REMOTE_USER'])){
-    $info['userinfo']     = $USERINFO;
-    $info['perm']         = auth_quickaclcheck($ID);
-    $info['subscribed']   = is_subscribed($ID,$_SERVER['REMOTE_USER'],false);
-    $info['subscribedns'] = is_subscribed($ID,$_SERVER['REMOTE_USER'],true);
-    $info['client']       = $_SERVER['REMOTE_USER'];
-
-    if($info['perm'] == AUTH_ADMIN){
-      $info['isadmin']   = true;
-      $info['ismanager'] = true;
-    }elseif(auth_ismanager()){
-      $info['ismanager'] = true;
-    }
-
-    // if some outside auth were used only REMOTE_USER is set
-    if(!$info['userinfo']['name']){
-      $info['userinfo']['name'] = $_SERVER['REMOTE_USER'];
-    }
-
-  }else{
-    $info['perm']       = auth_aclcheck($ID,'',null);
-    $info['subscribed'] = false;
-    $info['client']     = clientIP(true);
-  }
-
-  $info['namespace'] = getNS($ID);
-  $info['locked']    = checklock($ID);
-  $info['filepath']  = fullpath(wikiFN($ID));
-  $info['exists']    = @file_exists($info['filepath']);
-  if($REV){
-    //check if current revision was meant
-    if($info['exists'] && (@filemtime($info['filepath'])==$REV)){
-      $REV = '';
-    }elseif($RANGE){
-      //section editing does not work with old revisions!
-      $REV   = '';
-      $RANGE = '';
-      msg($lang['nosecedit'],0);
+    if(isset($_SERVER['REMOTE_USER'])){
+        $info['userinfo']     = $USERINFO;
+        $info['perm']         = auth_quickaclcheck($ID);
+        $info['subscribed']   = is_subscribed($ID,$_SERVER['REMOTE_USER'],false);
+        $info['subscribedns'] = is_subscribed($ID,$_SERVER['REMOTE_USER'],true);
+        $info['client']       = $_SERVER['REMOTE_USER'];
+
+        if($info['perm'] == AUTH_ADMIN){
+            $info['isadmin']   = true;
+            $info['ismanager'] = true;
+        }elseif(auth_ismanager()){
+            $info['ismanager'] = true;
+        }
+
+        // if some outside auth were used only REMOTE_USER is set
+        if(!$info['userinfo']['name']){
+            $info['userinfo']['name'] = $_SERVER['REMOTE_USER'];
+        }
+
     }else{
-      //really use old revision
-      $info['filepath'] = fullpath(wikiFN($ID,$REV));
-      $info['exists']   = @file_exists($info['filepath']);
-    }
-  }
-  $info['rev'] = $REV;
-  if($info['exists']){
-    $info['writable'] = (is_writable($info['filepath']) &&
-                         ($info['perm'] >= AUTH_EDIT));
-  }else{
-    $info['writable'] = ($info['perm'] >= AUTH_CREATE);
-  }
-  $info['editable']  = ($info['writable'] && empty($info['lock']));
-  $info['lastmod']   = @filemtime($info['filepath']);
-
-  //load page meta data
-  $info['meta'] = p_get_metadata($ID);
-
-  //who's the editor
-  if($REV){
-    $revinfo = getRevisionInfo($ID, $REV, 1024);
-  }else{
-    if (is_array($info['meta']['last_change'])) {
-       $revinfo = $info['meta']['last_change'];
-    } else {
-      $revinfo = getRevisionInfo($ID, $info['lastmod'], 1024);
-      // cache most recent changelog line in metadata if missing and still valid
-      if ($revinfo!==false) {
+        $info['perm']       = auth_aclcheck($ID,'',null);
+        $info['subscribed'] = false;
+        $info['client']     = clientIP(true);
+    }
+
+    $info['namespace'] = getNS($ID);
+    $info['locked']    = checklock($ID);
+    $info['filepath']  = fullpath(wikiFN($ID));
+    $info['exists']    = @file_exists($info['filepath']);
+    if($REV){
+        //check if current revision was meant
+        if($info['exists'] && (@filemtime($info['filepath'])==$REV)){
+            $REV = '';
+        }elseif($RANGE){
+            //section editing does not work with old revisions!
+            $REV   = '';
+            $RANGE = '';
+            msg($lang['nosecedit'],0);
+        }else{
+            //really use old revision
+            $info['filepath'] = fullpath(wikiFN($ID,$REV));
+            $info['exists']   = @file_exists($info['filepath']);
+        }
+    }
+    $info['rev'] = $REV;
+    if($info['exists']){
+        $info['writable'] = (is_writable($info['filepath']) &&
+                ($info['perm'] >= AUTH_EDIT));
+    }else{
+        $info['writable'] = ($info['perm'] >= AUTH_CREATE);
+    }
+    $info['editable']  = ($info['writable'] && empty($info['lock']));
+    $info['lastmod']   = @filemtime($info['filepath']);
+
+    //load page meta data
+    $info['meta'] = p_get_metadata($ID);
+
+    //who's the editor
+    if($REV){
+        $revinfo = getRevisionInfo($ID, $REV, 1024);
+    }else{
+        if (is_array($info['meta']['last_change'])) {
+            $revinfo = $info['meta']['last_change'];
+        } else {
+            $revinfo = getRevisionInfo($ID, $info['lastmod'], 1024);
+            // cache most recent changelog line in metadata if missing and still valid
+            if ($revinfo!==false) {
+                $info['meta']['last_change'] = $revinfo;
+                p_set_metadata($ID, array('last_change' => $revinfo));
+            }
+        }
+    }
+    //and check for an external edit
+    if($revinfo!==false && $revinfo['date']!=$info['lastmod']){
+        // cached changelog line no longer valid
+        $revinfo = false;
         $info['meta']['last_change'] = $revinfo;
         p_set_metadata($ID, array('last_change' => $revinfo));
-      }
-    }
-  }
-  //and check for an external edit
-  if($revinfo!==false && $revinfo['date']!=$info['lastmod']){
-    // cached changelog line no longer valid
-    $revinfo = false;
-    $info['meta']['last_change'] = $revinfo;
-    p_set_metadata($ID, array('last_change' => $revinfo));
-  }
-
-  $info['ip']     = $revinfo['ip'];
-  $info['user']   = $revinfo['user'];
-  $info['sum']    = $revinfo['sum'];
-  // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID.
-  // Use $INFO['meta']['last_change']['type']===DOKU_CHANGE_TYPE_MINOR_EDIT in place of $info['minor'].
-
-  if($revinfo['user']){
-    $info['editor'] = $revinfo['user'];
-  }else{
-    $info['editor'] = $revinfo['ip'];
-  }
-
-  // draft
-  $draft = getCacheName($info['client'].$ID,'.draft');
-  if(@file_exists($draft)){
-    if(@filemtime($draft) < @filemtime(wikiFN($ID))){
-      // remove stale draft
-      @unlink($draft);
+    }
+
+    $info['ip']     = $revinfo['ip'];
+    $info['user']   = $revinfo['user'];
+    $info['sum']    = $revinfo['sum'];
+    // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID.
+    // Use $INFO['meta']['last_change']['type']===DOKU_CHANGE_TYPE_MINOR_EDIT in place of $info['minor'].
+
+    if($revinfo['user']){
+        $info['editor'] = $revinfo['user'];
     }else{
-      $info['draft'] = $draft;
+        $info['editor'] = $revinfo['ip'];
+    }
+
+    // draft
+    $draft = getCacheName($info['client'].$ID,'.draft');
+    if(@file_exists($draft)){
+        if(@filemtime($draft) < @filemtime(wikiFN($ID))){
+            // remove stale draft
+            @unlink($draft);
+        }else{
+            $info['draft'] = $draft;
+        }
     }
-  }
 
-  // mobile detection
-  $info['ismobile'] = clientismobile();
+    // mobile detection
+    $info['ismobile'] = clientismobile();
 
-  return $info;
+    return $info;
 }
 
 /**
@@ -229,16 +229,16 @@ function pageinfo(){
  * @author Andreas Gohr
  */
 function buildURLparams($params, $sep='&amp;'){
-  $url = '';
-  $amp = false;
-  foreach($params as $key => $val){
-    if($amp) $url .= $sep;
-
-    $url .= $key.'=';
-    $url .= rawurlencode((string)$val);
-    $amp = true;
-  }
-  return $url;
+    $url = '';
+    $amp = false;
+    foreach($params as $key => $val){
+        if($amp) $url .= $sep;
+
+        $url .= $key.'=';
+        $url .= rawurlencode((string)$val);
+        $amp = true;
+    }
+    return $url;
 }
 
 /**
@@ -249,16 +249,16 @@ function buildURLparams($params, $sep='&amp;'){
  * @author Andreas Gohr
  */
 function buildAttributes($params,$skipempty=false){
-  $url = '';
-  foreach($params as $key => $val){
-    if($key{0} == '_') continue;
-    if($val === '' && $skipempty) continue;
-
-    $url .= $key.'="';
-    $url .= htmlspecialchars ($val);
-    $url .= '" ';
-  }
-  return $url;
+    $url = '';
+    foreach($params as $key => $val){
+        if($key{0} == '_') continue;
+        if($val === '' && $skipempty) continue;
+
+        $url .= $key.'="';
+        $url .= htmlspecialchars ($val);
+        $url .= '" ';
+    }
+    return $url;
 }
 
 
@@ -268,47 +268,47 @@ function buildAttributes($params,$skipempty=false){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function breadcrumbs(){
-  // we prepare the breadcrumbs early for quick session closing
-  static $crumbs = null;
-  if($crumbs != null) return $crumbs;
-
-  global $ID;
-  global $ACT;
-  global $conf;
-
-  //first visit?
-  $crumbs = isset($_SESSION[DOKU_COOKIE]['bc']) ? $_SESSION[DOKU_COOKIE]['bc'] : array();
-  //we only save on show and existing wiki documents
-  $file = wikiFN($ID);
-  if($ACT != 'show' || !@file_exists($file)){
+    // we prepare the breadcrumbs early for quick session closing
+    static $crumbs = null;
+    if($crumbs != null) return $crumbs;
+
+    global $ID;
+    global $ACT;
+    global $conf;
+
+    //first visit?
+    $crumbs = isset($_SESSION[DOKU_COOKIE]['bc']) ? $_SESSION[DOKU_COOKIE]['bc'] : array();
+    //we only save on show and existing wiki documents
+    $file = wikiFN($ID);
+    if($ACT != 'show' || !@file_exists($file)){
+        $_SESSION[DOKU_COOKIE]['bc'] = $crumbs;
+        return $crumbs;
+    }
+
+    // page names
+    $name = noNSorNS($ID);
+    if (useHeading('navigation')) {
+        // get page title
+        $title = p_get_first_heading($ID,true);
+        if ($title) {
+            $name = $title;
+        }
+    }
+
+    //remove ID from array
+    if (isset($crumbs[$ID])) {
+        unset($crumbs[$ID]);
+    }
+
+    //add to array
+    $crumbs[$ID] = $name;
+    //reduce size
+    while(count($crumbs) > $conf['breadcrumbs']){
+        array_shift($crumbs);
+    }
+    //save to session
     $_SESSION[DOKU_COOKIE]['bc'] = $crumbs;
     return $crumbs;
-  }
-
-  // page names
-  $name = noNSorNS($ID);
-  if (useHeading('navigation')) {
-    // get page title
-    $title = p_get_first_heading($ID,true);
-    if ($title) {
-      $name = $title;
-    }
-  }
-
-  //remove ID from array
-  if (isset($crumbs[$ID])) {
-    unset($crumbs[$ID]);
-  }
-
-  //add to array
-  $crumbs[$ID] = $name;
-  //reduce size
-  while(count($crumbs) > $conf['breadcrumbs']){
-    array_shift($crumbs);
-  }
-  //save to session
-  $_SESSION[DOKU_COOKIE]['bc'] = $crumbs;
-  return $crumbs;
 }
 
 /**
@@ -323,19 +323,19 @@ function breadcrumbs(){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function idfilter($id,$ue=true){
-  global $conf;
-  if ($conf['useslash'] && $conf['userewrite']){
-    $id = strtr($id,':','/');
-  }elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' &&
-      $conf['userewrite']) {
-    $id = strtr($id,':',';');
-  }
-  if($ue){
-    $id = rawurlencode($id);
-    $id = str_replace('%3A',':',$id); //keep as colon
-    $id = str_replace('%2F','/',$id); //keep as slash
-  }
-  return $id;
+    global $conf;
+    if ($conf['useslash'] && $conf['userewrite']){
+        $id = strtr($id,':','/');
+    }elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' &&
+            $conf['userewrite']) {
+        $id = strtr($id,':',';');
+    }
+    if($ue){
+        $id = rawurlencode($id);
+        $id = str_replace('%3A',':',$id); //keep as colon
+        $id = str_replace('%2F','/',$id); //keep as slash
+    }
+    return $id;
 }
 
 /**
@@ -347,35 +347,35 @@ function idfilter($id,$ue=true){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function wl($id='',$more='',$abs=false,$sep='&amp;'){
-  global $conf;
-  if(is_array($more)){
-    $more = buildURLparams($more,$sep);
-  }else{
-    $more = str_replace(',',$sep,$more);
-  }
-
-  $id    = idfilter($id);
-  if($abs){
-    $xlink = DOKU_URL;
-  }else{
-    $xlink = DOKU_BASE;
-  }
-
-  if($conf['userewrite'] == 2){
-    $xlink .= DOKU_SCRIPT.'/'.$id;
-    if($more) $xlink .= '?'.$more;
-  }elseif($conf['userewrite']){
-    $xlink .= $id;
-    if($more) $xlink .= '?'.$more;
-  }elseif($id){
-    $xlink .= DOKU_SCRIPT.'?id='.$id;
-    if($more) $xlink .= $sep.$more;
-  }else{
-    $xlink .= DOKU_SCRIPT;
-    if($more) $xlink .= '?'.$more;
-  }
-
-  return $xlink;
+    global $conf;
+    if(is_array($more)){
+        $more = buildURLparams($more,$sep);
+    }else{
+        $more = str_replace(',',$sep,$more);
+    }
+
+    $id    = idfilter($id);
+    if($abs){
+        $xlink = DOKU_URL;
+    }else{
+        $xlink = DOKU_BASE;
+    }
+
+    if($conf['userewrite'] == 2){
+        $xlink .= DOKU_SCRIPT.'/'.$id;
+        if($more) $xlink .= '?'.$more;
+    }elseif($conf['userewrite']){
+        $xlink .= $id;
+        if($more) $xlink .= '?'.$more;
+    }elseif($id){
+        $xlink .= DOKU_SCRIPT.'?id='.$id;
+        if($more) $xlink .= $sep.$more;
+    }else{
+        $xlink .= DOKU_SCRIPT;
+        if($more) $xlink .= '?'.$more;
+    }
+
+    return $xlink;
 }
 
 /**
@@ -386,33 +386,33 @@ function wl($id='',$more='',$abs=false,$sep='&amp;'){
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function exportlink($id='',$format='raw',$more='',$abs=false,$sep='&amp;'){
-  global $conf;
-  if(is_array($more)){
-    $more = buildURLparams($more,$sep);
-  }else{
-    $more = str_replace(',',$sep,$more);
-  }
-
-  $format = rawurlencode($format);
-  $id = idfilter($id);
-  if($abs){
-    $xlink = DOKU_URL;
-  }else{
-    $xlink = DOKU_BASE;
-  }
-
-  if($conf['userewrite'] == 2){
-    $xlink .= DOKU_SCRIPT.'/'.$id.'?do=export_'.$format;
-    if($more) $xlink .= $sep.$more;
-  }elseif($conf['userewrite'] == 1){
-    $xlink .= '_export/'.$format.'/'.$id;
-    if($more) $xlink .= '?'.$more;
-  }else{
-    $xlink .= DOKU_SCRIPT.'?do=export_'.$format.$sep.'id='.$id;
-    if($more) $xlink .= $sep.$more;
-  }
-
-  return $xlink;
+    global $conf;
+    if(is_array($more)){
+        $more = buildURLparams($more,$sep);
+    }else{
+        $more = str_replace(',',$sep,$more);
+    }
+
+    $format = rawurlencode($format);
+    $id = idfilter($id);
+    if($abs){
+        $xlink = DOKU_URL;
+    }else{
+        $xlink = DOKU_BASE;
+    }
+
+    if($conf['userewrite'] == 2){
+        $xlink .= DOKU_SCRIPT.'/'.$id.'?do=export_'.$format;
+        if($more) $xlink .= $sep.$more;
+    }elseif($conf['userewrite'] == 1){
+        $xlink .= '_export/'.$format.'/'.$id;
+        if($more) $xlink .= '?'.$more;
+    }else{
+        $xlink .= DOKU_SCRIPT.'?do=export_'.$format.$sep.'id='.$id;
+        if($more) $xlink .= $sep.$more;
+    }
+
+    return $xlink;
 }
 
 /**
@@ -430,71 +430,71 @@ function exportlink($id='',$format='raw',$more='',$abs=false,$sep='&amp;'){
  * @param boolean $abs    - Create an absolute URL
  */
 function ml($id='',$more='',$direct=true,$sep='&amp;',$abs=false){
-  global $conf;
-  if(is_array($more)){
-    // strip defaults for shorter URLs
-    if(isset($more['cache']) && $more['cache'] == 'cache') unset($more['cache']);
-    if(!$more['w']) unset($more['w']);
-    if(!$more['h']) unset($more['h']);
-    if(isset($more['id']) && $direct) unset($more['id']);
-    $more = buildURLparams($more,$sep);
-  }else{
-    $more = str_replace('cache=cache','',$more); //skip default
-    $more = str_replace(',,',',',$more);
-    $more = str_replace(',',$sep,$more);
-  }
-
-  if($abs){
-    $xlink = DOKU_URL;
-  }else{
-    $xlink = DOKU_BASE;
-  }
-
-  // external URLs are always direct without rewriting
-  if(preg_match('#^(https?|ftp)://#i',$id)){
-    $xlink .= 'lib/exe/fetch.php';
-    // add hash:
-    $xlink .= '?hash='.substr(md5(auth_cookiesalt().$id),0,6);
-    if($more){
-      $xlink .= $sep.$more;
-      $xlink .= $sep.'media='.rawurlencode($id);
+    global $conf;
+    if(is_array($more)){
+        // strip defaults for shorter URLs
+        if(isset($more['cache']) && $more['cache'] == 'cache') unset($more['cache']);
+        if(!$more['w']) unset($more['w']);
+        if(!$more['h']) unset($more['h']);
+        if(isset($more['id']) && $direct) unset($more['id']);
+        $more = buildURLparams($more,$sep);
     }else{
-      $xlink .= $sep.'media='.rawurlencode($id);
+        $more = str_replace('cache=cache','',$more); //skip default
+        $more = str_replace(',,',',',$more);
+        $more = str_replace(',',$sep,$more);
     }
-    return $xlink;
-  }
 
-  $id = idfilter($id);
+    if($abs){
+        $xlink = DOKU_URL;
+    }else{
+        $xlink = DOKU_BASE;
+    }
 
-  // decide on scriptname
-  if($direct){
-    if($conf['userewrite'] == 1){
-      $script = '_media';
+    // external URLs are always direct without rewriting
+    if(preg_match('#^(https?|ftp)://#i',$id)){
+        $xlink .= 'lib/exe/fetch.php';
+        // add hash:
+        $xlink .= '?hash='.substr(md5(auth_cookiesalt().$id),0,6);
+        if($more){
+            $xlink .= $sep.$more;
+            $xlink .= $sep.'media='.rawurlencode($id);
+        }else{
+            $xlink .= $sep.'media='.rawurlencode($id);
+        }
+        return $xlink;
+    }
+
+    $id = idfilter($id);
+
+    // decide on scriptname
+    if($direct){
+        if($conf['userewrite'] == 1){
+            $script = '_media';
+        }else{
+            $script = 'lib/exe/fetch.php';
+        }
     }else{
-      $script = 'lib/exe/fetch.php';
+        if($conf['userewrite'] == 1){
+            $script = '_detail';
+        }else{
+            $script = 'lib/exe/detail.php';
+        }
     }
-  }else{
-    if($conf['userewrite'] == 1){
-      $script = '_detail';
+
+    // build URL based on rewrite mode
+    if($conf['userewrite']){
+        $xlink .= $script.'/'.$id;
+        if($more) $xlink .= '?'.$more;
     }else{
-      $script = 'lib/exe/detail.php';
-    }
-  }
-
-  // build URL based on rewrite mode
-   if($conf['userewrite']){
-     $xlink .= $script.'/'.$id;
-     if($more) $xlink .= '?'.$more;
-   }else{
-     if($more){
-       $xlink .= $script.'?'.$more;
-       $xlink .= $sep.'media='.$id;
-     }else{
-       $xlink .= $script.'?media='.$id;
-     }
-   }
-
-  return $xlink;
+        if($more){
+            $xlink .= $script.'?'.$more;
+            $xlink .= $sep.'media='.$id;
+        }else{
+            $xlink .= $script.'?media='.$id;
+        }
+    }
+
+    return $xlink;
 }
 
 
@@ -506,10 +506,7 @@ function ml($id='',$more='',$direct=true,$sep='&amp;',$abs=false){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function script($script='doku.php'){
-#  $link = getBaseURL();
-#  $link .= $script;
-#  return $link;
-  return DOKU_BASE.DOKU_SCRIPT;
+    return DOKU_BASE.DOKU_SCRIPT;
 }
 
 /**
@@ -537,54 +534,54 @@ function script($script='doku.php'){
  * @return bool         - true if a spam word was found
  */
 function checkwordblock($text=''){
-  global $TEXT;
-  global $PRE;
-  global $SUF;
-  global $conf;
-  global $INFO;
-
-  if(!$conf['usewordblock']) return false;
-
-  if(!$text) $text = "$PRE $TEXT $SUF";
-
-  // we prepare the text a tiny bit to prevent spammers circumventing URL checks
-  $text = preg_replace('!(\b)(www\.[\w.:?\-;,]+?\.[\w.:?\-;,]+?[\w/\#~:.?+=&%@\!\-.:?\-;,]+?)([.:?\-;,]*[^\w/\#~:.?+=&%@\!\-.:?\-;,])!i','\1http://\2 \2\3',$text);
-
-  $wordblocks = getWordblocks();
-  //how many lines to read at once (to work around some PCRE limits)
-  if(version_compare(phpversion(),'4.3.0','<')){
-    //old versions of PCRE define a maximum of parenthesises even if no
-    //backreferences are used - the maximum is 99
-    //this is very bad performancewise and may even be too high still
-    $chunksize = 40;
-  }else{
-    //read file in chunks of 200 - this should work around the
-    //MAX_PATTERN_SIZE in modern PCRE
-    $chunksize = 200;
-  }
-  while($blocks = array_splice($wordblocks,0,$chunksize)){
-    $re = array();
-    #build regexp from blocks
-    foreach($blocks as $block){
-      $block = preg_replace('/#.*$/','',$block);
-      $block = trim($block);
-      if(empty($block)) continue;
-      $re[]  = $block;
-    }
-    if(count($re) && preg_match('#('.join('|',$re).')#si',$text,$matches)) {
-      //prepare event data
-      $data['matches'] = $matches;
-      $data['userinfo']['ip'] = $_SERVER['REMOTE_ADDR'];
-      if($_SERVER['REMOTE_USER']) {
-          $data['userinfo']['user'] = $_SERVER['REMOTE_USER'];
-          $data['userinfo']['name'] = $INFO['userinfo']['name'];
-          $data['userinfo']['mail'] = $INFO['userinfo']['mail'];
-      }
-      $callback = create_function('', 'return true;');
-      return trigger_event('COMMON_WORDBLOCK_BLOCKED', $data, $callback, true);
-    }
-  }
-  return false;
+    global $TEXT;
+    global $PRE;
+    global $SUF;
+    global $conf;
+    global $INFO;
+
+    if(!$conf['usewordblock']) return false;
+
+    if(!$text) $text = "$PRE $TEXT $SUF";
+
+    // we prepare the text a tiny bit to prevent spammers circumventing URL checks
+    $text = preg_replace('!(\b)(www\.[\w.:?\-;,]+?\.[\w.:?\-;,]+?[\w/\#~:.?+=&%@\!\-.:?\-;,]+?)([.:?\-;,]*[^\w/\#~:.?+=&%@\!\-.:?\-;,])!i','\1http://\2 \2\3',$text);
+
+    $wordblocks = getWordblocks();
+    // how many lines to read at once (to work around some PCRE limits)
+    if(version_compare(phpversion(),'4.3.0','<')){
+        // old versions of PCRE define a maximum of parenthesises even if no
+        // backreferences are used - the maximum is 99
+        // this is very bad performancewise and may even be too high still
+        $chunksize = 40;
+    }else{
+        // read file in chunks of 200 - this should work around the
+        // MAX_PATTERN_SIZE in modern PCRE
+        $chunksize = 200;
+    }
+    while($blocks = array_splice($wordblocks,0,$chunksize)){
+        $re = array();
+        // build regexp from blocks
+        foreach($blocks as $block){
+            $block = preg_replace('/#.*$/','',$block);
+            $block = trim($block);
+            if(empty($block)) continue;
+            $re[]  = $block;
+        }
+        if(count($re) && preg_match('#('.join('|',$re).')#si',$text,$matches)) {
+            // prepare event data
+            $data['matches'] = $matches;
+            $data['userinfo']['ip'] = $_SERVER['REMOTE_ADDR'];
+            if($_SERVER['REMOTE_USER']) {
+                $data['userinfo']['user'] = $_SERVER['REMOTE_USER'];
+                $data['userinfo']['name'] = $INFO['userinfo']['name'];
+                $data['userinfo']['mail'] = $INFO['userinfo']['mail'];
+            }
+            $callback = create_function('', 'return true;');
+            return trigger_event('COMMON_WORDBLOCK_BLOCKED', $data, $callback, true);
+        }
+    }
+    return false;
 }
 
 /**
@@ -601,60 +598,60 @@ function checkwordblock($text=''){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function clientIP($single=false){
-  $ip = array();
-  $ip[] = $_SERVER['REMOTE_ADDR'];
-  if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
-    $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']));
-  if(!empty($_SERVER['HTTP_X_REAL_IP']))
-    $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_REAL_IP']));
-
-  // some IPv4/v6 regexps borrowed from Feyd
-  // see: http://forums.devnetwork.net/viewtopic.php?f=38&t=53479
-  $dec_octet = '(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|[0-9])';
-  $hex_digit = '[A-Fa-f0-9]';
-  $h16 = "{$hex_digit}{1,4}";
-  $IPv4Address = "$dec_octet\\.$dec_octet\\.$dec_octet\\.$dec_octet";
-  $ls32 = "(?:$h16:$h16|$IPv4Address)";
-  $IPv6Address =
-    "(?:(?:{$IPv4Address})|(?:".
-    "(?:$h16:){6}$ls32" .
-    "|::(?:$h16:){5}$ls32" .
-    "|(?:$h16)?::(?:$h16:){4}$ls32" .
-    "|(?:(?:$h16:){0,1}$h16)?::(?:$h16:){3}$ls32" .
-    "|(?:(?:$h16:){0,2}$h16)?::(?:$h16:){2}$ls32" .
-    "|(?:(?:$h16:){0,3}$h16)?::(?:$h16:){1}$ls32" .
-    "|(?:(?:$h16:){0,4}$h16)?::$ls32" .
-    "|(?:(?:$h16:){0,5}$h16)?::$h16" .
-    "|(?:(?:$h16:){0,6}$h16)?::" .
-    ")(?:\\/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))?)";
-
-  // remove any non-IP stuff
-  $cnt = count($ip);
-  $match = array();
-  for($i=0; $i<$cnt; $i++){
-    if(preg_match("/^$IPv4Address$/",$ip[$i],$match) || preg_match("/^$IPv6Address$/",$ip[$i],$match)) {
-      $ip[$i] = $match[0];
-    } else {
-      $ip[$i] = '';
+    $ip = array();
+    $ip[] = $_SERVER['REMOTE_ADDR'];
+    if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
+        $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']));
+    if(!empty($_SERVER['HTTP_X_REAL_IP']))
+        $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_REAL_IP']));
+
+    // some IPv4/v6 regexps borrowed from Feyd
+    // see: http://forums.devnetwork.net/viewtopic.php?f=38&t=53479
+    $dec_octet = '(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|[0-9])';
+    $hex_digit = '[A-Fa-f0-9]';
+    $h16 = "{$hex_digit}{1,4}";
+    $IPv4Address = "$dec_octet\\.$dec_octet\\.$dec_octet\\.$dec_octet";
+    $ls32 = "(?:$h16:$h16|$IPv4Address)";
+    $IPv6Address =
+        "(?:(?:{$IPv4Address})|(?:".
+        "(?:$h16:){6}$ls32" .
+        "|::(?:$h16:){5}$ls32" .
+        "|(?:$h16)?::(?:$h16:){4}$ls32" .
+        "|(?:(?:$h16:){0,1}$h16)?::(?:$h16:){3}$ls32" .
+        "|(?:(?:$h16:){0,2}$h16)?::(?:$h16:){2}$ls32" .
+        "|(?:(?:$h16:){0,3}$h16)?::(?:$h16:){1}$ls32" .
+        "|(?:(?:$h16:){0,4}$h16)?::$ls32" .
+        "|(?:(?:$h16:){0,5}$h16)?::$h16" .
+        "|(?:(?:$h16:){0,6}$h16)?::" .
+        ")(?:\\/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))?)";
+
+    // remove any non-IP stuff
+    $cnt = count($ip);
+    $match = array();
+    for($i=0; $i<$cnt; $i++){
+        if(preg_match("/^$IPv4Address$/",$ip[$i],$match) || preg_match("/^$IPv6Address$/",$ip[$i],$match)) {
+            $ip[$i] = $match[0];
+        } else {
+            $ip[$i] = '';
+        }
+        if(empty($ip[$i])) unset($ip[$i]);
     }
-    if(empty($ip[$i])) unset($ip[$i]);
-  }
-  $ip = array_values(array_unique($ip));
-  if(!$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP
-
-  if(!$single) return join(',',$ip);
-
-  // decide which IP to use, trying to avoid local addresses
-  $ip = array_reverse($ip);
-  foreach($ip as $i){
-    if(preg_match('/^(127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$i)){
-      continue;
-    }else{
-      return $i;
+    $ip = array_values(array_unique($ip));
+    if(!$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP
+
+    if(!$single) return join(',',$ip);
+
+    // decide which IP to use, trying to avoid local addresses
+    $ip = array_reverse($ip);
+    foreach($ip as $i){
+        if(preg_match('/^(127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$i)){
+            continue;
+        }else{
+            return $i;
+        }
     }
-  }
-  // still here? just use the first (last) address
-  return $ip[0];
+    // still here? just use the first (last) address
+    return $ip[0];
 }
 
 /**
@@ -687,17 +684,17 @@ function clientismobile(){
  * @returns a comma separated list of hostnames
  */
 function gethostsbyaddrs($ips){
-  $hosts = array();
-  $ips = explode(',',$ips);
+    $hosts = array();
+    $ips = explode(',',$ips);
 
-  if(is_array($ips)) {
-    foreach($ips as $ip){
-      $hosts[] = gethostbyaddr(trim($ip));
+    if(is_array($ips)) {
+        foreach($ips as $ip){
+            $hosts[] = gethostbyaddr(trim($ip));
+        }
+        return join(',',$hosts);
+    } else {
+        return gethostbyaddr(trim($ips));
     }
-    return join(',',$hosts);
-  } else {
-    return gethostbyaddr(trim($ips));
-  }
 }
 
 /**
@@ -708,25 +705,25 @@ function gethostsbyaddrs($ips){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function checklock($id){
-  global $conf;
-  $lock = wikiLockFN($id);
+    global $conf;
+    $lock = wikiLockFN($id);
 
-  //no lockfile
-  if(!@file_exists($lock)) return false;
+    //no lockfile
+    if(!@file_exists($lock)) return false;
 
-  //lockfile expired
-  if((time() - filemtime($lock)) > $conf['locktime']){
-    @unlink($lock);
-    return false;
-  }
+    //lockfile expired
+    if((time() - filemtime($lock)) > $conf['locktime']){
+        @unlink($lock);
+        return false;
+    }
 
-  //my own lock
-  $ip = io_readFile($lock);
-  if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
-    return false;
-  }
+    //my own lock
+    $ip = io_readFile($lock);
+    if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
+        return false;
+    }
 
-  return $ip;
+    return $ip;
 }
 
 /**
@@ -735,12 +732,12 @@ function checklock($id){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function lock($id){
-  $lock = wikiLockFN($id);
-  if($_SERVER['REMOTE_USER']){
-    io_saveFile($lock,$_SERVER['REMOTE_USER']);
-  }else{
-    io_saveFile($lock,clientIP());
-  }
+    $lock = wikiLockFN($id);
+    if($_SERVER['REMOTE_USER']){
+        io_saveFile($lock,$_SERVER['REMOTE_USER']);
+    }else{
+        io_saveFile($lock,clientIP());
+    }
 }
 
 /**
@@ -750,15 +747,15 @@ function lock($id){
  * @return bool true if a lock was removed
  */
 function unlock($id){
-  $lock = wikiLockFN($id);
-  if(@file_exists($lock)){
-    $ip = io_readFile($lock);
-    if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
-      @unlink($lock);
-      return true;
+    $lock = wikiLockFN($id);
+    if(@file_exists($lock)){
+        $ip = io_readFile($lock);
+        if( ($ip == clientIP()) || ($ip == $_SERVER['REMOTE_USER']) ){
+            @unlink($lock);
+            return true;
+        }
     }
-  }
-  return false;
+    return false;
 }
 
 /**
@@ -768,8 +765,8 @@ function unlock($id){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function cleanText($text){
-  $text = preg_replace("/(\015\012)|(\015)/","\012",$text);
-  return $text;
+    $text = preg_replace("/(\015\012)|(\015)/","\012",$text);
+    return $text;
 }
 
 /**
@@ -781,8 +778,8 @@ function cleanText($text){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function formText($text){
-  $text = str_replace("\012","\015\012",$text);
-  return htmlspecialchars($text);
+    $text = str_replace("\012","\015\012",$text);
+    return htmlspecialchars($text);
 }
 
 /**
@@ -791,7 +788,7 @@ function formText($text){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function rawLocale($id){
-  return io_readFile(localeFN($id));
+    return io_readFile(localeFN($id));
 }
 
 /**
@@ -800,7 +797,7 @@ function rawLocale($id){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function rawWiki($id,$rev=''){
-  return io_readWikiPage(wikiFN($id, $rev), $id, $rev);
+    return io_readWikiPage(wikiFN($id, $rev), $id, $rev);
 }
 
 /**
@@ -809,66 +806,66 @@ function rawWiki($id,$rev=''){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function pageTemplate($data){
-  $id = $data[0];
-  global $conf;
-  global $INFO;
-
-  $path = dirname(wikiFN($id));
-
-  if(@file_exists($path.'/_template.txt')){
-    $tpl = io_readFile($path.'/_template.txt');
-  }else{
-    // search upper namespaces for templates
-    $len = strlen(rtrim($conf['datadir'],'/'));
-    while (strlen($path) >= $len){
-      if(@file_exists($path.'/__template.txt')){
-        $tpl = io_readFile($path.'/__template.txt');
-        break;
-      }
-      $path = substr($path, 0, strrpos($path, '/'));
-    }
-  }
-  if(!$tpl) return '';
-
-  // replace placeholders
-  $file = noNS($id);
-  $page = strtr($file,'_',' ');
-
-  $tpl = str_replace(array(
-                        '@ID@',
-                        '@NS@',
-                        '@FILE@',
-                        '@!FILE@',
-                        '@!FILE!@',
-                        '@PAGE@',
-                        '@!PAGE@',
-                        '@!!PAGE@',
-                        '@!PAGE!@',
-                        '@USER@',
-                        '@NAME@',
-                        '@MAIL@',
-                        '@DATE@',
-                     ),
-                     array(
-                        $id,
-                        getNS($id),
-                        $file,
-                        utf8_ucfirst($file),
-                        utf8_strtoupper($file),
-                        $page,
-                        utf8_ucfirst($page),
-                        utf8_ucwords($page),
-                        utf8_strtoupper($page),
-                        $_SERVER['REMOTE_USER'],
-                        $INFO['userinfo']['name'],
-                        $INFO['userinfo']['mail'],
-                        $conf['dformat'],
-                     ), $tpl);
-
-  // we need the callback to work around strftime's char limit
-  $tpl = preg_replace_callback('/%./',create_function('$m','return strftime($m[0]);'),$tpl);
-
-  return $tpl;
+    $id = $data[0];
+    global $conf;
+    global $INFO;
+
+    $path = dirname(wikiFN($id));
+
+    if(@file_exists($path.'/_template.txt')){
+        $tpl = io_readFile($path.'/_template.txt');
+    }else{
+        // search upper namespaces for templates
+        $len = strlen(rtrim($conf['datadir'],'/'));
+        while (strlen($path) >= $len){
+            if(@file_exists($path.'/__template.txt')){
+                $tpl = io_readFile($path.'/__template.txt');
+                break;
+            }
+            $path = substr($path, 0, strrpos($path, '/'));
+        }
+    }
+    if(!$tpl) return '';
+
+    // replace placeholders
+    $file = noNS($id);
+    $page = strtr($file,'_',' ');
+
+    $tpl = str_replace(array(
+                '@ID@',
+                '@NS@',
+                '@FILE@',
+                '@!FILE@',
+                '@!FILE!@',
+                '@PAGE@',
+                '@!PAGE@',
+                '@!!PAGE@',
+                '@!PAGE!@',
+                '@USER@',
+                '@NAME@',
+                '@MAIL@',
+                '@DATE@',
+                ),
+            array(
+                $id,
+                getNS($id),
+                $file,
+                utf8_ucfirst($file),
+                utf8_strtoupper($file),
+                $page,
+                utf8_ucfirst($page),
+                utf8_ucwords($page),
+                utf8_strtoupper($page),
+                $_SERVER['REMOTE_USER'],
+                $INFO['userinfo']['name'],
+                $INFO['userinfo']['mail'],
+                $conf['dformat'],
+                ), $tpl);
+
+    // we need the callback to work around strftime's char limit
+    $tpl = preg_replace_callback('/%./',create_function('$m','return strftime($m[0]);'),$tpl);
+
+    return $tpl;
 }
 
 
@@ -883,16 +880,16 @@ function pageTemplate($data){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function rawWikiSlices($range,$id,$rev=''){
-  list($from,$to) = explode('-',$range,2);
-  $text = io_readWikiPage(wikiFN($id, $rev), $id, $rev);
-  if(!$from) $from = 0;
-  if(!$to)   $to   = strlen($text)+1;
+    list($from,$to) = explode('-',$range,2);
+    $text = io_readWikiPage(wikiFN($id, $rev), $id, $rev);
+    if(!$from) $from = 0;
+    if(!$to)   $to   = strlen($text)+1;
 
-  $slices[0] = substr($text,0,$from-1);
-  $slices[1] = substr($text,$from-1,$to-$from);
-  $slices[2] = substr($text,$to);
+    $slices[0] = substr($text,0,$from-1);
+    $slices[1] = substr($text,$from-1,$to-$from);
+    $slices[2] = substr($text,$to);
 
-  return $slices;
+    return $slices;
 }
 
 /**
@@ -905,16 +902,15 @@ function rawWikiSlices($range,$id,$rev=''){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function con($pre,$text,$suf,$pretty=false){
+    if($pretty){
+        if($pre && substr($pre,-1) != "\n") $pre .= "\n";
+        if($suf && substr($text,-1) != "\n") $text .= "\n";
+    }
 
-  if($pretty){
-    if($pre && substr($pre,-1) != "\n") $pre .= "\n";
-    if($suf && substr($text,-1) != "\n") $text .= "\n";
-  }
-
-  // Avoid double newline above section when saving section edit
-  //if($pre) $pre .= "\n";
-  if($suf) $text .= "\n";
-  return $pre.$text.$suf;
+    // Avoid double newline above section when saving section edit
+    //if($pre) $pre .= "\n";
+    if($suf) $text .= "\n";
+    return $pre.$text.$suf;
 }
 
 /**
@@ -925,102 +921,102 @@ function con($pre,$text,$suf,$pretty=false){
  * @author Ben Coburn <btcoburn@silicodon.net>
  */
 function saveWikiText($id,$text,$summary,$minor=false){
-  /* Note to developers:
-     This code is subtle and delicate. Test the behavior of
-     the attic and changelog with dokuwiki and external edits
-     after any changes. External edits change the wiki page
-     directly without using php or dokuwiki.
-  */
-  global $conf;
-  global $lang;
-  global $REV;
-  // ignore if no changes were made
-  if($text == rawWiki($id,'')){
-    return;
-  }
-
-  $file = wikiFN($id);
-  $old = @filemtime($file); // from page
-  $wasRemoved = empty($text);
-  $wasCreated = !@file_exists($file);
-  $wasReverted = ($REV==true);
-  $newRev = false;
-  $oldRev = getRevisions($id, -1, 1, 1024); // from changelog
-  $oldRev = (int)(empty($oldRev)?0:$oldRev[0]);
-  if(!@file_exists(wikiFN($id, $old)) && @file_exists($file) && $old>=$oldRev) {
-    // add old revision to the attic if missing
-    saveOldRevision($id);
-    // add a changelog entry if this edit came from outside dokuwiki
-    if ($old>$oldRev) {
-      addLogEntry($old, $id, DOKU_CHANGE_TYPE_EDIT, $lang['external_edit'], '', array('ExternalEdit'=>true));
-      // remove soon to be stale instructions
-      $cache = new cache_instructions($id, $file);
-      $cache->removeCache();
-    }
-  }
-
-  if ($wasRemoved){
-    // Send "update" event with empty data, so plugins can react to page deletion
-    $data = array(array($file, '', false), getNS($id), noNS($id), false);
-    trigger_event('IO_WIKIPAGE_WRITE', $data);
-    // pre-save deleted revision
-    @touch($file);
-    clearstatcache();
-    $newRev = saveOldRevision($id);
-    // remove empty file
-    @unlink($file);
-    // remove old meta info...
-    $mfiles = metaFiles($id);
-    $changelog = metaFN($id, '.changes');
-    $metadata  = metaFN($id, '.meta');
-    foreach ($mfiles as $mfile) {
-      // but keep per-page changelog to preserve page history and keep meta data
-      if (@file_exists($mfile) && $mfile!==$changelog && $mfile!==$metadata) { @unlink($mfile); }
-    }
-    // purge meta data
-    p_purge_metadata($id);
-    $del = true;
-    // autoset summary on deletion
-    if(empty($summary)) $summary = $lang['deleted'];
-    // remove empty namespaces
-    io_sweepNS($id, 'datadir');
-    io_sweepNS($id, 'mediadir');
-  }else{
-    // save file (namespace dir is created in io_writeWikiPage)
-    io_writeWikiPage($file, $text, $id);
-    // pre-save the revision, to keep the attic in sync
-    $newRev = saveOldRevision($id);
-    $del = false;
-  }
-
-  // select changelog line type
-  $extra = '';
-  $type = DOKU_CHANGE_TYPE_EDIT;
-  if ($wasReverted) {
-    $type = DOKU_CHANGE_TYPE_REVERT;
-    $extra = $REV;
-  }
-  else if ($wasCreated) { $type = DOKU_CHANGE_TYPE_CREATE; }
-  else if ($wasRemoved) { $type = DOKU_CHANGE_TYPE_DELETE; }
-  else if ($minor && $conf['useacl'] && $_SERVER['REMOTE_USER']) { $type = DOKU_CHANGE_TYPE_MINOR_EDIT; } //minor edits only for logged in users
-
-  addLogEntry($newRev, $id, $type, $summary, $extra);
-  // send notify mails
-  notify($id,'admin',$old,$summary,$minor);
-  notify($id,'subscribers',$old,$summary,$minor);
-
-  // update the purgefile (timestamp of the last time anything within the wiki was changed)
-  io_saveFile($conf['cachedir'].'/purgefile',time());
-
-  // if useheading is enabled, purge the cache of all linking pages
-  if(useHeading('content')){
-    require_once(DOKU_INC.'inc/fulltext.php');
-    $pages = ft_backlinks($id);
-    foreach ($pages as $page) {
-      $cache = new cache_renderer($page, wikiFN($page), 'xhtml');
-      $cache->removeCache();
-    }
-  }
+    /* Note to developers:
+       This code is subtle and delicate. Test the behavior of
+       the attic and changelog with dokuwiki and external edits
+       after any changes. External edits change the wiki page
+       directly without using php or dokuwiki.
+     */
+    global $conf;
+    global $lang;
+    global $REV;
+    // ignore if no changes were made
+    if($text == rawWiki($id,'')){
+        return;
+    }
+
+    $file = wikiFN($id);
+    $old = @filemtime($file); // from page
+    $wasRemoved = empty($text);
+    $wasCreated = !@file_exists($file);
+    $wasReverted = ($REV==true);
+    $newRev = false;
+    $oldRev = getRevisions($id, -1, 1, 1024); // from changelog
+    $oldRev = (int)(empty($oldRev)?0:$oldRev[0]);
+    if(!@file_exists(wikiFN($id, $old)) && @file_exists($file) && $old>=$oldRev) {
+        // add old revision to the attic if missing
+        saveOldRevision($id);
+        // add a changelog entry if this edit came from outside dokuwiki
+        if ($old>$oldRev) {
+            addLogEntry($old, $id, DOKU_CHANGE_TYPE_EDIT, $lang['external_edit'], '', array('ExternalEdit'=>true));
+            // remove soon to be stale instructions
+            $cache = new cache_instructions($id, $file);
+            $cache->removeCache();
+        }
+    }
+
+    if ($wasRemoved){
+        // Send "update" event with empty data, so plugins can react to page deletion
+        $data = array(array($file, '', false), getNS($id), noNS($id), false);
+        trigger_event('IO_WIKIPAGE_WRITE', $data);
+        // pre-save deleted revision
+        @touch($file);
+        clearstatcache();
+        $newRev = saveOldRevision($id);
+        // remove empty file
+        @unlink($file);
+        // remove old meta info...
+        $mfiles = metaFiles($id);
+        $changelog = metaFN($id, '.changes');
+        $metadata  = metaFN($id, '.meta');
+        foreach ($mfiles as $mfile) {
+            // but keep per-page changelog to preserve page history and keep meta data
+            if (@file_exists($mfile) && $mfile!==$changelog && $mfile!==$metadata) { @unlink($mfile); }
+        }
+        // purge meta data
+        p_purge_metadata($id);
+        $del = true;
+        // autoset summary on deletion
+        if(empty($summary)) $summary = $lang['deleted'];
+        // remove empty namespaces
+        io_sweepNS($id, 'datadir');
+        io_sweepNS($id, 'mediadir');
+    }else{
+        // save file (namespace dir is created in io_writeWikiPage)
+        io_writeWikiPage($file, $text, $id);
+        // pre-save the revision, to keep the attic in sync
+        $newRev = saveOldRevision($id);
+        $del = false;
+    }
+
+    // select changelog line type
+    $extra = '';
+    $type = DOKU_CHANGE_TYPE_EDIT;
+    if ($wasReverted) {
+        $type = DOKU_CHANGE_TYPE_REVERT;
+        $extra = $REV;
+    }
+    else if ($wasCreated) { $type = DOKU_CHANGE_TYPE_CREATE; }
+    else if ($wasRemoved) { $type = DOKU_CHANGE_TYPE_DELETE; }
+    else if ($minor && $conf['useacl'] && $_SERVER['REMOTE_USER']) { $type = DOKU_CHANGE_TYPE_MINOR_EDIT; } //minor edits only for logged in users
+
+    addLogEntry($newRev, $id, $type, $summary, $extra);
+    // send notify mails
+    notify($id,'admin',$old,$summary,$minor);
+    notify($id,'subscribers',$old,$summary,$minor);
+
+    // update the purgefile (timestamp of the last time anything within the wiki was changed)
+    io_saveFile($conf['cachedir'].'/purgefile',time());
+
+    // if useheading is enabled, purge the cache of all linking pages
+    if(useHeading('content')){
+        require_once(DOKU_INC.'inc/fulltext.php');
+        $pages = ft_backlinks($id);
+        foreach ($pages as $page) {
+            $cache = new cache_renderer($page, wikiFN($page), 'xhtml');
+            $cache->removeCache();
+        }
+    }
 }
 
 /**
@@ -1030,13 +1026,13 @@ function saveWikiText($id,$text,$summary,$minor=false){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function saveOldRevision($id){
-  global $conf;
-  $oldf = wikiFN($id);
-  if(!@file_exists($oldf)) return '';
-  $date = filemtime($oldf);
-  $newf = wikiFN($id,$date);
-  io_writeWikiPage($newf, rawWiki($id), $id, $date);
-  return $date;
+    global $conf;
+    $oldf = wikiFN($id);
+    if(!@file_exists($oldf)) return '';
+    $date = filemtime($oldf);
+    $newf = wikiFN($id,$date);
+    io_writeWikiPage($newf, rawWiki($id), $id, $date);
+    return $date;
 }
 
 /**
@@ -1052,72 +1048,72 @@ function saveOldRevision($id){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function notify($id,$who,$rev='',$summary='',$minor=false,$replace=array()){
-  global $lang;
-  global $conf;
-  global $INFO;
-
-  // decide if there is something to do
-  if($who == 'admin'){
-    if(empty($conf['notify'])) return; //notify enabled?
-    $text = rawLocale('mailtext');
-    $to   = $conf['notify'];
-    $bcc  = '';
-  }elseif($who == 'subscribers'){
-    if(!$conf['subscribers']) return; //subscribers enabled?
-    if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return; //skip minors
-    $bcc  = subscriber_addresslist($id,false);
-    if(empty($bcc)) return;
-    $to   = '';
-    $text = rawLocale('subscribermail');
-  }elseif($who == 'register'){
-    if(empty($conf['registernotify'])) return;
-    $text = rawLocale('registermail');
-    $to   = $conf['registernotify'];
-    $bcc  = '';
-  }else{
-    return; //just to be safe
-  }
-
-  $ip   = clientIP();
-  $text = str_replace('@DATE@',dformat(),$text);
-  $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text);
-  $text = str_replace('@IPADDRESS@',$ip,$text);
-  $text = str_replace('@HOSTNAME@',gethostsbyaddrs($ip),$text);
-  $text = str_replace('@NEWPAGE@',wl($id,'',true,'&'),$text);
-  $text = str_replace('@PAGE@',$id,$text);
-  $text = str_replace('@TITLE@',$conf['title'],$text);
-  $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text);
-  $text = str_replace('@SUMMARY@',$summary,$text);
-  $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text);
-
-  foreach ($replace as $key => $substitution) {
-    $text = str_replace('@'.strtoupper($key).'@',$substitution, $text);
-  }
-
-  if($who == 'register'){
-    $subject = $lang['mail_new_user'].' '.$summary;
-  }elseif($rev){
-    $subject = $lang['mail_changed'].' '.$id;
-    $text = str_replace('@OLDPAGE@',wl($id,"rev=$rev",true,'&'),$text);
-    require_once(DOKU_INC.'inc/DifferenceEngine.php');
-    $df  = new Diff(explode("\n",rawWiki($id,$rev)),
-                    explode("\n",rawWiki($id)));
-    $dformat = new UnifiedDiffFormatter();
-    $diff    = $dformat->format($df);
-  }else{
-    $subject=$lang['mail_newpage'].' '.$id;
-    $text = str_replace('@OLDPAGE@','none',$text);
-    $diff = rawWiki($id);
-  }
-  $text = str_replace('@DIFF@',$diff,$text);
-  $subject = '['.$conf['title'].'] '.$subject;
-
-  $from = $conf['mailfrom'];
-  $from = str_replace('@USER@',$_SERVER['REMOTE_USER'],$from);
-  $from = str_replace('@NAME@',$INFO['userinfo']['name'],$from);
-  $from = str_replace('@MAIL@',$INFO['userinfo']['mail'],$from);
-
-  mail_send($to,$subject,$text,$from,'',$bcc);
+    global $lang;
+    global $conf;
+    global $INFO;
+
+    // decide if there is something to do
+    if($who == 'admin'){
+        if(empty($conf['notify'])) return; //notify enabled?
+        $text = rawLocale('mailtext');
+        $to   = $conf['notify'];
+        $bcc  = '';
+    }elseif($who == 'subscribers'){
+        if(!$conf['subscribers']) return; //subscribers enabled?
+        if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return; //skip minors
+        $bcc  = subscriber_addresslist($id,false);
+        if(empty($bcc)) return;
+        $to   = '';
+        $text = rawLocale('subscribermail');
+    }elseif($who == 'register'){
+        if(empty($conf['registernotify'])) return;
+        $text = rawLocale('registermail');
+        $to   = $conf['registernotify'];
+        $bcc  = '';
+    }else{
+        return; //just to be safe
+    }
+
+    $ip   = clientIP();
+    $text = str_replace('@DATE@',dformat(),$text);
+    $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text);
+    $text = str_replace('@IPADDRESS@',$ip,$text);
+    $text = str_replace('@HOSTNAME@',gethostsbyaddrs($ip),$text);
+    $text = str_replace('@NEWPAGE@',wl($id,'',true,'&'),$text);
+    $text = str_replace('@PAGE@',$id,$text);
+    $text = str_replace('@TITLE@',$conf['title'],$text);
+    $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text);
+    $text = str_replace('@SUMMARY@',$summary,$text);
+    $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text);
+
+    foreach ($replace as $key => $substitution) {
+        $text = str_replace('@'.strtoupper($key).'@',$substitution, $text);
+    }
+
+    if($who == 'register'){
+        $subject = $lang['mail_new_user'].' '.$summary;
+    }elseif($rev){
+        $subject = $lang['mail_changed'].' '.$id;
+        $text = str_replace('@OLDPAGE@',wl($id,"rev=$rev",true,'&'),$text);
+        require_once(DOKU_INC.'inc/DifferenceEngine.php');
+        $df  = new Diff(explode("\n",rawWiki($id,$rev)),
+                explode("\n",rawWiki($id)));
+        $dformat = new UnifiedDiffFormatter();
+        $diff    = $dformat->format($df);
+    }else{
+        $subject=$lang['mail_newpage'].' '.$id;
+        $text = str_replace('@OLDPAGE@','none',$text);
+        $diff = rawWiki($id);
+    }
+    $text = str_replace('@DIFF@',$diff,$text);
+    $subject = '['.$conf['title'].'] '.$subject;
+
+    $from = $conf['mailfrom'];
+    $from = str_replace('@USER@',$_SERVER['REMOTE_USER'],$from);
+    $from = str_replace('@NAME@',$INFO['userinfo']['name'],$from);
+    $from = str_replace('@MAIL@',$INFO['userinfo']['mail'],$from);
+
+    mail_send($to,$subject,$text,$from,'',$bcc);
 }
 
 /**
@@ -1127,32 +1123,32 @@ function notify($id,$who,$rev='',$summary='',$minor=false,$replace=array()){
  * @author Todd Augsburger <todd@rollerorgans.com>
  */
 function getGoogleQuery(){
-  if (!isset($_SERVER['HTTP_REFERER'])) {
-    return '';
-  }
-  $url = parse_url($_SERVER['HTTP_REFERER']);
-
-  $query = array();
-
-  // temporary workaround against PHP bug #49733
-  // see http://bugs.php.net/bug.php?id=49733
-  if(UTF8_MBSTRING) $enc = mb_internal_encoding();
-  parse_str($url['query'],$query);
-  if(UTF8_MBSTRING) mb_internal_encoding($enc);
-
-  $q = '';
-  if(isset($query['q']))
-    $q = $query['q'];        // google, live/msn, aol, ask, altavista, alltheweb, gigablast
-  elseif(isset($query['p']))
-    $q = $query['p'];        // yahoo
-  elseif(isset($query['query']))
-    $q = $query['query'];    // lycos, netscape, clusty, hotbot
-  elseif(preg_match("#a9\.com#i",$url['host'])) // a9
-    $q = urldecode(ltrim($url['path'],'/'));
-
-  if($q === '') return '';
-  $q = preg_split('/[\s\'"\\\\`()\]\[?:!\.{};,#+*<>\\/]+/',$q,-1,PREG_SPLIT_NO_EMPTY);
-  return $q;
+    if (!isset($_SERVER['HTTP_REFERER'])) {
+        return '';
+    }
+    $url = parse_url($_SERVER['HTTP_REFERER']);
+
+    $query = array();
+
+    // temporary workaround against PHP bug #49733
+    // see http://bugs.php.net/bug.php?id=49733
+    if(UTF8_MBSTRING) $enc = mb_internal_encoding();
+    parse_str($url['query'],$query);
+    if(UTF8_MBSTRING) mb_internal_encoding($enc);
+
+    $q = '';
+    if(isset($query['q']))
+        $q = $query['q'];        // google, live/msn, aol, ask, altavista, alltheweb, gigablast
+    elseif(isset($query['p']))
+        $q = $query['p'];        // yahoo
+    elseif(isset($query['query']))
+        $q = $query['query'];    // lycos, netscape, clusty, hotbot
+    elseif(preg_match("#a9\.com#i",$url['host'])) // a9
+        $q = urldecode(ltrim($url['path'],'/'));
+
+    if($q === '') return '';
+    $q = preg_split('/[\s\'"\\\\`()\]\[?:!\.{};,#+*<>\\/]+/',$q,-1,PREG_SPLIT_NO_EMPTY);
+    return $q;
 }
 
 /**
@@ -1162,18 +1158,18 @@ function getGoogleQuery(){
  * @author     Andreas Gohr <andi@splitbrain.org>
  */
 function setCorrectLocale(){
-  global $conf;
-  global $lang;
-
-  $enc = strtoupper($lang['encoding']);
-  foreach ($lang['locales'] as $loc){
-    //try locale
-    if(@setlocale(LC_ALL,$loc)) return;
-    //try loceale with encoding
-    if(@setlocale(LC_ALL,"$loc.$enc")) return;
-  }
-  //still here? try to set from environment
-  @setlocale(LC_ALL,"");
+    global $conf;
+    global $lang;
+
+    $enc = strtoupper($lang['encoding']);
+    foreach ($lang['locales'] as $loc){
+        //try locale
+        if(@setlocale(LC_ALL,$loc)) return;
+        //try loceale with encoding
+        if(@setlocale(LC_ALL,"$loc.$enc")) return;
+    }
+    //still here? try to set from environment
+    @setlocale(LC_ALL,"");
 }
 
 /**
@@ -1186,16 +1182,16 @@ function setCorrectLocale(){
  * @version     1.0.0
  */
 function filesize_h($size, $dec = 1){
-  $sizes = array('B', 'KB', 'MB', 'GB');
-  $count = count($sizes);
-  $i = 0;
+    $sizes = array('B', 'KB', 'MB', 'GB');
+    $count = count($sizes);
+    $i = 0;
 
-  while ($size >= 1024 && ($i < $count - 1)) {
-    $size /= 1024;
-    $i++;
-  }
+    while ($size >= 1024 && ($i < $count - 1)) {
+        $size /= 1024;
+        $i++;
+    }
 
-  return round($size, $dec) . ' ' . $sizes[$i];
+    return round($size, $dec) . ' ' . $sizes[$i];
 }
 
 /**
@@ -1204,29 +1200,28 @@ function filesize_h($size, $dec = 1){
  * @author Andreas Gohr <gohr@cosmocode.de>
  */
 function datetime_h($dt){
-  global $lang;
-
-  $ago = time() - $dt;
-  if($ago > 24*60*60*30*12*2){
-    return sprintf($lang['years'], round($ago/(24*60*60*30*12)));
-  }
-  if($ago > 24*60*60*30*2){
-    return sprintf($lang['months'], round($ago/(24*60*60*30)));
-  }
-  if($ago > 24*60*60*7*2){
-    return sprintf($lang['weeks'], round($ago/(24*60*60*7)));
-  }
-  if($ago > 24*60*60*2){
-    return sprintf($lang['days'], round($ago/(24*60*60)));
-  }
-  if($ago > 60*60*2){
-    return sprintf($lang['hours'], round($ago/(60*60)));
-  }
-  if($ago > 60*2){
-    return sprintf($lang['minutes'], round($ago/(60)));
-  }
-  return sprintf($lang['seconds'], $ago);
+    global $lang;
 
+    $ago = time() - $dt;
+    if($ago > 24*60*60*30*12*2){
+        return sprintf($lang['years'], round($ago/(24*60*60*30*12)));
+    }
+    if($ago > 24*60*60*30*2){
+        return sprintf($lang['months'], round($ago/(24*60*60*30)));
+    }
+    if($ago > 24*60*60*7*2){
+        return sprintf($lang['weeks'], round($ago/(24*60*60*7)));
+    }
+    if($ago > 24*60*60*2){
+        return sprintf($lang['days'], round($ago/(24*60*60)));
+    }
+    if($ago > 60*60*2){
+        return sprintf($lang['hours'], round($ago/(60*60)));
+    }
+    if($ago > 60*2){
+        return sprintf($lang['minutes'], round($ago/(60)));
+    }
+    return sprintf($lang['seconds'], $ago);
 }
 
 /**
@@ -1239,14 +1234,14 @@ function datetime_h($dt){
  * @author Andreas Gohr <gohr@cosmocode.de>
  */
 function dformat($dt=null,$format=''){
-  global $conf;
+    global $conf;
 
-  if(is_null($dt)) $dt = time();
-  $dt = (int) $dt;
-  if(!$format) $format = $conf['dformat'];
+    if(is_null($dt)) $dt = time();
+    $dt = (int) $dt;
+    if(!$format) $format = $conf['dformat'];
 
-  $format = str_replace('%f',datetime_h($dt),$format);
-  return strftime($format,$dt);
+    $format = str_replace('%f',datetime_h($dt),$format);
+    return strftime($format,$dt);
 }
 
 /**
@@ -1256,22 +1251,25 @@ function dformat($dt=null,$format=''){
  * @author Christopher Smith <chris@jalakai.co.uk>
  */
 function obfuscate($email) {
-  global $conf;
-
-  switch ($conf['mailguard']) {
-    case 'visible' :
-      $obfuscate = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
-      return strtr($email, $obfuscate);
-
-    case 'hex' :
-      $encode = '';
-      for ($x=0; $x < strlen($email); $x++) $encode .= '&#x' . bin2hex($email{$x}).';';
-      return $encode;
-
-    case 'none' :
-    default :
-      return $email;
-  }
+    global $conf;
+
+    switch ($conf['mailguard']) {
+        case 'visible' :
+            $obfuscate = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
+            return strtr($email, $obfuscate);
+
+        case 'hex' :
+            $encode = '';
+            $len = strlen($email);
+            for ($x=0; $x < $len; $x++){
+                $encode .= '&#x' . bin2hex($email{$x}).';';
+            }
+            return $encode;
+
+        case 'none' :
+        default :
+            return $email;
+    }
 }
 
 /**
@@ -1280,22 +1278,22 @@ function obfuscate($email) {
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function is_subscribed($id,$uid,$ns=false){
-  if(!$ns) {
-    $file=metaFN($id,'.mlist');
-  } else {
-    if(!getNS($id)) {
-      $file = metaFN(getNS($id),'.mlist');
+    if(!$ns) {
+        $file=metaFN($id,'.mlist');
     } else {
-      $file = metaFN(getNS($id),'/.mlist');
+        if(!getNS($id)) {
+            $file = metaFN(getNS($id),'.mlist');
+        } else {
+            $file = metaFN(getNS($id),'/.mlist');
+        }
+    }
+    if (@file_exists($file)) {
+        $mlist = file($file);
+        $pos = array_search($uid."\n",$mlist);
+        return is_int($pos);
     }
-  }
-  if (@file_exists($file)) {
-    $mlist = file($file);
-    $pos = array_search($uid."\n",$mlist);
-    return is_int($pos);
-  }
 
-  return false;
+    return false;
 }
 
 /**
@@ -1305,64 +1303,64 @@ function is_subscribed($id,$uid,$ns=false){
  * @author Steven Danz <steven-danz@kc.rr.com>
  */
 function subscriber_addresslist($id,$self=true){
-  global $conf;
-  global $auth;
-
-  if (!$conf['subscribers']) return '';
-
-  $users = array();
-  $emails = array();
-
-  // load the page mlist file content
-  $mlist = array();
-  $file=metaFN($id,'.mlist');
-  if (@file_exists($file)) {
-    $mlist = file($file);
-    foreach ($mlist as $who) {
-      $who = rtrim($who);
-      if(!$self && $who == $_SERVER['REMOTE_USER']) continue;
-      $users[$who] = true;
-    }
-  }
-
-  // load also the namespace mlist file content
-  $ns = getNS($id);
-  while ($ns) {
-    $nsfile = metaFN($ns,'/.mlist');
+    global $conf;
+    global $auth;
+
+    if (!$conf['subscribers']) return '';
+
+    $users = array();
+    $emails = array();
+
+    // load the page mlist file content
+    $mlist = array();
+    $file=metaFN($id,'.mlist');
+    if (@file_exists($file)) {
+        $mlist = file($file);
+        foreach ($mlist as $who) {
+            $who = rtrim($who);
+            if(!$self && $who == $_SERVER['REMOTE_USER']) continue;
+            $users[$who] = true;
+        }
+    }
+
+    // load also the namespace mlist file content
+    $ns = getNS($id);
+    while ($ns) {
+        $nsfile = metaFN($ns,'/.mlist');
+        if (@file_exists($nsfile)) {
+            $mlist = file($nsfile);
+            foreach ($mlist as $who) {
+                $who = rtrim($who);
+                if(!$self && $who == $_SERVER['REMOTE_USER']) continue;
+                $users[$who] = true;
+            }
+        }
+        $ns = getNS($ns);
+    }
+    // root namespace
+    $nsfile = metaFN('','.mlist');
     if (@file_exists($nsfile)) {
-      $mlist = file($nsfile);
-      foreach ($mlist as $who) {
-        $who = rtrim($who);
-        if(!$self && $who == $_SERVER['REMOTE_USER']) continue;
-        $users[$who] = true;
-      }
-    }
-    $ns = getNS($ns);
-  }
-  // root namespace
-  $nsfile = metaFN('','.mlist');
-  if (@file_exists($nsfile)) {
-    $mlist = file($nsfile);
-    foreach ($mlist as $who) {
-      $who = rtrim($who);
-      if(!$self && $who == $_SERVER['REMOTE_USER']) continue;
-      $users[$who] = true;
-    }
-  }
-  if(!empty($users)) {
-    foreach (array_keys($users) as $who) {
-      $info = $auth->getUserData($who);
-      if($info === false) continue;
-      $level = auth_aclcheck($id,$who,$info['grps']);
-      if ($level >= AUTH_READ) {
-        if (strcasecmp($info['mail'],$conf['notify']) != 0) {
-          $emails[] = $info['mail'];
+        $mlist = file($nsfile);
+        foreach ($mlist as $who) {
+            $who = rtrim($who);
+            if(!$self && $who == $_SERVER['REMOTE_USER']) continue;
+            $users[$who] = true;
+        }
+    }
+    if(!empty($users)) {
+        foreach (array_keys($users) as $who) {
+            $info = $auth->getUserData($who);
+            if($info === false) continue;
+            $level = auth_aclcheck($id,$who,$info['grps']);
+            if ($level >= AUTH_READ) {
+                if (strcasecmp($info['mail'],$conf['notify']) != 0) {
+                    $emails[] = $info['mail'];
+                }
+            }
         }
-      }
     }
-  }
 
-  return implode(',',$emails);
+    return implode(',',$emails);
 }
 
 /**
@@ -1371,7 +1369,7 @@ function subscriber_addresslist($id,$self=true){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function unslash($string,$char="'"){
-  return str_replace('\\'.$char,$char,$string);
+    return str_replace('\\'.$char,$char,$string);
 }
 
 /**
@@ -1422,7 +1420,7 @@ function preg_quote_cb($string){
  */
 function shorten($keep,$short,$max,$min=9,$char='…'){
     $max = $max - utf8_strlen($keep);
-   if($max < $min) return $keep;
+    if($max < $min) return $keep;
     $len = utf8_strlen($short);
     if($len <= $max) return $keep.$short;
     $half = floor($max/2);
@@ -1440,26 +1438,26 @@ function editorinfo($username){
     global $auth;
 
     switch($conf['showuseras']){
-      case 'username':
-      case 'email':
-      case 'email_link':
-        if($auth) $info = $auth->getUserData($username);
-        break;
-      default:
-        return hsc($username);
+        case 'username':
+        case 'email':
+        case 'email_link':
+            if($auth) $info = $auth->getUserData($username);
+            break;
+        default:
+            return hsc($username);
     }
 
     if(isset($info) && $info) {
         switch($conf['showuseras']){
-          case 'username':
-            return hsc($info['name']);
-          case 'email':
-            return obfuscate($info['mail']);
-          case 'email_link':
-            $mail=obfuscate($info['mail']);
-            return '<a href="mailto:'.$mail.'">'.$mail.'</a>';
-          default:
-            return hsc($username);
+            case 'username':
+                return hsc($info['name']);
+            case 'email':
+                return obfuscate($info['mail']);
+            case 'email_link':
+                $mail=obfuscate($info['mail']);
+                return '<a href="mailto:'.$mail.'">'.$mail.'</a>';
+            default:
+                return hsc($username);
         }
     } else {
         return hsc($username);
@@ -1503,22 +1501,24 @@ function license_img($type){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function is_mem_available($mem,$bytes=1048576){
-  $limit = trim(ini_get('memory_limit'));
-  if(empty($limit)) return true; // no limit set!
+    $limit = trim(ini_get('memory_limit'));
+    if(empty($limit)) return true; // no limit set!
 
-  // parse limit to bytes
-  $limit = php_to_byte($limit);
+    // parse limit to bytes
+    $limit = php_to_byte($limit);
 
-  // get used memory if possible
-  if(function_exists('memory_get_usage')){
-    $used = memory_get_usage();
-  }
+    // get used memory if possible
+    if(function_exists('memory_get_usage')){
+        $used = memory_get_usage();
+    }else{
+        $used = $bytes;
+    }
 
-  if($used+$mem > $limit){
-    return false;
-  }
+    if($used+$mem > $limit){
+        return false;
+    }
 
-  return true;
+    return true;
 }
 
 /**
@@ -1545,4 +1545,4 @@ function send_redirect($url){
     exit;
 }
 
-//Setup VIM: ex: et ts=2 enc=utf-8 :
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/confutils.php b/inc/confutils.php
index 9ec7a551e..abfde8a80 100644
--- a/inc/confutils.php
+++ b/inc/confutils.php
@@ -16,29 +16,29 @@
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function mimetype($file, $knownonly=true){
-  $ret    = array(false,false,false); // return array
-  $mtypes = getMimeTypes();     // known mimetypes
-  $exts   = join('|',array_keys($mtypes));  // known extensions (regexp)
-  if(!$knownonly){
-    $exts = $exts.'|[_\-A-Za-z0-9]+';  // any extension
-  }
-  if(preg_match('#\.('.$exts.')$#i',$file,$matches)){
-    $ext = strtolower($matches[1]);
-  }
-
-  if($ext){
-    if (isset($mtypes[$ext])){
-      if($mtypes[$ext][0] == '!'){
-          $ret = array($ext, substr($mtypes[$ext],1), true);
-      }else{
-          $ret = array($ext, $mtypes[$ext], false);
-      }
-    }elseif(!$knownonly){
-      $ret = array($ext, 'application/octet-stream', true);
+    $ret    = array(false,false,false); // return array
+    $mtypes = getMimeTypes();     // known mimetypes
+    $exts   = join('|',array_keys($mtypes));  // known extensions (regexp)
+    if(!$knownonly){
+        $exts = $exts.'|[_\-A-Za-z0-9]+';  // any extension
+    }
+    if(preg_match('#\.('.$exts.')$#i',$file,$matches)){
+        $ext = strtolower($matches[1]);
+    }
+
+    if($ext){
+        if (isset($mtypes[$ext])){
+            if($mtypes[$ext][0] == '!'){
+                $ret = array($ext, substr($mtypes[$ext],1), true);
+            }else{
+                $ret = array($ext, $mtypes[$ext], false);
+            }
+        }elseif(!$knownonly){
+            $ret = array($ext, 'application/octet-stream', true);
+        }
     }
-  }
 
-  return $ret;
+    return $ret;
 }
 
 /**
@@ -47,11 +47,11 @@ function mimetype($file, $knownonly=true){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function getMimeTypes() {
-  static $mime = NULL;
-  if ( !$mime ) {
-    $mime = retrieveConfig('mime','confToHash');
-  }
-  return $mime;
+    static $mime = null;
+    if ( !$mime ) {
+        $mime = retrieveConfig('mime','confToHash');
+    }
+    return $mime;
 }
 
 /**
@@ -60,11 +60,11 @@ function getMimeTypes() {
  * @author Harry Fuecks <hfuecks@gmail.com>
  */
 function getAcronyms() {
-  static $acronyms = NULL;
-  if ( !$acronyms ) {
-    $acronyms = retrieveConfig('acronyms','confToHash');
-  }
-  return $acronyms;
+    static $acronyms = null;
+    if ( !$acronyms ) {
+        $acronyms = retrieveConfig('acronyms','confToHash');
+    }
+    return $acronyms;
 }
 
 /**
@@ -73,11 +73,11 @@ function getAcronyms() {
  * @author Harry Fuecks <hfuecks@gmail.com>
  */
 function getSmileys() {
-  static $smileys = NULL;
-  if ( !$smileys ) {
-    $smileys = retrieveConfig('smileys','confToHash');
-  }
-  return $smileys;
+    static $smileys = null;
+    if ( !$smileys ) {
+        $smileys = retrieveConfig('smileys','confToHash');
+    }
+    return $smileys;
 }
 
 /**
@@ -86,11 +86,11 @@ function getSmileys() {
  * @author Harry Fuecks <hfuecks@gmail.com>
  */
 function getEntities() {
-  static $entities = NULL;
-  if ( !$entities ) {
-    $entities = retrieveConfig('entities','confToHash');
-  }
-  return $entities;
+    static $entities = null;
+    if ( !$entities ) {
+        $entities = retrieveConfig('entities','confToHash');
+    }
+    return $entities;
 }
 
 /**
@@ -99,13 +99,13 @@ function getEntities() {
  * @author Harry Fuecks <hfuecks@gmail.com>
  */
 function getInterwiki() {
-  static $wikis = NULL;
-  if ( !$wikis ) {
-    $wikis = retrieveConfig('interwiki','confToHash',array(true));
-  }
-  //add sepecial case 'this'
-  $wikis['this'] = DOKU_URL.'{NAME}';
-  return $wikis;
+    static $wikis = null;
+    if ( !$wikis ) {
+        $wikis = retrieveConfig('interwiki','confToHash',array(true));
+    }
+    //add sepecial case 'this'
+    $wikis['this'] = DOKU_URL.'{NAME}';
+    return $wikis;
 }
 
 /**
@@ -113,23 +113,23 @@ function getInterwiki() {
  *
  */
 function getWordblocks() {
-  static $wordblocks = NULL;
-  if ( !$wordblocks ) {
-    $wordblocks = retrieveConfig('wordblock','file');
-  }
-  return $wordblocks;
+    static $wordblocks = null;
+    if ( !$wordblocks ) {
+        $wordblocks = retrieveConfig('wordblock','file');
+    }
+    return $wordblocks;
 }
 
 
 function getSchemes() {
-  static $schemes = NULL;
-  if ( !$schemes ) {
-    $schemes = retrieveConfig('scheme','file');
-  }
-  $schemes = array_map('trim', $schemes);
-  $schemes = preg_replace('/^#.*/', '', $schemes);
-  $schemes = array_filter($schemes);
-  return $schemes;
+    static $schemes = null;
+    if ( !$schemes ) {
+        $schemes = retrieveConfig('scheme','file');
+    }
+    $schemes = array_map('trim', $schemes);
+    $schemes = preg_replace('/^#.*/', '', $schemes);
+    $schemes = array_filter($schemes);
+    return $schemes;
 }
 
 /**
@@ -143,22 +143,22 @@ function getSchemes() {
  * @author Gina Haeussge <gina@foosel.net>
  */
 function linesToHash($lines, $lower=false) {
-  foreach ( $lines as $line ) {
-    //ignore comments (except escaped ones)
-    $line = preg_replace('/(?<![&\\\\])#.*$/','',$line);
-    $line = str_replace('\\#','#',$line);
-    $line = trim($line);
-    if(empty($line)) continue;
-    $line = preg_split('/\s+/',$line,2);
-    // Build the associative array
-    if($lower){
-      $conf[strtolower($line[0])] = $line[1];
-    }else{
-      $conf[$line[0]] = $line[1];
+    foreach ( $lines as $line ) {
+        //ignore comments (except escaped ones)
+        $line = preg_replace('/(?<![&\\\\])#.*$/','',$line);
+        $line = str_replace('\\#','#',$line);
+        $line = trim($line);
+        if(empty($line)) continue;
+        $line = preg_split('/\s+/',$line,2);
+        // Build the associative array
+        if($lower){
+            $conf[strtolower($line[0])] = $line[1];
+        }else{
+            $conf[$line[0]] = $line[1];
+        }
     }
-  }
 
-  return $conf;
+    return $conf;
 }
 
 /**
@@ -172,11 +172,11 @@ function linesToHash($lines, $lower=false) {
  * @author Gina Haeussge <gina@foosel.net>
  */
 function confToHash($file,$lower=false) {
-  $conf = array();
-  $lines = @file( $file );
-  if ( !$lines ) return $conf;
+    $conf = array();
+    $lines = @file( $file );
+    if ( !$lines ) return $conf;
 
-  return linesToHash($lines, $lower);
+    return linesToHash($lines, $lower);
 }
 
 /**
@@ -190,23 +190,23 @@ function confToHash($file,$lower=false) {
  * @return array    configuration values
  */
 function retrieveConfig($type,$fn,$params=null) {
-  global $config_cascade;
-
-  if(!is_array($params)) $params = array();
-
-  $combined = array();
-  if (!is_array($config_cascade[$type])) trigger_error('Missing config cascade for "'.$type.'"',E_USER_WARNING);
-  foreach (array('default','local','protected') as $config_group) {
-    if (empty($config_cascade[$type][$config_group])) continue;
-    foreach ($config_cascade[$type][$config_group] as $file) {
-      if (@file_exists($file)) {
-        $config = call_user_func_array($fn,array_merge(array($file),$params));
-        $combined = array_merge($combined, $config);
-      }
+    global $config_cascade;
+
+    if(!is_array($params)) $params = array();
+
+    $combined = array();
+    if (!is_array($config_cascade[$type])) trigger_error('Missing config cascade for "'.$type.'"',E_USER_WARNING);
+    foreach (array('default','local','protected') as $config_group) {
+        if (empty($config_cascade[$type][$config_group])) continue;
+        foreach ($config_cascade[$type][$config_group] as $file) {
+            if (@file_exists($file)) {
+                $config = call_user_func_array($fn,array_merge(array($file),$params));
+                $combined = array_merge($combined, $config);
+            }
+        }
     }
-  }
 
-  return $combined;
+    return $combined;
 }
 
 /**
@@ -218,16 +218,16 @@ function retrieveConfig($type,$fn,$params=null) {
  * @return array              list of files, default before local before protected
  */
 function getConfigFiles($type) {
-  global $config_cascade;
-  $files = array();
+    global $config_cascade;
+    $files = array();
 
-  if (!is_array($config_cascade[$type])) trigger_error('Missing config cascade for "'.$type.'"',E_USER_WARNING);
-  foreach (array('default','local','protected') as $config_group) {
-    if (empty($config_cascade[$type][$config_group])) continue;
-    $files = array_merge($files, $config_cascade[$type][$config_group]);
-  }
+    if (!is_array($config_cascade[$type])) trigger_error('Missing config cascade for "'.$type.'"',E_USER_WARNING);
+    foreach (array('default','local','protected') as $config_group) {
+        if (empty($config_cascade[$type][$config_group])) continue;
+        $files = array_merge($files, $config_cascade[$type][$config_group]);
+    }
 
-  return $files;
+    return $files;
 }
 
 /**
@@ -237,23 +237,23 @@ function getConfigFiles($type) {
  * @returns boolean true if enabled, false if disabled
  */
 function actionOK($action){
-  static $disabled = null;
-  if(is_null($disabled)){
-    global $conf;
-
-    // prepare disabled actions array and handle legacy options
-    $disabled = explode(',',$conf['disableactions']);
-    $disabled = array_map('trim',$disabled);
-    if(isset($conf['openregister']) && !$conf['openregister']) $disabled[] = 'register';
-    if(isset($conf['resendpasswd']) && !$conf['resendpasswd']) $disabled[] = 'resendpwd';
-    if(isset($conf['subscribers']) && !$conf['subscribers']) {
-        $disabled[] = 'subscribe';
-        $disabled[] = 'subscribens';
+    static $disabled = null;
+    if(is_null($disabled)){
+        global $conf;
+
+        // prepare disabled actions array and handle legacy options
+        $disabled = explode(',',$conf['disableactions']);
+        $disabled = array_map('trim',$disabled);
+        if(isset($conf['openregister']) && !$conf['openregister']) $disabled[] = 'register';
+        if(isset($conf['resendpasswd']) && !$conf['resendpasswd']) $disabled[] = 'resendpwd';
+        if(isset($conf['subscribers']) && !$conf['subscribers']) {
+            $disabled[] = 'subscribe';
+            $disabled[] = 'subscribens';
+        }
+        $disabled = array_unique($disabled);
     }
-    $disabled = array_unique($disabled);
-  }
 
-  return !in_array($action,$disabled);
+    return !in_array($action,$disabled);
 }
 
 /**
@@ -266,25 +266,30 @@ function actionOK($action){
  * @returns boolean             true if headings should be used for $linktype, false otherwise
  */
 function useHeading($linktype) {
-  static $useHeading = null;
+    static $useHeading = null;
 
-  if (is_null($useHeading)) {
-    global $conf;
+    if (is_null($useHeading)) {
+        global $conf;
 
-    if (!empty($conf['useheading'])) {
-      switch ($conf['useheading']) {
-        case 'content'    : $useHeading['content'] = true; break;
-        case 'navigation' : $useHeading['navigation'] = true; break;
-        default:
-          $useHeading['content'] = true;
-          $useHeading['navigation'] = true;
-      }
-    } else {
-      $useHeading = array();
+        if (!empty($conf['useheading'])) {
+            switch ($conf['useheading']) {
+                case 'content':
+                    $useHeading['content'] = true;
+                    break;
+
+                case 'navigation':
+                    $useHeading['navigation'] = true;
+                    break;
+                default:
+                    $useHeading['content'] = true;
+                    $useHeading['navigation'] = true;
+            }
+        } else {
+            $useHeading = array();
+        }
     }
-  }
 
-  return (!empty($useHeading[$linktype]));
+    return (!empty($useHeading[$linktype]));
 }
 
 /**
@@ -295,13 +300,13 @@ function useHeading($linktype) {
  * @return string               the encoded value
  */
 function conf_encodeString($str,$code) {
-  switch ($code) {
-    case 'base64'   : return '<b>'.base64_encode($str);
-    case 'uuencode' : return '<u>'.convert_uuencode($str);
-    case 'plain':
-    default:
-      return $str;
-  }
+    switch ($code) {
+        case 'base64'   : return '<b>'.base64_encode($str);
+        case 'uuencode' : return '<u>'.convert_uuencode($str);
+        case 'plain':
+        default:
+                          return $str;
+    }
 }
 /**
  * return obscured data as plain text
@@ -310,11 +315,11 @@ function conf_encodeString($str,$code) {
  * @return string             plain text
  */
 function conf_decodeString($str) {
-  switch (substr($str,0,3)) {
-    case '<b>' : return base64_decode(substr($str,3));
-    case '<u>' : return convert_uudecode(substr($str,3));
-    default:  // not encode (or unknown)
-      return $str;
-  }
+    switch (substr($str,0,3)) {
+        case '<b>' : return base64_decode(substr($str,3));
+        case '<u>' : return convert_uudecode(substr($str,3));
+        default:  // not encode (or unknown)
+                     return $str;
+    }
 }
-//Setup VIM: ex: et ts=2 enc=utf-8 :
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/events.php b/inc/events.php
index 1604c73c6..e6b608f20 100644
--- a/inc/events.php
+++ b/inc/events.php
@@ -11,190 +11,190 @@ require_once(DOKU_INC.'inc/pluginutils.php');
 
 class Doku_Event {
 
-  // public properties
-  var $name = '';                // READONLY  event name, objects must register against this name to see the event
-  var $data = NULL;              // READWRITE data relevant to the event, no standardised format (YET!)
-  var $result = NULL;            // READWRITE the results of the event action, only relevant in "_AFTER" advise
-                                 //    event handlers may modify this if they are preventing the default action
-                                 //    to provide the after event handlers with event results
-  var $canPreventDefault = true; // READONLY  if true, event handlers can prevent the events default action
-
-  // private properties, event handlers can effect these through the provided methods
-  var $_default = true;     // whether or not to carry out the default action associated with the event
-  var $_continue = true;    // whether or not to continue propagating the event to other handlers
-
-  /**
-   * event constructor
-   */
-  function Doku_Event($name, &$data) {
-
-    $this->name = $name;
-    $this->data =& $data;
-
-  }
-
-  /**
-   * advise functions
-   *
-   * advise all registered handlers of this event
-   *
-   * if these methods are used by functions outside of this object, they must
-   * properly handle correct processing of any default action and issue an
-   * advise_after() signal. e.g.
-   *    $evt = new Doku_Event(name, data);
-   *    if ($evt->advise_before(canPreventDefault) {
-   *      // default action code block
-   *    }
-   *    $evt->advise_after();
-   *    unset($evt);
-   *
-   * @return  results of processing the event, usually $this->_default
-   */
-  function advise_before($enablePreventDefault=true) {
-    global $EVENT_HANDLER;
-
-    $this->canPreventDefault = $enablePreventDefault;
-    $EVENT_HANDLER->process_event($this,'BEFORE');
-
-    return (!$enablePreventDefault || $this->_default);
-  }
-
-  function advise_after() {
-    global $EVENT_HANDLER;
-
-    $this->_continue = true;
-    $EVENT_HANDLER->process_event($this,'AFTER');
-  }
-
-  /**
-   * trigger
-   *
-   * - advise all registered (<event>_BEFORE) handlers that this event is about to take place
-   * - carry out the default action using $this->data based on $enablePrevent and
-   *   $this->_default, all of which may have been modified by the event handlers.
-   * - advise all registered (<event>_AFTER) handlers that the event has taken place
-   *
-   * @return  $event->results
-   *          the value set by any <event>_before or <event> handlers if the default action is prevented
-   *          or the results of the default action (as modified by <event>_after handlers)
-   *          or NULL no action took place and no handler modified the value
-   */
-  function trigger($action=NULL, $enablePrevent=true) {
-
-    if (!is_callable($action)) $enablePrevent = false;
-
-    if ($this->advise_before($enablePrevent) && is_callable($action)) {
-      if (is_array($action)) {
-        list($obj,$method) = $action;
-        $this->result = $obj->$method($this->data);
-      } else {
-        $this->result = $action($this->data);
-      }
+    // public properties
+    var $name = '';                // READONLY  event name, objects must register against this name to see the event
+    var $data = null;              // READWRITE data relevant to the event, no standardised format (YET!)
+    var $result = null;            // READWRITE the results of the event action, only relevant in "_AFTER" advise
+    //    event handlers may modify this if they are preventing the default action
+    //    to provide the after event handlers with event results
+    var $canPreventDefault = true; // READONLY  if true, event handlers can prevent the events default action
+
+    // private properties, event handlers can effect these through the provided methods
+    var $_default = true;     // whether or not to carry out the default action associated with the event
+    var $_continue = true;    // whether or not to continue propagating the event to other handlers
+
+    /**
+     * event constructor
+     */
+    function Doku_Event($name, &$data) {
+
+        $this->name = $name;
+        $this->data =& $data;
+
+    }
+
+    /**
+     * advise functions
+     *
+     * advise all registered handlers of this event
+     *
+     * if these methods are used by functions outside of this object, they must
+     * properly handle correct processing of any default action and issue an
+     * advise_after() signal. e.g.
+     *    $evt = new Doku_Event(name, data);
+     *    if ($evt->advise_before(canPreventDefault) {
+     *      // default action code block
+     *    }
+     *    $evt->advise_after();
+     *    unset($evt);
+     *
+     * @return  results of processing the event, usually $this->_default
+     */
+    function advise_before($enablePreventDefault=true) {
+        global $EVENT_HANDLER;
+
+        $this->canPreventDefault = $enablePreventDefault;
+        $EVENT_HANDLER->process_event($this,'BEFORE');
+
+        return (!$enablePreventDefault || $this->_default);
+    }
+
+    function advise_after() {
+        global $EVENT_HANDLER;
+
+        $this->_continue = true;
+        $EVENT_HANDLER->process_event($this,'AFTER');
+    }
+
+    /**
+     * trigger
+     *
+     * - advise all registered (<event>_BEFORE) handlers that this event is about to take place
+     * - carry out the default action using $this->data based on $enablePrevent and
+     *   $this->_default, all of which may have been modified by the event handlers.
+     * - advise all registered (<event>_AFTER) handlers that the event has taken place
+     *
+     * @return  $event->results
+     *          the value set by any <event>_before or <event> handlers if the default action is prevented
+     *          or the results of the default action (as modified by <event>_after handlers)
+     *          or NULL no action took place and no handler modified the value
+     */
+    function trigger($action=null, $enablePrevent=true) {
+
+        if (!is_callable($action)) $enablePrevent = false;
+
+        if ($this->advise_before($enablePrevent) && is_callable($action)) {
+            if (is_array($action)) {
+                list($obj,$method) = $action;
+                $this->result = $obj->$method($this->data);
+            } else {
+                $this->result = $action($this->data);
+            }
+        }
+
+        $this->advise_after();
+
+        return $this->result;
     }
 
-    $this->advise_after();
-
-    return $this->result;
-  }
-
-  /**
-   * stopPropagation
-   *
-   * stop any further processing of the event by event handlers
-   * this function does not prevent the default action taking place
-   */
-  function stopPropagation() { $this->_continue = false;  }
-
-  /**
-   * preventDefault
-   *
-   * prevent the default action taking place
-   */
-  function preventDefault() { $this->_default = false;  }
+    /**
+     * stopPropagation
+     *
+     * stop any further processing of the event by event handlers
+     * this function does not prevent the default action taking place
+     */
+    function stopPropagation() { $this->_continue = false;  }
+
+    /**
+     * preventDefault
+     *
+     * prevent the default action taking place
+     */
+    function preventDefault() { $this->_default = false;  }
 }
 
 class Doku_Event_Handler {
 
-  // public properties:  none
+    // public properties:  none
 
-  // private properties
-  var $_hooks = array();          // array of events and their registered handlers
+    // private properties
+    var $_hooks = array();          // array of events and their registered handlers
 
-  /**
-   * event_handler
-   *
-   * constructor, loads all action plugins and calls their register() method giving them
-   * an opportunity to register any hooks they require
-   */
-  function Doku_Event_Handler() {
+    /**
+     * event_handler
+     *
+     * constructor, loads all action plugins and calls their register() method giving them
+     * an opportunity to register any hooks they require
+     */
+    function Doku_Event_Handler() {
 
-    // load action plugins
-    $plugin = NULL;
-    $pluginlist = plugin_list('action');
+        // load action plugins
+        $plugin = null;
+        $pluginlist = plugin_list('action');
 
-    foreach ($pluginlist as $plugin_name) {
-      $plugin =& plugin_load('action',$plugin_name);
+        foreach ($pluginlist as $plugin_name) {
+            $plugin =& plugin_load('action',$plugin_name);
 
-      if ($plugin !== NULL) $plugin->register($this);
-    }
-  }
-
-  /**
-   * register_hook
-   *
-   * register a hook for an event
-   *
-   * @PARAM  $event   (string)   name used by the event, (incl '_before' or '_after' for triggers)
-   * @PARAM  $obj     (obj)      object in whose scope method is to be executed,
-   *                             if NULL, method is assumed to be a globally available function
-   * @PARAM  $method  (function) event handler function
-   * @PARAM  $param   (mixed)    data passed to the event handler
-   */
-  function register_hook($event, $advise, &$obj, $method, $param=NULL) {
-    $this->_hooks[$event.'_'.$advise][] = array(&$obj, $method, $param);
-  }
-
-  function process_event(&$event,$advise='') {
-
-    $evt_name = $event->name . ($advise ? '_'.$advise : '_BEFORE');
-
-    if (!empty($this->_hooks[$evt_name])) {
-      $hook = reset($this->_hooks[$evt_name]);
-      do {
-//        list($obj, $method, $param) = $hook;
-        $obj =& $hook[0];
-        $method = $hook[1];
-        $param = $hook[2];
-
-        if (is_null($obj)) {
-          $method($event, $param);
-        } else {
-          $obj->$method($event, $param);
+            if ($plugin !== null) $plugin->register($this);
         }
+    }
+
+    /**
+     * register_hook
+     *
+     * register a hook for an event
+     *
+     * @param  $event   (string)   name used by the event, (incl '_before' or '_after' for triggers)
+     * @param  $obj     (obj)      object in whose scope method is to be executed,
+     *                             if NULL, method is assumed to be a globally available function
+     * @param  $method  (function) event handler function
+     * @param  $param   (mixed)    data passed to the event handler
+     */
+    function register_hook($event, $advise, &$obj, $method, $param=null) {
+        $this->_hooks[$event.'_'.$advise][] = array(&$obj, $method, $param);
+    }
 
-      } while ($event->_continue && $hook = next($this->_hooks[$evt_name]));
+    function process_event(&$event,$advise='') {
+
+        $evt_name = $event->name . ($advise ? '_'.$advise : '_BEFORE');
+
+        if (!empty($this->_hooks[$evt_name])) {
+            $hook = reset($this->_hooks[$evt_name]);
+            do {
+                //        list($obj, $method, $param) = $hook;
+                $obj =& $hook[0];
+                $method = $hook[1];
+                $param = $hook[2];
+
+                if (is_null($obj)) {
+                    $method($event, $param);
+                } else {
+                    $obj->$method($event, $param);
+                }
+
+            } while ($event->_continue && $hook = next($this->_hooks[$evt_name]));
+        }
     }
-  }
 }
 
 /**
- *  trigger_event
+ * trigger_event
  *
- *  function wrapper to process (create, trigger and destroy) an event
+ * function wrapper to process (create, trigger and destroy) an event
  *
- *  @PARAM  $name               (string)   name for the event
- *  @PARAM  $data               (mixed)    event data
- *  @PARAM  $action             (callback) (optional, default=NULL) default action, a php callback function
- *  @PARAM  $canPreventDefault  (bool)     (optional, default=true) can hooks prevent the default action
+ * @param  $name               (string)   name for the event
+ * @param  $data               (mixed)    event data
+ * @param  $action             (callback) (optional, default=NULL) default action, a php callback function
+ * @param  $canPreventDefault  (bool)     (optional, default=true) can hooks prevent the default action
  *
- *  @RETURN (mixed)                        the event results value after all event processing is complete
+ * @return (mixed)                        the event results value after all event processing is complete
  *                                         by default this is the return value of the default action however
  *                                         it can be set or modified by event handler hooks
  */
-function trigger_event($name, &$data, $action=NULL, $canPreventDefault=true) {
+function trigger_event($name, &$data, $action=null, $canPreventDefault=true) {
 
-  $evt = new Doku_Event($name, $data);
-  return $evt->trigger($action, $canPreventDefault);
+    $evt = new Doku_Event($name, $data);
+    return $evt->trigger($action, $canPreventDefault);
 }
 
 // create the event handler
diff --git a/inc/form.php b/inc/form.php
index a514526b7..6d496f414 100644
--- a/inc/form.php
+++ b/inc/form.php
@@ -859,7 +859,9 @@ function form_menufield($attrs) {
     $s .= ' <select '.buildAttributes($attrs,true).'>'.DOKU_LF;
     if (!empty($attrs['_options'])) {
         $selected = false;
-        for($n=0;$n<count($attrs['_options']);$n++){
+
+        $cnt = count($attrs['_options']);
+        for($n=0; $n < $cnt; $n++){
             @list($value,$text,$select) = $attrs['_options'][$n];
             $p = '';
             if (!is_null($text))
diff --git a/inc/fulltext.php b/inc/fulltext.php
index c8236e1d4..94c68d675 100644
--- a/inc/fulltext.php
+++ b/inc/fulltext.php
@@ -20,10 +20,10 @@ require_once(DOKU_INC.'inc/indexer.php');
  */
 function ft_pageSearch($query,&$highlight){
 
-  $data['query'] = $query;
-  $data['highlight'] =& $highlight;
+    $data['query'] = $query;
+    $data['highlight'] =& $highlight;
 
-  return trigger_event('SEARCH_QUERY_FULLPAGE', $data, '_ft_pageSearch');
+    return trigger_event('SEARCH_QUERY_FULLPAGE', $data, '_ft_pageSearch');
 }
 
 /**
@@ -189,7 +189,7 @@ function ft_mediause($id,$max){
         foreach($matches[1] as $img){
             $img = trim($img);
             if(preg_match('/^https?:\/\//i',$img)) continue; // skip external images
-            list($img) = explode('?',$img);                  // remove any parameters
+                list($img) = explode('?',$img);                  // remove any parameters
             resolve_mediaid($ns,$img,$exists);               // resolve the possibly relative img
 
             if($img == $id){                                 // we have a match
@@ -286,11 +286,11 @@ function ft_pagesorter($a, $b){
 function ft_snippet($id,$highlight){
     $text = rawWiki($id);
     $evdata = array(
-                'id'        => $id,
-                'text'      => &$text,
-                'highlight' => &$highlight,
-                'snippet'   => '',
-              );
+            'id'        => $id,
+            'text'      => &$text,
+            'highlight' => &$highlight,
+            'snippet'   => '',
+            );
 
     $evt = new Doku_Event('FULLTEXT_SNIPPET_CREATE',$evdata);
     if ($evt->advise_before()) {
@@ -305,60 +305,60 @@ function ft_snippet($id,$highlight){
         $re3 = "$re1.{0,45}(?!\\1)$re1.{0,45}(?!\\1)(?!\\2)$re1";
 
         for ($cnt=4; $cnt--;) {
-          if (0) {
-          } else if (preg_match('/'.$re3.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
-          } else if (preg_match('/'.$re2.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
-          } else if (preg_match('/'.$re1.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
-          } else {
-            break;
-          }
-
-          list($str,$idx) = $match[0];
-
-          // convert $idx (a byte offset) into a utf8 character offset
-          $utf8_idx = utf8_strlen(substr($text,0,$idx));
-          $utf8_len = utf8_strlen($str);
-
-          // establish context, 100 bytes surrounding the match string
-          // first look to see if we can go 100 either side,
-          // then drop to 50 adding any excess if the other side can't go to 50,
-          $pre = min($utf8_idx-$utf8_offset,100);
-          $post = min($len-$utf8_idx-$utf8_len,100);
-
-          if ($pre>50 && $post>50) {
-            $pre = $post = 50;
-          } else if ($pre>50) {
-            $pre = min($pre,100-$post);
-          } else if ($post>50) {
-            $post = min($post, 100-$pre);
-          } else {
-            // both are less than 50, means the context is the whole string
-            // make it so and break out of this loop - there is no need for the
-            // complex snippet calculations
-            $snippets = array($text);
-            break;
-          }
-
-          // establish context start and end points, try to append to previous
-          // context if possible
-          $start = $utf8_idx - $pre;
-          $append = ($start < $end) ? $end : false;  // still the end of the previous context snippet
-          $end = $utf8_idx + $utf8_len + $post;      // now set it to the end of this context
-
-          if ($append) {
-            $snippets[count($snippets)-1] .= utf8_substr($text,$append,$end-$append);
-          } else {
-            $snippets[] = utf8_substr($text,$start,$end-$start);
-          }
-
-          // set $offset for next match attempt
-          //   substract strlen to avoid splitting a potential search success,
-          //   this is an approximation as the search pattern may match strings
-          //   of varying length and it will fail if the context snippet
-          //   boundary breaks a matching string longer than the current match
-          $utf8_offset = $utf8_idx + $post;
-          $offset = $idx + strlen(utf8_substr($text,$utf8_idx,$post));
-          $offset = utf8_correctIdx($text,$offset);
+            if (0) {
+            } else if (preg_match('/'.$re3.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
+            } else if (preg_match('/'.$re2.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
+            } else if (preg_match('/'.$re1.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
+            } else {
+                break;
+            }
+
+            list($str,$idx) = $match[0];
+
+            // convert $idx (a byte offset) into a utf8 character offset
+            $utf8_idx = utf8_strlen(substr($text,0,$idx));
+            $utf8_len = utf8_strlen($str);
+
+            // establish context, 100 bytes surrounding the match string
+            // first look to see if we can go 100 either side,
+            // then drop to 50 adding any excess if the other side can't go to 50,
+            $pre = min($utf8_idx-$utf8_offset,100);
+            $post = min($len-$utf8_idx-$utf8_len,100);
+
+            if ($pre>50 && $post>50) {
+                $pre = $post = 50;
+            } else if ($pre>50) {
+                $pre = min($pre,100-$post);
+            } else if ($post>50) {
+                $post = min($post, 100-$pre);
+            } else {
+                // both are less than 50, means the context is the whole string
+                // make it so and break out of this loop - there is no need for the
+                // complex snippet calculations
+                $snippets = array($text);
+                break;
+            }
+
+            // establish context start and end points, try to append to previous
+            // context if possible
+            $start = $utf8_idx - $pre;
+            $append = ($start < $end) ? $end : false;  // still the end of the previous context snippet
+            $end = $utf8_idx + $utf8_len + $post;      // now set it to the end of this context
+
+            if ($append) {
+                $snippets[count($snippets)-1] .= utf8_substr($text,$append,$end-$append);
+            } else {
+                $snippets[] = utf8_substr($text,$start,$end-$start);
+            }
+
+            // set $offset for next match attempt
+            //   substract strlen to avoid splitting a potential search success,
+            //   this is an approximation as the search pattern may match strings
+            //   of varying length and it will fail if the context snippet
+            //   boundary breaks a matching string longer than the current match
+            $utf8_offset = $utf8_idx + $post;
+            $offset = $idx + strlen(utf8_substr($text,$utf8_idx,$post));
+            $offset = utf8_correctIdx($text,$offset);
         }
 
         $m = "\1";
@@ -391,16 +391,16 @@ function ft_resultCombine($args){
 
     $result = array();
     if ($array_count > 1) {
-      foreach ($args[0] as $key => $value) {
-        $result[$key] = $value;
-        for ($i = 1; $i !== $array_count; $i++) {
-            if (!isset($args[$i][$key])) {
-                unset($result[$key]);
-                break;
+        foreach ($args[0] as $key => $value) {
+            $result[$key] = $value;
+            for ($i = 1; $i !== $array_count; $i++) {
+                if (!isset($args[$i][$key])) {
+                    unset($result[$key]);
+                    break;
+                }
+                $result[$key] += $args[$i][$key];
             }
-            $result[$key] += $args[$i][$key];
         }
-      }
     }
     return $result;
 }
@@ -651,30 +651,30 @@ function ft_queryParser($query){
 
         switch (substr($token, 0, 3)) {
             case 'N+:':
-                $q['ns'][]        = $body; // for backward compatibility
-                break;
+                     $q['ns'][]        = $body; // for backward compatibility
+                     break;
             case 'N-:':
-                $q['notns'][]     = $body; // for backward compatibility
-                break;
+                     $q['notns'][]     = $body; // for backward compatibility
+                     break;
             case 'W_:':
-                $q['words'][]     = $body;
-                break;
+                     $q['words'][]     = $body;
+                     break;
             case 'W-:':
-                $q['words'][]     = $body;
-                $q['not'][]       = $body; // for backward compatibility
-                break;
+                     $q['words'][]     = $body;
+                     $q['not'][]       = $body; // for backward compatibility
+                     break;
             case 'W+:':
-                $q['words'][]     = $body;
-                $q['highlight'][] = str_replace('*', '', $body);
-                $q['and'][]       = $body; // for backward compatibility
-                break;
+                     $q['words'][]     = $body;
+                     $q['highlight'][] = str_replace('*', '', $body);
+                     $q['and'][]       = $body; // for backward compatibility
+                     break;
             case 'P-:':
-                $q['phrases'][]   = $body;
-                break;
+                     $q['phrases'][]   = $body;
+                     break;
             case 'P+:':
-                $q['phrases'][]   = $body;
-                $q['highlight'][] = str_replace('*', '', $body);
-                break;
+                     $q['phrases'][]   = $body;
+                     $q['highlight'][] = str_replace('*', '', $body);
+                     break;
         }
     }
     foreach (array('words', 'phrases', 'highlight', 'ns', 'notns', 'and', 'not') as $key) {
diff --git a/install.php b/install.php
index 414d3e99e..a9edbd445 100644
--- a/install.php
+++ b/install.php
@@ -202,16 +202,16 @@ function print_form($d){
 }
 
 function print_retry() {
-  global $lang;
-  global $LC;
-?>
+    global $lang;
+    global $LC;
+    ?>
     <form action="" method="get">
       <fieldset>
         <input type="hidden" name="l" value="<?php echo $LC ?>" />
         <input class="button" type="submit" value="<?php echo $lang['i_retry'];?>" />
       </fieldset>
     </form>
-<?php
+    <?php
 }
 
 /**
@@ -360,7 +360,6 @@ function check_configs(){
         'auth'  => DOKU_LOCAL.'acl.auth.php'
     );
 
-
     // main dokuwiki config file (conf/dokuwiki.php) must not have been modified
     $installation_hash = md5(preg_replace("/(\015\012)|(\015)/","\012",
                              @file_get_contents(DOKU_CONF.'dokuwiki.php')));
@@ -437,8 +436,8 @@ function check_functions(){
                          'preg_replace file_get_contents htmlspecialchars_decode');
 
     if (!function_exists('mb_substr')) {
-      $funcs[] = 'utf8_encode';
-      $funcs[] = 'utf8_decode';
+        $funcs[] = 'utf8_encode';
+        $funcs[] = 'utf8_decode';
     }
 
     foreach($funcs as $func){
@@ -505,12 +504,12 @@ function print_errors(){
  * @author Andreas Gohr <andi@splitbrain.org>
  */
 function remove_magic_quotes(&$array) {
-  foreach (array_keys($array) as $key) {
-    if (is_array($array[$key])) {
-      remove_magic_quotes($array[$key]);
-    }else {
-      $array[$key] = stripslashes($array[$key]);
+    foreach (array_keys($array) as $key) {
+        if (is_array($array[$key])) {
+            remove_magic_quotes($array[$key]);
+        }else {
+            $array[$key] = stripslashes($array[$key]);
+        }
     }
-  }
 }
 
-- 
GitLab