DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:superacl

This is an old revision of the document!


DokuWiki Plugin: superacl

Compatible with DokuWiki

2006-11-06, 2007-06-26, 2008-05-05

plugin Manage ACL settings globally and filter ACL table view

Last updated on
2008-05-25
Provides
Admin

This extension has not been updated in over 2 years. It may no longer be maintained or supported and may have compatibility issues.

Similar to acl

Tagged with access, acl, groups, users

Current edition

If you're looking for the SuperACL plugin for pre-2008-05-05 DokuWiki, please scroll down.

This plugin is based on acl, but allows to filter the bottom table of ACLs, so that you don't loose the overview over all the rules applying to your currently selected page/namespace.

Download / Installation

Download the plugin here (manually or via Plugin Manager): http://pb.wh4f.de/dokuwiki/superacl2.zip :!: Use this download only for DokuWiki 2008-05-05!

Former edition

The following only corresponds to the SuperACL-version for DokuWiki releases 2006-11-06 and 2007-06-26

This plugin is based on acl, but allows to select the namespace where you want to edit access rights, in opposite to the original plugin which requires you to browse a page in the corresponding namespace. This results in better overview about the global acl situation in the wiki.

Since in big wikis it takes some time to display all namespaces and all the pages of the selected namespace, the new version of SuperACL offers the configuration option to enable “Use AJAX”. This will speedup all roundtrip processes (e.g. set an ACL) by deferring the population of the dropdown-selectors.

Download / Installation

Download the plugin here (manually or via Plugin Manager): http://pb.wh4f.de/dokuwiki/superacl.zip :!: Use this download only for DokuWiki 2006-11-06 or 2007-06-26!
Old version (without AJAX support): http://pb.wh4f.de/dokuwiki/superacl-2007-08-16.zip

Code

admin.php:

admin.php
<?php
/**
 * Global ACL overview
 * 
 * Borrowed a lot of code from the aclPlugin
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Pascal Bihler <bihler@iai.uni-bonn.de>
 * @author     Frank Schubert <frank@schokilade.de>
 */
// must be run within DokuWiki
if(!defined('DOKU_INC')) die();
 
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'admin.php');
 
/**
 * All DokuWiki plugins to extend the admin function
 * need to inherit from this class
 */
class admin_plugin_superacl extends DokuWiki_Admin_Plugin {
 
        function admin_plugin_superacl(){
            $this->setupLocale();
        }
 
 
 
    /**
     * return some info
     */
    function getInfo(){
      return array(
        'author' => 'Pascal Bihler',
        'email'  => 'bihler@iai.uni-bonn.de',
        'date'   => '2008-03-18',
        'name'   => 'SuperACL',
        'desc'   => 'Manage Access Control Lists for all workspaces',
        'url'    => 'http://www.dokuwiki.org/plugin:superacl',
      );
    }
 
    /**
     * access for managers
     */
    function forAdminOnly(){
        return true; // set to false to allow Manager access to Super ACL
    }
 
    /**
     * return prompt for admin menu
     */
    function getMenuText($language) {
        return $this->lang['admin_acl'];
    }
 
    /**
     * return sort order for position in admin menu
     */
    function getMenuSort() {
      return 1;
    }
 
    /**
     * handle user request
     */
    function handle() {
      global $AUTH_ACL;
 
      $cmd   = $_REQUEST['acl_cmd'];
      $scope = $_REQUEST['acl_scope'];
      $type  = $_REQUEST['acl_type'];
      $user  = $_REQUEST['acl_user'];
      $perm  = $_REQUEST['acl_perm'];
 
      if(is_array($perm)){
        //use the maximum
        sort($perm);
        $perm = array_pop($perm);
      }else{
        $perm = 0;
      }
 
      //sanitize
      $user  = auth_nameencode($user);
      if($type == '@') $user = '@'.$user;
      if($user == '@all') $user = '@ALL'; //special group! (now case insensitive)
      $perm  = (int) $perm;
      if($perm > AUTH_DELETE) $perm = AUTH_DELETE;
      //FIXME sanitize scope!!!
 
      //nothing to do?
      if(empty($cmd) || empty($scope) || empty($user)) return;
 
 
      if($cmd == 'save'){
        $this->admin_acl_del($scope, $user);
        $this->admin_acl_add($scope, $user, $perm);
      }elseif($cmd == 'delete'){
        $this->admin_acl_del($scope, $user);
      }
 
      // reload ACL config
      $AUTH_ACL = file(DOKU_CONF.'acl.auth.php');
    }
 
