<?php
#
# DistributedACL Action Plugin
#
# License:    GPL 2 (http://www.gnu.org/licenses/gpl.html)
# Author:     Dael Maselli <Dael.Maselli@gmail.com>
#

if(!defined('DOKU_INC')) die();
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'action.php');

class action_plugin_distributedACL extends DokuWiki_Action_Plugin {

  function getInfo(){
    return array(
		 'author' => 'Dael Maselli',
		 'email'  => 'Dael.Maselli@gmail.com',
		 'date'   => rtrim(io_readFile(DOKU_PLUGIN.'distributedACL/VERSION.txt')),
		 'name'   => 'DistributedACL (action plugin component)',
		 'desc'   => 'DistributedACL action functions.',
		 'url'    => 'http://wiki.splitbrain.org/plugin:distributedACL',
		 );
  }

  function register(Doku_Event_Handler $controller) {
    $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE',  $this, '_doacl');
  }

  function _doacl(&$event, $param) {

    global $conf;

    $ACLNAMESPACE = "acl:";
    $MODE = 2;

    #$ofh = fopen( "/tmp/debug", "w" );
    #fputs ( $ofh, $event->data[1] . " " . $event->data[2] . " " . $event->data[3] . " " . "OK\n" );
    #fclose ( $ofh );

    if ( !$event->data[3] && preg_match( "/^$ACLNAMESPACE(.+)$/", $event->data[1], $c ) ) {

      $aclfor     = $c[1] . ":";
      $pagename = $event->data[2];
      if ( $pagename == $conf['start'] ) {
	$pagename = "*";
      }
      $aclfor .= $pagename;

      $aclfile    = DOKU_INC . "conf/acl.auth.php";

      $permarr      = array( "N" => 0, "R" => 1, "E" => 2, "C" => 4, "U" => 8, "D" => 16, "W" => 16 );

      $newconfacl  = "";
      $newwikipage = "";

      $aclfh = fopen( $aclfile, "r+" ) or die("Error opening '$aclfile' for writing");
      flock( $aclfh, LOCK_EX );

      while ( $confaclline = fgets( $aclfh ) ) {

	if ( $MODE == 1 ) {
	  $matchexclude = '/[\s\t]+# distributedACL autogenerated for '. str_replace  ( "*", "\*", $aclfor ) .' #\s*$/';
	} else {
	  $matchexclude = '/^\s*'. str_replace  ( "*", "\*", $aclfor ) .'[\s\t]+/';
	}

	if ( ! preg_match( $matchexclude, $confaclline ) ) {

	  $newconfacl .= $confaclline;

	}

      }

      if ( ! preg_match( "/^#\s+acl.auth.php/", $newconfacl ) ) {
	flock( $aclfh, LOCK_UN);
	fclose( $aclfh );
	return;
      }

      foreach ( explode( "\n", $event->data[0][1] ) as $line ) {

	$line = preg_replace( "/\#.*$/", "", $line );

	if ( preg_match( "/^\s*([^:]+)\s*:\s*(\S+)/", $line, $c ) && isset($permarr[$c[1]]) ) {

	  $u = $c[2];
	  $user = "";
	  for ($j=0; $j < strlen($u); $j++) {
	    if ( ! preg_match( "/[a-zA-Z0-9]/", $u[$j] ) ) {
	      $user .= "%".dechex(ord( $u[$j] ));
	    } else {
	      $user .= $u[$j];
	    }
	  }

	  $user = preg_replace( "/^%40/", "@", $user );

	  $perm = $permarr[$c[1]];

	  $newconfacl  .= sprintf ( "%-30s %-40s %3d %s",  $aclfor, $user, $perm, "# distributedACL autogenerated for $aclfor #\n" );

	  $newwikipage .= "  $c[1]:$c[2]\n";

	} else {
	  $newwikipage .= $line . "\n";
	}

      }

      $event->data[0][1] = $newwikipage;

      rewind( $aclfh );
      ftruncate( $aclfh, 0 );

      fputs( $aclfh, $newconfacl );

      flock( $aclfh, LOCK_UN);
      fclose( $aclfh ) or die("Error closing '$aclfile'.");

    }

  }

}
