summaryrefslogtreecommitdiff
path: root/lib/plugins
diff options
context:
space:
mode:
authorchris <chris@teacherscpd.co.uk>2005-08-25 00:47:18 +0200
committerchris <chris@teacherscpd.co.uk>2005-08-25 00:47:18 +0200
commit11e2ce226d64ac98b82ddc93a81eea66160bcc21 (patch)
treef19de21e96f8952161903dd34e01821b2e0ccb45 /lib/plugins
parentf00151b4e3d17bcf50767f821c0e3834d36e7b4f (diff)
downloadrpg-11e2ce226d64ac98b82ddc93a81eea66160bcc21.tar.gz
rpg-11e2ce226d64ac98b82ddc93a81eea66160bcc21.tar.bz2
admin plugin i/face + acl plugin
darcs-hash:20050824224718-50fdc-6d27ff70e60e6fe547aff6c2b305507c4ab3f669.gz
Diffstat (limited to 'lib/plugins')
-rw-r--r--lib/plugins/acl/admin.php436
-rw-r--r--lib/plugins/admin.php151
2 files changed, 587 insertions, 0 deletions
diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php
new file mode 100644
index 000000000..c122edfe6
--- /dev/null
+++ b/lib/plugins/acl/admin.php
@@ -0,0 +1,436 @@
+<?php
+/**
+ * ACL administration functions
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Frank Schubert <frank@schokilade.de>
+ */
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
+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_acl extends DokuWiki_Admin_Plugin {
+
+ /**
+ * return some info
+ */
+ function getInfo(){
+ return array(
+ 'author' => 'Frank Schubert',
+ 'email' => 'frank@schokilade.de',
+ 'date' => '2005-08-08',
+ 'name' => 'ACL',
+ 'desc' => 'Manage Page Access Control Lists',
+ 'url' => 'http://wiki.splitbrain.org/wiki:acl',
+ );
+ }
+
+ /**
+ * return prompt for admin menu
+ */
+ function getMenuText($language) {
+ global $lang;
+ return $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 = cleanID($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() {
+ global $ID;
+
+ print p_locale_xhtml('admin_acl');
+
+ ptln('<div class="acladmin">');
+ ptln('<table class="inline">');
+
+ //new
+ $this->admin_acl_html_new();
+
+ //current config
+ $acls = $this->get_acl_config($ID);
+ foreach ($acls as $id => $acl){
+ $this->admin_acl_html_current($id,$acl);
+ }
+
+ ptln('</table>');
+ ptln('</div>');
+ }
+
+
+ /**
+ * Get matching ACL lines for a page
+ *
+ * $ID is pagename, reads matching lines from $AUTH_ACL,
+ * also reads acls from namespace
+ * returns multi-array with key=pagename and value=array(user, acl)
+ *
+ * @todo Fix comment to make sense
+ * @todo should this moved to auth.php?
+ * @todo can this be combined with auth_aclcheck to avoid duplicate code?
+ * @author Frank Schubert <frank@schokilade.de>
+ */
+ function get_acl_config($id){
+ global $AUTH_ACL;
+
+ $acl_config=array();
+
+ // match exact name
+ $matches = preg_grep('/^'.$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
+ while(($id=getNS($id)) !== false){
+ $matches = preg_grep('/^'.$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[]=$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 --- //
+
+ /**
+ * print tablerows with the current permissions for one id
+ *
+ * @author Frank Schubert <frank@schokilade.de>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function admin_acl_html_dropdown($id){
+ global $lang;
+ $cur = $id;
+ $ret = '';
+ $opt = array();
+
+ //prepare all options
+
+ // current page
+ $opt[] = array('key'=> $id, 'val'=> $id.' ('.$lang['page'].')');
+
+ // additional namespaces
+ while(($id=getNS($id)) !== false){
+ $opt[] = array('key'=> $id.':*', 'val'=> $id.':* ('.$lang['namespace'].')');
+ }
+
+ // the top namespace
+ $opt[] = array('key'=> '*', 'val'=> '* ('.$lang['namespace'].')');
+
+ // set sel on second entry (current namespace)
+ $opt[1]['sel'] = ' selected="selected"';
+
+ // flip options
+ $opt = array_reverse($opt);
+
+ // create HTML
+ $att = array( 'name' => 'acl_scope',
+ 'class' => 'edit',
+ 'title' => $lang['page'].'/'.$lang['namespace']);
+ $ret .= '<select '.html_attbuild($att).'>';
+ foreach($opt as $o){
+ $ret .= '<option value="'.$o['key'].'"'.$o['sel'].'>'.$o['val'].'</option>';
+ }
+ $ret .= '</select>';
+
+ return $ret;
+ }
+
+ /**
+ * print tablerows with the current permissions for one id
+ *
+ * @author Frank Schubert <frank@schokilade.de>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function admin_acl_html_new(){
+ global $lang;
+ global $ID;
+
+ // table headers
+ ptln('<tr>',2);
+ ptln(' <th class="leftalign" colspan="3">'.$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).'">',4);
+ ptln(' <input type="hidden" name="do" value="admin" />',4);
+ ptln(' <input type="hidden" name="page" value="acl" />',4);
+ ptln(' <input type="hidden" name="acl_cmd" value="save" />',4);
+
+ //scope select
+ ptln($lang['acl_perms'],4);
+ ptln($this->admin_acl_html_dropdown($ID),4);
+
+ $att = array( 'name' => 'acl_type',
+ 'class' => 'edit',
+ 'title' => $lang['acl_user'].'/'.$lang['acl_group']);
+ ptln(' <select '.html_attbuild($att).'>',4);
+ ptln(' <option value="@">'.$lang['acl_group'].'</option>',4);
+ ptln(' <option value="">'.$lang['acl_user'].'</option>',4);
+ ptln(' </select>',4);
+
+ $att = array( 'name' => 'acl_user',
+ 'type' => 'text',
+ 'class' => 'edit',
+ 'title' => $lang['acl_user'].'/'.$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="edit" value="'.$lang['btn_save'].'" />',4);
+ ptln(' </form>');
+ ptln('</tr>',2);
+ }
+
+ /**
+ * print tablerows with the current permissions for one id
+ *
+ * @author Frank Schubert <frank@schokilade.de>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function admin_acl_html_current($id,$permissions){
+ global $lang;
+ global $ID;
+
+ //is it a page?
+ if(substr($id,-1) == '*'){
+ $ispage = false;
+ }else{
+ $ispage = true;
+ }
+
+ // table headers
+ ptln(' <tr>');
+ ptln(' <th class="leftalign" colspan="3">');
+ ptln($lang['acl_perms'],6);
+ if($ispage){
+ ptln($lang['page'],6);
+ }else{
+ ptln($lang['namespace'],6);
+ }
+ ptln('<em>'.$id.'</em>',6);
+ ptln(' </th>');
+ ptln(' </tr>');
+
+ sort($permissions);
+
+ foreach ($permissions as $conf){
+ //userfriendly group/user display
+ if(substr($conf['name'],0,1)=="@"){
+ $group = $lang['acl_group'];
+ $name = substr($conf['name'],1);
+ $type = '@';
+ }else{
+ $group = $lang['acl_user'];
+ $name = $conf['name'];
+ $type = '';
+ }
+
+ ptln('<tr>',2);
+ ptln('<td class="leftalign">'.$group.' '.$name.'</td>',4);
+
+ // update form
+ ptln('<td class="centeralign">',4);
+ ptln(' <form method="post" action="'.wl($ID).'">',4);
+ ptln(' <input type="hidden" name="do" value="admin" />',4);
+ ptln(' <input type="hidden" name="page" value="acl" />',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( $this->admin_acl_html_checkboxes($conf['perm'],$ispage),8);
+ ptln(' <input type="submit" class="edit" value="'.$lang['btn_update'].'" />',4);
+ ptln(' </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(\''.$ask.'\')">',4);
+ ptln(' <input type="hidden" name="do" value="admin" />',4);
+ ptln(' <input type="hidden" name="page" value="acl" />',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="submit" class="edit" value="'.$lang['btn_delete'].'" />',4);
+ ptln(' </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';
+ # if($perm > AUTH_READ) $atts['onchange'] = #FIXME JS to autoadd lower perms
+ if($ispage && $perm > AUTH_EDIT) $atts['disabled'] = 'disabled';
+
+ //build code
+ $ret .= '<label for="pbox'.$label.'" title="'.$lang['acl_perm'.$perm].'">';
+ $ret .= '<input '.html_attbuild($atts).' />';
+ $ret .= $lang['acl_perm'.$perm];
+ $ret .= "</label>\n";
+ }
+ return $ret;
+ }
+
+} \ No newline at end of file
diff --git a/lib/plugins/admin.php b/lib/plugins/admin.php
new file mode 100644
index 000000000..805689f2a
--- /dev/null
+++ b/lib/plugins/admin.php
@@ -0,0 +1,151 @@
+<?php
+/**
+ * Admin Plugin Prototype
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Christopher Smith <chris@jalakai.co.uk>
+ */
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+
+/**
+ * All DokuWiki plugins to extend the admin function
+ * need to inherit from this class
+ */
+class DokuWiki_Admin_Plugin {
+
+ var $localised = false;
+ var $lang = array();
+
+ /**
+ * General Info
+ *
+ * Needs to return a associative array with the following values:
+ *
+ * author - Author of the plugin
+ * email - Email address to contact the author
+ * date - Last modified date of the plugin in YYYY-MM-DD format
+ * name - Name of the plugin
+ * desc - Short description of the plugin (Text only)
+ * url - Website with more information on the plugin (eg. syntax description)
+ */
+ function getInfo(){
+ trigger_error('getInfo() not implemented in '.get_class($this), E_USER_WARNING);
+ }
+
+ function getMenuText($language) {
+ return $this->getLang('menu');
+ }
+
+ function getMenuSort() {
+ return 1000;
+ }
+
+ function handle() {
+ trigger_error('handle() not implemented in '.get_class($this), E_USER_WARNING);
+ }
+
+ function html() {
+ trigger_error('html() not implemented in '.get_class($this), E_USER_WARNING);
+ }
+
+ // private methods (maybe a dokuwiki plugin base class is required for these)
+
+ // plugin introspection methods
+ // extract from class name, format = <plugin type>_plugin_<name>[_<component name>]
+ function getPluginType() { list($t) = explode('_', get_class($this), 2); return $t; }
+ function getPluginName() { list($t, $p, $n) = explode('_', get_class($this), 4); return $n; }
+ function getPluginComponent() { list($t, $p, $n, $c) = explode('_', get_class($this), 4); return (isset($c)?$c:''); }
+
+ function setupLocale() {
+ global $conf; // definitely don't invoke "global $lang"
+ $path = DOKU_PLUGIN.$this->getPluginName().'/lang/';
+
+ // don't include once, in case several plugin components require the same language file
+ @include($path.'en/lang.php');
+ if ($conf['lang'] != 'en') @include($path.$conf['lang'].'/lang.php');
+
+ $this->lang = $lang;
+ $this->localised = true;
+ }
+
+ // plugin equivalent of localFN()
+ function plugin_localFN($id) {
+ global $conf;
+ $plugin = $this->getPluginName();
+ $file = DOKU_PLUGIN.$plugin.'/lang/'.$conf['lang'].'/'.$id.'.txt';
+ if(!@file_exists($file)){
+ //fall back to english
+ $file = DOKU_PLUGIN.$plugin.'inc/lang/en/'.$id.'.txt';
+ }
+ return $file;
+ }
+
+ // use this function to access plugin language strings
+ // to try to minimise unnecessary loading of the strings when the plugin doesn't require them
+ // e.g. when info plugin is querying plugins for information about themselves.
+ function getLang($id) {
+ if (!$this->localised) $this->setupLocale();
+
+ return (isset($this->lang[$id]) ? $this->lang[$id] : '');
+ }
+
+ // plugin equivalent of p_locale_xhtml()
+ function plugin_locale_xhtml($id) {
+ return p_cached_xhtml($this->plugin_localFN($id));
+ }
+
+ // standard functions for outputing email addresses and links
+ // use these to avoid having to duplicate code to produce links in line with the installation configuration
+ function plugin_email($email, $name='', $class='', $more='') {
+ if (!$email) return $name;
+ $email = $this->obfuscate($email);
+ if (!$name) $name = $email;
+ $class = "class='".($class ? $class : 'mail')."'";
+ return "<a href='mailto:$email' $class title='$email' $more>$name</a>";
+ }
+
+ function plugin_link($link, $title='', $class='', $target='', $more='') {
+ global $conf;
+
+ $link = htmlentities($link);
+ if (!$title) $title = $link;
+ if (!$target) $target = $conf['target']['extern'];
+ if ($conf['relnofollow']) $more .= ' rel="nofollow"';
+
+ if ($class) $class = " class='$class'";
+ if ($target) $target = " target='$target'";
+ if ($more) $more = " ".trim($more);
+
+ return "<a href='$link'$class$target$more>$title</a>";
+ }
+
+ // output text string through the parser, allows dokuwiki markup to be used
+ // very ineffecient for small pieces of data - try not to use
+ function plugin_render($text, $format='xhtml') {
+ return p_render($format, p_get_instructions($text),$info);
+ }
+
+ // return an obfuscated email address in line with $conf['mailguard'] setting
+ // FIXME?? this should really be a common function, used by the renderer as well - no point maintaining two!
+ 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;
+ }
+ }
+
+}
+//Setup VIM: ex: et ts=4 enc=utf-8 :