2 rcs_id('$Id: PagePerm.php,v 1.39 2005-05-06 16:57:54 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) {
183 $page = $request->getPage();
184 if (!$page->exists())
191 // probably create/edit but we cannot check all page permissions, can we?
201 //Todo: Plugins should be able to override its access type
202 if (isWikiWord($action))
210 // Recursive helper to do the real work.
211 // Using a simple perm cache for page-access pairs.
212 // Maybe page-(current+edit+change?)action pairs will help
213 function _requiredAuthorityForPagename($access, $pagename) {
214 static $permcache = array();
216 if (array_key_exists($pagename, $permcache)
217 and array_key_exists($access, $permcache[$pagename]))
218 return $permcache[$pagename][$access];
221 $page = $request->getPage($pagename);
222 // Page not found; check against default permissions
223 if (! $page->exists() ) {
224 $perm = new PagePermission();
225 $result = ($perm->isAuthorized($access, $request->_user) === true);
226 $permcache[$pagename][$access] = $result;
229 // no ACL defined; check for special dotfile or walk down
230 if (! ($perm = getPagePermissions($page))) {
231 if ($pagename == '.') {
232 $perm = new PagePermission();
233 if ($perm->isAuthorized('change', $request->_user)) {
234 // warn the user to set ACL of ".", if he has permissions to do so.
235 trigger_error(". (dotpage == rootpage for inheriting pageperm ACLs) exists without any ACL!\n".
236 "Please do ?action=setacl&pagename=.", E_USER_WARNING);
238 $result = ($perm->isAuthorized($access, $request->_user) === true);
239 $permcache[$pagename][$access] = $result;
241 } elseif ($pagename[0] == '.') {
242 $perm = new PagePermission(PagePermission::dotPerms());
243 $result = ($perm->isAuthorized($access, $request->_user) === true);
244 $permcache[$pagename][$access] = $result;
247 return _requiredAuthorityForPagename($access, getParentPage($pagename));
249 // ACL defined; check if isAuthorized returns true or false or undecided
250 $authorized = $perm->isAuthorized($access, $request->_user);
251 if ($authorized !== -1) { // interestingly true is also -1
252 $permcache[$pagename][$access] = $authorized;
254 } elseif ($pagename == '.') {
257 return _requiredAuthorityForPagename($access, getParentPage($pagename));
262 * @param string $pagename page from which the parent page is searched.
263 * @return string parent pagename or the (possibly pseudo) dot-pagename.
265 function getParentPage($pagename) {
266 if (isSubPage($pagename)) {
267 return subPageSlice($pagename,0);
273 // Read the ACL from the page
274 // Done: Not existing pages should NOT be queried.
275 // Check the parent page instead and don't take the default ACL's
276 function getPagePermissions ($page) {
277 if ($hash = $page->get('perm')) // hash => object
278 return new PagePermission(unserialize($hash));
283 // Store the ACL in the page
284 function setPagePermissions ($page,$perm) {
288 function getAccessDescription($access) {
289 static $accessDescriptions;
290 if (! $accessDescriptions) {
291 $accessDescriptions = array(
292 'list' => _("List this page and all subpages"),
293 'view' => _("View this page and all subpages"),
294 'edit' => _("Edit this page and all subpages"),
295 'create' => _("Create a new (sub)page"),
296 'dump' => _("Download the page contents"),
297 'change' => _("Change page attributes"),
298 'remove' => _("Remove this page"),
301 if (in_array($access, array_keys($accessDescriptions)))
302 return $accessDescriptions[$access];
308 function array_diff_assoc_recursive($array1, $array2) {
309 foreach ($array1 as $key => $value) {
310 if (is_array($value)) {
311 if (!is_array($array2[$key])) {
312 $difference[$key] = $value;
314 $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
315 if ($new_diff != false) {
316 $difference[$key] = $new_diff;
319 } elseif(!isset($array2[$key]) || $array2[$key] != $value) {
320 $difference[$key] = $value;
323 return !isset($difference) ? 0 : $difference;
327 * The ACL object per page. It is stored in a page, but can also
328 * be merged with ACL's from other pages or taken from the master (pseudo) dot-file.
330 * A hash of "access" => "requires" pairs.
331 * "access" is a shortcut for common actions, which map to main.php actions
332 * "requires" required username or groupname or any special group => true or false
334 * Define any special rules here, like don't list dot-pages.
336 class PagePermission {
339 function PagePermission($hash = array()) {
340 $this->_group = &$GLOBALS['request']->getGroup();
341 if (is_array($hash) and !empty($hash)) {
342 $accessTypes = $this->accessTypes();
343 foreach ($hash as $access => $requires) {
344 if (in_array($access, $accessTypes))
345 $this->perm[$access] = $requires;
347 trigger_error(sprintf(_("Unsupported ACL access type %s ignored."), $access),
351 // set default permissions, the so called dot-file acl's
352 $this->perm = $this->defaultPerms();
358 * The workhorse to check the user against the current ACL pairs.
359 * Must translate the various special groups to the actual users settings
360 * (userid, group membership).
362 function isAuthorized($access,$user) {
363 if (!empty($this->perm{$access})) {
364 foreach ($this->perm[$access] as $group => $bool) {
365 if ($this->isMember($user,$group)) {
370 return -1; // undecided
374 * Translate the various special groups to the actual users settings
375 * (userid, group membership).
377 function isMember($user, $group) {
379 if ($group === ACL_EVERY) return true;
380 if (!isset($this->_group)) $member =& $request->getGroup();
381 else $member =& $this->_group;
382 //$user = & $request->_user;
383 if ($group === ACL_ADMIN) // WIKI_ADMIN or member of _("Administrators")
384 return $user->isAdmin() or
385 ($user->isAuthenticated() and
386 $member->isMember(GROUP_ADMIN));
387 if ($group === ACL_ANONYMOUS)
388 return ! $user->isSignedIn();
389 if ($group === ACL_BOGOUSER)
391 return isa($user,'_BogoUser') or
392 (isWikiWord($user->_userid) and $user->_level >= WIKIAUTH_BOGO);
393 else return isWikiWord($user->UserName());
394 if ($group === ACL_HASHOMEPAGE)
395 return $user->hasHomePage();
396 if ($group === ACL_SIGNED)
397 return $user->isSignedIn();
398 if ($group === ACL_AUTHENTICATED)
399 return $user->isAuthenticated();
400 if ($group === ACL_OWNER) {
401 if (!$user->isAuthenticated()) return false;
402 $page = $request->getPage();
403 $owner = $page->getOwner();
404 return ($owner === $user->UserName()
405 or $member->isMember($owner));
407 if ($group === ACL_CREATOR) {
408 if (!$user->isAuthenticated()) return false;
409 $page = $request->getPage();
410 $creator = $page->getCreator();
411 return ($creator === $user->UserName()
412 or $member->isMember($creator));
414 /* Or named groups or usernames.
415 Note: We don't seperate groups and users here.
416 Users overrides groups with the same name.
418 return $user->UserName() === $group or
419 $member->isMember($group);
423 * returns hash of default permissions.
424 * check if the page '.' exists and returns this instead.
426 function defaultPerms() {
427 //Todo: check for the existance of '.' and take this instead.
428 //Todo: honor more config.ini auth settings here
429 $perm = array('view' => array(ACL_EVERY => true),
430 'edit' => array(ACL_EVERY => true),
431 'create' => array(ACL_EVERY => true),
432 'list' => array(ACL_EVERY => true),
433 'remove' => array(ACL_ADMIN => true,
435 'change' => array(ACL_ADMIN => true,
438 $perm['dump'] = array(ACL_ADMIN => true,
441 $perm['dump'] = array(ACL_EVERY => true);
442 if (defined('REQUIRE_SIGNIN_BEFORE_EDIT') && REQUIRE_SIGNIN_BEFORE_EDIT)
443 $perm['edit'] = array(ACL_SIGNED => true);
445 if (!ALLOW_ANON_USER) {
446 if (!ALLOW_USER_PASSWORDS)
447 $perm['view'] = array(ACL_SIGNED => true);
449 $perm['view'] = array(ACL_AUTHENTICATED => true);
450 $perm['view'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
453 if (!ALLOW_ANON_EDIT) {
454 if (!ALLOW_USER_PASSWORDS)
455 $perm['edit'] = array(ACL_SIGNED => true);
457 $perm['edit'] = array(ACL_AUTHENTICATED => true);
458 $perm['edit'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
459 $perm['create'] = $perm['edit'];
465 * FIXME: check valid groups and access
468 foreach ($this->perm as $access => $groups) {
469 foreach ($groups as $group => $bool) {
470 $this->perm[$access][$group] = (boolean) $bool;
476 * do a recursive comparison
478 function equal($otherperm) {
479 $diff = array_diff_assoc_recursive($this->perm, $otherperm);
484 * returns list of all supported access types.
486 function accessTypes() {
487 return array_keys(PagePermission::defaultPerms());
491 * special permissions for dot-files, beginning with '.'
492 * maybe also for '_' files?
494 function dotPerms() {
495 $def = array(ACL_ADMIN => true,
498 foreach (PagePermission::accessTypes() as $access) {
499 $perm[$access] = $def;
505 * dead code. not needed inside the object. see getPagePermissions($page)
507 function retrieve($page) {
508 $hash = $page->get('perm');
509 if ($hash) // hash => object
510 $perm = new PagePermission(unserialize($hash));
512 $perm = new PagePermission();
517 function store($page) {
520 return $page->set('perm',serialize($this->perm));
523 function groupName ($group) {
524 if ($group[0] == '_') return constant("GROUP".$group);
528 /* type: page, default, inherited */
529 function asTable($type) {
530 $table = HTML::table();
531 foreach ($this->perm as $access => $perms) {
532 $td = HTML::table(array('class' => 'cal','valign' => 'top'));
533 foreach ($perms as $group => $bool) {
534 $td->pushContent(HTML::tr(HTML::td(array('align'=>'right'),$group),
535 HTML::td($bool ? '[X]' : '[ ]')));
537 $table->pushContent(HTML::tr(array('valign' => 'top'),
538 HTML::td($access),HTML::td($td)));
540 if ($type == 'default')
541 $table->setAttr('style','border: dotted thin black; background-color:#eee;');
542 elseif ($type == 'inherited')
543 $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
544 elseif ($type == 'page')
545 $table->setAttr('style','border: solid thin black; font-weight: bold;');
549 /* type: page, default, inherited */
550 function asEditableTable($type) {
552 if (!isset($this->_group)) {
553 $this->_group =& $GLOBALS['request']->getGroup();
555 $table = HTML::table();
556 $table->pushContent(HTML::tr(
557 HTML::th(array('align' => 'left'),
559 HTML::th(array('align'=>'right'),
561 HTML::th(_("Grant")),
562 HTML::th(_("Del/+")),
563 HTML::th(_("Description"))));
565 $allGroups = $this->_group->_specialGroups();
566 foreach ($this->_group->getAllGroupsIn() as $group) {
567 if (!in_array($group,$this->_group->specialGroups()))
568 $allGroups[] = $group;
570 //array_unique(array_merge($this->_group->getAllGroupsIn(),
571 $deletesrc = $WikiTheme->_findData('images/delete.png');
572 $addsrc = $WikiTheme->_findData('images/add.png');
573 $nbsp = HTML::raw(' ');
574 foreach ($this->perm as $access => $groups) {
575 //$permlist = HTML::table(array('class' => 'cal','valign' => 'top'));
577 $newperm = HTML::input(array('type' => 'checkbox',
578 'name' => "acl[_new_perm][$access]",
580 $addbutton = HTML::input(array('type' => 'checkbox',
581 'name' => "acl[_add_group][$access]",
584 'title' => _("Add this ACL"),
586 $newgroup = HTML::select(array('name' => "acl[_new_group][$access]",
587 'style'=> 'text-align: right;',
589 foreach ($allGroups as $groupname) {
590 if (!isset($groups[$groupname]))
591 $newgroup->pushContent(HTML::option(array('value' => $groupname),
592 $this->groupName($groupname)));
594 if (empty($groups)) {
595 $addbutton->setAttr('checked','checked');
596 $newperm->setAttr('checked','checked');
598 HTML::tr(array('valign' => 'top'),
599 HTML::td(HTML::strong($access.":")),
601 HTML::td($nbsp,$newperm),
602 HTML::td($nbsp,$addbutton),
603 HTML::td(HTML::em(getAccessDescription($access)))));
605 foreach ($groups as $group => $bool) {
606 $checkbox = HTML::input(array('type' => 'checkbox',
607 'name' => "acl[$access][$group]",
608 'title' => _("Allow / Deny"),
610 if ($bool) $checkbox->setAttr('checked','checked');
611 $checkbox = HTML(HTML::input(array('type' => 'hidden',
612 'name' => "acl[$access][$group]",
615 $deletebutton = HTML::input(array('type' => 'checkbox',
616 'name' => "acl[_del_group][$access][$group]",
617 'style' => 'background: #aaa url('.$deletesrc.')',
618 //'src' => $deletesrc,
620 'title' => _("Delete this ACL"),
625 HTML::td(HTML::strong($access.":")),
626 HTML::td(array('class' => 'cal-today','align'=>'right'),
627 HTML::strong($this->groupName($group))),
628 HTML::td(array('align'=>'center'),$nbsp,$checkbox),
629 HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
630 HTML::td(HTML::em(getAccessDescription($access)))));
636 HTML::td(array('class' => 'cal-today','align'=>'right'),
637 HTML::strong($this->groupName($group))),
638 HTML::td(array('align'=>'center'),$nbsp,$checkbox),
639 HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
645 HTML::tr(array('valign' => 'top'),
646 HTML::td(array('align'=>'right'),_("add ")),
648 HTML::td(array('align'=>'center'),$nbsp,$newperm),
649 HTML::td(array('align'=>'right','style' => 'background: #ccc url('.$addsrc.') no-repeat'),$addbutton),
650 HTML::td(HTML::small(_("Check to add this Acl")))));
652 if ($type == 'default')
653 $table->setAttr('style','border: dotted thin black; background-color:#eee;');
654 elseif ($type == 'inherited')
655 $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
656 elseif ($type == 'page')
657 $table->setAttr('style','border: solid thin black; font-weight: bold;');
661 // Print ACL as lines of [+-]user[,group,...]:access[,access...]
662 // Seperate acl's by "; " or whitespace
663 // See http://opag.ca/wiki/HelpOnAccessControlLists
664 // As used by WikiAdminSetAclSimple
665 function asAclLines() {
668 foreach ($this->perm as $access => $groups) {
669 // unify groups for same access+bool
670 // view:CREATOR,-OWNER,
672 foreach ($groups as $group => $bool) {
673 $line .= ($bool?'':'-').$group.",";
675 if (substr($line,-1) == ',')
676 $s .= substr($line,0,-1)."; ";
678 if (substr($s,-2) == '; ')
679 $s = substr($s,0,-2);
684 // This is just a bad hack for testing.
685 // Simplify the ACL to a unix-like "rwx------+" string
687 function asRwxString($owner,$group=false) {
689 // simplify object => rwxrw---x+ string as in cygwin (+ denotes additional ACLs)
690 $perm =& $this->perm;
691 // get effective user and group
693 if (isset($perm['view'][$owner]) or
694 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
696 if (isset($perm['edit'][$owner]) or
697 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
699 if (isset($perm['change'][$owner]) or
700 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
702 if (!empty($group)) {
703 if (isset($perm['view'][$group]) or
704 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
706 if (isset($perm['edit'][$group]) or
707 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
709 if (isset($perm['change'][$group]) or
710 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
713 if (isset($perm['view'][ACL_EVERY]) or
714 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
716 if (isset($perm['edit'][ACL_EVERY]) or
717 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
719 if (isset($perm['change'][ACL_EVERY]) or
720 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
726 // $Log: not supported by cvs2svn $
727 // Revision 1.38 2004/11/30 17:48:38 rurban
730 // Revision 1.37 2004/11/23 13:06:30 rurban
731 // several fixes and suggestions by Charles Corrigan:
732 // * fix GROUP_BOGO_USER check
733 // * allow group pages to have the link to the user page in [ ] brackets
734 // * fix up the implementation of GroupWikiPage::getMembersOf and allow the
735 // user page to be linked in [ ] brackets
736 // * added _OWNER and _CREATOR to special wikigroups
737 // * check against those two for group membership also, not only the user.
739 // Revision 1.36 2004/11/21 11:59:16 rurban
740 // remove final \n to be ob_cache independent
742 // Revision 1.35 2004/11/15 15:56:40 rurban
743 // don't load PagePerm on ENABLE_PAGEPERM = false to save memory. Move mayAccessPage() to main.php
745 // Revision 1.34 2004/11/01 10:43:55 rurban
746 // seperate PassUser methods into seperate dir (memory usage)
747 // fix WikiUser (old) overlarge data session
748 // remove wikidb arg from various page class methods, use global ->_dbi instead
751 // Revision 1.33 2004/09/26 11:47:52 rurban
752 // fix another reecursion loop when . exists: deny if ACL not defined; implement pageperm cache
754 // Revision 1.32 2004/09/25 18:56:09 rurban
755 // avoid recursion bug on setacl for "."
757 // Revision 1.31 2004/09/25 18:34:45 rurban
758 // fix and warn on too restrictive ACL handling without ACL in existing . (dotpage)
760 // Revision 1.30 2004/09/25 16:24:02 rurban
761 // fix interesting PagePerm problem: -1 == true
763 // Revision 1.29 2004/07/03 08:04:19 rurban
764 // fixed implicit PersonalPage login (e.g. on edit), fixed to check against create ACL on create, not edit
766 // Revision 1.28 2004/06/25 14:29:17 rurban
767 // WikiGroup refactoring:
768 // global group attached to user, code for not_current user.
769 // improved helpers for special groups (avoid double invocations)
770 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
771 // fixed a XHTML validation error on userprefs.tmpl
773 // Revision 1.27 2004/06/16 10:38:58 rurban
774 // Disallow refernces in calls if the declaration is a reference
775 // ("allow_call_time_pass_reference clean").
776 // PhpWiki is now allow_call_time_pass_reference = Off clean,
777 // but several external libraries may not.
778 // In detail these libs look to be affected (not tested):
782 // Revision 1.26 2004/06/14 11:31:36 rurban
783 // renamed global $Theme to $WikiTheme (gforge nameclash)
784 // inherit PageList default options from PageList
785 // default sortby=pagename
786 // use options in PageList_Selectable (limit, sortby, ...)
787 // added action revert, with button at action=diff
788 // added option regex to WikiAdminSearchReplace
790 // Revision 1.25 2004/06/08 13:51:57 rurban
791 // some comments only
793 // Revision 1.24 2004/06/08 10:54:46 rurban
794 // better acl dump representation, read back acl and owner
796 // Revision 1.23 2004/06/08 10:05:11 rurban
797 // simplified admin action shortcuts
799 // Revision 1.22 2004/06/07 22:44:14 rurban
800 // added simplified chown, setacl actions
802 // Revision 1.21 2004/06/07 22:28:03 rurban
803 // add acl field to mimified dump
805 // Revision 1.20 2004/06/07 18:39:03 rurban
806 // support for SetAclSimple
808 // Revision 1.19 2004/06/06 17:12:28 rurban
809 // fixed PagePerm non-object problem (mayAccessPage), also bug #967150
811 // Revision 1.18 2004/05/27 17:49:05 rurban
812 // renamed DB_Session to DbSession (in CVS also)
813 // added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
814 // remove leading slash in error message
815 // added force_unlock parameter to File_Passwd (no return on stale locks)
816 // fixed adodb session AffectedRows
817 // added FileFinder helpers to unify local filenames and DATA_PATH names
818 // editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
820 // Revision 1.17 2004/05/16 23:10:44 rurban
821 // update_locale wrongly resetted LANG, which broke japanese.
822 // japanese now correctly uses EUC_JP, not utf-8.
823 // more charset and lang headers to help the browser.
825 // Revision 1.16 2004/05/16 22:32:53 rurban
828 // Revision 1.15 2004/05/16 22:07:35 rurban
829 // check more config-default and predefined constants
830 // various PagePerm fixes:
831 // fix default PagePerms, esp. edit and view for Bogo and Password users
832 // implemented Creator and Owner
833 // BOGOUSERS renamed to BOGOUSER
834 // fixed syntax errors in signin.tmpl
836 // Revision 1.14 2004/05/15 22:54:49 rurban
837 // fixed important WikiDB bug with DEBUG > 0: wrong assertion
838 // improved SetAcl (works) and PagePerms, some WikiGroup helpers.
840 // Revision 1.13 2004/05/15 19:48:33 rurban
841 // fix some too loose PagePerms for signed, but not authenticated users
842 // (admin, owner, creator)
843 // no double login page header, better login msg.
844 // moved action_pdf to lib/pdf.php
846 // Revision 1.12 2004/05/04 22:34:25 rurban
849 // Revision 1.11 2004/05/02 21:26:38 rurban
850 // limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
851 // because they will not survive db sessions, if too large.
852 // extended action=upgrade
853 // some WikiTranslation button work
854 // revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
855 // some temp. session debug statements
857 // Revision 1.10 2004/04/29 22:32:56 zorloc
858 // Slightly more elegant fix. Instead of WIKIAUTH_FORBIDDEN, the current user's level + 1 is returned on a false.
860 // Revision 1.9 2004/04/29 17:18:19 zorloc
861 // 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.
863 // Revision 1.8 2004/03/14 16:24:35 rurban
864 // authenti(fi)cation spelling
866 // Revision 1.7 2004/02/28 22:25:07 rurban
867 // First PagePerm implementation:
869 // $WikiTheme->setAnonEditUnknownLinks(false);
871 // Layout improvement with dangling links for mostly closed wiki's:
872 // If false, only users with edit permissions will be presented the
873 // special wikiunknown class with "?" and Tooltip.
874 // If true (default), any user will see the ?, but will be presented
875 // the PrintLoginForm on a click.
877 // Revision 1.6 2004/02/24 15:20:05 rurban
878 // fixed minor warnings: unchecked args, POST => Get urls for sortby e.g.
880 // Revision 1.5 2004/02/23 21:30:25 rurban
881 // more PagePerm stuff: (working against 1.4.0)
882 // ACL editing and simplification of ACL's to simple rwx------ string
885 // Revision 1.4 2004/02/12 13:05:36 rurban
886 // Rename functional for PearDB backend
887 // some other minor changes
888 // SiteMap comes with a not yet functional feature request: includepages (tbd)
890 // Revision 1.3 2004/02/09 03:58:12 rurban
891 // for now default DB_SESSION to false
893 // * not existing perms will now query the parent, and not
894 // return the default perm
895 // * added pagePermissions func which returns the object per page
896 // * added getAccessDescription
898 // * added global ->prepare (not yet used) with smart user/pref/member table prefixing.
899 // * force init of authdbh in the 2 db classes
901 // * fixed session handling (not triple auth request anymore)
902 // * don't store cookie prefs with sessions
903 // stdlib: global obj2hash helper from _AuthInfo, also needed for PagePerm
905 // Revision 1.2 2004/02/08 13:17:48 rurban
906 // This should be the functionality. Needs testing and some minor todos.
908 // Revision 1.1 2004/02/08 12:29:30 rurban
909 // initial version, not yet hooked into lib/main.php
917 // c-hanging-comment-ender-p: nil
918 // indent-tabs-mode: nil