2 rcs_id('$Id: PagePerm.php,v 1.37 2004-11-23 13:06:30 rurban Exp $');
4 Copyright 2004 $ThePhpWikiProgrammingTeam
6 This file is part of PhpWiki.
8 PhpWiki is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 PhpWiki is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with PhpWiki; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 Permissions per page and action based on current user,
25 ownership and group membership implemented with ACL's (Access Control Lists),
26 opposed to the simplier unix like ugo:rwx system.
27 The previous system was only based on action and current user. (lib/main.php)
29 Permissions may be inherited from its parent pages, a optional the
30 optional master page ("."), and predefined default permissions, if "."
32 Pagenames starting with "." have special default permissions.
33 For Authentication see WikiUserNew.php, WikiGroup.php and main.php
34 Page Permissions are in PhpWiki since v1.3.9 and enabled since v1.4.0
36 This file might replace the following functions from main.php:
37 Request::_notAuthorized($require_level)
38 display the denied message and optionally a login form
39 to gain higher privileges
40 Request::getActionDescription($action)
41 helper to localize the _notAuthorized message per action,
43 Request::getDisallowedActionDescription($action)
44 helper to localize the _notAuthorized message per action,
46 Request::requiredAuthority($action)
47 returns the needed user level
48 has a hook for plugins on POST
49 Request::requiredAuthorityForAction($action)
50 just returns the level per action, will be replaced with the
53 The defined main.php actions map to simplier access types:
56 create => edit or create
60 list in PageList => list
63 /* Symbolic special ACL groups. Untranslated to be stored in page metadata*/
64 define('ACL_EVERY', '_EVERY');
65 define('ACL_ANONYMOUS', '_ANONYMOUS');
66 define('ACL_BOGOUSER', '_BOGOUSER');
67 define('ACL_HASHOMEPAGE', '_HASHOMEPAGE');
68 define('ACL_SIGNED', '_SIGNED');
69 define('ACL_AUTHENTICATED','_AUTHENTICATED');
70 define('ACL_ADMIN', '_ADMIN');
71 define('ACL_OWNER', '_OWNER');
72 define('ACL_CREATOR', '_CREATOR');
74 // Return an page permissions array for this page.
75 // To provide ui helpers to view and change page permissions:
76 // <tr><th>Group</th><th>Access</th><th>Allow or Forbid</th></tr>
77 // <tr><td>$group</td><td>_($access)</td><td> [ ] </td></tr>
78 function pagePermissions($pagename) {
80 $page = $request->getPage($pagename);
81 // Page not found (new page); returned inherited permissions, to be displayed in gray
82 if (! $page->exists() ) {
83 if ($pagename == '.') // stop recursion
84 return array('default', new PagePermission());
86 return array('inherited', pagePermissions(getParentPage($pagename)));
88 } elseif ($perm = getPagePermissions($page)) {
89 return array('page',$perm);
90 // or no permissions defined; returned inherited permissions, to be displayed in gray
91 } elseif ($pagename == '.') { // stop recursion in pathological case.
92 // "." defined, without any acl
93 return array('default', new PagePermission());
95 return array('inherited', pagePermissions(getParentPage($pagename)));
99 function pagePermissionsSimpleFormat($perm_tree, $owner, $group=false) {
100 list($type,$perm) = pagePermissionsAcl($perm_tree[0], $perm_tree);
102 $type = $perm_tree[0];
103 $perm = pagePermissionsAcl($perm_tree);
104 if (is_object($perm_tree[1]))
105 $perm = $perm_tree[1];
106 elseif (is_array($perm_tree[1])) {
107 $perm_tree = pagePermissionsSimpleFormat($perm_tree[1],$owner,$group);
108 if (isa($perm_tree[1],'pagepermission'))
109 $perm = $perm_tree[1];
110 elseif (isa($perm_tree,'htmlelement'))
115 return HTML::tt(HTML::strong($perm->asRwxString($owner, $group)));
116 elseif ($type == 'default')
117 return HTML::tt($perm->asRwxString($owner, $group));
118 elseif ($type == 'inherited') {
119 return HTML::tt(array('class'=>'inherited', 'style'=>'color:#aaa;'),
120 $perm->asRwxString($owner, $group));
124 function pagePermissionsAcl($type,$perm_tree) {
125 $perm = $perm_tree[1];
126 while (!is_object($perm)) {
127 $perm_tree = pagePermissionsAcl($type, $perm);
128 $perm = $perm_tree[1];
130 return array($type,$perm);
135 function pagePermissionsAclFormat($perm_tree, $editable=false) {
136 list($type,$perm) = pagePermissionsAcl($perm_tree[0], $perm_tree);
138 return $perm->asEditableTable($type);
140 return $perm->asTable($type);
144 * Check the permissions for the current action.
145 * Walk down the inheritance tree. Collect all permissions until
146 * the minimum required level is gained, which is not
147 * overruled by more specific forbid rules.
148 * Todo: cache result per access and page in session?
150 function requiredAuthorityForPage ($action) {
152 $auth = _requiredAuthorityForPagename(action2access($action),
153 $request->getArg('pagename'));
154 assert($auth !== -1);
156 return $request->_user->_level;
158 return WIKIAUTH_UNOBTAINABLE;
161 // Translate action or plugin to the simplier access types:
162 function action2access ($action) {
182 $page = $request->getPage();
183 if (!$page->exists())
190 // probably create/edit but we cannot check all page permissions, can we?
200 //Todo: Plugins should be able to override its access type
201 if (isWikiWord($action))
209 // Recursive helper to do the real work
210 // TODO: check if a perm cache for page-(current+edit+change?)action pairs will help
211 function _requiredAuthorityForPagename($access, $pagename) {
212 static $permcache = array();
214 if (array_key_exists($pagename, $permcache)
215 and array_key_exists($access, $permcache[$pagename]))
216 return $permcache[$pagename][$access];
219 $page = $request->getPage($pagename);
220 // Page not found; check against default permissions
221 if (! $page->exists() ) {
222 $perm = new PagePermission();
223 $result = ($perm->isAuthorized($access, $request->_user) === true);
224 $permcache[$pagename][$access] = $result;
227 // no ACL defined; check for special dotfile or walk down
228 if (! ($perm = getPagePermissions($page))) {
229 if ($pagename == '.') {
230 $perm = new PagePermission();
231 if ($perm->isAuthorized('change', $request->_user)) {
232 // warn the user to set ACL of ".", if he has permissions to do so.
233 trigger_error(". (dotpage == rootpage for inheriting pageperm ACLs) exists without any ACL!\n".
234 "Please do ?action=setacl&pagename=.", E_USER_WARNING);
236 $result = ($perm->isAuthorized($access, $request->_user) === true);
237 $permcache[$pagename][$access] = $result;
239 } elseif ($pagename[0] == '.') {
240 $perm = new PagePermission(PagePermission::dotPerms());
241 $result = ($perm->isAuthorized($access, $request->_user) === true);
242 $permcache[$pagename][$access] = $result;
245 return _requiredAuthorityForPagename($access, getParentPage($pagename));
247 // ACL defined; check if isAuthorized returns true or false or undecided
248 $authorized = $perm->isAuthorized($access, $request->_user);
249 if ($authorized !== -1) { // interestingly true is also -1
250 $permcache[$pagename][$access] = $authorized;
252 } elseif ($pagename == '.') {
255 return _requiredAuthorityForPagename($access, getParentPage($pagename));
260 * @param string $pagename page from which the parent page is searched.
261 * @return string parent pagename or the (possibly pseudo) dot-pagename.
263 function getParentPage($pagename) {
264 if (isSubPage($pagename)) {
265 return subPageSlice($pagename,0);
271 // Read the ACL from the page
272 // Done: Not existing pages should NOT be queried.
273 // Check the parent page instead and don't take the default ACL's
274 function getPagePermissions ($page) {
275 if ($hash = $page->get('perm')) // hash => object
276 return new PagePermission(unserialize($hash));
281 // Store the ACL in the page
282 function setPagePermissions ($page,$perm) {
286 function getAccessDescription($access) {
287 static $accessDescriptions;
288 if (! $accessDescriptions) {
289 $accessDescriptions = array(
290 'list' => _("List this page and all subpages"),
291 'view' => _("View this page and all subpages"),
292 'edit' => _("Edit this page and all subpages"),
293 'create' => _("Create a new (sub)page"),
294 'dump' => _("Download the page contents"),
295 'change' => _("Change page attributes"),
296 'remove' => _("Remove this page"),
299 if (in_array($access, array_keys($accessDescriptions)))
300 return $accessDescriptions[$access];
306 function array_diff_assoc_recursive($array1, $array2) {
307 foreach ($array1 as $key => $value) {
308 if (is_array($value)) {
309 if (!is_array($array2[$key])) {
310 $difference[$key] = $value;
312 $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
313 if ($new_diff != false) {
314 $difference[$key] = $new_diff;
317 } elseif(!isset($array2[$key]) || $array2[$key] != $value) {
318 $difference[$key] = $value;
321 return !isset($difference) ? 0 : $difference;
325 * The ACL object per page. It is stored in a page, but can also
326 * be merged with ACL's from other pages or taken from the master (pseudo) dot-file.
328 * A hash of "access" => "requires" pairs.
329 * "access" is a shortcut for common actions, which map to main.php actions
330 * "requires" required username or groupname or any special group => true or false
332 * Define any special rules here, like don't list dot-pages.
334 class PagePermission {
337 function PagePermission($hash = array()) {
338 $this->_group = &$GLOBALS['request']->getGroup();
339 if (is_array($hash) and !empty($hash)) {
340 $accessTypes = $this->accessTypes();
341 foreach ($hash as $access => $requires) {
342 if (in_array($access, $accessTypes))
343 $this->perm[$access] = $requires;
345 trigger_error(sprintf(_("Unsupported ACL access type %s ignored."), $access),
349 // set default permissions, the so called dot-file acl's
350 $this->perm = $this->defaultPerms();
356 * The workhorse to check the user against the current ACL pairs.
357 * Must translate the various special groups to the actual users settings
358 * (userid, group membership).
360 function isAuthorized($access,$user) {
361 if (!empty($this->perm{$access})) {
362 foreach ($this->perm[$access] as $group => $bool) {
363 if ($this->isMember($user,$group)) {
368 return -1; // undecided
372 * Translate the various special groups to the actual users settings
373 * (userid, group membership).
375 function isMember($user, $group) {
377 if ($group === ACL_EVERY) return true;
378 if (!isset($this->_group)) $member =& $request->getGroup();
379 else $member =& $this->_group;
380 //$user = & $request->_user;
381 if ($group === ACL_ADMIN) // WIKI_ADMIN or member of _("Administrators")
382 return $user->isAdmin() or
383 ($user->isAuthenticated() and
384 $member->isMember(GROUP_ADMIN));
385 if ($group === ACL_ANONYMOUS)
386 return ! $user->isSignedIn();
387 if ($group === ACL_BOGOUSER)
389 return isa($user,'_BogoUser') or
390 (isWikiWord($user->_userid) and $user->_level >= WIKIAUTH_BOGO);
391 else return isWikiWord($user->UserName());
392 if ($group === ACL_HASHOMEPAGE)
393 return $user->hasHomePage();
394 if ($group === ACL_SIGNED)
395 return $user->isSignedIn();
396 if ($group === ACL_AUTHENTICATED)
397 return $user->isAuthenticated();
398 if ($group === ACL_OWNER) {
399 if (!$user->isAuthenticated()) return false;
400 $page = $request->getPage();
401 $owner = $page->getOwner();
402 return ($owner === $user->UserName()
403 or $member->isMember($owner));
405 if ($group === ACL_CREATOR) {
406 if (!$user->isAuthenticated()) return false;
407 $page = $request->getPage();
408 $creator = $page->getCreator();
409 return ($creator === $user->UserName()
410 or $member->isMember($creator));
412 /* Or named groups or usernames.
413 Note: We don't seperate groups and users here.
414 Users overrides groups with the same name.
416 return $user->UserName() === $group or
417 $member->isMember($group);
421 * returns hash of default permissions.
422 * check if the page '.' exists and returns this instead.
424 function defaultPerms() {
425 //Todo: check for the existance of '.' and take this instead.
426 //Todo: honor more config.ini auth settings here
427 $perm = array('view' => array(ACL_EVERY => true),
428 'edit' => array(ACL_EVERY => true),
429 'create' => array(ACL_EVERY => true),
430 'list' => array(ACL_EVERY => true),
431 'remove' => array(ACL_ADMIN => true,
433 'change' => array(ACL_ADMIN => true,
436 $perm['dump'] = array(ACL_ADMIN => true,
439 $perm['dump'] = array(ACL_EVERY => true);
440 if (defined('REQUIRE_SIGNIN_BEFORE_EDIT') && REQUIRE_SIGNIN_BEFORE_EDIT)
441 $perm['edit'] = array(ACL_SIGNED => true);
443 if (!ALLOW_ANON_USER) {
444 if (!ALLOW_USER_PASSWORDS)
445 $perm['view'] = array(ACL_SIGNED => true);
447 $perm['view'] = array(ACL_AUTHENTICATED => true);
448 $perm['view'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
451 if (!ALLOW_ANON_EDIT) {
452 if (!ALLOW_USER_PASSWORDS)
453 $perm['edit'] = array(ACL_SIGNED => true);
455 $perm['edit'] = array(ACL_AUTHENTICATED => true);
456 $perm['edit'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
457 $perm['create'] = $perm['edit'];
463 * FIXME: check valid groups and access
466 foreach ($this->perm as $access => $groups) {
467 foreach ($groups as $group => $bool) {
468 $this->perm[$access][$group] = (boolean) $bool;
474 * do a recursive comparison
476 function equal($otherperm) {
477 $diff = array_diff_assoc_recursive($this->perm, $otherperm);
482 * returns list of all supported access types.
484 function accessTypes() {
485 return array_keys(PagePermission::defaultPerms());
489 * special permissions for dot-files, beginning with '.'
490 * maybe also for '_' files?
492 function dotPerms() {
493 $def = array(ACL_ADMIN => true,
496 foreach (PagePermission::accessTypes() as $access) {
497 $perm[$access] = $def;
503 * dead code. not needed inside the object. see getPagePermissions($page)
505 function retrieve($page) {
506 $hash = $page->get('perm');
507 if ($hash) // hash => object
508 $perm = new PagePermission(unserialize($hash));
510 $perm = new PagePermission();
515 function store($page) {
518 return $page->set('perm',serialize($this->perm));
521 function groupName ($group) {
522 if ($group[0] == '_') return constant("GROUP".$group);
526 /* type: page, default, inherited */
527 function asTable($type) {
528 $table = HTML::table();
529 foreach ($this->perm as $access => $perms) {
530 $td = HTML::table(array('class' => 'cal','valign' => 'top'));
531 foreach ($perms as $group => $bool) {
532 $td->pushContent(HTML::tr(HTML::td(array('align'=>'right'),$group),
533 HTML::td($bool ? '[X]' : '[ ]')));
535 $table->pushContent(HTML::tr(array('valign' => 'top'),
536 HTML::td($access),HTML::td($td)));
538 if ($type == 'default')
539 $table->setAttr('style','border: dotted thin black; background-color:#eee;');
540 elseif ($type == 'inherited')
541 $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
542 elseif ($type == 'page')
543 $table->setAttr('style','border: solid thin black; font-weight: bold;');
547 /* type: page, default, inherited */
548 function asEditableTable($type) {
550 if (!isset($this->_group)) {
551 $this->_group =& $GLOBALS['request']->getGroup();
553 $table = HTML::table();
554 $table->pushContent(HTML::tr(
555 HTML::th(array('align' => 'left'),
557 HTML::th(array('align'=>'right'),
559 HTML::th(_("Grant")),
560 HTML::th(_("Del/+")),
561 HTML::th(_("Description"))));
563 $allGroups = $this->_group->_specialGroups();
564 foreach ($this->_group->getAllGroupsIn() as $group) {
565 if (!in_array($group,$this->_group->specialGroups()))
566 $allGroups[] = $group;
568 //array_unique(array_merge($this->_group->getAllGroupsIn(),
569 $deletesrc = $WikiTheme->_findData('images/delete.png');
570 $addsrc = $WikiTheme->_findData('images/add.png');
571 $nbsp = HTML::raw(' ');
572 foreach ($this->perm as $access => $groups) {
573 //$permlist = HTML::table(array('class' => 'cal','valign' => 'top'));
575 $newperm = HTML::input(array('type' => 'checkbox',
576 'name' => "acl[_new_perm][$access]",
578 $addbutton = HTML::input(array('type' => 'checkbox',
579 'name' => "acl[_add_group][$access]",
582 'title' => _("Add this ACL"),
584 $newgroup = HTML::select(array('name' => "acl[_new_group][$access]",
585 'style'=> 'text-align: right;',
587 foreach ($allGroups as $groupname) {
588 if (!isset($groups[$groupname]))
589 $newgroup->pushContent(HTML::option(array('value' => $groupname),
590 $this->groupName($groupname)));
592 if (empty($groups)) {
593 $addbutton->setAttr('checked','checked');
594 $newperm->setAttr('checked','checked');
596 HTML::tr(array('valign' => 'top'),
597 HTML::td(HTML::strong($access.":")),
599 HTML::td($nbsp,$newperm),
600 HTML::td($nbsp,$addbutton),
601 HTML::td(HTML::em(getAccessDescription($access)))));
603 foreach ($groups as $group => $bool) {
604 $checkbox = HTML::input(array('type' => 'checkbox',
605 'name' => "acl[$access][$group]",
606 'title' => _("Allow / Deny"),
608 if ($bool) $checkbox->setAttr('checked','checked');
609 $checkbox = HTML(HTML::input(array('type' => 'hidden',
610 'name' => "acl[$access][$group]",
613 $deletebutton = HTML::input(array('type' => 'checkbox',
614 'name' => "acl[_del_group][$access][$group]",
615 'style' => 'background: #aaa url('.$deletesrc.')',
616 //'src' => $deletesrc,
618 'title' => _("Delete this ACL"),
623 HTML::td(HTML::strong($access.":")),
624 HTML::td(array('class' => 'cal-today','align'=>'right'),
625 HTML::strong($this->groupName($group))),
626 HTML::td(array('align'=>'center'),$nbsp,$checkbox),
627 HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
628 HTML::td(HTML::em(getAccessDescription($access)))));
634 HTML::td(array('class' => 'cal-today','align'=>'right'),
635 HTML::strong($this->groupName($group))),
636 HTML::td(array('align'=>'center'),$nbsp,$checkbox),
637 HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
643 HTML::tr(array('valign' => 'top'),
644 HTML::td(array('align'=>'right'),_("add ")),
646 HTML::td(array('align'=>'center'),$nbsp,$newperm),
647 HTML::td(array('align'=>'right','style' => 'background: #ccc url('.$addsrc.') no-repeat'),$addbutton),
648 HTML::td(HTML::small(_("Check to add this Acl")))));
650 if ($type == 'default')
651 $table->setAttr('style','border: dotted thin black; background-color:#eee;');
652 elseif ($type == 'inherited')
653 $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
654 elseif ($type == 'page')
655 $table->setAttr('style','border: solid thin black; font-weight: bold;');
659 // Print ACL as lines of [+-]user[,group,...]:access[,access...]
660 // Seperate acl's by "; " or whitespace
661 // See http://opag.ca/wiki/HelpOnAccessControlLists
662 // As used by WikiAdminSetAclSimple
663 function asAclLines() {
666 foreach ($this->perm as $access => $groups) {
667 // unify groups for same access+bool
668 // view:CREATOR,-OWNER,
670 foreach ($groups as $group => $bool) {
671 $line .= ($bool?'':'-').$group.",";
673 if (substr($line,-1) == ',')
674 $s .= substr($line,0,-1)."; ";
676 if (substr($s,-2) == '; ')
677 $s = substr($s,0,-2);
682 // This is just a bad hack for testing.
683 // Simplify the ACL to a unix-like "rwx------+" string
685 function asRwxString($owner,$group=false) {
687 // simplify object => rwxrw---x+ string as in cygwin (+ denotes additional ACLs)
688 $perm =& $this->perm;
689 // get effective user and group
691 if (isset($perm['view'][$owner]) or
692 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
694 if (isset($perm['edit'][$owner]) or
695 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
697 if (isset($perm['change'][$owner]) or
698 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
700 if (!empty($group)) {
701 if (isset($perm['view'][$group]) or
702 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
704 if (isset($perm['edit'][$group]) or
705 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
707 if (isset($perm['change'][$group]) or
708 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
711 if (isset($perm['view'][ACL_EVERY]) or
712 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
714 if (isset($perm['edit'][ACL_EVERY]) or
715 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
717 if (isset($perm['change'][ACL_EVERY]) or
718 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
724 // $Log: not supported by cvs2svn $
725 // Revision 1.36 2004/11/21 11:59:16 rurban
726 // remove final \n to be ob_cache independent
728 // Revision 1.35 2004/11/15 15:56:40 rurban
729 // don't load PagePerm on ENABLE_PAGEPERM = false to save memory. Move mayAccessPage() to main.php
731 // Revision 1.34 2004/11/01 10:43:55 rurban
732 // seperate PassUser methods into seperate dir (memory usage)
733 // fix WikiUser (old) overlarge data session
734 // remove wikidb arg from various page class methods, use global ->_dbi instead
737 // Revision 1.33 2004/09/26 11:47:52 rurban
738 // fix another reecursion loop when . exists: deny if ACL not defined; implement pageperm cache
740 // Revision 1.32 2004/09/25 18:56:09 rurban
741 // avoid recursion bug on setacl for "."
743 // Revision 1.31 2004/09/25 18:34:45 rurban
744 // fix and warn on too restrictive ACL handling without ACL in existing . (dotpage)
746 // Revision 1.30 2004/09/25 16:24:02 rurban
747 // fix interesting PagePerm problem: -1 == true
749 // Revision 1.29 2004/07/03 08:04:19 rurban
750 // fixed implicit PersonalPage login (e.g. on edit), fixed to check against create ACL on create, not edit
752 // Revision 1.28 2004/06/25 14:29:17 rurban
753 // WikiGroup refactoring:
754 // global group attached to user, code for not_current user.
755 // improved helpers for special groups (avoid double invocations)
756 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
757 // fixed a XHTML validation error on userprefs.tmpl
759 // Revision 1.27 2004/06/16 10:38:58 rurban
760 // Disallow refernces in calls if the declaration is a reference
761 // ("allow_call_time_pass_reference clean").
762 // PhpWiki is now allow_call_time_pass_reference = Off clean,
763 // but several external libraries may not.
764 // In detail these libs look to be affected (not tested):
768 // Revision 1.26 2004/06/14 11:31:36 rurban
769 // renamed global $Theme to $WikiTheme (gforge nameclash)
770 // inherit PageList default options from PageList
771 // default sortby=pagename
772 // use options in PageList_Selectable (limit, sortby, ...)
773 // added action revert, with button at action=diff
774 // added option regex to WikiAdminSearchReplace
776 // Revision 1.25 2004/06/08 13:51:57 rurban
777 // some comments only
779 // Revision 1.24 2004/06/08 10:54:46 rurban
780 // better acl dump representation, read back acl and owner
782 // Revision 1.23 2004/06/08 10:05:11 rurban
783 // simplified admin action shortcuts
785 // Revision 1.22 2004/06/07 22:44:14 rurban
786 // added simplified chown, setacl actions
788 // Revision 1.21 2004/06/07 22:28:03 rurban
789 // add acl field to mimified dump
791 // Revision 1.20 2004/06/07 18:39:03 rurban
792 // support for SetAclSimple
794 // Revision 1.19 2004/06/06 17:12:28 rurban
795 // fixed PagePerm non-object problem (mayAccessPage), also bug #967150
797 // Revision 1.18 2004/05/27 17:49:05 rurban
798 // renamed DB_Session to DbSession (in CVS also)
799 // added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
800 // remove leading slash in error message
801 // added force_unlock parameter to File_Passwd (no return on stale locks)
802 // fixed adodb session AffectedRows
803 // added FileFinder helpers to unify local filenames and DATA_PATH names
804 // editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
806 // Revision 1.17 2004/05/16 23:10:44 rurban
807 // update_locale wrongly resetted LANG, which broke japanese.
808 // japanese now correctly uses EUC_JP, not utf-8.
809 // more charset and lang headers to help the browser.
811 // Revision 1.16 2004/05/16 22:32:53 rurban
814 // Revision 1.15 2004/05/16 22:07:35 rurban
815 // check more config-default and predefined constants
816 // various PagePerm fixes:
817 // fix default PagePerms, esp. edit and view for Bogo and Password users
818 // implemented Creator and Owner
819 // BOGOUSERS renamed to BOGOUSER
820 // fixed syntax errors in signin.tmpl
822 // Revision 1.14 2004/05/15 22:54:49 rurban
823 // fixed important WikiDB bug with DEBUG > 0: wrong assertion
824 // improved SetAcl (works) and PagePerms, some WikiGroup helpers.
826 // Revision 1.13 2004/05/15 19:48:33 rurban
827 // fix some too loose PagePerms for signed, but not authenticated users
828 // (admin, owner, creator)
829 // no double login page header, better login msg.
830 // moved action_pdf to lib/pdf.php
832 // Revision 1.12 2004/05/04 22:34:25 rurban
835 // Revision 1.11 2004/05/02 21:26:38 rurban
836 // limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
837 // because they will not survive db sessions, if too large.
838 // extended action=upgrade
839 // some WikiTranslation button work
840 // revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
841 // some temp. session debug statements
843 // Revision 1.10 2004/04/29 22:32:56 zorloc
844 // Slightly more elegant fix. Instead of WIKIAUTH_FORBIDDEN, the current user's level + 1 is returned on a false.
846 // Revision 1.9 2004/04/29 17:18:19 zorloc
847 // Fixes permission failure issues. With PagePermissions and Disabled Actions when user did not have permission WIKIAUTH_FORBIDDEN was returned. In WikiUser this was ok because WIKIAUTH_FORBIDDEN had a value of 11 -- thus no user could perform that action. But WikiUserNew has a WIKIAUTH_FORBIDDEN value of -1 -- thus a user without sufficent permission to do anything. The solution is a new high value permission level (WIKIAUTH_UNOBTAINABLE) to be the default level for access failure.
849 // Revision 1.8 2004/03/14 16:24:35 rurban
850 // authenti(fi)cation spelling
852 // Revision 1.7 2004/02/28 22:25:07 rurban
853 // First PagePerm implementation:
855 // $WikiTheme->setAnonEditUnknownLinks(false);
857 // Layout improvement with dangling links for mostly closed wiki's:
858 // If false, only users with edit permissions will be presented the
859 // special wikiunknown class with "?" and Tooltip.
860 // If true (default), any user will see the ?, but will be presented
861 // the PrintLoginForm on a click.
863 // Revision 1.6 2004/02/24 15:20:05 rurban
864 // fixed minor warnings: unchecked args, POST => Get urls for sortby e.g.
866 // Revision 1.5 2004/02/23 21:30:25 rurban
867 // more PagePerm stuff: (working against 1.4.0)
868 // ACL editing and simplification of ACL's to simple rwx------ string
871 // Revision 1.4 2004/02/12 13:05:36 rurban
872 // Rename functional for PearDB backend
873 // some other minor changes
874 // SiteMap comes with a not yet functional feature request: includepages (tbd)
876 // Revision 1.3 2004/02/09 03:58:12 rurban
877 // for now default DB_SESSION to false
879 // * not existing perms will now query the parent, and not
880 // return the default perm
881 // * added pagePermissions func which returns the object per page
882 // * added getAccessDescription
884 // * added global ->prepare (not yet used) with smart user/pref/member table prefixing.
885 // * force init of authdbh in the 2 db classes
887 // * fixed session handling (not triple auth request anymore)
888 // * don't store cookie prefs with sessions
889 // stdlib: global obj2hash helper from _AuthInfo, also needed for PagePerm
891 // Revision 1.2 2004/02/08 13:17:48 rurban
892 // This should be the functionality. Needs testing and some minor todos.
894 // Revision 1.1 2004/02/08 12:29:30 rurban
895 // initial version, not yet hooked into lib/main.php
903 // c-hanging-comment-ender-p: nil
904 // indent-tabs-mode: nil