    /**
     * ACL Output function
     *
     * print a table with all significant permissions for the
     * current id
     *
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function html() {
 
      print $this->locale_xhtml('intro');
 
      ptln('<div id="acl__manager">');
      ptln('<table class="inline">');
 
      //namespace selector
      $this->admin_superacl_select_ns();
 
      //new
      $this->admin_superacl_html_new();
 
      //current config
      $acls = $this->get_superacl_config($this->get_selected_ns());
      foreach ($acls as $id => $acl){
        $this->admin_superacl_html_current($id,$acl);
      }
 
 
      ptln('</table>');
      ptln('</div>');
    }
 
	/**
	 * 
	 * Get current selected namespace (or namespace of $ID as alternative)
	 * 
	 */
	 function get_selected_ns() {
	     global $ID;
 
         $id  = $_REQUEST['superacl_ns'];
 
	     if (! $id) $id = getNS($ID);
	     if (! $id) $id = '*';
 
	     return $id;
	 }
 
	/**
	 * 
	 * Get current selected acl_scope (or namespace of Selected NS as alternative)
	 * 
	 */
	 function get_acl_scope() {
 
         $scope  = $_REQUEST['acl_scope'];
 
	     if (! $scope) $scope = $this->get_selected_ns() . ':*';
	     if (! $scope) $scope = '*';
 
	     return $scope;
	 }
 
