2 rcs_id('$Id: PagePerm.php,v 1.40 2005-10-29 14:16:58 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.39 2005/05/06 16:57:54 rurban
730 // Revision 1.38 2004/11/30 17:48:38 rurban
733 // Revision 1.37 2004/11/23 13:06:30 rurban
734 // several fixes and suggestions by Charles Corrigan:
735 // * fix GROUP_BOGO_USER check
736 // * allow group pages to have the link to the user page in [ ] brackets
737 // * fix up the implementation of GroupWikiPage::getMembersOf and allow the
738 // user page to be linked in [ ] brackets
739 // * added _OWNER and _CREATOR to special wikigroups
740 // * check against those two for group membership also, not only the user.
742 // Revision 1.36 2004/11/21 11:59:16 rurban
743 // remove final \n to be ob_cache independent
745 // Revision 1.35 2004/11/15 15:56:40 rurban
746 // don't load PagePerm on ENABLE_PAGEPERM = false to save memory. Move mayAccessPage() to main.php
748 // Revision 1.34 2004/11/01 10:43:55 rurban
749 // seperate PassUser methods into seperate dir (memory usage)
750 // fix WikiUser (old) overlarge data session
751 // remove wikidb arg from various page class methods, use global ->_dbi instead
754 // Revision 1.33 2004/09/26 11:47:52 rurban
755 // fix another reecursion loop when . exists: deny if ACL not defined; implement pageperm cache
757 // Revision 1.32 2004/09/25 18:56:09 rurban
758 // avoid recursion bug on setacl for "."
760 // Revision 1.31 2004/09/25 18:34:45 rurban
761 // fix and warn on too restrictive ACL handling without ACL in existing . (dotpage)
763 // Revision 1.30 2004/09/25 16:24:02 rurban
764 // fix interesting PagePerm problem: -1 == true
766 // Revision 1.29 2004/07/03 08:04:19 rurban
767 // fixed implicit PersonalPage login (e.g. on edit), fixed to check against create ACL on create, not edit
769 // Revision 1.28 2004/06/25 14:29:17 rurban
770 // WikiGroup refactoring:
771 // global group attached to user, code for not_current user.
772 // improved helpers for special groups (avoid double invocations)
773 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
774 // fixed a XHTML validation error on userprefs.tmpl
776 // Revision 1.27 2004/06/16 10:38:58 rurban
777 // Disallow refernces in calls if the declaration is a reference
778 // ("allow_call_time_pass_reference clean").
779 // PhpWiki is now allow_call_time_pass_reference = Off clean,
780 // but several external libraries may not.
781 // In detail these libs look to be affected (not tested):
785 // Revision 1.26 2004/06/14 11:31:36 rurban
786 // renamed global $Theme to $WikiTheme (gforge nameclash)
787 // inherit PageList default options from PageList
788 // default sortby=pagename
789 // use options in PageList_Selectable (limit, sortby, ...)
790 // added action revert, with button at action=diff
791 // added option regex to WikiAdminSearchReplace
793 // Revision 1.25 2004/06/08 13:51:57 rurban
794 // some comments only
796 // Revision 1.24 2004/06/08 10:54:46 rurban
797 // better acl dump representation, read back acl and owner
799 // Revision 1.23 2004/06/08 10:05:11 rurban
800 // simplified admin action shortcuts
802 // Revision 1.22 2004/06/07 22:44:14 rurban
803 // added simplified chown, setacl actions
805 // Revision 1.21 2004/06/07 22:28:03 rurban
806 // add acl field to mimified dump
808 // Revision 1.20 2004/06/07 18:39:03 rurban
809 // support for SetAclSimple
811 // Revision 1.19 2004/06/06 17:12:28 rurban
812 // fixed PagePerm non-object problem (mayAccessPage), also bug #967150
814 // Revision 1.18 2004/05/27 17:49:05 rurban
815 // renamed DB_Session to DbSession (in CVS also)
816 // added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
817 // remove leading slash in error message
818 // added force_unlock parameter to File_Passwd (no return on stale locks)
819 // fixed adodb session AffectedRows
820 // added FileFinder helpers to unify local filenames and DATA_PATH names
821 // editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
823 // Revision 1.17 2004/05/16 23:10:44 rurban
824 // update_locale wrongly resetted LANG, which broke japanese.
825 // japanese now correctly uses EUC_JP, not utf-8.
826 // more charset and lang headers to help the browser.
828 // Revision 1.16 2004/05/16 22:32:53 rurban
831 // Revision 1.15 2004/05/16 22:07:35 rurban
832 // check more config-default and predefined constants
833 // various PagePerm fixes:
834 // fix default PagePerms, esp. edit and view for Bogo and Password users
835 // implemented Creator and Owner
836 // BOGOUSERS renamed to BOGOUSER
837 // fixed syntax errors in signin.tmpl
839 // Revision 1.14 2004/05/15 22:54:49 rurban
840 // fixed important WikiDB bug with DEBUG > 0: wrong assertion
841 // improved SetAcl (works) and PagePerms, some WikiGroup helpers.
843 // Revision 1.13 2004/05/15 19:48:33 rurban
844 // fix some too loose PagePerms for signed, but not authenticated users
845 // (admin, owner, creator)
846 // no double login page header, better login msg.
847 // moved action_pdf to lib/pdf.php
849 // Revision 1.12 2004/05/04 22:34:25 rurban
852 // Revision 1.11 2004/05/02 21:26:38 rurban
853 // limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
854 // because they will not survive db sessions, if too large.
855 // extended action=upgrade
856 // some WikiTranslation button work
857 // revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
858 // some temp. session debug statements
860 // Revision 1.10 2004/04/29 22:32:56 zorloc
861 // Slightly more elegant fix. Instead of WIKIAUTH_FORBIDDEN, the current user's level + 1 is returned on a false.
863 // Revision 1.9 2004/04/29 17:18:19 zorloc
864 // 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.
866 // Revision 1.8 2004/03/14 16:24:35 rurban
867 // authenti(fi)cation spelling
869 // Revision 1.7 2004/02/28 22:25:07 rurban
870 // First PagePerm implementation:
872 // $WikiTheme->setAnonEditUnknownLinks(false);
874 // Layout improvement with dangling links for mostly closed wiki's:
875 // If false, only users with edit permissions will be presented the
876 // special wikiunknown class with "?" and Tooltip.
877 // If true (default), any user will see the ?, but will be presented
878 // the PrintLoginForm on a click.
880 // Revision 1.6 2004/02/24 15:20:05 rurban
881 // fixed minor warnings: unchecked args, POST => Get urls for sortby e.g.
883 // Revision 1.5 2004/02/23 21:30:25 rurban
884 // more PagePerm stuff: (working against 1.4.0)
885 // ACL editing and simplification of ACL's to simple rwx------ string
888 // Revision 1.4 2004/02/12 13:05:36 rurban
889 // Rename functional for PearDB backend
890 // some other minor changes
891 // SiteMap comes with a not yet functional feature request: includepages (tbd)
893 // Revision 1.3 2004/02/09 03:58:12 rurban
894 // for now default DB_SESSION to false
896 // * not existing perms will now query the parent, and not
897 // return the default perm
898 // * added pagePermissions func which returns the object per page
899 // * added getAccessDescription
901 // * added global ->prepare (not yet used) with smart user/pref/member table prefixing.
902 // * force init of authdbh in the 2 db classes
904 // * fixed session handling (not triple auth request anymore)
905 // * don't store cookie prefs with sessions
906 // stdlib: global obj2hash helper from _AuthInfo, also needed for PagePerm
908 // Revision 1.2 2004/02/08 13:17:48 rurban
909 // This should be the functionality. Needs testing and some minor todos.
911 // Revision 1.1 2004/02/08 12:29:30 rurban
912 // initial version, not yet hooked into lib/main.php
920 // c-hanging-comment-ender-p: nil
921 // indent-tabs-mode: nil