<?php if (!defined('PmWiki')) exit(); # vim: set ts=4 sw=4 et: /* === UserAdminAuthUser === * Copyright 2010 Peter Bowers * * Extension to Cookbook/UserAdmin to allow self-registration info * and other user info to be stored in SiteAdmin.AuthUser in an * extended syntax as compared to the standard syntax for that page. * * To install, add the following line to your configuration file : include_once("$FarmD/cookbook/useradmin-authuser.php"); * * For more information, please see the online documentation at * http://www.pmwiki.org/wiki/Cookbook/UserAdmin * * This script is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This script is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ $RecipeInfo['UserAdmin-AuthUser']['Version'] = '2011-04-03'; if (!IsEnabled($EnableAuthorTracking,1)) Abort('$EnableAuthorTracking required for UserAdmin-AuthUser'); $AuthUserPat = "/^\\s*([@\\w][^\\s:]*)\\s*:([^:\\n]*)(?::(.*$)|$)/m"; if (strncmp($action, 'user', 4)) return; require_once('useradmin-core.php'); class UserAdminAuthUser extends UserAdmin { var $AuthUserProps = array(); // Get entities, using the extended syntax in AuthUser // (this is ParseArgs() format after a second colon) // user: HASH : useremail='user@example.com' userfoo='bar' ... function AuthUserProps($userpat = null, $forceread = false) { if ($this->AuthUserProps && !$forceread) return $this->array_match($userpat, $this->AuthUserProps); if (!$this->AuthUserData) $this->AuthUserPage(); // cache AuthUser $this->AuthUserProps = array(); foreach($this->AuthUserData as $m) { if (!@$m[3]) continue; $fields = preg_grep_keys("/^user/", ParseArgs($m[3])); $this->AuthUserProps[$m[1]] = empty($this->AuthUserProps[$m[1]]) ? $fields : array_merge($this->AuthUserProps[$m[1]], $fields); } #echo "AuthUserProps: Full Props=<pre>".print_r($this->AuthUserProps,true)."</pre><br>\n"; #echo "AuthUserProps(pat=".print_r($pat,true)."): Returning ".pre_r($this->array_match($userpat, $this->AuthUserProps))."<br>\n"; return $this->array_match($userpat, $this->AuthUserProps); } function ReadUser($username, $readgroup=false) { $data = parent::ReadUser($username, $readgroup); if ($props = $this->AuthUserProps($username)) { $data = array_merge($data, $props[$username]); } return $data; } // Read a given username // array( // 'username'=>username // 'userpwhash'=>password-hash // 'groups'=>array('@group1', '@group2', etc.) // 'useremail'=>email // 'other fields'=>... // ) function TODELETE_ReadUser($username) { echo "ReadUser($username): Entering<br>\n"; if (!$username) return array(); $auth = $this->AuthUserEntities(); echo "ReadUser($username): Auth read by AuthUserEntities(): ".pre_r($users)."<br>\n"; if (!isset($users[$username])) { echo "ReadUser($username): user=$username NOT FOUND - returning array()<br>\n"; return array(); // no user found } echo "ReadUser($username): authtokens=".$users[$username]['authtokens']."<br>\n"; $authtoken = strtok($users[$username]['authtokens'], " ,\t"); while ($authtoken !== false) { echo "ReadUser($username): authtoken=$authtoken<br>\n"; if ($authtoken{0} == '@') $groups[] = $authtoken; else $passwd = $authtoken; $authtoken = strtok(" ,\t"); } foreach ($this->normalGCache as $g => $members) if (in_array($username, $members)) $groups[] = $g; echo "ReadUser($username): userinfo=".$users[$username]['userinfo']."<br>\n"; $user = ParseArgs($users[$username]['userinfo']); unset($user['#']); // unneeded and causes errors in useradmin-core $user['username'] = $username; ## UserAdmin-core is not prepared to handle this as an array yet ## converted to a space-separated string... $user['usergroups'] = implode(" ",$groups); $user['userpwhash'] = $passwd; echo "Read($username): Returning: ".pre_r($user)."<br>\n"; $this->UCache[$username]['parsed'] = $user; return($user); } // Write the data for a given user back to SiteAdmin.AuthUser // // Note that if a given @group is included in a normal group specification // then it will be stripped from the authtokens as an inline group // specification. // Thus this: // @group1: user1, user2 // user1: HASH @group1 @group2: email="user1@example.com" // will be changed to this: // @group1: user1, user2 // user1: HASH @group2: email="user1@example.com" // // MISSING FUNCTIONALITY: // If a user is a member of @group1 by means of a normal group // specification in SiteAdmin.AuthUser but they are removed from that // group by manipulations in the forms that user will NOT be removed // from @group1 in the current implementation. function WriteUser($username, $data, $csum='', $auth=false) { global $AuthUserPageFmt, $Now, $EditFunctions, $IsPagePosted; parent::WriteUser($username, $data, $csum, $auth); SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser'); $pn = FmtPageName($AuthUserPageFmt, ''); $olddata = $this->ReadUser($username, true); $data = array_merge($olddata, $data); Lock(2); if ($auth) $page = RetrieveAuthPage($pn, $auth, TRUE); else $page = ReadPage($pn, 0); // often AuthUser is unreadable if (!$page) Abort("?cannot write to $pn"); $new = $page; #echo "UserAdminAuthUser::Write: Data=<pre>".print_r($data,true)."</pre><br>\n"; #echo "Starting with this text: <pre><br>\n".print_r($page['text'],true)."</pre><br>\n"; $authtoken = ''; #echo "entering loop: data=<pre>".print_r($data,true)."</pre><br>\n"; foreach ($data as $k => $v) { #echo "top loop k=$k, v=".print_r($v,true)."<br>\n"; if (!$v) continue; switch ($k) { case 'username': case '#': case '': break; case 'userpwhash': $authtoken .= ' '.$v; break; case 'usergroups': echo "DEVELOP: writing usergroups is NOT fully implemented!<br>\n"; /* // Get a full list of group memberships which are in the // "normal" group specification syntax ($mynormalgroups) echo "usergroups: $v<br>\n"; $mynormalgroups = array(); foreach ($this->normalGCache as $g => $members) if (in_array($username, $members)) $mynormalgroups[] = $g; // Now create $myinlinegroups as all groups which are not // in the $mynormalgroups (above) $mynewgroups = array_unique(preg_split("/[\\s,]+/", $v, null, PREG_SPLIT_NO_EMPTY)); $myinlinegroups = ''; echo "mynewgroups=<pre>".print_r($mynewgroups,true)."</pre><br>\n"; foreach ($mynewgroups as $g) { if (!in_array($g, $mynormalgroups)) $myinlinegroups .= ' '.$g; echo "g=$g, myinlinegroups=$myinlinegroups<br>\n"; } if ($myinlinegroups) $authtoken .= $myinlinegroups; // Now check if there are groups in $mynormalgroups which // are NOT in $mynewgroups // if so then issue an error message (until implemented) foreach ($mynormalgroups as $g) if (!in_array($g, $mynewgroups)) echo "ERROR: Cannot remove group ($g) membership from \"normal\" groups via forms. Please edit ".$this->AuthUserPageName." page manually.<br>\n"; */ break; default: $userinfo .= " $k='$v'"; break; } #echo "After $k=>$v: authtoken=$authtoken, userinfo=$userinfo<br>\n"; } $newline = "$username : $authtoken : $userinfo"; if (preg_match_all("/^\\s*$username\\s*:[^\\n]*$/m", $page['text'], $userlines)) { #echo "user=<pre>".print_r($user,true)."</pre><br>\n"; $new['text'] = str_replace($userlines[0][0], $newline, $new['text']); #echo "DEBUG: Deleting userlines=<pre>".print_r(array_slice($userlines[0], 1),true)."</pre><br>\n"; $new['text'] = str_replace(array_slice($userlines[0], 1), '', $new['text']); } else $new['text'] .= "\n$newline"; #echo "Would have written this text: <pre><br>\n".print_r($new['text'],true)."</pre><br>\n"; $new['csum'] = $csum; if ($csum) $new["csum:$Now"] = $csum; UpdatePage($pn, $page, $new); Lock(0); return $IsPagePosted; } // Return true/false whether the given $user is a member of the given // $group function UserInGroup($user, $group) { $users = $this->_readallusers(); // sets $normalGCache return (in_array($user, $this->normalGCache[$group]) || preg_match("/\\b$group\\b/", $users[$user]['authtokens'])); } // Return an array of all groups as key. // if $username is set then the value of each element of array will indicate // membership of that user in that group. // if $username is not set then the value of each element will be a list // of users that are members of that group. function OLD_TODELETE_ListGroups($username = null) { $users = $this->_readallusers(); // sets $normalGCache $this->_fillgcache(); $rtn = array(); if ($username) { foreach ($this->GCache as $g=>$v) if ($this->UserInGroup($username, $g)) $rtn[$g] = 1; else $rtn[$g] = 0; return($rtn); } return($this->GCache); } } $UserAdmin = new UserAdminAuthUser($pagename, null, array());