*
* AuthUser account self-registration and management
*
* 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 .
*/
$RecipeInfo['UserAdmin']['Version'] = '2010-06-14';
SDV($HandleActions[$action], 'HandleUserAdmin');
function HandleUserAdmin($pagename, $auth = 'read') {
global $action, $UserAdmin;
$UserAdmin->action = preg_match('#^user/(.+)$#', $action, $m) ? preg_replace('/\W+/', '', $m[1]) : NULL;
$hm = 'Handle'.ucfirst($UserAdmin->action);
if (method_exists($UserAdmin, $hm)) $result = $UserAdmin->{$hm}($pagename);
else { $UserAdmin->action = NULL; $result = NULL; }
$UserAdmin->PrintPage($pagename, $result);
}
########################################################################################################################
## set defaults
SDV($FmtPV['$Username'], '$GLOBALS["UserAdmin"]->Username($pn, $_REQUEST)');
SDV($Conditions['superuser'], '@$GLOBALS["UserAdmin"]->Superuser()');
XLSDV('en', array(
'UA_contact_admin' => 'Please contact site admin',
'UA_diff_userpasswd' => 'New passwords don't match',
'UA_email_fail' => 'Error sending email',
'UA_email_from' => "no-reply@{$_SERVER['HTTP_HOST']}",
'UA_empty_key' => 'Activation key is required',
'UA_empty_useremail' => 'An e-mail address is required',
'UA_empty_username' => 'Username is required',
'UA_empty_useroldpasswd' => 'Current password is required',
'UA_empty_userpasswd' => 'Password is required',
'UA_empty_userpasswd2' => 'Please enter your password twice',
'UA_exists' => 'User already exists',
'UA_fail_unknown_action' => 'Error: unknown user action',
'UA_invalid_useremail' => 'E-mail address is not valid',
'UA_invalid_username' => 'Username is not valid',
'UA_invalid_userpasswd' => 'Password is not valid',
'UA_return_link' => "\\\\\n\n[[ {\$PageUrl}?action=user | $[Return to user actions] ]]",
'UA_title' => 'User account management',
'UA_txt_key' => 'Activation key',
'UA_txt_useremail' => 'E-mail address',
'UA_txt_usergroups' => 'User groups',
'UA_txt_username' => 'Username',
'UA_txt_useroldpasswd' => 'Current password',
'UA_txt_userpasswd' => 'New password',
'UA_txt_userpasswd2' => 'New password, again',
'UA_unauthorized' => 'Not authorized',
'UA_unsupported_user_format' => 'User data can't be edited',
'UA_wrong_passwd' => 'Password not recognized',
'UAedit_fail' => 'Error updating user account',
'UAedit_submit' => 'Submit',
'UAedit_success' => 'User account updated',
'UAedit_success_unchanged' => 'User account not modified',
'UAedit_title' => 'Edit user account',
'UAgroup_fail' => 'Error updating user group',
'UAgroup_submit' => 'Submit',
'UAgroup_success' => 'User group updated',
'UAgroup_success_unchanged' => 'User group not modified',
'UAgroup_title' => 'Edit user group',
'UAnew_email_body' => "Welcome \$username!\n
Thank you for registering at $WikiTitle.
To activate your account and confirm your e-mail address, please visit
the following location:
\$link\n",
'UAnew_email_subject' => "Welcome to $WikiTitle",
'UAnew_email_sent' => 'E-mail sent with activation link',
'UAnew_fail' => 'Error creating account',
'UAnew_submit' => 'Sign up',
'UAnew_success' => 'New user account created',
'UAnew_title' => 'Register as a new user',
'UAresetpasswd_email_body' => "To set a new password for the user \$username at $WikiTitle, please
visit the following location:
\$link
If you've received this message in error, please contact the site admin
at <$ScriptUrl>.\n",
'UAresetpasswd_email_empty' => 'User has no e-mail address defined',
'UAresetpasswd_email_subject' => "Password reset for $WikiTitle",
'UAresetpasswd_fail' => 'Error sending reset link',
'UAresetpasswd_submit' => 'Send reset link to user's e-mail address',
'UAresetpasswd_success' => 'Password reset link sent to user's e-mail address',
'UAresetpasswd_title' => 'Reset password',
'UAunlock_already_active' => 'Account is already active',
'UAunlock_bad_key' => 'Bad activation key',
'UAunlock_fail' => 'Error activating account',
'UAunlock_new_passwd' => 'Enter new password',
'UAunlock_submit' => 'Activate/set password',
'UAunlock_success_activated' => 'User account activated',
'UAunlock_success_set_pw' => 'User password set',
'UAunlock_title' => 'Account activation',
));
define('UA_REQ_NOT_EMPTY', 0);
define('UA_REQ_ANY', 1);
define('UA_REQ_TWICE', 2); ## implies not empty
define('UA_REQ_TWICE_ANY', 3);
define('UA_REQ_PRESET', 4); ## implies not empty
define('UA_REQ_PRESET_ANY', 5);
## return array entries with keys that match the pattern
## ie. exactly like preg_grep but for array keys instead of values
if (!function_exists('preg_grep_keys')) {
function preg_grep_keys($pattern, $input, $flags = NULL) {
$keys = preg_grep($pattern, array_keys($input), $flags);
$out = array();
foreach ($keys as $key) $out[$key] = $input[$key];
return $out;
}}
########################################################################################################################
## framework class
class UserAdmin {
var $confirm_email = TRUE;
var $fields = array(
'new' => array(
'username' => UA_REQ_NOT_EMPTY,
'userpasswd' => UA_REQ_TWICE,
'useremail' => UA_REQ_NOT_EMPTY),
'resetpasswd' => array(
'username' => UA_REQ_NOT_EMPTY),
'unlock' => array(
'username' => UA_REQ_PRESET,
'key' => UA_REQ_PRESET),
'newpasswd' => array(
'username' => UA_REQ_PRESET,
'key' => UA_REQ_PRESET,
'userpasswd' => UA_REQ_TWICE),
'edit' => array(
'username' => UA_REQ_PRESET,
'usergroups' => UA_REQ_PRESET_ANY,
'useroldpasswd' => UA_REQ_NOT_EMPTY,
'useremail' => UA_REQ_NOT_EMPTY,
'userpasswd' => UA_REQ_TWICE_ANY),
'group' => array(
'groupname' => UA_REQ_NOT_EMPTY),
);
var $action;
var $input;
####################################################################################################################
## authuser page access
## returns array('userA' => array(HASH, '@groupA', ...), '@groupA' => array('userB', ...), ...)
function AuthUserPage() {
static $auth = array();
if ($auth) return $auth;
global $AuthUserPageFmt;
SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser');
$pn = FmtPageName($AuthUserPageFmt, '');
$apage = ReadPage($pn, READPAGE_CURRENT);
if (!$apage
|| empty($apage['text'])
|| !preg_match_all("/^\\s*([@\\w][^\\s:]*):(.*)/m", $apage['text'], $matches, PREG_SET_ORDER)
) return array();
$auth = array();
foreach($matches as $m) {
if (!preg_match_all('/\\bldaps?:\\S+|[^\\s,]+/', $m[2], $v)) continue;
$auth[$m[1]] = empty($auth[$m[1]]) ? $v[0] : array_merge($auth[$m[1]], $v[0]);
}
return $auth;
}
function DelValue(&$page, $name, $value) {
if (!preg_match('/^[@\w][^\s:]*$/', $name) || !preg_match('/^[^\s,]+$/', $value)) return FALSE;
$page['text'] = preg_replace("/^(\s*$name:)(?:(.*?)[\s,]+)?$value([\s,]|$)/m", '$1$2$3', $page['text'], -1, $count);
$page['text'] = preg_replace("/^(\s*$name:)[\s,]*\n/m", '', $page['text']);
return $count;
}
function AddValue(&$page, $name, $value) {
if (!preg_match('/^[@\w][^\s:]*$/', $name) || !preg_match('/^[^\s,]+$/', $value)) return FALSE;
if (preg_match("/^\s*$name:/m", $page['text'])) {
if (preg_match("/^\s*$name:(.*[\s,])?$value([\s,]|$)/m", $page['text'])) {
return 0;
} else {
$page['text'] = preg_replace("/^(\s*$name:.*?)\s*$/m", "$1 $value", $page['text'], 1, $count);
return $count;
}
} else {
$page['text'] = "$name: $value\n\n{$page['text']}";
return 1;
}
}
####################################################################################################################
## groups
## with username: returns array('@groupA', '@groupB', ...)
## w/o username: returns array('@groupA' => array('userA', 'userB', ...), '@groupB' => ...)
function Groups($username=NULL) {
static $groups = array();
if (!$groups) {
$auth = $this->AuthUserPage();
$groups = preg_grep_keys('/^@/', $auth);
foreach ($auth as $k => $v) if ($k[0] != '@') foreach (preg_grep('/^@/', $v) as $g) $groups[$g][] = $k;
foreach ($groups as $g => $a) $groups[$g] = array_unique($a);
ksort($groups);
}
if ($username) {
$ug = array();
foreach ($groups as $g => $a) {
if (in_array($username, $a) || in_array('*', $a)) $ug[] = $g;
//if (in_array("-$username", $a)
}
return $ug;
}
return $groups;
}
## returns array('userA', 'userB', ...)
function ReadGroup($groupname) {
$groups = $this->Groups();
return empty($groups[$groupname]) ? array() : $groups[$groupname];
}
## $add is an array of members to add to group
## $del is an array of members to remove from group
function WriteGroup($groupname, $add, $del, $csum='', $auth='read') {
global $AuthUserPageFmt, $Now, $EditFunctions, $IsPagePosted;
if (!preg_match('/^[@\w][^\s:]*$/', $groupname)) return FALSE;
SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser');
$pn = FmtPageName($AuthUserPageFmt, '');
Lock(2);
$page = RetrieveAuthPage($pn, $auth, TRUE);
if (!$page) Abort("?cannot write to $pn");
$new = $page;
$del_count = 0;
if ($del) foreach ($del as $d) {
$del_count += $this->DelValue($new, $d, $groupname);
$del_count += $this->DelValue($new, $groupname, $d);
}
$add_count = 0;
if ($add) foreach ($add as $a) {
$add_count += $this->AddValue($new, $groupname, $a);
}
$new['csum'] = str_replace(array('$add', '$del'), array($add_count, $del_count), $csum);
if ($csum) $new["csum:$Now"] = $new['csum'];
PCache($pn, $new);
$k = array_search('SaveAttributes', $EditFunctions);
if ($k !== FALSE) unset($EditFunctions[$k]);
UpdatePage($pn, $page, $new);
Lock(0);
return $IsPagePosted;
}
function ListGroups($pat=NULL) { return MatchPageNames(array_keys($this->Groups()), $pat); }
function AdminGroup($groupname) { return preg_match('/_admin$/', $groupname) ? $groupname : "{$groupname}_admin"; }
####################################################################################################################
## users
function ReadUser($username) {
$auth = $this->AuthUserPage(TRUE);
if (empty($auth[$username])) return array();
$data = array('username' => $username);
foreach ($auth[$username] as $v) if ($v[0] == '$') $data['userpwhash'] = $v;
return $data;
}
// function ReadUser($username) { exit('UserAdmin::Read not implemented'); } // virtual
function WriteUser($username, $data, $csum='', $auth='read') { exit('UserAdmin::Write not implemented'); } // virtual
function Exists($username) {
return (boolean)$this->ReadUser($username);
}
function ListUsers($pat=NULL) {
global $AuthUserFunctions;
$pat = (array)$pat;
$x = array('htpasswd' => 1, 'htgroup' => 1, 'ldap' => 1, 'userprofilegroup' => 1) + (array)@$AuthUserFunctions;
array_push($pat, '!^('.implode('|', array_keys($x)).')$!');
$ls = preg_grep('/^\w/', array_keys($this->AuthUserPage()));
return MatchPageNames($ls, $pat);
}
####################################################################################################################
## utility functions
function MailUser($username, $fmt, $opt = array()) {
if ($username) $opt = array_merge($this->ReadUser($username), $opt);
if (empty($opt['useremail'])) return FALSE;
$fmt = array_merge(array('to' => '$useremail', 'head' => 'From: '.XL('UA_email_from')), $fmt);
$msg = array();
foreach ($fmt as $fk => $f) {
foreach($opt as $k => $v) $f = preg_replace("/\\$$k\b`?/", $v, $f);
$msg[$fk] = $f;
}
$msg['body'] = preg_replace('/^\t+/m', '', $msg['body']); ## allow pretty XLSDV with indentation
//exit(pre_r($msg));
return mail($msg['to'], @$msg['subject'], @$msg['body'], $msg['head']);
}
function MakeActivationKey() { return strval(mt_rand() + 1); }
function MakeUserLink($username, $useraction = '', $opt = array()) {
global $ScriptUrl;
$action = $useraction ? 'user/'.urlencode($useraction) : 'user';
$url = "$ScriptUrl?action=$action&username=".urlencode($username);
foreach ($opt as $k => $v) $url .= '&'.urlencode($k).'='.urlencode($v);
return $url;
}
####################################################################################################################
## authentication
## return TRUE for authenticated user with admin rights
function Superuser($pagename, $prompt=FALSE) {
return (boolean)RetrieveAuthPage($pagename, 'admin', $prompt, READPAGE_CURRENT);
}
function Username($pagename, $opt) {
global $AuthId;
$n = @$opt['username'] or !$this->Superuser($pagename) and $n = @$AuthId;
if (!$n) return FALSE;
if (method_exists($this, 'ValidName') && !$this->ValidName($n)) return FALSE;
if (!$this->Exists($n)) return FALSE;
return $n;
}
function AuthorizedUser($pagename, $username, $auth='edit', $prompt=FALSE) {
global $AuthId;
return ($username && ($AuthId == $username)) || $this->Superuser($pagename, $prompt);
}
function AuthorizedGroup($pagename, $groupname, $auth='edit', $prompt=FALSE) {
global $AuthId, $AuthList;
if ($groupname[0] != '@') return FALSE;
return !empty($AuthList[$this->AdminGroup($groupname)]) || $this->Superuser($pagename, $prompt);
}
####################################################################################################################
## input processing
## returns TRUE if form has been posted
function ReadInput($pagename, $valid_username=TRUE) {
if (preg_grep('/^cancel/', array_keys($_POST))) Redirect($pagename, '$PageUrl?action=user');
$this->input = array_merge($_GET, $_POST);
if ($valid_username) $this->input['username'] = $this->Username($pagename, $_REQUEST);
return (boolean)preg_grep('/^post/', array_keys($_POST));
}
function ValidEmail(&$address) { return !$address || preg_match('/^.+@.+\..+$/', $address); }
function ValidateInput($fmt = '') {
if (!$fmt) $fmt = $this->action;
if (empty($this->fields[$fmt])) return 'UA_fail_unknown_action';
$result = array();
foreach ($this->fields[$fmt] as $k => $req) {
$this->input[$k] = stripmagic($this->input[$k]);
if (!($req & UA_REQ_ANY) && empty($this->input[$k])) {
$result[$k] = "UA_empty_$k";
continue;
}
if (($req & UA_REQ_TWICE) && (stripmagic(@$this->input["{$k}2"]) != $this->input[$k])) {
$result[$k] = "UA_diff_$k";
continue;
}
$vm = preg_replace('/^user(.+)$/e', "'Valid'.ucfirst('$1')", $k);
if (method_exists($this, $vm) && !$this->{$vm}($this->input[$k])) {
$result[$k] = "UA_invalid_$k";
continue;
}
}
return $result;
}
####################################################################################################################
## action handlers
function HandleNew($pagename) {
if (!$this->ReadInput($pagename, FALSE)) return NULL;
$result = $this->ValidateInput();
$username = $this->input['username'];
if ($this->Exists($username)) $result['username'] = 'UA_exists';
if ($result) return $result;
$hash = crypt($this->input['userpasswd']);
if ($this->confirm_email && !$this->Superuser($pagename)) {
$key = $this->MakeActivationKey();
$link = $this->MakeUserLink($username, 'unlock', array('key' => $key));
//$link = $this->MakeActivationLink($username, $key);
$mail_fmt = array(
'subject' => XL('UAnew_email_subject'),
'body' => XL('UAnew_email_body')
);
$mail_opt = array(
'username' => $username,
'useremail' => $this->input['useremail'],
'key' => $key,
'link' => $link
);
if (!$this->MailUser('', $mail_fmt, $mail_opt)) return array('UA_email_fail', 'UA_contact_admin');
$success = array('UAnew_success', 'UAnew_email_sent');
$data = array(
'useremail' => $this->input['useremail'],
'username' => $username,
'userkey' => "$key $hash",
);
} else {
$success = 'UAnew_success';
$data = array(
'userpwhash' => $hash,
'useremail' => @$this->input['useremail'],
'username' => $username,
);
}
$fail = array('UAnew_fail', 'UA_contact_admin');
return $this->WriteUser($username, $data, implode('; ', array_map('XL', (array)$success))) ? $success : $fail;
}
function HandleResetpasswd($pagename) {
$posted = $this->ReadInput($pagename);
if (!$posted) return NULL;
$result = $this->ValidateInput();
if ($result) return $result;
$username = $this->input['username'];
$user = $this->ReadUser($username);
if (!$user) return array('UAresetpasswd_fail', 'UA_invalid_username');
if (empty($user['useremail'])) return array('UAresetpasswd_fail', 'UAresetpasswd_email_empty', 'UA_contact_admin');
$key = $this->MakeActivationKey();
$link = $this->MakeUserLink($username, 'unlock', array('key' => $key));
//$link = $this->MakeActivationLink($username, $key);
$mail_fmt = array(
'subject' => XL('UAresetpasswd_email_subject'),
'body' => XL('UAresetpasswd_email_body')
);
$mail_opt = array(
'key' => $key,
'link' => $link
);
if (!$this->MailUser($username, $mail_fmt, $mail_opt)) return array('UA_email_fail', 'UA_contact_admin');
return $this->WriteUser($username, array('userkey' => $key), XL('UAresetpasswd_success'))
? 'UAresetpasswd_success'
: array('UAresetpasswd_fail', 'UA_contact_admin');
}
## handles e-mail address verification and password resets
function HandleUnlock($pagename) {
$posted = $this->ReadInput($pagename);
if (empty($this->input['username'])) return NULL;
$user = $this->ReadUser($this->input['username']);
if (!$user) return array('UAunlock_fail', 'UA_invalid_username');
if (empty($user['userkey'])) return array('UAunlock_fail', 'UAunlock_already_active');
$result = $this->ValidateInput();
if ($result) return $result;
$key = preg_replace('/[^0-9]+/', '', $this->input['key']);
if (!preg_match("/^$key( .*)?$/", $user['userkey'], $match)) return array('UAunlock_fail', 'UAunlock_bad_key');
$hash = trim($match[1]);
if (!$hash) {
$this->fields['unlock'] = $this->fields['newpasswd'];
if (!$posted) return NULL;
$result = $this->ValidateInput('newpasswd');
if ($result) return $result;
$hash = crypt($this->input['userpasswd']);
$reset = TRUE;
} else $reset = FALSE;
$result = $reset ? 'UAunlock_success_set_pw' : 'UAunlock_success_activated';
$data = array('userpwhash' => $hash, 'userkey' => '');
return $this->WriteUser($this->input['username'], $data, XL($result))
? $result
: array('UAnew_fail', 'UA_contact_admin');
}
function HandleEdit($pagename) {
$posted = $this->ReadInput($pagename);
unset($this->input['usergroups']);
$username = $this->input['username'];
if (empty($username)) {
$this->fields[$this->action] = array('username' => UA_REQ_NOT_EMPTY);
return NULL;
}
if (!$this->AuthorizedUser($pagename, $username, 'edit', TRUE)) return array('UAedit_fail', 'UA_unauthorized');
$admin = $this->Superuser($pagename);
if ($admin) unset($this->fields[$this->action]['useroldpasswd']);
$user = $this->ReadUser($username);
if (!$user) return array(
'UAedit_fail',
$this->Exists($username) ? 'UA_unsupported_user_format' : 'UA_invalid_username'
);
$ef = preg_grep('/passwd|^username$/', array_keys($this->fields[$this->action]), PREG_GREP_INVERT);
$posted = FALSE;
foreach ($ef as $f) {
if (isset($this->input[$f])) $posted = TRUE;
else $this->input[$f] = @$user[$f];
}
if (!$posted) return NULL;
$result = $this->ValidateInput();
if ($result) return $result;
if (!$admin && (_crypt($this->input['useroldpasswd'], $user['userpwhash']) != $user['userpwhash']))
return 'UA_wrong_passwd';
$data = array();
foreach ($this->fields[$this->action] as $f => $req) {
if (($req & UA_REQ_PRESET) || preg_match('/passwd/', $f)) continue;
if (@$this->input[$f] === @$user[$f]) continue;
$data[$f] = @$this->input[$f];
}
if (!empty($this->input['userpasswd'])) $data['userpwhash'] = crypt($this->input['userpasswd']);
if (!$data) return 'UAedit_success_unchanged';
return $this->WriteUser($user['username'], $data, XL('UAedit_success'))
? 'UAedit_success'
: array('UAedit_fail', 'UA_contact_admin');
}
function HandleGroup($pagename) {
global $UserAdminFmt;
$posted = $this->ReadInput($pagename, FALSE);
$fields = &$this->fields[$this->action];
if (empty($this->input['gn'])) {
$fields = array('groupname' => UA_REQ_NOT_EMPTY);
return NULL;
} else $groupname = $this->input['gn'];
if (!$this->AuthorizedGroup($pagename, $groupname, 'edit', TRUE)) return array('UAgroup_fail', 'UA_unauthorized');
$group = $this->ReadGroup($groupname);
$UserAdminFmt = '$[Current group members:]';
$UserAdminFmt .= "\n(:input form action='\$PageUrl?action=user/{$this->action}&gn=$groupname' class='uag-users':)";
foreach ($group as $n) {
$checked = !empty($this->input['select']) && in_array($n, $this->input['select']) ? ' checked' : '';
if (preg_match('/^\w/', $n) && $this->Exists($n)) {
$url = $this->MakeUserLink($n, 'edit');
$txt = "[[$url|$n]]";
} else $txt = $n;
$UserAdminFmt .= "\n* (:input checkbox name='select[]' value='$n' $checked:) $txt";
}
$UserAdminFmt .= "\n(:input submit name=postdel value='$[Remove selected]':)\n(:input end:)";
$UserAdminFmt .= "\n\n$[Add new group members (each on a separate line):]";
$UserAdminFmt .= "\n(:input form action='\$PageUrl?action=user/{$this->action}&gn=$groupname' class='uag-new':)";
$UserAdminFmt .= "\n(:input textarea name=new rows=8 cols=30:)";
$UserAdminFmt .= "\n(:input submit name=postadd value='$[Add new members]':)\n(:input end:)";
$UserAdminFmt .= "\n\n".Keep(pre_r($this->input));
return NULL;
//$this->WriteGroup('@obix', array(), array('EA3'), 'WriteGroup test: +$add/-$del');
}
####################################################################################################################
## display page
function Menu($pagename) {
global $AuthId, $UserAdminAnonActions;
SDV($UserAdminAnonActions, array('new', 'resetpasswd', 'unlock'));
$actions = preg_replace(
'/^Handle(.)/e', "strtolower('$1')",
preg_grep('/^Handle/', get_class_methods($this))
);
$username = $this->Username($pagename, $_REQUEST);
if ($this->AuthorizedUser($pagename, $username, 'edit') && !$this->Superuser($pagename)) {
$actions = array_diff($actions, $UserAdminAnonActions);
} else if (empty($AuthId)) {
$actions = array_intersect($actions, $UserAdminAnonActions);
}
$out = "\n!!! Available actions\n";
foreach($actions as $a) $out .= "* [[ {\$PageUrl}?action=user/$a | $[UA{$a}_title] ]]\n";
if (empty($AuthId)) $out .= "* [[ {\$PageUrl}?action=user/edit | $[Login to edit your account details] ]]\n";
return $out;
}
function Form($pagename, $result) {
global $InputValues;
if (empty($this->fields[$this->action])) return '';
$f = $this->fields[$this->action];
if (count($f) == 1) switch (key($f)) {
case 'username':
$list = '$[Please select a user:]';
foreach ($this->ListUsers() as $n) {
$url = $this->MakeUserLink($n, 'edit');
$list .= "\n* [[$url|$n]]";
}
return $list;
case 'groupname':
$list = '$[Please select a group:]';
$url = $this->MakeUserLink('', 'group');
foreach ($this->ListGroups() as $n) {
$list .= "\n* [[$url&gn=$n|$n]]";
}
return $list;
}
$form = "(:input form action='\$PageUrl?action=user/{$this->action}':)";
$form .= "\n(:table class=ua-form:)";
foreach ($f as $k => $req) {
$highlight = isset($result[$k]) ? ' class=ua-error' : '';
$form .= "\n(:cellnr$highlight:)$[UA_txt_$k]\n(:cell$highlight:)";
## note: autocomplete is not included by default in $InputAttrs, so setting it won't do anything
$type = (strpos($k, 'passwd') !== FALSE) ? 'password autocomplete=off' : 'text';
$req_note = !($req & UA_REQ_ANY);
if ($req & UA_REQ_PRESET) {
if (!($req_note && empty($InputValues[$k]))) {
$req_note = FALSE;
$form .= "'''{$InputValues[$k]}'''";
$type = 'hidden';
}
}
if (($k == 'username') && ($type == 'text') && ($this->action != 'new')) $type = 'select';
$form .= "(:input $type name='$k':)";
if ($req_note) $form .= ' *';
if ($req & UA_REQ_TWICE) {
$form .= "\n(:cellnr$highlight:)$[UA_txt_{$k}2]\n(:cell$highlight:)(:input $type name='{$k}2':)";
if ($req_note) $form .= ' *';
}
}
$form .= "\n(:cellnr:)\n(:cell:)(:input submit name=post value='$[UA{$this->action}_submit]':) (:input submit name=cancel value='$[Cancel]':)";
$form .= "\n(:tableend:)\n(:input end:)";
return $form;
}
function FormExpand($markup) {
if (!preg_match('/^\(:input select\b(.*?):\)$/', $markup, $match))
return preg_replace('/\(:input select\b.*?:\)/e', "\$this->FormExpand('$0')", $markup);
$opt = ParseArgs($match[1]);
if (empty($opt['name'])) {
if (empty($opt[''])) return $markup;
else $opt['name'] = $opt[''][0];
}
switch($opt['name']) {
case 'username':
//$out = "(:input select name='username' value='' '':)";
//foreach ($this->ListUsers(NULL, TRUE) as $n) $out .= "\n(:input select name='username' value='$n' '$n':)";
foreach ($this->ListUsers(NULL, TRUE) as $n) {
$url = $this->MakeUserLink($n, 'edit');
$out .= "\n* [[$url|$n]]";
}
return $out;
default:
return $markup;
}
}
function PrintPage($pagename, $result) {
global $MessagesFmt, $SiteGroup, $InputValues, $PageStartFmt, $PageEndFmt, $UserAdminForm, $UserAdminFmt, $HandleUserAdminFmt;
//$ls = array($this->ListGroups('@a*'), $this->ListUsers('/^[a-z]/', TRUE));
//exit(pre_r($ls));
$status = preg_match('/(\b|_)(fail|success)(\b|_)/', implode(' ', (array)$result), $m) ? " ua-{$m[2]}" : '';
if ($result) $MessagesFmt[] = "
$[".implode("]
\n$[", (array)$result).']
';
foreach((array)$this->input as $k => $v)
if (!is_array($v) && (strpos($k, 'passwd') === FALSE)) $InputValues[$k] = htmlspecialchars($v, ENT_QUOTES);
if (empty($UserAdminFmt)) {
if (!$this->action || $status) $UserAdminFmt = $this->Menu($pagename);
else {
//if (PageExists("$SiteGroup.UserAdminTemplates")) SDV($UserAdminForm, "$SiteGroup.UserAdminTemplates");
if (empty($UserAdminForm) || !($UserAdminFmt = RetrieveAuthSection($UserAdminForm, "#ua-{$this->action}")))
$UserAdminFmt = $this->Form($pagename, $result);
$UserAdminFmt .= '$[UA_return_link]';
}
$UserAdminFmt = $this->FormExpand($UserAdminFmt);
}
$UserAdminFmt = MarkupToHTML($pagename, "(:messages:)\n\n$UserAdminFmt");
$title = XL("UA{$this->action}_title");
$username = $this->Username($pagename, $_REQUEST);
if ($username && ($this->action != 'new')) $title .= ": $username";
PCache($pagename, array('title' => $title));
SDV($HandleUserAdminFmt, array(&$PageStartFmt, &$UserAdminFmt, &$PageEndFmt));
PrintFmt($pagename, $HandleUserAdminFmt);
}
}