4 # An Object for Handling User Information 6 # Copyright 1999-2001 Axis Data 7 # This code is free software that can be used or redistributed under the 8 # terms of Version 2 of the GNU General Public License, as published by the 9 # Free Software Foundation (http://www.fsf.org). 11 # Author: Edward Almasy (almasy@axisdata.com) 13 # Part of the AxisPHP library v1.2.4 14 # For more information see http://www.axisdata.com/AxisPHP/ 17 # status values (error codes) 20 define(
"U_BADPASSWORD", 2);
21 define(
"U_NOSUCHUSER", 3);
22 define(
"U_PASSWORDSDONTMATCH", 4);
23 define(
"U_EMAILSDONTMATCH", 5);
24 define(
"U_DUPLICATEUSERNAME", 6);
25 define(
"U_ILLEGALUSERNAME", 7);
26 define(
"U_EMPTYUSERNAME", 8);
27 define(
"U_ILLEGALPASSWORD", 9);
28 define(
"U_ILLEGALPASSWORDAGAIN", 10);
29 define(
"U_EMPTYPASSWORD", 11);
30 define(
"U_EMPTYPASSWORDAGAIN", 12);
31 define(
"U_ILLEGALEMAIL", 13);
32 define(
"U_ILLEGALEMAILAGAIN", 14);
33 define(
"U_EMPTYEMAIL", 15);
34 define(
"U_EMPTYEMAILAGAIN", 16);
35 define(
"U_NOTLOGGEDIN", 17);
36 define(
"U_MAILINGERROR", 18);
37 define(
"U_TEMPLATENOTFOUND", 19);
38 define(
"U_DUPLICATEEMAIL", 20);
39 define(
"U_NOTACTIVATED", 21);
43 # ---- PUBLIC INTERFACE -------------------------------------------------- 45 public function __construct($UserInfoOne = NULL, $UserInfoTwo = NULL)
47 # assume constructor will succeed and user is not logged in 49 $this->LoggedIn = FALSE;
51 # create database connection 54 # if user info passed in 55 if (is_int($UserInfoOne) || is_string($UserInfoOne)
56 || is_int($UserInfoTwo) || is_string($UserInfoTwo))
58 # if user ID was passed in 59 if (is_int($UserInfoOne) || is_int($UserInfoTwo))
62 $this->UserId = is_int($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
64 # get whether the user is logged in 65 $this->LoggedIn = (bool)$this->DB->Query(
" 66 SELECT LoggedIn FROM APUsers 67 WHERE UserId='".addslashes($this->UserId).
"'",
72 # look up user ID in database 73 $UserInfoTwo = is_string($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
74 $this->DB->Query(
"SELECT UserId, LoggedIn FROM APUsers" 75 .
" WHERE UserName='".addslashes($UserInfoTwo).
"'");
76 $Record = $this->DB->FetchRow();
79 $this->UserId = $Record[
"UserId"];
80 $this->LoggedIn = $Record[
"LoggedIn"];
83 # if user ID was not found 84 if ($Record === FALSE)
86 # if name looks like it could actually be a user ID 87 if (preg_match(
"/^[-]*[0-9]+$/", $UserInfoTwo))
89 # assume name was user ID 90 $this->UserId = intval($UserInfoTwo);
94 # set code indicating no user found 103 # if user ID is available from session 104 if (isset($_SESSION[
"APUserId"]))
107 $this->UserId = $_SESSION[
"APUserId"];
109 # set flag indicating user is currently logged in 110 $this->LoggedIn = TRUE;
120 # return text message corresponding to current (or specified) status code 123 $APUserStatusMessages = array(
124 U_OKAY =>
"The operation was successful.",
125 U_ERROR =>
"There has been an error.",
136 .
" short, too long, or contains" 137 .
" illegal characters.",
139 .
" too short, too long, or" 140 .
" contains illegal characters.",
142 .
" appears to be invalid.",
145 .
" to send e-mail. Please notify" 146 .
" the system administrator.",
148 .
" to generate e-mail. Please" 149 .
" notify the system administrator.",
151 .
" has an account associated with it.",
154 return ($StatusCode === NULL) ? $APUserStatusMessages[
$this->Result]
155 : $APUserStatusMessages[$StatusCode];
160 # clear priv list values 161 $this->DB->Query(
"DELETE FROM APUserPrivileges WHERE UserId = '" 164 # delete user record from database 165 $this->DB->Query(
"DELETE FROM APUsers WHERE UserId = '".$this->UserId.
"'");
167 # report to caller that everything succeeded 179 if (is_callable($NewValue))
181 self::$EmailFunc = $NewValue;
186 # ---- Getting/Setting Values -------------------------------------------- 194 return $this->
Get(
"UserName");
204 $RealName = $this->
Get(
"RealName");
206 # the real name is available, so use it 207 if (strlen(trim($RealName)))
212 # the real name isn't available, so use the user name 213 return $this->
Get(
"UserName");
218 # return NULL if not associated with a particular user 219 if ($this->UserId === NULL) {
return NULL; }
223 $this->DB->Query(
"UPDATE APUsers SET" 224 .
" LastLocation = '".addslashes($NewLocation).
"'," 225 .
" LastActiveDate = NOW()," 226 .
" LastIPAddress = '".$_SERVER[
"REMOTE_ADDR"].
"'" 227 .
" WHERE UserId = '".addslashes($this->UserId).
"'");
228 if (isset($this->DBFields))
230 $this->DBFields[
"LastLocation"] = $NewLocation;
231 $this->DBFields[
"LastActiveDate"] = date(
"Y-m-d H:i:s");
234 return $this->
Get(
"LastLocation");
238 return $this->
Get(
"LastActiveDate");
242 return $this->
Get(
"LastIPAddress");
245 # get value from specified field 246 public function Get($FieldName)
248 # return NULL if not associated with a particular user 249 if ($this->UserId === NULL) {
return NULL; }
254 # get value (formatted as a date) from specified field 255 public function GetDate($FieldName, $Format =
"")
257 # return NULL if not associated with a particular user 258 if ($this->UserId === NULL) {
return NULL; }
260 # retrieve specified value from database 261 if (strlen($Format) > 0)
263 $this->DB->Query(
"SELECT DATE_FORMAT(`".addslashes($FieldName)
264 .
"`, '".addslashes($Format).
"') AS `".addslashes($FieldName)
265 .
"` FROM APUsers WHERE UserId='".$this->UserId.
"'");
269 $this->DB->Query(
"SELECT `".addslashes($FieldName).
"` FROM APUsers WHERE UserId='".$this->UserId.
"'");
271 $Record = $this->DB->FetchRow();
273 # return value to caller 274 return $Record[$FieldName];
277 # set value in specified field 278 public function Set($FieldName, $NewValue)
280 # return error if not associated with a particular user 289 # ---- Login Functions --------------------------------------------------- 291 public function Login($UserName, $Password, $IgnorePassword = FALSE)
293 # if user not found in DB 294 $this->DB->Query(
"SELECT * FROM APUsers" 295 .
" WHERE UserName = '" 296 .addslashes(self::NormalizeUserName($UserName)).
"'");
297 if ($this->DB->NumRowsSelected() < 1)
299 # result is no user by that name 304 # if user account not yet activated 305 $Record = $this->DB->FetchRow();
306 if (!$Record[
"RegistrationConfirmed"])
308 # result is user registration not confirmed 313 # grab password from DB 314 $StoredPassword = $Record[
"UserPassword"];
316 if (isset($Password[0]) && $Password[0] ==
" ")
318 $Challenge = md5(date(
"Ymd").$_SERVER[
"REMOTE_ADDR"]);
319 $StoredPassword = md5( $Challenge . $StoredPassword );
321 $EncryptedPassword = trim($Password);
325 # if supplied password matches encrypted password 326 $EncryptedPassword = crypt($Password, $StoredPassword);
329 if (($EncryptedPassword == $StoredPassword) || $IgnorePassword)
334 # store user ID for session 335 $this->UserId = $Record[
"UserId"];
338 # update last login date 339 $this->DB->Query(
"UPDATE APUsers SET LastLoginDate = NOW()," 341 .
" WHERE UserId = '".$this->UserId.
"'");
343 # Check for old format hashes, and rehash if possible 344 if ($EncryptedPassword === $StoredPassword &&
345 substr($StoredPassword, 0, 3) !==
"$1$" &&
346 $Password[0] !==
" " &&
349 $NewPassword = crypt($Password, self::GetSaltForCrypt() );
351 "UPDATE APUsers SET UserPassword='" 352 .addslashes($NewPassword).
"' " 353 .
"WHERE UserId='".$this->UserId.
"'");
356 # since self::DBFields might already have been set to false if 357 # the user wasn't logged in when this is called, populate it 358 # with user data so that a call to self::UpdateValue will be 359 # able to properly fetch the data associated with the user 360 $this->DBFields = $Record;
362 # set flag to indicate we are logged in 363 $this->LoggedIn = TRUE;
367 # result is bad password 373 # return result to caller 380 # clear user ID (if any) for session 381 unset($_SESSION[
"APUserId"]);
383 # if user is marked as logged in 386 # set flag to indicate user is no longer logged in 387 $this->LoggedIn = FALSE;
389 # clear login flag in database 391 "UPDATE APUsers SET LoggedIn = '0' " 392 .
"WHERE UserId='".$this->UserId.
"'");
399 "SELECT * FROM APUsers WHERE UserName = '" 400 .addslashes(self::NormalizeUserName($UserName)).
"'");
402 if ($this->DB->NumRowsSelected() < 1)
404 # result is no user by that name, generate a fake salt 405 # to discourage user enumeration. Make it be an old-format 406 # crypt() salt so that it's harder. 407 $SaltString = $_SERVER[
"SERVER_ADDR"].$UserName;
408 $Result = substr(base64_encode(md5($SaltString)), 0, 2);
412 # grab password from DB 413 # Assumes that we used php's crypt() for the passowrd 414 # management stuff, and will need to be changed if we 415 # go to something else. 416 $Record = $this->DB->FetchRow();
417 $StoredPassword = $Record[
"UserPassword"];
419 if (substr($StoredPassword, 0, 3) ===
"$1$")
421 $Result = substr($StoredPassword, 0, 12);
425 $Result = substr($StoredPassword, 0, 2);
432 # report whether this user is or is not currently logged in 443 # ---- Password Functions ------------------------------------------------ 445 # set new password (with checks against old password) 448 # return error if not associated with a particular user 451 # if old password is not correct 452 $StoredPassword = $this->DB->Query(
"SELECT UserPassword FROM APUsers" 453 .
" WHERE UserId='".$this->UserId.
"'",
"UserPassword");
454 $EncryptedPassword = crypt($OldPassword, $StoredPassword);
455 if ($EncryptedPassword != $StoredPassword)
457 # set status to indicate error 460 # else if new password is not legal 463 # set status to indicate error 466 # else if both instances of new password do not match 467 elseif (self::NormalizePassword($NewPassword)
468 != self::NormalizePassword($NewPasswordAgain))
470 # set status to indicate error 478 # set status to indicate password successfully changed 482 # report to caller that everything succeeded 489 # generate encrypted password 490 $EncryptedPassword = crypt(self::NormalizePassword($NewPassword),
491 self::GetSaltForCrypt() );
493 # save encrypted password 494 $this->
UpdateValue(
"UserPassword", $EncryptedPassword);
499 # save encrypted password 500 $this->
UpdateValue(
"UserPassword", $NewEncryptedPassword);
504 $UserName, $EMail, $EMailAgain,
505 $TemplateFile =
"Axis--User--EMailTemplate.txt")
508 $UserName, $EMail, $EMailAgain, $TemplateFile);
512 $UserName, $EMail, $EMailAgain,
513 $TemplateFile =
"Axis--User--EMailTemplate.txt")
515 # load e-mail template from file (first line is subject) 516 $Template = file($TemplateFile, 1);
517 $EMailSubject = array_shift($Template);
518 $EMailBody = join(
"", $Template);
521 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody);
525 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
527 # make sure e-mail addresses match 528 if ($EMail != $EMailAgain)
534 # make sure e-mail address looks valid 541 # generate random password 544 # attempt to create new user with password 545 $Result = $this->CreateNewUser($UserName, $Password, $Password);
547 # if user creation failed 550 # report error result to caller 556 # set e-mail address in user record 557 $this->
Set(
"EMail", $EMail);
559 # plug appropriate values into subject and body of e-mail message 560 $EMailSubject = str_replace(
"X-USERNAME-X", $UserName, $EMailSubject);
561 $EMailBody = str_replace(
"X-USERNAME-X", $UserName, $EMailBody);
562 $EMailBody = str_replace(
"X-PASSWORD-X", $Password, $EMailBody);
564 # send out e-mail message with new account info 565 if (is_Callable(self::$EmailFunc))
567 $Result = call_user_func(self::$EmailFunc,
568 $EMail, $EMailSubject, $EMailBody,
569 "Auto-Submitted: auto-generated");
573 $Result = mail($EMail, $EMailSubject, $EMailBody,
574 "Auto-Submitted: auto-generated");
577 # if mailing attempt failed 580 # report error to caller 587 # report success to caller 594 # get code for user to submit to confirm registration 597 # code is MD5 sum based on user name and encrypted password 598 $ActivationCodeLength = 6;
599 return $this->
GetUniqueCode(
"Activation", $ActivationCodeLength);
602 # check whether confirmation code is valid 609 # get/set whether user registration has been confirmed 612 return $this->
UpdateValue(
"RegistrationConfirmed", $NewValue);
615 # get code for user to submit to confirm password reset 618 # code is MD5 sum based on user name and encrypted password 619 $ResetCodeLength = 10;
623 # check whether password reset code is valid 626 return (strtoupper(trim($Code)) == $this->
GetResetCode())
630 # get code for user to submit to confirm mail change request 633 $ResetCodeLength = 10;
635 .$this->
Get(
"NewEMail"),
645 # send e-mail to user (returns TRUE on success) 647 $TemplateTextOrFileName, $FromAddress = NULL, $MoreSubstitutions = NULL,
650 # if template is file name 651 if (@is_file($TemplateTextOrFileName))
653 # load in template from file 654 $Template = file($TemplateTextOrFileName, 1);
656 # report error to caller if template load failed 657 if ($Template == FALSE)
660 return $this->Status;
663 # join into one text block 664 $TemplateTextOrFileName = join(
"", $Template);
667 # split template into lines 668 $Template = explode(
"\n", $TemplateTextOrFileName);
670 # strip any comments out of template 671 $FilteredTemplate = array();
672 foreach ($Template as $Line)
674 if (!preg_match(
"/^[\\s]*#/", $Line))
676 $FilteredTemplate[] = $Line;
680 # split subject line out of template (first non-comment line in file) 681 $EMailSubject = array_shift($FilteredTemplate);
682 $EMailBody = join(
"\n", $FilteredTemplate);
684 # set up our substitutions 685 $Substitutions = array(
686 "X-USERNAME-X" => $this->
Get(
"UserName"),
687 "X-EMAILADDRESS-X" => $this->
Get(
"EMail"),
691 "X-IPADDRESS-X" => @$_SERVER[
"REMOTE_ADDR"],
694 # if caller provided additional substitutions 695 if (is_array($MoreSubstitutions))
697 # add in entries from caller to substitution list 698 $Substitutions = array_merge(
699 $Substitutions, $MoreSubstitutions);
702 # perform substitutions on subject and body of message 703 $EMailSubject = str_replace(array_keys($Substitutions),
704 array_values($Substitutions), $EMailSubject);
705 $EMailBody = str_replace(array_keys($Substitutions),
706 array_values($Substitutions), $EMailBody);
708 $AdditionalHeaders =
"Auto-Submitted: auto-generated";
710 # if caller provided "From" address 713 # prepend "From" address onto message 714 $AdditionalHeaders .=
"\r\nFrom: ".$FromAddress;
717 # send out mail message 718 if (is_Callable(self::$EmailFunc))
720 $Result = call_user_func(self::$EmailFunc,
721 is_null($ToAddress)?$this->
Get(
"EMail"):$ToAddress,
722 $EMailSubject, $EMailBody, $AdditionalHeaders);
726 $Result = mail(is_null($ToAddress)?$this->
Get(
"EMail"):$ToAddress,
728 $EMailBody, $AdditionalHeaders);
731 # report result of mailing attempt to caller 737 # ---- Privilege Functions ----------------------------------------------- 747 public function HasPriv($Privilege, $Privileges = NULL)
749 # return FALSE if not associated with a particular user 750 if ($this->UserId === NULL) {
return FALSE; }
752 # bail out if empty array of privileges passed in 753 if (is_array($Privilege) && !count($Privilege) && (func_num_args() < 2))
756 # set up beginning of database query 757 $Query =
"SELECT COUNT(*) AS PrivCount FROM APUserPrivileges " 758 .
"WHERE UserId='".$this->UserId.
"' AND (";
760 # add first privilege(s) to query (first arg may be single value or array) 761 if (is_array($Privilege))
764 foreach ($Privilege as $Priv)
766 $Query .= $Sep.
"Privilege='".addslashes($Priv).
"'";
772 $Query .=
"Privilege='".$Privilege.
"'";
776 # add any privileges from additional args to query 777 $Args = func_get_args();
779 foreach ($Args as $Arg)
781 $Query .= $Sep.
"Privilege='".$Arg.
"'";
788 # look for privilege in database 789 $PrivCount = $this->DB->Query($Query,
"PrivCount");
791 # return value to caller 792 return ($PrivCount > 0) ? TRUE : FALSE;
805 # set up beginning of database query 806 $Query =
"SELECT DISTINCT UserId FROM APUserPrivileges " 809 # add first privilege(s) to query (first arg may be single value or array) 810 if (is_array($Privilege))
813 foreach ($Privilege as $Priv)
815 $Query .= $Sep.
"Privilege='".addslashes($Priv).
"'";
821 $Query .=
"Privilege='".$Privilege.
"'";
825 # add any privileges from additional args to query 826 $Args = func_get_args();
828 foreach ($Args as $Arg)
830 $Query .= $Sep.
"Privilege='".$Arg.
"'";
834 # return query to caller 848 # set up beginning of database query 849 $Query =
"SELECT DISTINCT UserId FROM APUserPrivileges " 852 # add first privilege(s) to query (first arg may be single value or array) 853 if (is_array($Privilege))
856 foreach ($Privilege as $Priv)
858 $Query .= $Sep.
"Privilege != '".addslashes($Priv).
"'";
864 $Query .=
"Privilege != '".$Privilege.
"'";
868 # add any privileges from additional args to query 869 $Args = func_get_args();
871 foreach ($Args as $Arg)
873 $Query .= $Sep.
"Privilege != '".$Arg.
"'";
877 # return query to caller 883 # return error if not associated with a particular user 886 # if privilege value is invalid 887 if (intval($Privilege) != trim($Privilege))
889 # set code to indicate error 894 # if user does not already have privilege 895 $PrivCount = $this->DB->Query(
"SELECT COUNT(*) AS PrivCount" 896 .
" FROM APUserPrivileges" 897 .
" WHERE UserId='".$this->UserId.
"'" 898 .
" AND Privilege='".$Privilege.
"'",
902 # add privilege for this user to database 903 $this->DB->Query(
"INSERT INTO APUserPrivileges" 904 .
" (UserId, Privilege) VALUES" 905 .
" ('".$this->UserId.
"', ".$Privilege.
")");
908 # set code to indicate success 912 # report result to caller 918 # return error if not associated with a particular user 921 # remove privilege from database (if present) 922 $this->DB->Query(
"DELETE FROM APUserPrivileges" 923 .
" WHERE UserId = '".$this->UserId.
"'" 924 .
" AND Privilege = '".$Privilege.
"'");
926 # report success to caller 933 # return empty list if not associated with a particular user 934 if ($this->UserId === NULL) {
return array(); }
936 # read privileges from database and return array to caller 937 $this->DB->Query(
"SELECT Privilege FROM APUserPrivileges" 938 .
" WHERE UserId='".$this->UserId.
"'");
939 return $this->DB->FetchColumn(
"Privilege");
944 # return error if not associated with a particular user 947 # clear old priv list values 948 $this->DB->Query(
"DELETE FROM APUserPrivileges" 949 .
" WHERE UserId='".$this->UserId.
"'");
951 # for each priv value passed in 952 foreach ($NewPrivileges as $Privilege)
960 # ---- Miscellaneous Functions ------------------------------------------- 962 # get unique alphanumeric code for user 965 # return NULL if not associated with a particular user 966 if ($this->UserId === NULL) {
return NULL; }
968 return substr(strtoupper(md5(
969 $this->
Get(
"UserName").$this->
Get(
"UserPassword").$SeedString)),
974 # ---- PRIVATE INTERFACE ------------------------------------------------- 976 protected $DB; # handle to SQL database we use to store user information
977 protected $UserId = NULL; # user ID number
for reference into database
979 protected $LoggedIn; # flag indicating whether user is logged in
980 private $DBFields; # used
for caching user values
982 # optional mail function to use instead of mail() 983 private static $EmailFunc = NULL;
985 # check whether a user name is valid (alphanumeric string of 2-24 chars) 988 if (preg_match(
"/^[a-zA-Z0-9]{2,24}$/", $UserName))
998 # check whether a password is valid (at least 6 characters) 1001 if (strlen(self::NormalizePassword($Password)) < 6)
1011 # check whether an e-mail address looks valid 1014 if (preg_match(
"/^[a-zA-Z0-9._\-]+@[a-zA-Z0-9._\-]+\.[a-zA-Z]{2,3}$/",
1025 # get normalized version of e-mail address 1028 return strtolower(trim($EMailAddress));
1031 # get normalized version of user name 1034 return trim($UserName);
1037 # get normalized version of password 1040 return trim($Password);
1043 # generate random password 1046 # seed random number generator 1047 mt_srand((
double)microtime() * 1000000);
1049 # generate password of requested length 1050 return sprintf(
"%06d", mt_rand(pow(10, ($PasswordMinLength - 1)),
1051 (pow(10, $PasswordMaxLength) - 1)));
1054 # convenience function to supply parameters to Database->UpdateValue() 1057 return $this->DB->UpdateValue(
"APUsers", $FieldName, $NewValue,
1058 "UserId = '".$this->UserId.
"'", $this->DBFields);
1061 # methods for backward compatibility with earlier versions of User 1070 private static function GetSaltForCrypt()
1072 # generate a password salt by grabbing CRYPT_SALT_LENGTH 1073 # random bytes, then base64 encoding while filtering out 1074 # non-alphanumeric characters to get a string all the hashes 1076 $Salt = preg_replace(
"/[^A-Za-z0-9]/",
"",
1077 base64_encode(openssl_random_pseudo_bytes(
1078 CRYPT_SALT_LENGTH) ));
1080 # select the best available hashing algorithm, provide a salt 1081 # in the correct format for that algorithm 1082 if (CRYPT_SHA512==1)
1084 return '$6$'.substr($Salt, 0, 16);
1086 elseif (CRYPT_SHA256==1)
1088 return '$5$'.substr($Salt, 0, 16);
1090 elseif (CRYPT_BLOWFISH==1)
1092 return '$2y$'.substr($Salt, 0, 22);
1094 elseif (CRYPT_MD5==1)
1096 return '$1$'.substr($Salt, 0, 12);
1098 elseif (CRYPT_EXT_DES==1)
1100 return '_'.substr($Salt, 0, 8);
1104 return substr($Salt, 0, 2);
GetRandomPassword($PasswordMinLength=6, $PasswordMaxLength=8)
static NormalizeUserName($UserName)
static IsValidLookingEMailAddress($EMail)
GetUniqueCode($SeedString, $CodeLength)
__construct($UserInfoOne=NULL, $UserInfoTwo=NULL)
SQL database abstraction object with smart query caching.
IsMailChangeCodeGood($Code)
UpdateValue($FieldName, $NewValue=DB_NOVALUE)
static NormalizePassword($Password)
CreateNewUserAndMailPassword($UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
static IsValidPassword($Password)
Login($UserName, $Password, $IgnorePassword=FALSE)
SetEncryptedPassword($NewEncryptedPassword)
StatusMessage($StatusCode=NULL)
static IsValidUserName($UserName)
static GetSqlQueryForUsersWithPriv($Privilege, $Privileges=NULL)
Get an SQL query that will return IDs of all users that have the specified privilege flags...
GetPasswordSalt($UserName)
LastLocation($NewLocation=NULL)
IsActivated($NewValue=DB_NOVALUE)
HasPriv($Privilege, $Privileges=NULL)
Check whether user has specified privilege(s).
GetBestName()
Get the best available name associated with a user, i.e., the real name or, if it isn't available...
SendEMail($TemplateTextOrFileName, $FromAddress=NULL, $MoreSubstitutions=NULL, $ToAddress=NULL)
Set($FieldName, $NewValue)
const U_DUPLICATEUSERNAME
static SetEmailFunction($NewValue)
Set email function to use instead of mail().
static NormalizeEMailAddress($EMailAddress)
GetDate($FieldName, $Format="")
CreateNewUserWithEMailedPassword($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
CreateNewUserAndMailPasswordFromFile($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
SetPassword($NewPassword)
SetPrivList($NewPrivileges)
ChangePassword($OldPassword, $NewPassword, $NewPasswordAgain)
IsActivationCodeGood($Code)
static GetSqlQueryForUsersWithoutPriv($Privilege, $Privileges=NULL)
Get an SQL query that will return IDs of all users that do not have the specified privilege flags...
const U_PASSWORDSDONTMATCH