/** * Adds a new acl-entry to conf/acl.auth.php, as well as lib/plugins/daftdrafts/daft.auth.php. * * @author Jon Magne Bøe <*****@*****.**> * @author Frank Schubert <*****@*****.**> * @author Gerry Weissbach <*****@*****.**> */ function acl_add($acl_scope, $acl_user, $acl_level, $additional = 'DAFTDRAFTS') { global $AUTH_ACL; $acl_config = $AUTH_ACL; if (empty($acl_config)) { $acl_config = file(DOKU_CONF . 'acl.auth.php'); } $daftAcl = file(dirname(__FILE__) . '/daft.auth.php'); $acl_user = auth_nameencode($acl_user, true); if (empty($acl_user)) { return false; } if (!empty($additional)) { $additionalCheck = '\\t#' . $additional; $additional = "\t#" . $additional; } //Checks that the acl_level is not higher than the permitted maximum for pages: if (strpos($acl_scope, '*') === false) { if ($acl_level > AUTH_EDIT) { $acl_level = AUTH_EDIT; } } $existInDaft = false; $existInAcl = false; $acl_pattern = '^' . preg_quote($acl_scope, '/') . '\\s+' . $acl_user . '\\s+[0-8].*' . $additionalCheck . '$'; $acl_pattern_nocomment = '^' . preg_quote($acl_scope, '/') . '\\s+' . $acl_user . '\\s+[0-8].*$'; //Checks if this exists in daftAcl: if (preg_grep("/{$acl_pattern}/", $daftAcl)) { if (preg_grep("/{$acl_pattern_nocomment}/", $acl_config)) { return true; } else { $existInDaft = true; } } elseif (preg_grep("/{$acl_pattern_nocomment}/", $acl_config)) { $existInAcl = true; } if (!$existInDaft) { $daftAcl[] = "{$acl_scope}\t{$acl_user}\t{$acl_level}{$additional}\n"; //Adds acl-info to daftAcl io_saveFile(dirname(__FILE__) . '/daft.auth.php', join('', $daftAcl)); } if (!$existInAcl) { $acl_config[] = "{$acl_scope}\t{$acl_user}\t{$acl_level}{$additional}\n"; //Adds acl-info to acl_config $AUTH_ACL = $acl_config; io_saveFile(DOKU_CONF . 'acl.auth.php', join('', $acl_config)); } return true; //The function does not check if the files were actually saved. }
/** * Returns the maximum rights a user has for * the given ID or its namespace * * @author Andreas Gohr <*****@*****.**> * * @param string $id page ID (needs to be resolved and cleaned) * @param string $user Username * @param array|null $groups Array of groups the user is in * @return int permission level */ function auth_aclcheck($id, $user, $groups) { global $conf; global $AUTH_ACL; /* @var auth_basic $auth */ global $auth; // for PART-DB return !$conf['useacl'] && file_exists(DOKU_INC . '../../data/ENABLE-DOKUWIKI-WRITE-PERMS.txt') ? AUTH_ADMIN : AUTH_READ; // if no ACL is used always return upload rights if (!$conf['useacl']) { return AUTH_UPLOAD; } if (!$auth) { return AUTH_NONE; } //make sure groups is an array if (!is_array($groups)) { $groups = array(); } //if user is superuser or in superusergroup return 255 (acl_admin) if (auth_isadmin($user, $groups)) { return AUTH_ADMIN; } $ci = ''; if (!$auth->isCaseSensitive()) { $ci = 'ui'; } $user = $auth->cleanUser($user); $groups = array_map(array($auth, 'cleanGroup'), (array) $groups); $user = auth_nameencode($user); //prepend groups with @ and nameencode $cnt = count($groups); for ($i = 0; $i < $cnt; $i++) { $groups[$i] = '@' . auth_nameencode($groups[$i]); } $ns = getNS($id); $perm = -1; if ($user || count($groups)) { //add ALL group $groups[] = '@ALL'; //add User if ($user) { $groups[] = $user; } } else { $groups[] = '@ALL'; } //check exact match first $matches = preg_grep('/^' . preg_quote($id, '/') . '\\s+(\\S+)\\s+/' . $ci, $AUTH_ACL); if (count($matches)) { foreach ($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/\\s+/', $match); if (!in_array($acl[1], $groups)) { continue; } if ($acl[2] > AUTH_DELETE) { $acl[2] = AUTH_DELETE; } //no admins in the ACL! if ($acl[2] > $perm) { $perm = $acl[2]; } } if ($perm > -1) { //we had a match - return it return $perm; } } //still here? do the namespace checks if ($ns) { $path = $ns . ':*'; } else { $path = '*'; //root document } do { $matches = preg_grep('/^' . preg_quote($path, '/') . '\\s+(\\S+)\\s+/' . $ci, $AUTH_ACL); if (count($matches)) { foreach ($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/\\s+/', $match); if (!in_array($acl[1], $groups)) { continue; } if ($acl[2] > AUTH_DELETE) { $acl[2] = AUTH_DELETE; } //no admins in the ACL! if ($acl[2] > $perm) { $perm = $acl[2]; } } //we had a match - return it if ($perm != -1) { return $perm; } } //get next higher namespace $ns = getNS($ns); if ($path != '*') { $path = $ns . ':*'; if ($path == ':*') { $path = '*'; } } else { //we did this already //looks like there is something wrong with the ACL //break here msg('No ACL setup yet! Denying access to everyone.'); return AUTH_NONE; } } while (1); //this should never loop endless return AUTH_NONE; }
/** * Adds a new subscription for the given page or namespace * * This will automatically overwrite any existent subscription for the given user on this * *exact* page or namespace. It will *not* modify any subscription that may exist in higher namespaces. * * @param string $id The target page or namespace, specified by id; Namespaces * are identified by appending a colon. * @param string $user * @param string $style * @param string $data * @throws Exception when user or style is empty * @return bool */ public function add($id, $user, $style, $data = '') { if (!$this->isenabled()) { return false; } // delete any existing subscription $this->remove($id, $user); $user = auth_nameencode(trim($user)); $style = trim($style); $data = trim($data); if (!$user) { throw new Exception('no subscription user given'); } if (!$style) { throw new Exception('no subscription style given'); } if (!$data) { $data = time(); } //always add current time for new subscriptions $line = "{$user} {$style} {$data}\n"; $file = $this->file($id); return io_saveFile($file, $line, true); }
/** * remove acl-entry from conf/acl.auth.php * * @author Frank Schubert <*****@*****.**> */ function _acl_del($acl_scope, $acl_user) { global $config_cascade; $acl_config = file($config_cascade['acl']['default']); $acl_user = auth_nameencode($acl_user, true); $acl_pattern = '^' . preg_quote($acl_scope, '/') . '\\s+' . $acl_user . '\\s+[0-8].*$'; // save all non!-matching $new_config = preg_grep("/{$acl_pattern}/", $acl_config, PREG_GREP_INVERT); return io_saveFile($config_cascade['acl']['default'], join('', $new_config)); }
/** * default ACL check method * * DO NOT CALL DIRECTLY, use auth_aclcheck() instead * * @author Andreas Gohr <*****@*****.**> * @param array $data event data * @return int permission level */ function auth_aclcheck_cb($data) { $id =& $data['id']; $user =& $data['user']; $groups =& $data['groups']; global $conf; global $AUTH_ACL; /* @var DokuWiki_Auth_Plugin $auth */ global $auth; // if no ACL is used always return upload rights if (!$conf['useacl']) { return AUTH_UPLOAD; } if (!$auth) { return AUTH_NONE; } //make sure groups is an array if (!is_array($groups)) { $groups = array(); } //if user is superuser or in superusergroup return 255 (acl_admin) if (auth_isadmin($user, $groups)) { return AUTH_ADMIN; } if (!$auth->isCaseSensitive()) { $user = utf8_strtolower($user); $groups = array_map('utf8_strtolower', $groups); } $user = $auth->cleanUser($user); $groups = array_map(array($auth, 'cleanGroup'), (array) $groups); $user = auth_nameencode($user); //prepend groups with @ and nameencode $cnt = count($groups); for ($i = 0; $i < $cnt; $i++) { $groups[$i] = '@' . auth_nameencode($groups[$i]); } $ns = getNS($id); $perm = -1; if ($user || count($groups)) { //add ALL group $groups[] = '@ALL'; //add User if ($user) { $groups[] = $user; } } else { $groups[] = '@ALL'; } //check exact match first $matches = preg_grep('/^' . preg_quote($id, '/') . '[ \\t]+([^ \\t]+)[ \\t]+/', $AUTH_ACL); if (count($matches)) { foreach ($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/[ \\t]+/', $match); if (!$auth->isCaseSensitive() && $acl[1] !== '@ALL') { $acl[1] = utf8_strtolower($acl[1]); } if (!in_array($acl[1], $groups)) { continue; } if ($acl[2] > AUTH_DELETE) { $acl[2] = AUTH_DELETE; } //no admins in the ACL! if ($acl[2] > $perm) { $perm = $acl[2]; } } if ($perm > -1) { //we had a match - return it return (int) $perm; } } //still here? do the namespace checks if ($ns) { $path = $ns . ':*'; } else { $path = '*'; //root document } do { $matches = preg_grep('/^' . preg_quote($path, '/') . '[ \\t]+([^ \\t]+)[ \\t]+/', $AUTH_ACL); if (count($matches)) { foreach ($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/[ \\t]+/', $match); if (!$auth->isCaseSensitive() && $acl[1] !== '@ALL') { $acl[1] = utf8_strtolower($acl[1]); } if (!in_array($acl[1], $groups)) { continue; } if ($acl[2] > AUTH_DELETE) { $acl[2] = AUTH_DELETE; } //no admins in the ACL! if ($acl[2] > $perm) { $perm = $acl[2]; } } //we had a match - return it if ($perm != -1) { return (int) $perm; } } //get next higher namespace $ns = getNS($ns); if ($path != '*') { $path = $ns . ':*'; if ($path == ':*') { $path = '*'; } } else { //we did this already //looks like there is something wrong with the ACL //break here msg('No ACL setup yet! Denying access to everyone.'); return AUTH_NONE; } } while (1); //this should never loop endless return AUTH_NONE; }
/** * Set subscription information * * Allows to set subscription information for permanent storage in meta files. * Subscriptions consist of a target object, a subscribing user, a subscribe * style and optional data. * A subscription may be deleted by specifying an empty subscribe style. * Only one subscription per target and user is allowed. * The function returns false on error, otherwise true. Note that no error is * returned if a subscription should be deleted but the user is not subscribed * and the subscription meta file exists. * * @param string $user The subscriber or unsubscriber * @param string $page The target object (page or namespace), specified by * id; Namespaces are identified by a trailing colon. * @param string $style The subscribe style; DokuWiki currently implements * “every”, “digest”, and “list”. * @param string $data An optional data blob * @param bool $overwrite Whether an existing subscription may be overwritten * * @author Adrian Lang <*****@*****.**> */ function subscription_set($user, $page, $style, $data = null, $overwrite = false) { global $lang; if (is_null($style)) { // Delete subscription. $file = subscription_filename($page); if (!@file_exists($file)) { msg(sprintf($lang['subscr_not_subscribed'], $user, prettyprint_id($page)), -1); return false; } // io_deleteFromFile does not return false if no line matched. return io_deleteFromFile($file, subscription_regex(array('user' => auth_nameencode($user))), true); } // Delete subscription if one exists and $overwrite is true. If $overwrite // is false, fail. $subs = subscription_find($page, array('user' => $user)); if (count($subs) > 0 && array_pop(array_keys($subs)) === $page) { if (!$overwrite) { msg(sprintf($lang['subscr_already_subscribed'], $user, prettyprint_id($page)), -1); return false; } // Fail if deletion failed, else continue. if (!subscription_set($user, $page, null)) { return false; } } $file = subscription_filename($page); $content = auth_nameencode($user) . ' ' . $style; if (!is_null($data)) { $content .= ' ' . $data; } return io_saveFile($file, $content . "\n", true); }
/** * Show a banner when viewing pages that are not published. * * @author Jon Magne Bøe <*****@*****.**> */ function show_banner(&$event, $param) { global $AUTH_ACL, $ID, $INFO; $autorizationList = $AUTH_ACL; $pageIdentification = $ID; $allUsers = auth_nameencode('@ALL', true); //all users $additional = 'DAFTDRAFTS'; $autorizationList = $AUTH_ACL; if (empty($authorizationList)) { $authorizationList = file(DOKU_CONF . 'acl.auth.php'); } $daftAuthorizationList = file(dirname(__FILE__) . '/daft.auth.php'); $additional = '\\t#' . $additional; $acl_pattern_nocomment = '^' . preg_quote($pageIdentification, '/') . '\\s+.*\\s+[0-8].*$'; //pattern for searching acl.auth.php $authorizationHits = preg_grep("/{$acl_pattern_nocomment}/", $authorizationList); $numberOfAuthorizations = count($authorizationHits); $daftHits = preg_grep("/{$acl_pattern_nocomment}/", $daftAuthorizationList); $numberOfDaftauthorizations = count($daftHits); //If both acl.auth.php and daft.auth.php contains restrictions of authorization, it's safe to assume it's not published. if ($numberOfAuthorizations != 0 && $numberOfDaftauthorizations != 0) { $published = false; } else { //Ideally the acl.auth.php and the daft.auth.php-files should be in sync, meaning we don't need to check anything else. $published = true; } $htmlcode = array(); //This code runs if the page is unpublished, i.e. tagged as a draft and hidden from unregistered users. if (!$published && isset($INFO['userinfo'])) { $htmlcode[] = '<div class="unpublished">'; $htmlcode[] = '<span class="draft">'; $htmlcode[] = $this->getLang('unpublished'); $htmlcode[] = '<br>'; $htmlcode[] = $this->getLang('howtopublish') . ' ~~' . $this->getLang('code') . '~~'; $htmlcode[] = '</span>'; $htmlcode[] = '</div>'; ptln(implode($htmlcode)); return true; } else { return; } }
/** * remove acl-entry from conf/acl.auth.php * * @author Frank Schubert <*****@*****.**> */ function _acl_del($acl_scope, $acl_user) { $acl_config = file(DOKU_CONF . 'acl.auth.php'); $acl_user = auth_nameencode($acl_user, true); $acl_pattern = '^' . preg_quote($acl_scope, '/') . '\\s+' . $acl_user . '\\s+[0-8].*$'; // save all non!-matching $new_config = preg_grep("/{$acl_pattern}/", $acl_config, PREG_GREP_INVERT); return io_saveFile(DOKU_CONF . 'acl.auth.php', join('', $new_config)); }
function handle_magicacl2(&$event, $param) { $debug = true; global $ID; global $AUTH_ACL; global $INFO; global $USERINFO; $dodebug = false; if ($debug && $_GET['doit']) { $dodebug = true; } //print "DEBUG: ". $_SERVER['REMOTE_ADDR']; // if($_SERVER['REMOTE_ADDR'] == '134.84.199.3') { // $dodebug = true; // } $ns = $event->data['ns']; if ($dodebug) { print "<pre>\n\n"; print "physmagicACL pluggin hook running. ns={$ns}\n"; } $areas = $this->getConf('areas'); if (!count($areas)) { return; } foreach ($areas as $magicns => $area) { //$magicns = $area['ns_base']; $level = $area['level']; $cust_acl = $area['acl']; //$perm = $area['perm_level']; //$groupbase = $area['group_base']; if ($dodebug) { print "Looking at physmagicacl config area:{$magicns}\n"; } if (!$cust_acl || !$level) { if ($dodebug) { print "DEBUG: bailing because no cust_acl or no level\n"; } continue; } $namespaces = array(); // continue only if $magicns area is a substring of $ns and theres no weird chars in $ns if (preg_match("/^{$magicns}/", $ns) && count(preg_grep('/^[*:\\-\\.\\w]*$/', array($ns)))) { // Check for any groups that match the namespace $groups = $USERINFO['grps']; foreach ($groups as $group) { $area_slice = explode('_', $group, $level); if (count($area_slice) == $level && $area_slice[0] == $magicns) { $namespace['ns'] = implode(':', $area_slice); $namespace['group'] = $group; if ($dodebug) { print "Adding ns " . $namespace['ns'] . " and group {$group}\n"; } $namespaces[] = $namespace; } } // Take the current ns, explode it to the specified level // and implode it back to get the namespace and group for ACL $magicns = array_slice(explode(':', $ns), 0, $level); if ($dodebug) { foreach ($magicns as $test) { if ($test == '*') { print "Yep, {$ns} has a * in it\n"; } } } $rootns = implode(':', $magicns); $group = ($groupbase ? $groupbase : '') . implode('_', $magicns); // Update ACL if ($cust_acl) { foreach ($cust_acl as $entry) { if (!empty($entry)) { $entryarr = preg_split('/\\s+/', $entry); if ($dodebug) { //print "entryarr: "; //print_r($entryarr); } if (count($entryarr) >= 3) { $AUTH_ACL[] = $rootns . $entryarr[0] . ' ' . auth_nameencode(str_replace('%GROUP%', $group, $entryarr[1]), true) . ' ' . $entryarr[2]; foreach ($namespaces as $aclns) { $AUTH_ACL[] = $aclns['ns'] . $entryarr[0] . ' ' . auth_nameencode(str_replace('%GROUP%', $aclns['group'], $entryarr[1]), true) . ' ' . $entryarr[2]; } } } } } // If this isn't the mediamanager, we may need to update page permisions } else { if ($dodebug) { print "Skipped area because its not in ns: {$ns} or ns is invalid\n"; } } } if ($dodebug) { print '</pre><br>'; } }
/** * Loads the ACL setup and handle user wildcards * * @author Andreas Gohr <*****@*****.**> * @returns array */ function auth_loadACL($acl_file) { global $config_cascade; $acl = $acl_file; $sess_id = session_id(); if (!isset($sess_id) || $sess_id != $_COOKIE['FCK_NmSp_acl']) { session_id($_COOKIE['FCK_NmSp_acl']); session_start(); if (isset($_SESSION['dwfck_client'])) { $_SERVER['REMOTE_USER'] = $_SESSION['dwfck_client']; } } else { if (isset($_SESSION['dwfck_client'])) { $_SERVER['REMOTE_USER'] = $_SESSION['dwfck_client']; } } //support user wildcard if (isset($_SERVER['REMOTE_USER'])) { $len = count($acl); for ($i = 0; $i < $len; $i++) { if ($acl[$i][0] == '#') { continue; } list($id, $rest) = preg_split('/\\s+/', $acl[$i], 2); $id = str_replace('%USER%', cleanID($_SERVER['REMOTE_USER']), $id); $rest = str_replace('%USER%', auth_nameencode($_SERVER['REMOTE_USER']), $rest); $acl[$i] = "{$id}\t{$rest}"; } } else { $acl = str_replace('%USER%', $user, $acl); // fall-back, in case client not found } return $acl; }
function test_groupskipoff() { $in = '@hey$you'; $out = '%40hey%24you'; $this->assertEqual(auth_nameencode($in), $out); }
function test_devanagiri() { $in = 'ut-fठ8'; $expect = 'ut%2dfठ8'; $this->assertEquals($expect, auth_nameencode($in)); }
/** * remove acl-entry from conf/acl.auth.php * * @author Frank Schubert <*****@*****.**> */ function _acl_del($acl_scope, $acl_user) { global $config_cascade; $acl_user = auth_nameencode($acl_user, true); $acl_pattern = '^' . preg_quote($acl_scope, '/') . '[ \\t]+' . $acl_user . '[ \\t]+[0-8].*$'; return io_deleteFromFile($config_cascade['acl']['default'], "/{$acl_pattern}/", true); }
/** * adds new acl-entry to conf/acl.auth.php * * @author Frank Schubert <*****@*****.**> */ function _acl_add($acl_scope, $acl_user) { $acl_config = loadModlist(); $acl_user = auth_nameencode($acl_user, true); $new_acl = "{$acl_scope}\t{$acl_user}\n"; $acl_config[] = $new_acl; return io_saveFile(DOKUTRANSLATE_MODLIST, join('', $acl_config)); }
/** * remove acl-entry from conf/acl.auth.php * * @author Frank Schubert <*****@*****.**> */ function _acl_del($acl_scope, $acl_user) { $acl_config = $this->load_acl_config(false); $acl_user = auth_nameencode($acl_user, true); $acl_pattern = '^' . preg_quote($acl_scope, '/') . '\\s+' . $acl_user . '\\s+[0-8].*$'; // save all non!-matching $new_config = preg_grep("/{$acl_pattern}/", $acl_config, PREG_GREP_INVERT); return $this->save_acl_config(join("\n", $new_config) . "\n"); }
/** * Returns the maximum rights a user has for * the given ID or its namespace * * @author Andreas Gohr <*****@*****.**> * * @param string $id page ID * @param string $user Username * @param array $groups Array of groups the user is in * @return int permission level */ function auth_aclcheck($id, $user, $groups) { global $conf; global $AUTH_ACL; // if no ACL is used always return upload rights if (!$conf['useacl']) { return AUTH_UPLOAD; } //make sure groups is an array if (!is_array($groups)) { $groups = array(); } //if user is superuser or in superusergroup return 255 (acl_admin) if (auth_isadmin($user, $groups)) { return AUTH_ADMIN; } $user = auth_nameencode($user); //prepend groups with @ and nameencode $cnt = count($groups); for ($i = 0; $i < $cnt; $i++) { $groups[$i] = '@' . auth_nameencode($groups[$i]); } $ns = getNS($id); $perm = -1; if ($user || count($groups)) { //add ALL group $groups[] = '@ALL'; //add User if ($user) { $groups[] = $user; } //build regexp $regexp = join('|', $groups); } else { $regexp = '@ALL'; } //check exact match first $matches = preg_grep('/^' . preg_quote($id, '/') . '\\s+(' . $regexp . ')\\s+/', $AUTH_ACL); if (count($matches)) { foreach ($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/\\s+/', $match); if ($acl[2] > AUTH_DELETE) { $acl[2] = AUTH_DELETE; } //no admins in the ACL! if ($acl[2] > $perm) { $perm = $acl[2]; } } if ($perm > -1) { //we had a match - return it return $perm; } } //still here? do the namespace checks if ($ns) { $path = $ns . ':\\*'; } else { $path = '\\*'; //root document } do { $matches = preg_grep('/^' . $path . '\\s+(' . $regexp . ')\\s+/', $AUTH_ACL); if (count($matches)) { foreach ($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/\\s+/', $match); if ($acl[2] > AUTH_DELETE) { $acl[2] = AUTH_DELETE; } //no admins in the ACL! if ($acl[2] > $perm) { $perm = $acl[2]; } } //we had a match - return it return $perm; } //get next higher namespace $ns = getNS($ns); if ($path != '\\*') { $path = $ns . ':\\*'; if ($path == ':\\*') { $path = '\\*'; } } else { //we did this already //looks like there is something wrong with the ACL //break here msg('No ACL setup yet! Denying access to everyone.'); return AUTH_NONE; } } while (1); //this should never loop endless //still here? return no permissions return AUTH_NONE; }