    /**
     * Get matching ACL lines for a namespace
     *
     * $id is namespacename, reads matching lines from $AUTH_ACL,
     * also reads ACLs from namespace
     * returns multi-array with key=pagename and value=array(user, acl)
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     */
    function get_superacl_config($id){
      global $AUTH_ACL;
 
 
      $acl_config=array();
 
      // match exact name
      $pages = $this->get_pages($id);
 
      foreach ($pages as $page_id) {
          if ($id != '*')
            $page_id = $id . ':' . $page_id;
	      $matches = preg_grep('/^'.$page_id.'\s+.*/',$AUTH_ACL);
	      if(count($matches)){
	        foreach($matches as $match){
	          $match = preg_replace('/#.*$/','',$match); //ignore comments
	          $acl   = preg_split('/\s+/',$match);
	          //0 is pagename, 1 is user, 2 is acl
	          $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]);
	        }
	      }
      }
 
      $specific_found=array();
 
      // match ns      
      for(;$id !== false; $id = getNS($id)){
	    $id_pattern = str_replace('+', '\\+',str_replace('*', '\\*', $id));
        $matches = preg_grep('/^'.$id_pattern.':\*\s+.*/',$AUTH_ACL);
 
        if(count($matches)){
          foreach($matches as $match){
            $match = preg_replace('/#.*$/','',$match); //ignore comments
            $acl   = preg_split('/\s+/',$match);
            //0 is pagename, 1 is user, 2 is acl
            $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]);
            $specific_found[]=$acl[1];
          }
        }
      }
 
      //include *-config
      $matches = preg_grep('/^\*\s+.*/',$AUTH_ACL);
      if(count($matches)){
        foreach($matches as $match){
          $match = preg_replace('/#.*$/','',$match); //ignore comments
          $acl   = preg_split('/\s+/',$match);
          // only include * for this user if not already found in ns
          if(!in_array($acl[1], $specific_found)){
            //0 is pagename, 1 is user, 2 is acl
            $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]);
          }
        }
      }
 
      //sort
      //FIXME: better sort algo: first sort by key, then sort by first value
      krsort($acl_config, SORT_STRING);
 
      return($acl_config);
    }
 
 
    /**
     * adds new acl-entry to conf/acl.auth.php
     *
     * @author  Frank Schubert <frank@schokilade.de>
     */
    function admin_acl_add($acl_scope, $acl_user, $acl_level){
      $acl_config = join("",file(DOKU_CONF.'acl.auth.php'));
 
      // max level for pagenames is edit
      if(strpos($acl_scope,'*') === false) {
        if($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT;
      }
 
      $new_acl = "$acl_scope\t$acl_user\t$acl_level\n";
 
      $new_config = $acl_config.$new_acl;
 
      return io_saveFile(DOKU_CONF.'acl.auth.php', $new_config);
    }
 
    /**
     * remove acl-entry from conf/acl.auth.php
     *
     * @author  Frank Schubert <frank@schokilade.de>
     */
    function admin_acl_del($acl_scope, $acl_user){
      $acl_config = file(DOKU_CONF.'acl.auth.php');
 
      $acl_pattern = '^'.preg_quote($acl_scope,'/').'\s+'.$acl_user.'\s+[0-8].*$';
 
      // save all non!-matching #FIXME invert is available from 4.2.0 only!
      $new_config = preg_grep("/$acl_pattern/", $acl_config, PREG_GREP_INVERT);
 
      return io_saveFile(DOKU_CONF.'acl.auth.php', join('',$new_config));
    }
 
    // --- HTML OUTPUT FUNCTIONS BELOW --- //
 
    /**
     * create dropdown with parent namespaces and pages of one namespace ID
     *
     *
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_superacl_html_dropdown($id){
      $cur = $id;
      $ret = '';
      $selected_id = $this->get_acl_scope();
      $opt = array();
 
      //prepare all options (in reversed order)
      $pages = array();
      if ($this->getConf('use_ajax')) {      
          $ret .= sprintf('<input type="hidden" id="superacl__aclid" value="%s"/>',$id);
          $ret .= sprintf('<input type="hidden" id="superacl__pageselid" value="%s"/>',$selected_id);
          $ret .= sprintf('<input type="hidden" id="superacl__page_text" value="%s"/>',$this->lang['page']);
          $ret .= sprintf('<input type="hidden" id="superacl__namespace_text" value="%s"/>',$this->lang['namespace']);
 
      } else { 
	      // pages in this namespace
	      $pages = array_reverse($this->get_pages($id));
      }
 
      // add pages in list
      foreach ($pages as $page_id) {
          $page_id = ($id != '*' ? $id . ':' : '') . $page_id;
          $opt[] = array('value'=> $page_id, 
                         'text'=> $page_id.' ('.$this->lang['page'].')');
          if ($page_id ==  $selected_id)
            $opt[count($opt)-1]['sel'] = true;
      }
 
      // add selected page (if not in list above)
      if (!($pages) && ($this->is_page($selected_id))) {
         $opt[] = array('value'=> $selected_id, 
                         'text'=> $selected_id.' ('.$this->lang['page'].')',
                         'sel' => true);
      }
 
 
      // additional namespaces
      for(; $id !== false && $id != '*'; $id=getNS($id)){
        $opt[] = array('value'=> $id.':*', 'text'=> $id.':* ('.$this->lang['namespace'].')');
        if ($id.':*' ==  $selected_id)
          $opt[count($opt)-1]['sel'] = true;
 
      }
 
      // the top namespace
      $opt[] = array('value'=> '*', 'text'=> '* ('.$this->lang['namespace'].')');
 
 
 
      // flip options
      $opt = array_reverse($opt);
 
      // create HTML
      $att = array( 'name'  => 'acl_scope',
      				'id' => 'superacl__pageselect',
                    'class' => 'edit',
                    'title' => $this->lang['page'].'/'.$this->lang['namespace']);
      $ret .= '<select '.html_attbuild($att).'>';
      foreach($opt as $o){
        $ret .= '<option value="'.$o['value'].'"'.($o['sel'] ? ' selected="selected"' : '').'>'.$o['text'].'</option>';
      }
      $ret .= '</select>';
 
      return $ret;
    }
 
    /**
     * Decides, if a id is a page
     * */
    function is_page($id){
      return (id != "") && ! (substr($id,-1) == '*');
    }
 
     /**
     * creates dropdown with all namespaces
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     */
    function admin_superacl_html_ns_dropdown($id){
      global $ID;
      $ret = '';
      $opt = array();
 
 
      $namespaces = array();
 
      if ($this->getConf('use_ajax')) {
	      $ret .= sprintf('<input type="hidden" id="superacl__pageid" value="%s"/>',$ID);
	      $ret .= sprintf('<input type="hidden" id="superacl__nsselid" value="%s"/>',$id);
      } else {
          $namespaces = $this->get_namespaces();
	  }
 
      // add namespaces of current page to the list of namespaces (even if the namespaces doesn't exist yet
      $ns_id = getNS($ID);
      for(;$ns_id !== false; $ns_id = getNS($ns_id)){
          if (array_search($ns_id,$namespaces) === false)
             $namespaces[] = $ns_id;
      }
 
      // add selected namespace, if not in list above
     if ($id && (array_search($id,$namespaces) === false))
             $namespaces[] = $id;
 
      sort($namespaces);
 
      $namespaces = array_reverse($namespaces);
      foreach ($namespaces as $ns_id) {
          if ($ns_id == "*") continue;
 
          $opt[] = array('value'=> $ns_id, 'text'=> $ns_id.':*');
          if ($ns_id == $id) // set sel on current selected namespcase 
      		$opt[count($opt)-1]['sel'] = true; 
      }
 
      $opt[] = array('value'=> '*', 'text'=> '*');
 
 
      // flip options
      $opt = array_reverse($opt); 
 
 
      // create HTML
      $att = array( 'name'  => 'superacl_ns',
                    'id' => 'superacl__nsselect',
                    'class' => 'edit',
                    'title' => $this->lang['page'].'/'.$this->lang['namespace']);
      $ret .= '<select '.html_attbuild($att).' onchange="submit();">';
      foreach($opt as $o){
        $ret .= '<option value="'.$o['value'].'"'.($o['sel'] ? ' selected="selected"' : '').'>'.$o['text'].'</option>';
      }
      $ret .= '</select>';
 
      return $ret;
    }
 
    /**
     * print form to select namespace to modify 
     * 
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * 
     */
     function admin_superacl_select_ns() {
       global $ID;
       global $lang;
 
      // table headers
      ptln('<tr>',2);
      ptln('  <th class="leftalign" colspan="3">'.$this->lang['acl_select'].'</th>',2);
      ptln('</tr>',2);
 
      ptln('<tr>',2);
 
      ptln('<td class="centeralign" colspan="3">',4);
 
      ptln('  <form method="post" action="'.wl($ID).'"><div class="no">',4);
      ptln('    <input type="hidden" name="do"   value="admin" />',4);
      ptln('    <input type="hidden" name="page" value="superacl" />',4);
      ptln('    <input type="hidden" name="acl_cmd" value="select_ns" />',4);
 
      //scope select
      ptln($this->lang['acl_perms'],4);
      ptln($this->admin_superacl_html_ns_dropdown($this->get_selected_ns()),4);
 
      ptln('    <input type="submit" class="button" value="'.$lang['btn_update'].'" />',4);
      ptln('  </div></form>');
      ptln('</td>',4);
      ptln('</tr>',2);
 
     }
 
 
    /**
     * print form to add new Permissions
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_superacl_html_new(){
      global $ID;
      global $lang;
 
      // table headers
      ptln('<tr>',2);
      ptln('  <th class="leftalign" colspan="3">'.$this->lang['acl_new'].'</th>',2);
      ptln('</tr>',2);
 
      ptln('<tr>',2);
 
      ptln('<td class="centeralign" colspan="3">',4);
 
      ptln('  <form method="post" action="'.wl($ID).'"><div class="no">',4);
      ptln('    <input type="hidden" name="do"   value="admin" />',4);
      ptln('    <input type="hidden" name="page" value="superacl" />',4);
      ptln('    <input type="hidden" name="acl_cmd" value="save" />',4);
      ptln('    <input type="hidden" name="superacl_ns" value="' . $this->get_selected_ns() . '" />',4);
 
 
 
 
 
      //scope select
      ptln($this->lang['acl_perms'],4);
      ptln($this->admin_superacl_html_dropdown($this->get_selected_ns()),4);
 
      $att = array( 'name'  => 'acl_type',
                    'class' => 'edit',
                    'title' => $this->lang['acl_user'].'/'.$this->lang['acl_group']);
      ptln('    <select '.html_attbuild($att).'>',4);
      ptln('      <option value="@">'.$this->lang['acl_group'].'</option>',4);
      ptln('      <option value="">'.$this->lang['acl_user'].'</option>',4);
      ptln('    </select>',4);
 
      $att = array( 'name'  => 'acl_user',
                    'type'  => 'text',
                    'class' => 'edit',
                    'title' => $this->lang['acl_user'].'/'.$this->lang['acl_group']);
      ptln('    <input '.html_attbuild($att).' />',4);
      ptln('    <br />');
 
      ptln(     $this->admin_acl_html_checkboxes(0,false),8);
 
      ptln('    <input type="submit" class="button" value="'.$lang['btn_save'].'" />',4);
      ptln('  </div></form>');
      ptln('</td>',4);
      ptln('</tr>',2);
    }
 
    /**
     * print tablerows with the current permissions for one id
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_superacl_html_current($id,$permissions){
      global $lang;
      global $ID;
 
      //is it a page?
      $idpage = $this->is_page($id);
 
      // table headers
      ptln('  <tr>');
      ptln('    <th class="leftalign" colspan="3">');
      ptln($this->lang['acl_perms'],6);
      if($ispage){
        ptln($this->lang['page'],6);
      }else{
        ptln($this->lang['namespace'],6);
      }
      ptln('<em>'.$id.'</em>',6);
      ptln('    </th>');
      ptln('  </tr>');
 
      sort($permissions);
 
      foreach ($permissions as $conf){
        //userfriendly group/user display
        $conf['name'] = rawurldecode($conf['name']);
        if(substr($conf['name'],0,1)=="@"){
          $group = $this->lang['acl_group'];
          $name  = substr($conf['name'],1);
          $type  = '@';
        }else{
          $group = $this->lang['acl_user'];
          $name  = $conf['name'];
          $type  = '';
        }
 
        ptln('<tr>',2);
        ptln('<td class="leftalign">'.htmlspecialchars($group.' '.$name).'</td>',4);
 
        // update form
        ptln('<td class="centeralign">',4);
        ptln('  <form method="post" action="'.wl($ID).'"><div class="no">',4);
        ptln('    <input type="hidden" name="do"   value="admin" />',4);
        ptln('    <input type="hidden" name="page" value="superacl" />',4);
        ptln('    <input type="hidden" name="acl_cmd"   value="save" />',4);
        ptln('    <input type="hidden" name="acl_scope" value="'.formtext($id).'" />',4);
        ptln('    <input type="hidden" name="acl_type" value="'.$type.'" />',4);
        ptln('    <input type="hidden" name="acl_user"  value="'.formtext($name).'" />',4);
        ptln('    <input type="hidden" name="superacl_ns" value="' . $this->get_selected_ns() . '" />',4);
        ptln(     $this->admin_acl_html_checkboxes($conf['perm'],$ispage),8);
        ptln('    <input type="submit" class="button" value="'.$lang['btn_update'].'" />',4);
        ptln('  </div></form>');
        ptln('</td>',4);
 
 
        // deletion form
 
        $ask  = $lang['del_confirm'].'\\n';
        $ask .= $id.'  '.$conf['name'].'  '.$conf['perm'];
        ptln('<td class="centeralign">',4);
        ptln('  <form method="post" action="'.wl($ID).'" onsubmit="return confirm(\''.str_replace('\\\\n','\\n',addslashes($ask)).'\')"><div class="no">',4);
        ptln('    <input type="hidden" name="do"        value="admin" />',4);
        ptln('    <input type="hidden" name="page"      value="superacl" />',4);
        ptln('    <input type="hidden" name="acl_cmd"   value="delete" />',4);
        ptln('    <input type="hidden" name="acl_scope" value="'.formtext($id).'" />',4);
        ptln('    <input type="hidden" name="acl_type" value="'.$type.'" />',4);
        ptln('    <input type="hidden" name="acl_user"  value="'.formtext($name).'" />',4);
        ptln('    <input type="hidden" name="superacl_ns" value="' . $this->get_selected_ns() . '" />',4);
        ptln('    <input type="submit" class="button" value="'.$lang['btn_delete'].'" />',4);
        ptln('  </div></form>',4);
        ptln('</td>',4);
 
        ptln('</tr>',2);
      }
 
    }
 
 
    /**
     * print the permission checkboxes
     *
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_acl_html_checkboxes($setperm,$ispage){
      global $lang;
 
      static $label = 0; //number labels
      $ret = '';
 
      foreach(array(AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){
        $label += 1;
 
        //general checkbox attributes
        $atts = array( 'type'  => 'checkbox',
                       'id'    => 'pbox'.$label,
                       'name'  => 'acl_perm[]',
                       'value' => $perm );
        //dynamic attributes
        if($setperm >= $perm) $atts['checked']  = 'checked';
        $atts['onchange'] = "superacl_autoselect_permissions(this);";
        if($ispage && $perm > AUTH_EDIT) $atts['disabled'] = 'disabled';
 
        //build code
        $ret .= '<label for="pbox'.$label.'" title="'.$this->lang['acl_perm'.$perm].'">';
        $ret .= '<input '.html_attbuild($atts).' />';
        $ret .= $this->lang['acl_perm'.$perm];
        $ret .= "</label>\n";
      }
      return $ret;
    }
 
    function get_pages($tns='') {
        return $this->_getlist($tns,false,false,true);
    }
 
    function get_namespaces($tns='') {
        return $this->_getlist($tns,true,true,false);
    }
    // inspired from addnewpageplugin: 
     function _getlist ($tns='',$recursive = true, $namespaces=true,$pages=false) {
		require_once(DOKU_INC.'inc/search.php');
		global $conf;
 
        if ($tns == '*') $tns = '';
 
		if (!is_dir($tns))
			$tns  = str_replace(':','/',$tns);
 
		$data = array();
 
 
		search($data,$conf['datadir'] ."/" . $tns,'search_index',array('ns' => ''));
 
		$data2 = array();
		foreach($data as $k => $v) {
			if ($v['type']=='d') { //Namespace
			    if ($namespaces)
				    array_push($data2,$v['id']);
				if ($recursive) {
					$r=$this->_getlist($tns.'/'.$v['id'],$recursive,$namespaces,$pages);
					foreach ($r as $vv) {
						array_push($data2,$v['id'].':'.$vv);
					}
				}
			} elseif ($v['type']=='f') { //Page
			    if ($pages)
				    array_push($data2,$v['id']);
			}
		}
		return $data2;
	} 
 
}

ajax.php:

ajax.php
<?php
/**
 * SuperACL Ajax Handler 
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author    Pascal Bihler <bihler@iai.uni-bonn.de>
 * */
//fix for Opera XMLHttpRequests
if(!count($_POST) && $HTTP_RAW_POST_DATA){
  parse_str($HTTP_RAW_POST_DATA, $_POST);
}
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/common.php');
require_once(DOKU_INC.'inc/pageutils.php');
require_once(DOKU_INC.'inc/auth.php');
require_once(DOKU_INC.'inc/JSON.php');
//close session
session_write_close();
 
// check, if user is admin (or at least manager)
if (! auth_ismanager()) {
	exit;
}
 
if ($_POST["q"] == "namespaces") {
   get_namespace_list();
} elseif ($_POST["q"] == "pages") {
   get_pages_list();
}
 
function get_namespace_list() {
 
	$ID = $_POST["pageid"];
	$selid = $_POST["selid"];
 
      $opt = array();
 
 		// all namespace
     $namespaces = get_namespaces();
 
      // add namespaces of current page to the list of namespaces (even if the namespaces doesn't exist yet
      $ns_id = getNS($ID);
      for(;$ns_id !== false; $ns_id = getNS($ns_id)){
          if (array_search($ns_id,$namespaces) === false)
             $namespaces[] = $ns_id;
      }
      sort($namespaces);
 
      $namespaces = array_reverse($namespaces);
      foreach ($namespaces as $ns_id) {
          $opt[] = array('value'=> $ns_id, 'text'=> $ns_id.':*');
          if ($ns_id == $selid) // set sel on current selected namespcase 
      		$opt[count($opt)-1]['sel'] = true; 
      }
 
      $opt[] = array('value'=> '*', 'text'=> '*');
 
 
      // flip options
      $opt = array_reverse($opt); 
 
 
 /* now construct a json */
  $json = new JSON();
 
 
  //header('Content-Type: application/json');
  header('Content-Type: text/javascript');
  print $json->encode($opt);
}
 
 
function get_pages_list() {
 
	$id = $_POST["aclid"];
	$selected_id = $_POST["selid"];
 
    $opt = array();
 
	$pages = array_reverse(get_pages($id));
 
      // add pages in list
      foreach ($pages as $page_id) {
          $page_id = ($id != '*' ? $id . ':' : '') . $page_id;
          $opt[] = array('value'=> $page_id, 
                         'text'=> $page_id.' ('.$_POST['page_text'].')');
          if ($page_id ==  $selected_id)
            $opt[count($opt)-1]['sel'] = true;
      }      
 
      // additional namespaces
      for(; $id !== false && $id != '*'; $id=getNS($id)){
        $opt[] = array('value'=> $id.':*', 'text'=> $id.':* ('.$_POST['ns_text'].')');
        if ($id.':*' ==  $selected_id)
          $opt[count($opt)-1]['sel'] = true;
 
      }
 
      // the top namespace
      $opt[] = array('value'=> '*', 'text'=> '* ('.$_POST['ns_text'].')');
 
 
 
      // flip options
      $opt = array_reverse($opt);
 
 
	 /* now construct a json */
	  $json = new JSON();
 
 
	  //header('Content-Type: application/json');
	  header('Content-Type: text/javascript');
	  print $json->encode($opt);
}
 
    function get_pages($tns='') {
        return _getlist($tns,false,false,true);
    }
 
 
   function get_namespaces($tns='') {
        return _getlist($tns,true,true,false);
    }
    // inspired from addnewpageplugin: 
     function _getlist ($tns='',$recursive = true, $namespaces=true,$pages=false) {
		require_once(DOKU_INC.'inc/search.php');
		global $conf;
 
        if ($tns == '*') $tns = '';
 
		if (!is_dir($tns))
			$tns  = str_replace(':','/',$tns);
 
		$data = array();
 
 
		search($data,$conf['datadir'] ."/" . $tns,'search_index',array('ns' => ''));
 
		$data2 = array();
		foreach($data as $k => $v) {
			if ($v['type']=='d') { //Namespace
			    if ($namespaces)
				    array_push($data2,$v['id']);
				if ($recursive) {
					$r=_getlist($tns.'/'.$v['id'],$recursive,$namespaces,$pages);
					foreach ($r as $vv) {
						array_push($data2,$v['id'].':'.$vv);
					}
				}
			} elseif ($v['type']=='f') { //Page
			    if ($pages)
				    array_push($data2,$v['id']);
			}
		}
		return $data2;
	} 
?>

script.js:

script.js
function superacl_autoselect_permissions(caller) {
    callerLabel = parseInt(caller.id.substring(4));
    baseLabel = caller.id.substring(0,4);
    parent = caller.parentNode.parentNode;
    boxes = parent.getElementsByTagName('input');
	for (i = 0; i < boxes.length; i++) {
	    e = boxes[i];
	    if (! e) continue;
	    id = e.id;
	    if (!id || id.length<4 || id.substring(0,4) != baseLabel) continue;
	    label = parseInt(id.substring(4));
	    if (caller.checked && label < callerLabel)  //check lower rights, too
	        e.checked = true;
	    else if (! caller.checked && label > callerLabel) //uncheck upper rights too
	        e.checked = false;
	}
}
 
 
function ajax_superacl_class() {
	this.sack = null;
	this.inObj = null;
	this.outObj = null;
	this.timer = null;
}
 
function fillNamespaceDropdown()
{
	// fill namespace selector
	if ($('superacl__nsselid')) {
 
		var ajax_superaclns = new ajax_superacl_class();
 
		ajax_superaclns.sack = new sack(DOKU_BASE + 'lib/plugins/superacl/ajax.php');
		ajax_superaclns.sack.AjaxFailedAlert = '';
		ajax_superaclns.sack.encodeURIString = false;
 
		ajax_superaclns.exec = function() {
			pageid = $("superacl__pageid").value;
			ns_selid = $("superacl__nsselid").value;
			ajax_superaclns.sack.runAJAX('q=namespaces&pageid=' + encodeURI(pageid) + '&selid=' + encodeURI(ns_selid));
		};
 
		ajax_superaclns.sack.onCompletion = function() {
			var data = eval(ajax_superaclns.sack.response);
			if(data === '') {
			   return;
			   }
 
 
			// add namespaces to select box
			select = $('superacl__nsselect');
			for(i = 0; i < data.length; ++i) {
			  option = new Option(data[i].text, data[i].value, data[i].sel, data[i].sel);
			  select.options[i] = option;			
			}
		};
 
        ajax_superaclns.exec();
    }
 
    // fill page selector
    if ($('superacl__aclid')) {
      	var ajax_superaclpage = new ajax_superacl_class();
 
		ajax_superaclpage.sack = new sack(DOKU_BASE + 'lib/plugins/superacl/ajax.php');
		ajax_superaclpage.sack.AjaxFailedAlert = '';
		ajax_superaclpage.sack.encodeURIString = false;
 
		ajax_superaclpage.exec = function() {
			acl_id = $("superacl__aclid").value;
			page_selid = $("superacl__pageselid").value;
			page_text = $("superacl__page_text").value;
			ns_text = $("superacl__namespace_text").value;
			ajax_superaclpage.sack.runAJAX('q=pages&aclid=' + encodeURI(acl_id) +
			                               '&selid=' + encodeURI(page_selid) +
			                               '&page_text=' + encodeURI(page_text) +
			                               '&ns_text=' + encodeURI(ns_text) );
		};
 
		ajax_superaclpage.sack.onCompletion = function() {
			var data = eval(ajax_superaclpage.sack.response);
			if(data === '') {
			   return;
			   }
 
 
			// add namespaces to select box
			select = $('superacl__pageselect');
			for(i = 0; i < data.length; ++i) {
			  option = new Option(data[i].text, data[i].value, data[i].sel, data[i].sel);
			  select.options[i] = option;			
			} 
		};
 
        ajax_superaclpage.exec();
    }
}
 
addInitEvent(function(){fillNamespaceDropdown();});

Patches

Bug : Problem with * and + characters

  • description : if you try to get ACL for “*” (the first namespace in the list) you get at least 2 warnings “warning: Compilation failed: nothing to repeat at offset 1” for preg_grep on line 183.
  • solution I've put the following code just before line 183 :
$id = str_replace('*', '\\*', $id);
$id = str_replace('+', '\\+', $id);

It seems it works…

Thank you for the hint, I included it with the new version 2007-08-13.
Pascal Bihler 2007/08/13 16:06

Bug : wrong variable name

In admin.php line 528

$idpage $ispage = $this→is_page($id);

plugin/superacl.1252615435.txt.gz · Last modified: 2009-09-10 22:43 by HåkanS