]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/PagePerm.php
better acl dump representation, read back acl and owner
[SourceForge/phpwiki.git] / lib / PagePerm.php
1 <?php // -*-php-*-
2 rcs_id('$Id: PagePerm.php,v 1.24 2004-06-08 10:54:46 rurban Exp $');
3 /*
4  Copyright 2004 $ThePhpWikiProgrammingTeam
5
6  This file is part of PhpWiki.
7
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.
12
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.
17
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
21  */
22
23 /**
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)
28
29    Permissions may be inherited from its parent pages, a optional the 
30    optional master page ("."), and predefined default permissions, if "." 
31    is not defined.
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
35
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, 
42        when login is tried.
43      Request::getDisallowedActionDescription($action)
44        helper to localize the _notAuthorized message per action, 
45        when it aborts
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 
51        action + page pair
52
53      The defined main.php actions map to simplier access types:
54        browse => view
55        edit   => edit
56        create => edit or create
57        remove => remove
58        rename => change
59        store prefs => change
60        list in PageList => list
61 */
62
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');
73
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) {
79     global $request;
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());
85         else {
86             return array('inherited',pagePermissions(getParentPage($pagename)));
87         }
88     } elseif ($perm = getPagePermissions($page)) {
89         return array('page',$perm);
90     // or no permissions defined; returned inherited permissions, to be displayed in gray
91     } else {
92         return array('inherited',pagePermissions(getParentPage($pagename)));
93     }
94 }
95
96 function pagePermissionsSimpleFormat($perm_tree,$owner,$group=false) {
97     list($type,$perm) = pagePermissionsAcl($perm_tree[0], $perm_tree);
98     /*
99     $type = $perm_tree[0];
100     $perm = pagePermissionsAcl($perm_tree);
101     if (is_object($perm_tree[1]))
102         $perm = $perm_tree[1];
103     elseif (is_array($perm_tree[1])) {
104         $perm_tree = pagePermissionsSimpleFormat($perm_tree[1],$owner,$group);
105         if (isa($perm_tree[1],'pagepermission'))
106             $perm = $perm_tree[1];
107         elseif (isa($perm_tree,'htmlelement'))
108             return $perm_tree;
109     }
110     */
111     if ($type == 'page')
112         return HTML::tt(HTML::bold($perm->asRwxString($owner,$group).'+'));
113     elseif ($type == 'default')
114         return HTML::tt($perm->asRwxString($owner,$group));
115     elseif ($type == 'inherited') {
116         return HTML::tt(array('class'=>'inherited','style'=>'color:#aaa;'),
117                         $perm->asRwxString($owner,$group));
118     }
119 }
120
121 function pagePermissionsAcl($type,$perm_tree) {
122     $perm = $perm_tree[1];
123     while (!is_object($perm)) {
124         $perm_tree = pagePermissionsAcl($type, $perm);
125         $perm = $perm_tree[1];
126     }
127     return array($type,$perm);
128 }
129
130 // view => who
131 // edit => who
132 function pagePermissionsAclFormat($perm_tree, $editable=false) {
133     list($type,$perm) = pagePermissionsAcl($perm_tree[0], $perm_tree);
134     if ($editable)
135         return $perm->asEditableTable($type);
136     else
137         return $perm->asTable($type);
138 }
139
140 /**
141  * Check permission per page.
142  * Returns true or false.
143  */
144 function mayAccessPage ($access, $pagename) {
145     if (ENABLE_PAGEPERM)
146         return _requiredAuthorityForPagename($access, $pagename);
147     else
148         return true;
149 }
150
151 /** 
152  * Check the permissions for the current action.
153  * Walk down the inheritance tree. Collect all permissions until 
154  * the minimum required level is gained, which is not 
155  * overruled by more specific forbid rules.
156  * Todo: cache result per access and page in session?
157  */
158 function requiredAuthorityForPage ($action) {
159     $auth = _requiredAuthorityForPagename(action2access($action),
160                                           $GLOBALS['request']->getArg('pagename'));
161     assert($auth !== -1);
162     if ($auth)
163         return $GLOBALS['request']->_user->_level;
164     else
165         return WIKIAUTH_UNOBTAINABLE;
166 }
167
168 // Translate action or plugin to the simplier access types:
169 function action2access ($action) {
170     global $request;
171     switch ($action) {
172     case 'browse':
173     case 'viewsource':
174     case 'diff':
175     case 'select':
176     case 'xmlrpc':
177     case 'search':
178     case 'pdf':
179         return 'view';
180     case 'zip':
181     case 'ziphtml':
182     case 'dumpserial':
183     case 'dumphtml':
184         return 'dump';
185     case 'edit':
186         return 'edit';
187     case 'create':
188         $page = $request->getPage();
189         $current = $page->getCurrentRevision();
190         if ($current->hasDefaultContents())
191             return 'edit';
192         else
193             return 'view'; 
194         break;
195     case 'upload':
196     case 'loadfile': 
197         // probably create/edit but we cannot check all page permissions, can we?
198     case 'remove':
199     case 'lock':
200     case 'unlock':
201     case 'upgrade':
202     case 'chown':
203     case 'setacl':
204     case 'rename':
205             return 'change';
206     default:
207         //Todo: Plugins should be able to override its access type
208         if (isWikiWord($action))
209             return 'view';
210         else
211             return 'change';
212         break;
213     }
214 }
215
216 // Recursive helper to do the real work
217 function _requiredAuthorityForPagename($access, $pagename) {
218     global $request;
219     $page = $request->getPage($pagename);
220     // Page not found; check against default permissions
221     if (! $page->exists() ) {
222         $perm = new PagePermission();
223         return ($perm->isAuthorized($access, $request->_user) === true);
224     }
225     // no ACL defined; check for special dotfile or walk down
226     if (! ($perm = getPagePermissions($page))) { 
227         if ($pagename[0] == '.') {
228             $perm = new PagePermission(PagePermission::dotPerms());
229             return ($perm->isAuthorized($access, $request->_user) === true);
230         }
231         return _requiredAuthorityForPagename($access, getParentPage($pagename));
232     }
233     // ACL defined; check if isAuthorized returns true or false or undecided
234     $authorized = $perm->isAuthorized($access, $request->_user);
235     if ($authorized != -1) // -1 for undecided
236         return $authorized;
237     else
238         return _requiredAuthorityForPagename($access, getParentPage($pagename));
239 }
240
241 /**
242  * @param  string $pagename   page from which the parent page is searched.
243  * @return string parent      pagename or the (possibly pseudo) dot-pagename.
244  */
245 function getParentPage($pagename) {
246     if (isSubPage($pagename)) {
247         return subPageSlice($pagename,0);
248     } else {
249         return '.';
250     }
251 }
252
253 // Read the ACL from the page
254 // Done: Not existing pages should NOT be queried. 
255 // Check the parent page instead and don't take the default ACL's
256 function getPagePermissions ($page) {
257     if ($hash = $page->get('perm'))  // hash => object
258         return new PagePermission(unserialize($hash));
259     else 
260         return false;
261 }
262
263 // Store the ACL in the page
264 function setPagePermissions ($page,$perm) {
265     $perm->store($page);
266 }
267
268 function getAccessDescription($access) {
269     static $accessDescriptions;
270     if (! $accessDescriptions) {
271         $accessDescriptions = array(
272                                     'list'     => _("List this page and all subpages"),
273                                     'view'     => _("View this page and all subpages"),
274                                     'edit'     => _("Edit this page and all subpages"),
275                                     'create'   => _("Create a new (sub)page"),
276                                     'dump'     => _("Download the page contents"),
277                                     'change'   => _("Change page attributes"),
278                                     'remove'   => _("Remove this page"),
279                                     );
280     }
281     if (in_array($access, array_keys($accessDescriptions)))
282         return $accessDescriptions[$access];
283     else
284         return $access;
285 }
286
287 // from php.net docs
288 function array_diff_assoc_recursive($array1, $array2) {
289     foreach ($array1 as $key => $value) {
290          if (is_array($value)) {
291              if (!is_array($array2[$key])) {
292                  $difference[$key] = $value;
293              } else {
294                  $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
295                  if ($new_diff != false) {
296                      $difference[$key] = $new_diff;
297                  } 
298              }
299          } elseif(!isset($array2[$key]) || $array2[$key] != $value) {
300              $difference[$key] = $value;
301          }
302     }
303     return !isset($difference) ? 0 : $difference;
304 }
305
306 /**
307  * The ACL object per page. It is stored in a page, but can also 
308  * be merged with ACL's from other pages or taken from the master (pseudo) dot-file.
309  *
310  * A hash of "access" => "requires" pairs.
311  *   "access"   is a shortcut for common actions, which map to main.php actions
312  *   "requires" required username or groupname or any special group => true or false
313  *
314  * Define any special rules here, like don't list dot-pages.
315  */ 
316 class PagePermission {
317     var $perm;
318
319     function PagePermission($hash = array()) {
320         $this->_group = &WikiGroup::getGroup($GLOBALS['request']);
321         if (is_array($hash) and !empty($hash)) {
322             $accessTypes = $this->accessTypes();
323             foreach ($hash as $access => $requires) {
324                 if (in_array($access, $accessTypes))
325                     $this->perm[$access] = $requires;
326                 else
327                     trigger_error(sprintf(_("Unsupported ACL access type %s ignored."), $access),
328                                   E_USER_WARNING);
329             }
330         } else {
331             // set default permissions, the so called dot-file acl's
332             $this->perm = $this->defaultPerms();
333         }
334         return $this;
335     }
336
337     /**
338      * The workhorse to check the user against the current ACL pairs.
339      * Must translate the various special groups to the actual users settings 
340      * (userid, group membership).
341      */
342     function isAuthorized($access,$user) {
343         if (!empty($this->perm{$access})) {
344             foreach ($this->perm[$access] as $group => $bool) {
345                 if ($this->isMember($user,$group)) {
346                     return $bool;
347                 }
348             }
349         }
350         return -1; // undecided
351     }
352
353     /**
354      * Translate the various special groups to the actual users settings 
355      * (userid, group membership).
356      */
357     function isMember($user, $group) {
358         global $request;
359         if ($group === ACL_EVERY) return true;
360         if (!isset($this->_group)) $member =& WikiGroup::getGroup($request);
361         else $member =& $this->_group;
362         //$user = & $request->_user;
363         if ($group === ACL_ADMIN)   // WIKI_ADMIN or member of _("Administrators")
364             return $user->isAdmin() or 
365                    ($user->isAuthenticated() and 
366                    $member->isMember(GROUP_ADMIN));
367         if ($group === ACL_ANONYMOUS) 
368             return ! $user->isSignedIn();
369         if ($group === ACL_BOGOUSER)
370             if (ENABLE_USER_NEW)
371                 return isa($user,'_BogoUser') or 
372                       (isWikiWord($user->_userid) and $user->_level >= WIKIAUTH_BOGO);
373             else return isWikiWord($user->UserName());
374         if ($group === ACL_HASHOMEPAGE)
375             return $user->hasHomePage();
376         if ($group === ACL_SIGNED)
377             return $user->isSignedIn();
378         if ($group === ACL_AUTHENTICATED)
379             return $user->isAuthenticated();
380         if ($group === ACL_OWNER) {
381             $page = $request->getPage();
382             return ($user->isAuthenticated() and 
383                     $page->getOwner() === $user->UserName());
384         }
385         if ($group === ACL_CREATOR) {
386             $page = $request->getPage();
387             return ($user->isAuthenticated() and 
388                     $page->getCreator() === $user->UserName());
389         }
390         /* Or named groups or usernames.
391            Note: We don't seperate groups and users here. 
392            Users overrides groups with the same name. 
393         */
394         return $user->UserName() === $group or
395                $member->isMember($group);
396     }
397
398     /**
399      * returns hash of default permissions.
400      * check if the page '.' exists and returns this instead.
401      */
402     function defaultPerms() {
403         //Todo: check for the existance of '.' and take this instead.
404         //Todo: honor more config.ini auth settings here
405         $perm = array('view'   => array(ACL_EVERY => true),
406                       'edit'   => array(ACL_EVERY => true),
407                       'create' => array(ACL_EVERY => true),
408                       'list'   => array(ACL_EVERY => true),
409                       'remove' => array(ACL_ADMIN => true,
410                                         ACL_OWNER => true),
411                       'change' => array(ACL_ADMIN => true,
412                                         ACL_OWNER => true));
413         if (ZIPDUMP_AUTH)
414             $perm['dump'] = array(ACL_ADMIN => true,
415                                   ACL_OWNER => true);
416         else
417             $perm['dump'] = array(ACL_EVERY => true);
418         // view:
419         if (!ALLOW_ANON_USER) {
420             if (!ALLOW_USER_PASSWORDS) 
421                 $perm['view'] = array(ACL_SIGNED => true);
422             else                
423                 $perm['view'] = array(ACL_AUTHENTICATED => true);
424             $perm['view'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
425         }
426         // edit:
427         if (!ALLOW_ANON_EDIT) {
428             if (!ALLOW_USER_PASSWORDS) 
429                 $perm['edit'] = array(ACL_SIGNED => true);
430             else                
431                 $perm['edit'] = array(ACL_AUTHENTICATED => true);
432             $perm['edit'][ACL_BOGOUSER] = ALLOW_BOGO_LOGIN ? true : false;
433             $perm['create'] = $perm['edit'];
434         }
435         return $perm;
436     }
437
438     /**
439      * FIXME: check valid groups and access
440      */
441     function sanify() {
442         foreach ($this->perm as $access => $groups) {
443             foreach ($groups as $group => $bool) {
444                 $this->perm[$access][$group] = (boolean) $bool;
445             }
446         }
447     }
448
449     /**
450      * do a recursive comparison
451      */
452     function equal($otherperm) {
453         $diff = array_diff_assoc_recursive($this->perm, $otherperm);
454         return empty($diff);
455     }
456     
457     /**
458      * returns list of all supported access types.
459      */
460     function accessTypes() {
461         return array_keys(PagePermission::defaultPerms());
462     }
463
464     /**
465      * special permissions for dot-files, beginning with '.'
466      * maybe also for '_' files?
467      */
468     function dotPerms() {
469         $def = array(ACL_ADMIN => true,
470                      ACL_OWNER => true);
471         $perm = array();
472         foreach (PagePermission::accessTypes() as $access) {
473             $perm[$access] = $def;
474         }
475         return $perm;
476     }
477
478     /**
479      *  dead code. not needed inside the object. see getPagePermissions($page)
480      */
481     function retrieve($page) {
482         $hash = $page->get('perm');
483         if ($hash)  // hash => object
484             $perm = new PagePermission(unserialize($hash));
485         else 
486             $perm = new PagePermission();
487         $perm->sanify();
488         return $perm;
489     }
490
491     function store($page) {
492         // object => hash
493         $this->sanify();
494         return $page->set('perm',serialize($this->perm));
495     }
496
497     function groupName ($group) {
498         if ($group[0] == '_') return constant("GROUP".$group);
499         else return $group;
500     }
501     
502     /* type: page, default, inherited */
503     function asTable($type) {
504         $table = HTML::table();
505         foreach ($this->perm as $access => $perms) {
506             $td = HTML::table(array('class' => 'cal','valign' => 'top'));
507             foreach ($perms as $group => $bool) {
508                 $td->pushContent(HTML::tr(HTML::td(array('align'=>'right'),$group),
509                                                    HTML::td($bool ? '[X]' : '[ ]')));
510             }
511             $table->pushContent(HTML::tr(array('valign' => 'top'),
512                                          HTML::td($access),HTML::td($td)));
513         }
514         if ($type == 'default')
515             $table->setAttr('style','border: dotted thin black; background-color:#eee;');
516         elseif ($type == 'inherited')
517             $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
518         elseif ($type == 'page')
519             $table->setAttr('style','border: solid thin black; font-weight: bold;');
520         return $table;
521     }
522     
523     /* type: page, default, inherited */
524     function asEditableTable($type) {
525         global $Theme;
526         if (!isset($this->_group)) { 
527             $this->_group =& WikiGroup::getGroup($GLOBALS['request']);
528         }
529         $table = HTML::table();
530         $table->pushContent(HTML::tr(
531                                      HTML::th(array('align' => 'left'),
532                                               _("Access")),
533                                      HTML::th(array('align'=>'right'),
534                                               _("Group/User")),
535                                      HTML::th(_("Grant")),
536                                      HTML::th(_("Del/+")),
537                                      HTML::th(_("Description"))));
538         
539         $allGroups = $this->_group->_specialGroups();
540         foreach ($this->_group->getAllGroupsIn() as $group) {
541             if (!in_array($group,$this->_group->specialGroups()))
542                 $allGroups[] = $group;
543         }
544         //array_unique(array_merge($this->_group->getAllGroupsIn(),
545         $deletesrc = $Theme->_findData('images/delete.png');
546         $addsrc = $Theme->_findData('images/add.png');
547         $nbsp = HTML::raw('&nbsp;');
548         foreach ($this->perm as $access => $groups) {
549             //$permlist = HTML::table(array('class' => 'cal','valign' => 'top'));
550             $first_only = true;
551             $newperm = HTML::input(array('type' => 'checkbox',
552                                          'name' => "acl[_new_perm][$access]",
553                                          'value' => 1));
554             $addbutton = HTML::input(array('type' => 'checkbox',
555                                            'name' => "acl[_add_group][$access]",
556                                            //'src'  => $addsrc,
557                                            //'alt'   => "Add",
558                                            'title' => _("Add this ACL"),
559                                            'value' => 1));
560             $newgroup = HTML::select(array('name' => "acl[_new_group][$access]",
561                                            'style'=> 'text-align: right;',
562                                            'size' => 1));
563             foreach ($allGroups as $groupname) {
564                 if (!isset($groups[$groupname]))
565                     $newgroup->pushContent(HTML::option(array('value' => $groupname),
566                                                         $this->groupName($groupname)));
567             }
568             if (empty($groups)) {
569                 $addbutton->setAttr('checked','checked');
570                 $newperm->setAttr('checked','checked');
571                 $table->pushContent(
572                     HTML::tr(array('valign' => 'top'),
573                              HTML::td(HTML::strong($access.":")),
574                              HTML::td($newgroup),
575                              HTML::td($nbsp,$newperm),
576                              HTML::td($nbsp,$addbutton),
577                              HTML::td(HTML::em(getAccessDescription($access)))));
578             }
579             foreach ($groups as $group => $bool) {
580                 $checkbox = HTML::input(array('type' => 'checkbox',
581                                               'name' => "acl[$access][$group]",
582                                               'title' => _("Allow / Deny"),
583                                               'value' => 1));
584                 if ($bool) $checkbox->setAttr('checked','checked');
585                 $checkbox = HTML(HTML::input(array('type' => 'hidden',
586                                                    'name' => "acl[$access][$group]",
587                                                    'value' => 0)),
588                                  $checkbox);
589                 $deletebutton = HTML::input(array('type' => 'checkbox',
590                                                   'name' => "acl[_del_group][$access][$group]",
591                                                   'style' => 'background: #aaa url('.$deletesrc.')',
592                                                   //'src'  => $deletesrc,
593                                                   //'alt'   => "Del",
594                                                   'title' => _("Delete this ACL"),
595                                                   'value' => 1));
596                 if ($first_only) {
597                     $table->pushContent(
598                         HTML::tr(
599                                  HTML::td(HTML::strong($access.":")),
600                                  HTML::td(array('class' => 'cal-today','align'=>'right'),
601                                           HTML::strong($this->groupName($group))),
602                                  HTML::td(array('align'=>'center'),$nbsp,$checkbox),
603                                  HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
604                                  HTML::td(HTML::em(getAccessDescription($access)))));
605                     $first_only = false;
606                 } else {
607                     $table->pushContent(
608                         HTML::tr(
609                                  HTML::td(),
610                                  HTML::td(array('class' => 'cal-today','align'=>'right'),
611                                           HTML::strong($this->groupName($group))),
612                                  HTML::td(array('align'=>'center'),$nbsp,$checkbox),
613                                  HTML::td(array('align'=>'right','style' => 'background: #aaa url('.$deletesrc.') no-repeat'),$deletebutton),
614                                  HTML::td()));
615                 }
616             }
617             if (!empty($groups))
618                 $table->pushContent(
619                     HTML::tr(array('valign' => 'top'),
620                              HTML::td(array('align'=>'right'),_("add ")),
621                              HTML::td($newgroup),
622                              HTML::td(array('align'=>'center'),$nbsp,$newperm),
623                              HTML::td(array('align'=>'right','style' => 'background: #ccc url('.$addsrc.') no-repeat'),$addbutton),
624                              HTML::td(HTML::small(_("Check to add this Acl")))));
625         }
626         if ($type == 'default')
627             $table->setAttr('style','border: dotted thin black; background-color:#eee;');
628         elseif ($type == 'inherited')
629             $table->setAttr('style','border: dotted thin black; background-color:#ddd;');
630         elseif ($type == 'page')
631             $table->setAttr('style','border: solid thin black; font-weight: bold;');
632         return $table;
633     }
634
635     // Print ACL as lines of [+-]user[,group,...]:access[,access...]
636     // Seperate acl's by "; " or whitespace
637     // See http://opag.ca/wiki/HelpOnAccessControlLists
638     // As used by WikiAdminSetAclSimple
639     function asAclLines() {
640         $s = ''; $line = '';
641         $this->sanify();
642         foreach ($this->perm as $access => $groups) {
643             // unify groups for same access+bool
644             //    view:CREATOR,-OWNER,
645             $line = $access.':';
646             foreach ($groups as $group => $bool) {
647                 $line .= ($bool?'':'-').$group.",";
648             }
649             if (substr($line,-1) == ',')
650                 $s .= substr($line,0,-1)."; ";
651         }
652         if (substr($s,-2) == '; ')
653             $s = substr($s,0,-2);
654         return $s;
655     }
656
657
658     // This is just a bad hack for testing.
659     // Simplify the ACL to a unix-like "rwx------+" string
660     // See getfacl(8)
661     function asRwxString($owner,$group=false) {
662         global $request;
663         // simplify object => rwxrw---x+ string as in cygwin (+ denotes additional ACLs)
664         $perm =& $this->perm;
665         // get effective user and group
666         $s = '---------+';
667         if (isset($perm['view'][$owner]) or 
668             (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
669             $s[0] = 'r';
670         if (isset($perm['edit'][$owner]) or 
671             (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
672             $s[1] = 'w';
673         if (isset($perm['change'][$owner]) or 
674             (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
675             $s[2] = 'x';
676         if (!empty($group)) {
677             if (isset($perm['view'][$group]) or 
678                 (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
679                 $s[3] = 'r';
680             if (isset($perm['edit'][$group]) or 
681                 (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
682                 $s[4] = 'w';
683             if (isset($perm['change'][$group]) or 
684                 (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
685                 $s[5] = 'x';
686         }
687         if (isset($perm['view'][ACL_EVERY]) or 
688             (isset($perm['view'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
689             $s[6] = 'r';
690         if (isset($perm['edit'][ACL_EVERY]) or 
691             (isset($perm['edit'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
692             $s[7] = 'w';
693         if (isset($perm['change'][ACL_EVERY]) or 
694             (isset($perm['change'][ACL_AUTHENTICATED]) and $request->_user->isAuthenticated()))
695             $s[8] = 'x';
696         return $s;
697     }
698 }
699
700 // $Log: not supported by cvs2svn $
701 // Revision 1.23  2004/06/08 10:05:11  rurban
702 // simplified admin action shortcuts
703 //
704 // Revision 1.22  2004/06/07 22:44:14  rurban
705 // added simplified chown, setacl actions
706 //
707 // Revision 1.21  2004/06/07 22:28:03  rurban
708 // add acl field to mimified dump
709 //
710 // Revision 1.20  2004/06/07 18:39:03  rurban
711 // support for SetAclSimple
712 //
713 // Revision 1.19  2004/06/06 17:12:28  rurban
714 // fixed PagePerm non-object problem (mayAccessPage), also bug #967150
715 //
716 // Revision 1.18  2004/05/27 17:49:05  rurban
717 // renamed DB_Session to DbSession (in CVS also)
718 // added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
719 // remove leading slash in error message
720 // added force_unlock parameter to File_Passwd (no return on stale locks)
721 // fixed adodb session AffectedRows
722 // added FileFinder helpers to unify local filenames and DATA_PATH names
723 // editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
724 //
725 // Revision 1.17  2004/05/16 23:10:44  rurban
726 // update_locale wrongly resetted LANG, which broke japanese.
727 // japanese now correctly uses EUC_JP, not utf-8.
728 // more charset and lang headers to help the browser.
729 //
730 // Revision 1.16  2004/05/16 22:32:53  rurban
731 // setacl icons
732 //
733 // Revision 1.15  2004/05/16 22:07:35  rurban
734 // check more config-default and predefined constants
735 // various PagePerm fixes:
736 //   fix default PagePerms, esp. edit and view for Bogo and Password users
737 //   implemented Creator and Owner
738 //   BOGOUSERS renamed to BOGOUSER
739 // fixed syntax errors in signin.tmpl
740 //
741 // Revision 1.14  2004/05/15 22:54:49  rurban
742 // fixed important WikiDB bug with DEBUG > 0: wrong assertion
743 // improved SetAcl (works) and PagePerms, some WikiGroup helpers.
744 //
745 // Revision 1.13  2004/05/15 19:48:33  rurban
746 // fix some too loose PagePerms for signed, but not authenticated users
747 //  (admin, owner, creator)
748 // no double login page header, better login msg.
749 // moved action_pdf to lib/pdf.php
750 //
751 // Revision 1.12  2004/05/04 22:34:25  rurban
752 // more pdf support
753 //
754 // Revision 1.11  2004/05/02 21:26:38  rurban
755 // limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
756 //   because they will not survive db sessions, if too large.
757 // extended action=upgrade
758 // some WikiTranslation button work
759 // revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
760 // some temp. session debug statements
761 //
762 // Revision 1.10  2004/04/29 22:32:56  zorloc
763 // Slightly more elegant fix.  Instead of WIKIAUTH_FORBIDDEN, the current user's level + 1 is returned on a false.
764 //
765 // Revision 1.9  2004/04/29 17:18:19  zorloc
766 // 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.
767 //
768 // Revision 1.8  2004/03/14 16:24:35  rurban
769 // authenti(fi)cation spelling
770 //
771 // Revision 1.7  2004/02/28 22:25:07  rurban
772 // First PagePerm implementation:
773 //
774 // $Theme->setAnonEditUnknownLinks(false);
775 //
776 // Layout improvement with dangling links for mostly closed wiki's:
777 // If false, only users with edit permissions will be presented the
778 // special wikiunknown class with "?" and Tooltip.
779 // If true (default), any user will see the ?, but will be presented
780 // the PrintLoginForm on a click.
781 //
782 // Revision 1.6  2004/02/24 15:20:05  rurban
783 // fixed minor warnings: unchecked args, POST => Get urls for sortby e.g.
784 //
785 // Revision 1.5  2004/02/23 21:30:25  rurban
786 // more PagePerm stuff: (working against 1.4.0)
787 //   ACL editing and simplification of ACL's to simple rwx------ string
788 //   not yet working.
789 //
790 // Revision 1.4  2004/02/12 13:05:36  rurban
791 // Rename functional for PearDB backend
792 // some other minor changes
793 // SiteMap comes with a not yet functional feature request: includepages (tbd)
794 //
795 // Revision 1.3  2004/02/09 03:58:12  rurban
796 // for now default DB_SESSION to false
797 // PagePerm:
798 //   * not existing perms will now query the parent, and not
799 //     return the default perm
800 //   * added pagePermissions func which returns the object per page
801 //   * added getAccessDescription
802 // WikiUserNew:
803 //   * added global ->prepare (not yet used) with smart user/pref/member table prefixing.
804 //   * force init of authdbh in the 2 db classes
805 // main:
806 //   * fixed session handling (not triple auth request anymore)
807 //   * don't store cookie prefs with sessions
808 // stdlib: global obj2hash helper from _AuthInfo, also needed for PagePerm
809 //
810 // Revision 1.2  2004/02/08 13:17:48  rurban
811 // This should be the functionality. Needs testing and some minor todos.
812 //
813 // Revision 1.1  2004/02/08 12:29:30  rurban
814 // initial version, not yet hooked into lib/main.php
815 //
816 //
817
818 // Local Variables:
819 // mode: php
820 // tab-width: 8
821 // c-basic-offset: 4
822 // c-hanging-comment-ender-p: nil
823 // indent-tabs-mode: nil
824 // End:
825 ?>