4 Copyright 2004,2007 $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) {
176 if (INSECURE_ACTIONS_LOCALHOST_ONLY and is_localhost())
181 // performance and security relevant
188 // invent a new access-perm massedit? or switch back to change, or keep it at edit?
189 case _("PhpWikiAdministration")."/"._("Rename"):
190 case _("PhpWikiAdministration")."/"._("Replace"):
197 $page = $request->getPage();
198 if (!$page->exists())
205 // probably create/edit but we cannot check all page permissions, can we?
214 //Todo: Plugins should be able to override its access type
215 if (isWikiWord($action))
223 // Recursive helper to do the real work.
224 // Using a simple perm cache for page-access pairs.
225 // Maybe page-(current+edit+change?)action pairs will help
226 function _requiredAuthorityForPagename($access, $pagename) {
227 static $permcache = array();
229 if (array_key_exists($pagename, $permcache)
230 and array_key_exists($access, $permcache[$pagename]))
231 return $permcache[$pagename][$access];
234 $page = $request->getPage($pagename);
235 // Page not found; check against default permissions
236 if (! $page->exists() ) {
237 $perm = new PagePermission();
238 $result = ($perm->isAuthorized($access, $request->_user) === true);
239 $permcache[$pagename][$access] = $result;
242 // no ACL defined; check for special dotfile or walk down
243 if (! ($perm = getPagePermissions($page))) {
244 if ($pagename == '.') {
245 $perm = new PagePermission();
246 if ($perm->isAuthorized('change', $request->_user)) {
247 // warn the user to set ACL of ".", if he has permissions to do so.
248 trigger_error(". (dotpage == rootpage for inheriting pageperm ACLs) exists without any ACL!\n".
249 "Please do ?action=setacl&pagename=.", E_USER_WARNING);
251 $result = ($perm->isAuthorized($access, $request->_user) === true);
252 $permcache[$pagename][$access] = $result;
254 } elseif ($pagename[0] == '.') {
255 $perm = new PagePermission(PagePermission::dotPerms());
256 $result = ($perm->isAuthorized($access, $request->_user) === true);
257 $permcache[$pagename][$access] = $result;
260 return _requiredAuthorityForPagename($access, getParentPage($pagename));
262 // ACL defined; check if isAuthorized returns true or false or undecided
263 $authorized = $perm->isAuthorized($access, $request->_user);
264 if ($authorized !== -1) { // interestingly true is also -1
265 $permcache[$pagename][$access] = $authorized;
267 } elseif ($pagename == '.') {
270 return _requiredAuthorityForPagename($access, getParentPage($pagename));
275 * @param string $pagename page from which the parent page is searched.
276 * @return string parent pagename or the (possibly pseudo) dot-pagename.
278 function getParentPage($pagename) {
279 if (isSubPage($pagename)) {
280 return subPageSlice($pagename, 0);
286 // Read the ACL from the page
287 // Done: Not existing pages should NOT be queried.
288 // Check the parent page instead and don't take the default ACL's
289 function getPagePermissions ($page) {
290 if ($hash = $page->get('perm')) // hash => object
291 return new PagePermission(unserialize($hash));
296 // Store the ACL in the page
297 function setPagePermissions ($page,$perm) {
301 function getAccessDescription($access) {
302 static $accessDescriptions;
303 if (! $accessDescriptions) {
304 $accessDescriptions = array(
305 'list' => _("List this page and all subpages"),
306 'view' => _("View this page and all subpages"),
307 'edit' => _("Edit this page and all subpages"),
308 'create' => _("Create a new (sub)page"),
309 'dump' => _("Download page contents"),
310 'change' => _("Change page attributes"),
311 'remove' => _("Remove this page"),
314 if (in_array($access, array_keys($accessDescriptions)))
315 return $accessDescriptions[$access];
321 function array_diff_assoc_recursive($array1, $array2) {
322 foreach ($array1 as $key => $value) {
323 if (is_array($value)) {
324 if (!is_array($array2[$key])) {
325 $difference[$key] = $value;
327 $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
328 if ($new_diff != false) {
329 $difference[$key] = $new_diff;
332 } elseif(!isset($array2[$key]) || $array2[$key] != $value) {
333 $difference[$key] = $value;
336 return !isset($difference) ? 0 : $difference;
340 * The ACL object per page. It is stored in a page, but can also
341 * be merged with ACL's from other pages or taken from the master (pseudo) dot-file.
343 * A hash of "access" => "requires" pairs.
344 * "access" is a shortcut for common actions, which map to main.php actions
345 * "requires" required username or groupname or any special group => true or false
347 * Define any special rules here, like don't list dot-pages.
349 class PagePermission {
352 function PagePermission($hash = array()) {
353 $this->_group = &$GLOBALS['request']->getGroup();
354 if (is_array($hash) and !empty($hash)) {
355 $accessTypes = $this->accessTypes();
356 foreach ($hash as $access => $requires) {
357 if (in_array($access, $accessTypes))
358 $this->perm[$access] = $requires;
360 trigger_error(sprintf(_("Unsupported ACL access type %s ignored."), $access),
364 // set default permissions, the so called dot-file acl's
365 $this->perm = $this->defaultPerms();
371 * The workhorse to check the user against the current ACL pairs.
372 * Must translate the various special groups to the actual users settings
373 * (userid, group membership).
375 function isAuthorized($access, $user) {
376 if (!empty($this->perm{$access})) {
378 foreach ($this->perm[$access] as $group => $bool) {
379 if ($this->isMember($user, $group)) {
381 } elseif ($allow == -1) { // not a member and undecided: check other groups
386 return $allow; // undecided
390 * Translate the various special groups to the actual users settings
391 * (userid, group membership).
393 function isMember($user, $group) {
395 if ($group === ACL_EVERY) return true;
396 if (!isset($this->_group)) $member =& $request->getGroup();
397 else $member =& $this->_group;
398 //$user = & $request->_user;
399 if ($group === ACL_ADMIN) // WIKI_ADMIN or member of _("Administrators")
400 return $user->isAdmin() or
401 ($user->isAuthenticated() and
402 $member->isMember(GROUP_ADMIN));
403 if ($group === ACL_ANONYMOUS)
404 return ! $user->isSignedIn();
405 if ($group === ACL_BOGOUSER)
407 return isa($user,'_BogoUser') or
408 (isWikiWord($user->_userid) and $user->_level >= WIKIAUTH_BOGO);
409 else return isWikiWord($user->UserName());
410 if ($group === ACL_HASHOMEPAGE)
411 return $user->hasHomePage();
412 if ($group === ACL_SIGNED)
413 return $user->isSignedIn();
414 if ($group === ACL_AUTHENTICATED)
415 return $user->isAuthenticated();
416 if ($group === ACL_OWNER) {
417 if (!$user->isAuthenticated()) return false;
418 $page = $request->getPage();
419 $owner = $page->getOwner();
420 return ($owner === $user->UserName()
421 or $member->isMember($owner));
423 if ($group === ACL_CREATOR) {
424 if (!$user->isAuthenticated()) return false;
425 $page = $request->getPage();
426 $creator = $page->getCreator();
427 return ($creator === $user->UserName()
428 or $member->isMember($creator));
430 /* Or named groups or usernames.
431 Note: We don't seperate groups and users here.
432 Users overrides groups with the same name.
434 return $user->UserName() === $group or
435 $member->isMember($group);
439 * returns hash of default permissions.
440 * check if the page '.' exists and returns this instead.
442 function defaultPerms() {
443 //Todo: check for the existance of '.' and take this instead.
444 //Todo: honor more config.ini auth settings here
445 $perm = array('view' => array(ACL_EVERY => true),
446 'edit' => array(ACL_EVERY => true),
447 'create' => array(ACL_EVERY => true),
448 'list' => array(ACL_EVERY => true),
449 'remove' => array(ACL_ADMIN => true,
451 'dump' => array(ACL_ADMIN => true,
453 'change' => array(ACL_ADMIN => true,
456 $perm['dump'] = array(ACL_ADMIN => true,
458 elseif (INSECURE_ACTIONS_LOCALHOST_ONLY) {
460 $perm['dump'] = array(ACL_EVERY => true);
462 $perm['dump'] = array(ACL_ADMIN => true);
465 $perm['dump'] = array(ACL_EVERY => true);
466 if (defined('REQUIRE_SIGNIN_BEFORE_EDIT') && REQUIRE_SIGNIN_BEFORE_EDIT)
467 $perm['edit'] = array(ACL_SIGNED => true);
469 if (!ALLOW_ANON_USER) {
470 if (!ALLOW_USER_PASSWORDS)
471 $perm['view'] = array(ACL_SIGNED => true);
473 $perm['view'] = array(ACL_AUTHENTICATED => true);
474 $perm['view'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
477 if (!ALLOW_ANON_EDIT) {
478 if (!ALLOW_USER_PASSWORDS)
479 $perm['edit'] = array(ACL_SIGNED => true);
481 $perm['edit'] = array(ACL_AUTHENTICATED => true);
482 $perm['edit'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
483 $perm['create'] = $perm['edit'];
489 * FIXME: check valid groups and access
492 foreach ($this->perm as $access => $groups) {
493 foreach ($groups as $group => $bool) {
494 $this->perm[$access][$group] = (boolean) $bool;
500 * do a recursive comparison
502 function equal($otherperm) {
503 $diff = array_diff_assoc_recursive($this->perm, $otherperm);
508 * returns list of all supported access types.
510 function accessTypes() {
511 return array_keys(PagePermission::defaultPerms());
515 * special permissions for dot-files, beginning with '.'
516 * maybe also for '_' files?
518 function dotPerms() {
519 $def = array(ACL_ADMIN => true,
522 foreach (PagePermission::accessTypes() as $access) {
523 $perm[$access] = $def;
529 * dead code. not needed inside the object. see getPagePermissions($page)
531 function retrieve($page) {
532 $hash = $page->get('perm');
533 if ($hash) // hash => object
534 $perm = new PagePermission(unserialize($hash));
536 $perm = new PagePermission();
541 function store($page) {
544 return $page->set('perm',serialize($this->perm));
547 function groupName ($group) {
548 if ($group[0] == '_') return constant("GROUP".$group);
552 /* type: page, default, inherited */
553 function asTable($type) {
554 $table = HTML::table();
555 foreach ($this->perm as $access => $perms) {
556 $td = HTML::table(array('class' => 'cal','valign' => 'top'));
557 foreach ($perms as $group => $bool) {
558 $td->pushContent(HTML::tr(HTML::td(array('align'=>'right'),$group),
559 HTML::td($bool ? '[X]' : '[ ]')));
561 $table->pushContent(HTML::tr(array('valign' => 'top'),
562 HTML::td($access),HTML::td($td)));
564 if ($type == 'default')
565 $table->setAttr('style','border: dotted thin black; background-color:#eee;');
566 elseif ($type == 'inherited')
567 $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
568 elseif ($type == 'page')
569 $table->setAttr('style','border: solid thin black; font-weight: bold;');
573 /* type: page, default, inherited */
574 function asEditableTable($type) {
576 if (!isset($this->_group)) {
577 $this->_group =& $GLOBALS['request']->getGroup();
579 $table = HTML::table();
580 $table->pushContent(HTML::tr(
581 HTML::th(array('align' => 'left'),
583 HTML::th(array('align'=>'right'),
585 HTML::th(_("Grant")),
586 HTML::th(_("Del/+")),
587 HTML::th(_("Description"))));
589 $allGroups = $this->_group->_specialGroups();
590 foreach ($this->_group->getAllGroupsIn() as $group) {
591 if (!in_array($group,$this->_group->specialGroups()))
592 $allGroups[] = $group;
594 //array_unique(array_merge($this->_group->getAllGroupsIn(),
595 $deletesrc = $WikiTheme->_findData('images/delete.png');
596 $addsrc = $WikiTheme->_findData('images/add.png');
597 $nbsp = HTML::raw(' ');
598 foreach ($this->perm as $access => $groups) {
599 //$permlist = HTML::table(array('class' => 'cal','valign' => 'top'));
601 $newperm = HTML::input(array('type' => 'checkbox',
602 'name' => "acl[_new_perm][$access]",
604 $addbutton = HTML::input(array('type' => 'checkbox',
605 'name' => "acl[_add_group][$access]",
608 'title' => _("Add this ACL"),
610 $newgroup = HTML::select(array('name' => "acl[_new_group][$access]",
611 'style'=> 'text-align: right;',
613 foreach ($allGroups as $groupname) {
614 if (!isset($groups[$groupname]))
615 $newgroup->pushContent(HTML::option(array('value' => $groupname),
616 $this->groupName($groupname)));
618 if (empty($groups)) {
619 $addbutton->setAttr('checked','checked');
620 $newperm->setAttr('checked','checked');
622 HTML::tr(array('valign' => 'top'),
623 HTML::td(HTML::strong($access.":")),
625 HTML::td($nbsp,$newperm),
626 HTML::td($nbsp,$addbutton),
627 HTML::td(HTML::em(getAccessDescription($access)))));
629 foreach ($groups as $group => $bool) {
630 $checkbox = HTML::input(array('type' => 'checkbox',
631 'name' => "acl[$access][$group]",
632 'title' => _("Allow / Deny"),
634 if ($bool) $checkbox->setAttr('checked','checked');
635 $checkbox = HTML(HTML::input(array('type' => 'hidden',
636 'name' => "acl[$access][$group]",
639 $deletebutton = HTML::input(array('type' => 'checkbox',
640 'name' => "acl[_del_group][$access][$group]",
641 'style' => 'background: #aaa url('.$deletesrc.')',
642 //'src' => $deletesrc,
644 'title' => _("Delete this ACL"),
649 HTML::td(HTML::strong($access.":")),
650 HTML::td(array('class' => 'cal-today','align'=>'right'),
651 HTML::strong($this->groupName($group))),
652 HTML::td(array('align'=>'center'),$nbsp,$checkbox),
653 HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
654 HTML::td(HTML::em(getAccessDescription($access)))));
660 HTML::td(array('class' => 'cal-today','align'=>'right'),
661 HTML::strong($this->groupName($group))),
662 HTML::td(array('align'=>'center'),$nbsp,$checkbox),
663 HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
669 HTML::tr(array('valign' => 'top'),
670 HTML::td(array('align'=>'right'),_("add ")),
672 HTML::td(array('align'=>'center'),$nbsp,$newperm),
673 HTML::td(array('align'=>'right','style' => 'background: #ccc url('.$addsrc.') no-repeat'),$addbutton),
674 HTML::td(HTML::small(_("Check to add this ACL")))));
676 if ($type == 'default')
677 $table->setAttr('style','border: dotted thin black; background-color:#eee;');
678 elseif ($type == 'inherited')
679 $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
680 elseif ($type == 'page')
681 $table->setAttr('style','border: solid thin black; font-weight: bold;');
685 // Print ACL as lines of [+-]user[,group,...]:access[,access...]
686 // Seperate acl's by "; " or whitespace
687 // See http://opag.ca/wiki/HelpOnAccessControlLists
688 // As used by WikiAdminSetAclSimple
689 function asAclLines() {
692 foreach ($this->perm as $access => $groups) {
693 // unify groups for same access+bool
694 // view:CREATOR,-OWNER,
696 foreach ($groups as $group => $bool) {
697 $line .= ($bool?'':'-').$group.",";
699 if (substr($line,-1) == ',')
700 $s .= substr($line,0,-1)."; ";
702 if (substr($s,-2) == '; ')
703 $s = substr($s,0,-2);
708 // This is just a bad hack for testing.
709 // Simplify the ACL to a unix-like "rwx------+" string
711 function asRwxString($owner,$group=false) {
713 // simplify object => rwxrw---x+ string as in cygwin (+ denotes additional ACLs)
714 $perm =& $this->perm;
715 // get effective user and group
717 if (isset($perm['view'][$owner]) or
718 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
720 if (isset($perm['edit'][$owner]) or
721 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
723 if (isset($perm['change'][$owner]) or
724 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
726 if (!empty($group)) {
727 if (isset($perm['view'][$group]) or
728 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
730 if (isset($perm['edit'][$group]) or
731 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
733 if (isset($perm['change'][$group]) or
734 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
737 if (isset($perm['view'][ACL_EVERY]) or
738 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
740 if (isset($perm['edit'][ACL_EVERY]) or
741 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
743 if (isset($perm['change'][ACL_EVERY]) or
744 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
750 // $Log: not supported by cvs2svn $
751 // Revision 1.44 2007/09/12 19:34:31 rurban
752 // revise INSECURE_ACTIONS_LOCALHOST_ONLY actions
754 // Revision 1.43 2007/09/01 13:24:23 rurban
755 // add INSECURE_ACTIONS_LOCALHOST_ONLY. advanced security settings
757 // Revision 1.42 2007/08/25 18:03:34 rurban
758 // change rename action from access perm change to edit: allow the signed in user to rename.
760 // Revision 1.41 2007/07/14 12:03:25 rurban
761 // fix for mult. group membership: not a member and undecided: check other groups
763 // Revision 1.40 2005/10/29 14:16:58 rurban
766 // Revision 1.39 2005/05/06 16:57:54 rurban
769 // Revision 1.38 2004/11/30 17:48:38 rurban
772 // Revision 1.37 2004/11/23 13:06:30 rurban
773 // several fixes and suggestions by Charles Corrigan:
774 // * fix GROUP_BOGO_USER check
775 // * allow group pages to have the link to the user page in [ ] brackets
776 // * fix up the implementation of GroupWikiPage::getMembersOf and allow the
777 // user page to be linked in [ ] brackets
778 // * added _OWNER and _CREATOR to special wikigroups
779 // * check against those two for group membership also, not only the user.
781 // Revision 1.36 2004/11/21 11:59:16 rurban
782 // remove final \n to be ob_cache independent
784 // Revision 1.35 2004/11/15 15:56:40 rurban
785 // don't load PagePerm on ENABLE_PAGEPERM = false to save memory. Move mayAccessPage() to main.php
787 // Revision 1.34 2004/11/01 10:43:55 rurban
788 // seperate PassUser methods into seperate dir (memory usage)
789 // fix WikiUser (old) overlarge data session
790 // remove wikidb arg from various page class methods, use global ->_dbi instead
793 // Revision 1.33 2004/09/26 11:47:52 rurban
794 // fix another reecursion loop when . exists: deny if ACL not defined; implement pageperm cache
796 // Revision 1.32 2004/09/25 18:56:09 rurban
797 // avoid recursion bug on setacl for "."
799 // Revision 1.31 2004/09/25 18:34:45 rurban
800 // fix and warn on too restrictive ACL handling without ACL in existing . (dotpage)
802 // Revision 1.30 2004/09/25 16:24:02 rurban
803 // fix interesting PagePerm problem: -1 == true
805 // Revision 1.29 2004/07/03 08:04:19 rurban
806 // fixed implicit PersonalPage login (e.g. on edit), fixed to check against create ACL on create, not edit
808 // Revision 1.28 2004/06/25 14:29:17 rurban
809 // WikiGroup refactoring:
810 // global group attached to user, code for not_current user.
811 // improved helpers for special groups (avoid double invocations)
812 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
813 // fixed a XHTML validation error on userprefs.tmpl
815 // Revision 1.27 2004/06/16 10:38:58 rurban
816 // Disallow refernces in calls if the declaration is a reference
817 // ("allow_call_time_pass_reference clean").
818 // PhpWiki is now allow_call_time_pass_reference = Off clean,
819 // but several external libraries may not.
820 // In detail these libs look to be affected (not tested):
824 // Revision 1.26 2004/06/14 11:31:36 rurban
825 // renamed global $Theme to $WikiTheme (gforge nameclash)
826 // inherit PageList default options from PageList
827 // default sortby=pagename
828 // use options in PageList_Selectable (limit, sortby, ...)
829 // added action revert, with button at action=diff
830 // added option regex to WikiAdminSearchReplace
832 // Revision 1.25 2004/06/08 13:51:57 rurban
833 // some comments only
835 // Revision 1.24 2004/06/08 10:54:46 rurban
836 // better acl dump representation, read back acl and owner
838 // Revision 1.23 2004/06/08 10:05:11 rurban
839 // simplified admin action shortcuts
841 // Revision 1.22 2004/06/07 22:44:14 rurban
842 // added simplified chown, setacl actions
844 // Revision 1.21 2004/06/07 22:28:03 rurban
845 // add acl field to mimified dump
847 // Revision 1.20 2004/06/07 18:39:03 rurban
848 // support for SetAclSimple
850 // Revision 1.19 2004/06/06 17:12:28 rurban
851 // fixed PagePerm non-object problem (mayAccessPage), also bug #967150
853 // Revision 1.18 2004/05/27 17:49:05 rurban
854 // renamed DB_Session to DbSession (in CVS also)
855 // added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
856 // remove leading slash in error message
857 // added force_unlock parameter to File_Passwd (no return on stale locks)
858 // fixed adodb session AffectedRows
859 // added FileFinder helpers to unify local filenames and DATA_PATH names
860 // editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
862 // Revision 1.17 2004/05/16 23:10:44 rurban
863 // update_locale wrongly resetted LANG, which broke japanese.
864 // japanese now correctly uses EUC_JP, not utf-8.
865 // more charset and lang headers to help the browser.
867 // Revision 1.16 2004/05/16 22:32:53 rurban
870 // Revision 1.15 2004/05/16 22:07:35 rurban
871 // check more config-default and predefined constants
872 // various PagePerm fixes:
873 // fix default PagePerms, esp. edit and view for Bogo and Password users
874 // implemented Creator and Owner
875 // BOGOUSERS renamed to BOGOUSER
876 // fixed syntax errors in signin.tmpl
878 // Revision 1.14 2004/05/15 22:54:49 rurban
879 // fixed important WikiDB bug with DEBUG > 0: wrong assertion
880 // improved SetAcl (works) and PagePerms, some WikiGroup helpers.
882 // Revision 1.13 2004/05/15 19:48:33 rurban
883 // fix some too loose PagePerms for signed, but not authenticated users
884 // (admin, owner, creator)
885 // no double login page header, better login msg.
886 // moved action_pdf to lib/pdf.php
888 // Revision 1.12 2004/05/04 22:34:25 rurban
891 // Revision 1.11 2004/05/02 21:26:38 rurban
892 // limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
893 // because they will not survive db sessions, if too large.
894 // extended action=upgrade
895 // some WikiTranslation button work
896 // revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
897 // some temp. session debug statements
899 // Revision 1.10 2004/04/29 22:32:56 zorloc
900 // Slightly more elegant fix. Instead of WIKIAUTH_FORBIDDEN, the current user's level + 1 is returned on a false.
902 // Revision 1.9 2004/04/29 17:18:19 zorloc
903 // 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.
905 // Revision 1.8 2004/03/14 16:24:35 rurban
906 // authenti(fi)cation spelling
908 // Revision 1.7 2004/02/28 22:25:07 rurban
909 // First PagePerm implementation:
911 // $WikiTheme->setAnonEditUnknownLinks(false);
913 // Layout improvement with dangling links for mostly closed wiki's:
914 // If false, only users with edit permissions will be presented the
915 // special wikiunknown class with "?" and Tooltip.
916 // If true (default), any user will see the ?, but will be presented
917 // the PrintLoginForm on a click.
919 // Revision 1.6 2004/02/24 15:20:05 rurban
920 // fixed minor warnings: unchecked args, POST => Get urls for sortby e.g.
922 // Revision 1.5 2004/02/23 21:30:25 rurban
923 // more PagePerm stuff: (working against 1.4.0)
924 // ACL editing and simplification of ACL's to simple rwx------ string
927 // Revision 1.4 2004/02/12 13:05:36 rurban
928 // Rename functional for PearDB backend
929 // some other minor changes
930 // SiteMap comes with a not yet functional feature request: includepages (tbd)
932 // Revision 1.3 2004/02/09 03:58:12 rurban
933 // for now default DB_SESSION to false
935 // * not existing perms will now query the parent, and not
936 // return the default perm
937 // * added pagePermissions func which returns the object per page
938 // * added getAccessDescription
940 // * added global ->prepare (not yet used) with smart user/pref/member table prefixing.
941 // * force init of authdbh in the 2 db classes
943 // * fixed session handling (not triple auth request anymore)
944 // * don't store cookie prefs with sessions
945 // stdlib: global obj2hash helper from _AuthInfo, also needed for PagePerm
947 // Revision 1.2 2004/02/08 13:17:48 rurban
948 // This should be the functionality. Needs testing and some minor todos.
950 // Revision 1.1 2004/02/08 12:29:30 rurban
951 // initial version, not yet hooked into lib/main.php
959 // c-hanging-comment-ender-p: nil
960 // indent-tabs-mode: nil