From 95b84981f82ffc81881f370a40fc90c603f6e76a Mon Sep 17 00:00:00 2001 From: rurban Date: Mon, 9 Feb 2004 03:58:20 +0000 Subject: [PATCH] for now default DB_SESSION to false PagePerm: * not existing perms will now query the parent, and not return the default perm * added pagePermissions func which returns the object per page * added getAccessDescription WikiUserNew: * added global ->prepare (not yet used) with smart user/pref/member table prefixing. * force init of authdbh in the 2 db classes main: * fixed session handling (not triple auth request anymore) * don't store cookie prefs with sessions stdlib: global obj2hash helper from _AuthInfo, also needed for PagePerm git-svn-id: svn://svn.code.sf.net/p/phpwiki/code/trunk@2988 96ab9672-09ca-45d6-a79d-3d69d39ca109 --- index.php | 13 ++++- lib/PagePerm.php | 113 +++++++++++++++++++++++++++++---------- lib/WikiUserNew.php | 43 +++++++++++++-- lib/main.php | 69 +++++++++++++++--------- lib/plugin/_AuthInfo.php | 34 ++++++------ lib/stdlib.php | 35 +++++++++++- 6 files changed, 228 insertions(+), 79 deletions(-) diff --git a/index.php b/index.php index 83dfe4287..a7b62232e 100644 --- a/index.php +++ b/index.php @@ -73,7 +73,7 @@ define('ENABLE_USER_NEW',true); define ('PHPWIKI_VERSION', '1.3.8pre'); require "lib/prepend.php"; -rcs_id('$Id: index.php,v 1.122 2004-02-07 14:20:18 rurban Exp $'); +rcs_id('$Id: index.php,v 1.123 2004-02-09 03:58:07 rurban Exp $'); ///////////////////////////////////////////////////////////////////// // @@ -319,9 +319,15 @@ $DBParams = array( ///////////////////////////////////////////////////////////////////// // PHP Session settings: // + +// USE_DB_SESSION fails with the current CVS code. +define('USE_DB_SESSION',false); // Only for $DBParams['dbtype'] => 'SQL'. See schemas/mysql.sql or // schemas/psql.sql. $DBParams['db_session_table'] must be defined. -if ($DBParams['dbtype'] == 'SQL' and $DBParams['db_session_table']) define('USE_DB_SESSION',true); +if (!defined('USE_DB_SESSION') and + $DBParams['dbtype'] == 'SQL' and + $DBParams['db_session_table']) + define('USE_DB_SESSION',true); // If your php was compiled with --enable-trans-sid it tries to // add a PHPSESSID query argument to all URL strings when cookie @@ -904,6 +910,9 @@ if (defined('VIRTUAL_PATH') and defined('USE_PATH_INFO')) { include "lib/main.php"; // $Log: not supported by cvs2svn $ +// Revision 1.122 2004/02/07 14:20:18 rurban +// consistent mysql schema with index.php (userid) +// // Revision 1.121 2004/02/07 10:41:25 rurban // fixed auth from session (still double code but works) // fixed GroupDB diff --git a/lib/PagePerm.php b/lib/PagePerm.php index ffa067583..3b0dbc64f 100644 --- a/lib/PagePerm.php +++ b/lib/PagePerm.php @@ -1,5 +1,5 @@ view edit => edit create => edit or create @@ -68,13 +69,40 @@ define('ACL_ADMIN', '_ADMIN'); define('ACL_OWNER', '_OWNER'); define('ACL_CREATOR', '_CREATOR'); +// Return the page permissions object for this page. +// To provide ui helpers to view and change page permissions: +// GroupAccessAllow or Forbid +// $group_($access) [ ] +function pagePermissions($pagename) { + global $request; + $page = $request->getPage($pagename); + // Page not found (new page); returned inherited permissions, to be displayed in gray + if (! $page ) { + if ($pagename == '.') // stop recursion + return array('default' => new PagePermissions()); + else + return array('inherited' => pagePermissions(getParentPage($pagename))); + } elseif ($perm = getPagePermissions($page)) { + return array('ok' => $perm); + // or no permissions defined; returned inherited permissions, to be displayed in gray + } else { + return array('inherited' => pagePermissions(getParentPage($pagename))); + } +} + +// Check the permissions for the current action. // Walk down the inheritance tree. Collect all permissions until // the minimum required level is gained, which is not // overruled by more specific forbid rules. -// Todo: cache result per access and page in session +// Todo: cache result per access and page in session? function requiredAuthorityForPage ($action) { + return _requiredAuthorityForPagename(action2access($action), + $GLOBALS['request']->getArg('pagename')); +} + +// Translate action or plugin to the simplier access types: +function action2access ($action) { global $request; - // translate action to access switch ($action) { case 'browse': case 'viewsource': @@ -82,19 +110,19 @@ function requiredAuthorityForPage ($action) { case 'select': case 'xmlrpc': case 'search': - $access = 'view'; break; + return 'view'; case 'zip': case 'ziphtml': - $access = 'dump'; break; + return 'dump'; case 'edit': - $access = 'edit'; break; + return 'edit'; case 'create': - $page = $this->getPage(); + $page = $request->getPage(); $current = $page->getCurrentRevision(); if ($current->hasDefaultContents()) - $access = 'edit'; + return 'edit'; else - $access = 'view'; + return 'view'; break; case 'upload': case 'dumpserial': @@ -103,36 +131,45 @@ function requiredAuthorityForPage ($action) { case 'remove': case 'lock': case 'unlock': - $access = 'change'; break; + return 'change'; default: + //Todo: Plugins should be able to override its access type if (isWikiWord($action)) - $access = 'view'; + return 'view'; else - $access = 'change'; + return 'change'; break; } - return _requiredAuthorityForPagename($access,$request->getArg('pagename')); } -function _requiredAuthorityForPagename ($access,$pagename) { +// Recursive helper to do the real work +function _requiredAuthorityForPagename($access, $pagename) { global $request; $page = $request->getPage($pagename); + // Page not found; check against default permissions if (! $page ) { - $perm = new PagePermission(); // check against default permissions + $perm = new PagePermission(); return ($perm->isAuthorized($access,$request->_user) === true); } - $perm = getPagePermissions($page); + // no ACL defined; check for special dotfile or walk down + if (! ($perm = getPagePermissions($page))) { + if ($pagename[0] == '.') { + $perm = new PagePermission(PagePermission::dotPerms()); + return ($perm->isAuthorized($access,$request->_user) === true); + } + return _requiredAuthorityForPagename($access,getParentPage($pagename)); + } + // ACL defined; check if isAuthorized returns true or false $authorized = $perm->isAuthorized($access,$request->_user); - if ($authorized != -1) + if ($authorized != -1) // -1 for undecided return $authorized ? $request->_user->_level : WIKIAUTH_FORBIDDEN; else return _requiredAuthorityForPagename($access,getParentPage($pagename)); } - -/* +/** * @param string $pagename page from which the parent page is searched. - * @return string parent pagename or the (possibly pseudo) dot-pagename. + * @return string parent pagename or the (possibly pseudo) dot-pagename. */ function getParentPage($pagename) { global $request; @@ -143,23 +180,38 @@ function getParentPage($pagename) { } } -// read the ACL from the page +// Read the ACL from the page +// Done: Not existing pages should NOT be queried. +// Check the parent page instead and don't take the default ACL's function getPagePermissions ($page) { - $hash = $page->get('perm'); - if ($hash) // hash => object + if ($hash = $page->get('perm')) // hash => object return new PagePermission(unserialize($hash)); else - return new PagePermission(); + return false; } -// store the ACL in the page +// Store the ACL in the page function setPagePermissions ($page,$perm) { $perm->store($page); } -// provide ui helpers to view and change page permissions -function displayPagePermissions () { - return ''; +function getAccessDescription($access) { + static $accessDescriptions; + if (! $accessDescriptions) { + $accessDescriptions = array( + 'list' => _("List this page and all subpages"), + 'view' => _("View this page and all subpages"), + 'edit' => _("Edit this page and all subpages"), + 'create' => _("Create a new (sub)page"), + 'dump' => _("Download the page contents"), + 'change' => _("Change page attributes"), + 'remove' => _("Remove this page"), + ); + } + if (in_array($action, array_keys($accessDescriptions))) + return $accessDescriptions[$access]; + else + return $access; } /** @@ -317,6 +369,9 @@ class PagePermission { } // $Log: not supported by cvs2svn $ +// Revision 1.2 2004/02/08 13:17:48 rurban +// This should be the functionality. Needs testing and some minor todos. +// // Revision 1.1 2004/02/08 12:29:30 rurban // initial version, not yet hooked into lib/main.php // diff --git a/lib/WikiUserNew.php b/lib/WikiUserNew.php index 71c0e66bf..2ca8dce9a 100644 --- a/lib/WikiUserNew.php +++ b/lib/WikiUserNew.php @@ -1,5 +1,5 @@ getPreferences(); // Upgrade to the next parent _PassUser class. Avoid recursion. - if ( get_class($this) === '_passuser' ) { + if ( get_class($this) === '_passuser' ) { // hopefully PHP will keep this lowercase //auth policy: Check the order of the configured auth methods // 1. first-only: Upgrade the class here in the constructor // 2. old: ignore USER_AUTH_ORDER and try to use all available methods as in the previous PhpWiki releases (slow) @@ -687,6 +687,33 @@ extends _AnonUser return $this->_auth_dbi; } + function prepare ($stmt, $variables) { + global $DBParams, $request; + // preparate the SELECT statement, for ADODB and PearDB (MDB not) + $this->getAuthDbh(); + $place = ($DBParams['dbtype'] == 'ADODB') ? '%s' : '?'; + if (is_array($variables)) { + $new = array(); + foreach ($variables as $v) { $new[] = $place; } + } else { + $new = $place; + } + // probably prefix table names if in same database + if (!empty($DBParams['prefix']) and + $this->_auth_dbi === $request->_dbi->_backend->_dbh) { + if (!stristr($DBParams['prefix'],$stmt)) { + //Do it automatically for the lazy admin? Esp. on sf.net it's nice to have + trigger_error("TODO: Need to prefix the DBAuthParam tablename in index.php: $stmt", + E_USER_WARNING); + $stmt = str_replace(array(" user "," pref "," member "), + array(" ".$prefix."user ", + " ".$prefix."prefs ", + " ".$prefix."member "),$stmt); + } + } + return $this->_auth_dbi->prepare(str_replace($variables,$new,$stmt)); + } + //TODO: password changing //TODO: email verification @@ -883,7 +910,7 @@ extends _PassUser if (!$this->_prefs) _PassUser::_PassUser($UserName); $this->_authmethod = 'DB'; - $this->_auth_dbi = $this->getAuthDbh(); + $this->getAuthDbh(); $this->_auth_crypt_method = $GLOBALS['DBAuthParams']['auth_crypt_method']; if ($GLOBALS['DBParams']['dbtype'] == 'ADODB') @@ -908,6 +935,8 @@ extends _DbPassUser global $DBAuthParams; if (!$this->_prefs) _PassUser::_PassUser($UserName); + $this->getAuthDbh(); + $this->_auth_crypt_method = $GLOBALS['DBAuthParams']['auth_crypt_method']; // Prepare the configured auth statements if (!empty($DBAuthParams['auth_check']) and !isset($this->_authselect)) { $this->_authselect = $this->_auth_dbi->prepare ( @@ -1053,6 +1082,8 @@ extends _DbPassUser global $DBAuthParams; if (!$this->_prefs) _PassUser::_PassUser($UserName); + $this->getAuthDbh(); + $this->_auth_crypt_method = $GLOBALS['DBAuthParams']['auth_crypt_method']; // Prepare the configured auth statements if (!empty($DBAuthParams['auth_check'])) { $this->_authselect = str_replace(array('"$userid"','"$password"'),array('%s','%s'), @@ -1762,6 +1793,12 @@ extends UserPreferences // $Log: not supported by cvs2svn $ +// Revision 1.12 2004/02/07 10:41:25 rurban +// fixed auth from session (still double code but works) +// fixed GroupDB +// fixed DbPassUser upgrade and policy=old +// added GroupLdap +// // Revision 1.11 2004/02/03 09:45:39 rurban // LDAP cleanup, start of new Pref classes // diff --git a/lib/main.php b/lib/main.php index 41797a785..b0c5c9cd1 100644 --- a/lib/main.php +++ b/lib/main.php @@ -1,5 +1,5 @@ _deduceUsername(); if (isset($this->_user) and $this->_user->_authhow == 'session') { - $user = $this->_user; + // users might switch in a session between the two objects. + // restore old auth level here or in updateAuthAndPrefs? + $user = $this->getSessionVar('wiki_user'); + if (isa($user,WikiUserClassname()) and !empty($user->_level)) { + ; + /* not needed: + if (empty($this->_user)) { + $c = get_class($user); + $userid = $user->UserName(); + $this->_user = new $c($userid); + } + if ($user = UpgradeUser($this->_user,$user)) + $this->_user = $user; + */ + } else { + $user = UpgradeUser($this->_user,$user); + } $this->_prefs = $this->_user->_prefs; } else { $user = WikiUser($userid); - // todo: upgrade later at updateAuthAndPrefs() - // fixme: already done in _deduceUsername() + //Todo: upgrade later at updateAuthAndPrefs() if (isset($this->_user)) $user = UpgradeUser($this->_user,$user); $this->_user = $user; $this->_prefs = $this->_user->_prefs; } } else { + // no upgrade from session $this->_user = new WikiUser($this, $this->_deduceUsername()); $this->_prefs = $this->_user->getPreferences(); } @@ -119,11 +136,14 @@ class WikiRequest extends Request { } // Save preferences in session and cookie - // FIXME: hey! what about anonymous users? Can't they have - // preferences too? - - $id_only = true; - $this->_user->setPreferences($this->_prefs, $id_only); + if (isset($this->_user) and + (!isset($this->_user->_authhow) or $this->_user->_authhow != 'session')) { + $id_only = true; + $this->_user->setPreferences($this->_prefs, $id_only); + } else { + $this->setSessionVar('wiki_user', $this->_user); + $this->setSessionVar('wiki_prefs', $this->_prefs); + } // Ensure user has permissions for action $require_level = $this->requiredAuthority($this->getArg('action')); @@ -257,6 +277,8 @@ class WikiRequest extends Request { $user->isSignedIn() ? $user->getId() : ''); } + /* Permission system */ + function _notAuthorized ($require_level) { // Display the authority message in the Wiki's default // language, in case it is not english. @@ -288,6 +310,8 @@ class WikiRequest extends Request { $this->finish(); // NORETURN } + // Fixme: for PagePermissions we'll need other strings, + // relevant to the requested page, not just for the action on the whole wiki. function getActionDescription($action) { static $actionDescriptions; if (! $actionDescriptions) { @@ -410,6 +434,7 @@ class WikiRequest extends Request { return WIKIAUTH_ADMIN; } } + /* End of Permission system */ function possiblyDeflowerVirginWiki () { if ($this->getArg('action') != 'browse') @@ -541,23 +566,9 @@ class WikiRequest extends Request { return $this->args['auth']['userid']; if ($user = $this->getSessionVar('wiki_user')) { - // users might switch in a session between the two objects - // restore old auth level here or in updateAuthAndPrefs()? - if (isa($user,WikiUserClassname()) and !empty($user->_level)) { - if (empty($this->_user)) { - $c = get_class($user); - $userid = $user->UserName(); - if (ENABLE_USER_NEW) - $this->_user = new $c($userid); - else - $this->_user = new $c($this,$userid,$user->_level); - } - if ($user = UpgradeUser($this->_user,$user)) - $this->_user = $user; - $this->_user->_authhow = 'session'; - } - if (isa($user,WikiUserClassname())) - return $user->UserName(); + $this->_user = $user; + $this->_user->_authhow = 'session'; + return $user->UserName(); } if ($userid = $this->getCookieVar('WIKI_ID')) { if (!empty($this->_user)) @@ -860,6 +871,12 @@ main(); // $Log: not supported by cvs2svn $ +// Revision 1.111 2004/02/07 10:41:25 rurban +// fixed auth from session (still double code but works) +// fixed GroupDB +// fixed DbPassUser upgrade and policy=old +// added GroupLdap +// // Revision 1.110 2004/02/03 09:45:39 rurban // LDAP cleanup, start of new Pref classes // diff --git a/lib/plugin/_AuthInfo.php b/lib/plugin/_AuthInfo.php index 1de756277..80f488257 100644 --- a/lib/plugin/_AuthInfo.php +++ b/lib/plugin/_AuthInfo.php @@ -1,5 +1,5 @@ pushContent($this->_showhash("LDAP DEFINES", - $this->_buildConstHash(array("LDAP_AUTH_HOST","LDAP_AUTH_SEARCH")))); + $this->_buildConstHash(array("LDAP_AUTH_HOST","LDAP_BASE_DN")))); if ((defined('ALLOW_IMAP_LOGIN') && ALLOW_IMAP_LOGIN) or in_array("IMAP",$GLOBALS['USER_AUTH_ORDER'])) $table->pushContent($this->_showhash("IMAP DEFINES", array("IMAP_AUTH_HOST" => IMAP_AUTH_HOST))); if (defined('AUTH_USER_FILE') or in_array("File",$GLOBALS['USER_AUTH_ORDER'])) @@ -92,7 +94,7 @@ extends WikiPlugin 'cellpadding' => 2, 'cellspacing' => 0)); //$table->pushContent(HTML::tr(HTML::td(array('colspan' => 2)))); - $userdata = $this->_obj2hash($user); + $userdata = obj2hash($user); $table->pushContent($this->_showhash("User: Object of ".get_class($user), $userdata)); $group = &WikiGroup::getGroup($request); $table->pushContent($this->_showhash("Group: Object of ".get_class($group), $group)); @@ -108,18 +110,6 @@ extends WikiPlugin return $html; } - function _obj2hash ($obj, $exclude = false, $fields = false) { - $a = array(); - if (! $fields ) $fields = get_object_vars($obj); - foreach ($fields as $key => $val) { - if (is_array($exclude)) { - if (in_array($key,$exclude)) continue; - } - $a[$key] = $val; - } - return $a; - } - function _showhash ($heading, $hash) { static $seen = array(); $rows = array(); @@ -129,6 +119,8 @@ extends WikiPlugin HTML::td(array('colspan' => 2, 'style' => 'color:#000000'), $heading)); + if (is_object($hash)) + $hash = obj2hash($hash); if (!empty($hash)) { ksort($hash); foreach ($hash as $key => $val) { @@ -141,7 +133,7 @@ extends WikiPlugin $val = HTML::table(array('border' => 1, 'cellpadding' => 2, 'cellspacing' => 0), - $this->_showhash($heading, $this->_obj2hash($val))); + $this->_showhash($heading, obj2hash($val))); } else { $val = $heading; } @@ -184,6 +176,12 @@ extends WikiPlugin }; // $Log: not supported by cvs2svn $ +// Revision 1.4 2004/02/07 10:41:25 rurban +// fixed auth from session (still double code but works) +// fixed GroupDB +// fixed DbPassUser upgrade and policy=old +// added GroupLdap +// // Revision 1.3 2004/02/02 05:36:29 rurban // Simplification and more options, but no passwd or admin protection yet. // diff --git a/lib/stdlib.php b/lib/stdlib.php index 907320a4f..bdeda83d6 100644 --- a/lib/stdlib.php +++ b/lib/stdlib.php @@ -1,4 +1,4 @@ - $val) { + if (is_array($exclude)) { + if (in_array($key,$exclude)) continue; + } + $a[$key] = $val; + } + return $a; +} + // $Log: not supported by cvs2svn $ +// Revision 1.156 2004/01/26 09:17:49 rurban +// * changed stored pref representation as before. +// the array of objects is 1) bigger and 2) +// less portable. If we would import packed pref +// objects and the object definition was changed, PHP would fail. +// This doesn't happen with an simple array of non-default values. +// * use $prefs->retrieve and $prefs->store methods, where retrieve +// understands the interim format of array of objects also. +// * simplified $prefs->get() and fixed $prefs->set() +// * added $user->_userid and class '_WikiUser' portability functions +// * fixed $user object ->_level upgrading, mostly using sessions. +// this fixes yesterdays problems with loosing authorization level. +// * fixed WikiUserNew::checkPass to return the _level +// * fixed WikiUserNew::isSignedIn +// * added explodePageList to class PageList, support sortby arg +// * fixed UserPreferences for WikiUserNew +// * fixed WikiPlugin for empty defaults array +// * UnfoldSubpages: added pagename arg, renamed pages arg, +// removed sort arg, support sortby arg +// // Revision 1.155 2004/01/25 10:52:22 rurban // added sortby support to explodePageList() and UnfoldSubpages // fixes [ 758044 ] Plugin UnfoldSubpages does not sort (includes fix) -- 2.45.0