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);
40 define(
"U_PASSWORDCONTAINSUSERNAME", 22);
41 define(
"U_PASSWORDCONTAINSEMAIL", 23);
42 define(
"U_PASSWORDTOOSHORT", 24);
43 define(
"U_PASSWORDTOOSIMPLE", 25);
44 define(
"U_PASSWORDNEEDSPUNCTUATION", 26);
45 define(
"U_PASSWORDNEEDSMIXEDCASE", 27);
46 define(
"U_PASSWORDNEEDSDIGIT", 28);
50 # ---- CLASS CONSTANTS --------------------------------------------------- 55 # ---- PUBLIC INTERFACE -------------------------------------------------- 57 public function __construct($UserInfoOne = NULL, $UserInfoTwo = NULL)
59 # create database connection 62 # if we're looking up a user by UserId 63 if (is_numeric($UserInfoOne) || is_numeric($UserInfoTwo))
65 $UserId = is_numeric($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
66 $this->DB->Query(
"SELECT * FROM APUsers" 67 .
" WHERE UserId='".intval(
$UserId).
"'");
68 $Record = $this->DB->FetchRow();
70 # if we're looking up a user by name or email address 71 elseif (is_string($UserInfoOne) || is_string($UserInfoTwo))
73 $UserName = is_string($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
74 $this->DB->Query(
"SELECT * FROM APUsers" 75 .
" WHERE UserName='".addslashes($UserName).
"'");
76 $Record = $this->DB->FetchRow();
78 if ($Record === FALSE)
80 $this->DB->Query(
"SELECT * FROM APUsers" 81 .
" WHERE EMail='".addslashes(
82 self::NormalizeEMailAddress($UserName)).
"'");
83 $Record = $this->DB->FetchRow();
86 # if a UserId is available from the session 87 elseif (isset($_SESSION[
"APUserId"]))
89 $UserId = $_SESSION[
"APUserId"];
90 $this->DB->Query(
"SELECT * FROM APUsers" 91 .
" WHERE UserId='".intval(
$UserId).
"'");
92 $Record = $this->DB->FetchRow();
94 # otherwise, create an anonymous user 102 # if a record was found, load data from it 103 if ($Record !== FALSE)
105 $this->DBFields = $Record;
106 $this->UserId = $Record[
"UserId"];
107 $this->LoggedIn = $Record[
"LoggedIn"] ? TRUE : FALSE;
112 # otherwise, set code indicating no user found 122 # return text message corresponding to current status code 125 return self::GetStatusMessageForCode($this->Result);
135 $APUserStatusMessages = array(
136 U_OKAY =>
"The operation was successful.",
137 U_ERROR =>
"There has been an error.",
141 "The new passwords you entered do not match.",
143 "The e-mail addresses you entered do not match.",
145 "The user name you requested is already in use.",
147 "The user name you requested is too short, too long, " 148 .
"does not start with a letter, " 149 .
"or contains illegal characters.",
151 "The new password you requested is not valid.",
153 "The e-mail address you entered appears to be invalid.",
156 "An error occurred while attempting to send e-mail. " 157 .
"Please notify the system administrator.",
159 "An error occurred while attempting to generate e-mail. " 160 .
"Please notify the system administrator.",
162 "The e-mail address you supplied already has an account " 163 .
"associated with it.",
165 "The password you entered contains your username.",
167 "The password you entered contains your email address.",
170 "Passwords must be at least ".self::$PasswordMinLength
171 .
" characters long.",
173 "Passwords must have at least ".self::$PasswordMinUniqueChars
174 .
" different characters.",
176 "Passwords must contain at least one punctuation character.",
178 "Passwords must contain a mixture of uppercase and " 179 .
"lowercase letters",
181 "Passwords must contain at least one number.",
184 return (isset($APUserStatusMessages[$StatusCode]) ?
185 $APUserStatusMessages[$StatusCode] :
186 "Unknown user status code: ".$StatusCode );
191 # clear priv list values 192 $this->DB->Query(
"DELETE FROM APUserPrivileges WHERE UserId = '" 195 # delete user record from database 196 $this->DB->Query(
"DELETE FROM APUsers WHERE UserId = '".$this->UserId.
"'");
198 # report to caller that everything succeeded 210 if (is_callable($NewValue))
212 self::$EmailFunc = $NewValue;
216 # ---- Getting/Setting Values -------------------------------------------- 224 return $this->
Get(
"UserName");
234 $RealName = $this->
Get(
"RealName");
236 # the real name is available, so use it 237 if (strlen(trim($RealName)))
242 # the real name isn't available, so use the user name 243 return $this->
Get(
"UserName");
248 # return NULL if not associated with a particular user 249 if ($this->UserId === NULL) {
return NULL; }
253 $this->DB->Query(
"UPDATE APUsers SET" 254 .
" LastLocation = '".addslashes($NewLocation).
"'," 255 .
" LastActiveDate = NOW()," 256 .
" LastIPAddress = '".$_SERVER[
"REMOTE_ADDR"].
"'" 257 .
" WHERE UserId = '".addslashes($this->UserId).
"'");
258 if (isset($this->DBFields))
260 $this->DBFields[
"LastLocation"] = $NewLocation;
261 $this->DBFields[
"LastActiveDate"] = date(
"Y-m-d H:i:s");
264 return $this->
Get(
"LastLocation");
268 return $this->
Get(
"LastActiveDate");
272 return $this->
Get(
"LastIPAddress");
275 # get value from specified field 276 public function Get($FieldName)
278 # return NULL if not associated with a particular user 279 if ($this->UserId === NULL) {
return NULL; }
284 # get value (formatted as a date) from specified field 285 public function GetDate($FieldName, $Format =
"")
287 # return NULL if not associated with a particular user 288 if ($this->UserId === NULL) {
return NULL; }
290 # retrieve specified value from database 291 if (strlen($Format) > 0)
293 $this->DB->Query(
"SELECT DATE_FORMAT(`".addslashes($FieldName)
294 .
"`, '".addslashes($Format).
"') AS `".addslashes($FieldName)
295 .
"` FROM APUsers WHERE UserId='".$this->UserId.
"'");
299 $this->DB->Query(
"SELECT `".addslashes($FieldName).
"` FROM APUsers WHERE UserId='".$this->UserId.
"'");
301 $Record = $this->DB->FetchRow();
303 # return value to caller 304 return $Record[$FieldName];
307 # set value in specified field 308 public function Set($FieldName, $NewValue)
310 # return error if not associated with a particular user 313 # transform booleans to 0 or 1 for storage 314 if (is_bool($NewValue))
316 $NewValue = $NewValue ? 1 : 0;
326 # ---- Login Functions --------------------------------------------------- 328 public function Login($UserName, $Password, $IgnorePassword = FALSE)
330 # if user not found in DB 331 $this->DB->Query(
"SELECT * FROM APUsers" 332 .
" WHERE UserName = '" 333 .addslashes(self::NormalizeUserName($UserName)).
"'");
334 if ($this->DB->NumRowsSelected() < 1)
336 # result is no user by that name 341 # if user account not yet activated 342 $Record = $this->DB->FetchRow();
343 if (!$Record[
"RegistrationConfirmed"])
345 # result is user registration not confirmed 350 # grab password from DB 351 $StoredPassword = $Record[
"UserPassword"];
353 if (isset($Password[0]) && $Password[0] ==
" ")
355 $Challenge = md5(date(
"Ymd").$_SERVER[
"REMOTE_ADDR"]);
356 $StoredPassword = md5( $Challenge . $StoredPassword );
358 $EncryptedPassword = trim($Password);
362 # if supplied password matches encrypted password 363 $EncryptedPassword = crypt($Password, $StoredPassword);
366 if (($EncryptedPassword == $StoredPassword) || $IgnorePassword)
371 # store user ID for session 372 $this->UserId = $Record[
"UserId"];
375 # update last login date 376 $this->DB->Query(
"UPDATE APUsers SET LastLoginDate = NOW()," 378 .
" WHERE UserId = '".$this->UserId.
"'");
380 # Check for old format hashes, and rehash if possible 381 if ($EncryptedPassword === $StoredPassword &&
382 substr($StoredPassword, 0, 3) !==
"$1$" &&
383 $Password[0] !==
" " &&
386 $NewPassword = crypt($Password, self::GetSaltForCrypt() );
388 "UPDATE APUsers SET UserPassword='" 389 .addslashes($NewPassword).
"' " 390 .
"WHERE UserId='".$this->UserId.
"'");
393 # since self::DBFields might already have been set to false if 394 # the user wasn't logged in when this is called, populate it 395 # with user data so that a call to self::UpdateValue will be 396 # able to properly fetch the data associated with the user 397 $this->DBFields = $Record;
399 # set flag to indicate we are logged in 400 $this->LoggedIn = TRUE;
404 # result is bad password 410 # return result to caller 417 # clear user ID (if any) for session 418 unset($_SESSION[
"APUserId"]);
420 # if user is marked as logged in 423 # set flag to indicate user is no longer logged in 424 $this->LoggedIn = FALSE;
426 # clear login flag in database 428 "UPDATE APUsers SET LoggedIn = '0' " 429 .
"WHERE UserId='".$this->UserId.
"'");
436 "SELECT * FROM APUsers WHERE UserName = '" 437 .addslashes(self::NormalizeUserName($UserName)).
"'");
439 if ($this->DB->NumRowsSelected() < 1)
441 # result is no user by that name, generate a fake salt 442 # to discourage user enumeration. Make it be an old-format 443 # crypt() salt so that it's harder. 444 $SaltString = $_SERVER[
"SERVER_ADDR"].$UserName;
445 $Result = substr(base64_encode(md5($SaltString)), 0, 2);
449 # grab password from DB 450 # Assumes that we used php's crypt() for the passowrd 451 # management stuff, and will need to be changed if we 452 # go to something else. 453 $Record = $this->DB->FetchRow();
454 $StoredPassword = $Record[
"UserPassword"];
456 if (substr($StoredPassword, 0, 3) ===
"$1$")
458 $Result = substr($StoredPassword, 0, 12);
462 $Result = substr($StoredPassword, 0, 2);
476 if (!isset($this->LoggedIn))
478 $this->LoggedIn = $this->DB->Query(
" 479 SELECT LoggedIn FROM APUsers 480 WHERE UserId='".addslashes($this->UserId).
"'",
481 "LoggedIn") ? TRUE : FALSE;
502 return ($this->UserId === NULL) ? TRUE : FALSE;
506 # ---- Password Functions ------------------------------------------------ 508 # set new password (with checks against old password) 518 # return error if not associated with a particular user 519 if ($this->UserId === NULL)
524 # if old password is not correct 525 $StoredPassword = $this->DB->Query(
"SELECT UserPassword FROM APUsers" 526 .
" WHERE UserId='".$this->UserId.
"'",
"UserPassword");
527 $EncryptedPassword = crypt($OldPassword, $StoredPassword);
528 if ($EncryptedPassword != $StoredPassword)
530 # set status to indicate error 533 # else if both instances of new password do not match 534 elseif (self::NormalizePassword($NewPassword)
535 != self::NormalizePassword($NewPasswordAgain))
537 # set status to indicate error 540 # perform other validity checks 541 elseif (!self::IsValidPassword(
542 $NewPassword, $this->
Get(
"UserName"), $this->
Get(
"EMail")) )
544 # set status to indicate error 552 # set status to indicate password successfully changed 556 # report to caller that everything succeeded 563 # generate encrypted password 564 $EncryptedPassword = crypt(self::NormalizePassword($NewPassword),
565 self::GetSaltForCrypt() );
567 # save encrypted password 568 $this->
UpdateValue(
"UserPassword", $EncryptedPassword);
573 # save encrypted password 574 $this->
UpdateValue(
"UserPassword", $NewEncryptedPassword);
578 $UserName, $EMail, $EMailAgain,
579 $TemplateFile =
"Axis--User--EMailTemplate.txt")
582 $UserName, $EMail, $EMailAgain, $TemplateFile);
586 $UserName, $EMail, $EMailAgain,
587 $TemplateFile =
"Axis--User--EMailTemplate.txt")
589 # load e-mail template from file (first line is subject) 590 $Template = file($TemplateFile, 1);
591 $EMailSubject = array_shift($Template);
592 $EMailBody = join(
"", $Template);
595 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody);
599 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
601 # make sure e-mail addresses match 602 if ($EMail != $EMailAgain)
608 # make sure e-mail address looks valid 615 # generate random password 618 # attempt to create new user with password 619 $Result = $this->CreateNewUser($UserName, $Password, $Password);
621 # if user creation failed 624 # report error result to caller 630 # set e-mail address in user record 631 $this->
Set(
"EMail", $EMail);
633 # plug appropriate values into subject and body of e-mail message 634 $EMailSubject = str_replace(
"X-USERNAME-X", $UserName, $EMailSubject);
635 $EMailBody = str_replace(
"X-USERNAME-X", $UserName, $EMailBody);
636 $EMailBody = str_replace(
"X-PASSWORD-X", $Password, $EMailBody);
638 # send out e-mail message with new account info 639 if (is_Callable(self::$EmailFunc))
641 $Result = call_user_func(self::$EmailFunc,
642 $EMail, $EMailSubject, $EMailBody,
643 "Auto-Submitted: auto-generated");
647 $Result = mail($EMail, $EMailSubject, $EMailBody,
648 "Auto-Submitted: auto-generated");
651 # if mailing attempt failed 654 # report error to caller 661 # report success to caller 668 # get code for user to submit to confirm registration 671 # code is MD5 sum based on user name and encrypted password 672 $ActivationCodeLength = 6;
673 return $this->
GetUniqueCode(
"Activation", $ActivationCodeLength);
676 # check whether confirmation code is valid 683 # get/set whether user registration has been confirmed 686 return $this->
UpdateValue(
"RegistrationConfirmed", $NewValue);
689 # get code for user to submit to confirm password reset 692 # code is MD5 sum based on user name and encrypted password 693 $ResetCodeLength = 10;
697 # check whether password reset code is valid 700 return (strtoupper(trim($Code)) == $this->
GetResetCode())
704 # get code for user to submit to confirm mail change request 707 $ResetCodeLength = 10;
709 .$this->
Get(
"EMailNew"),
719 # send e-mail to user (returns TRUE on success) 721 $TemplateTextOrFileName, $FromAddress = NULL, $MoreSubstitutions = NULL,
724 # if template is file name 725 if (@is_file($TemplateTextOrFileName))
727 # load in template from file 728 $Template = file($TemplateTextOrFileName, 1);
730 # report error to caller if template load failed 731 if ($Template == FALSE)
734 return $this->Status;
737 # join into one text block 738 $TemplateTextOrFileName = join(
"", $Template);
741 # split template into lines 742 $Template = explode(
"\n", $TemplateTextOrFileName);
744 # strip any comments out of template 745 $FilteredTemplate = array();
746 foreach ($Template as $Line)
748 if (!preg_match(
"/^[\\s]*#/", $Line))
750 $FilteredTemplate[] = $Line;
754 # split subject line out of template (first non-comment line in file) 755 $EMailSubject = array_shift($FilteredTemplate);
756 $EMailBody = join(
"\n", $FilteredTemplate);
758 # set up our substitutions 759 $Substitutions = array(
760 "X-USERNAME-X" => $this->
Get(
"UserName"),
761 "X-EMAILADDRESS-X" => $this->
Get(
"EMail"),
765 "X-IPADDRESS-X" => @$_SERVER[
"REMOTE_ADDR"],
768 # if caller provided additional substitutions 769 if (is_array($MoreSubstitutions))
771 # add in entries from caller to substitution list 772 $Substitutions = array_merge(
773 $Substitutions, $MoreSubstitutions);
776 # perform substitutions on subject and body of message 777 $EMailSubject = str_replace(array_keys($Substitutions),
778 array_values($Substitutions), $EMailSubject);
779 $EMailBody = str_replace(array_keys($Substitutions),
780 array_values($Substitutions), $EMailBody);
782 $AdditionalHeaders =
"Auto-Submitted: auto-generated";
784 # if caller provided "From" address 787 # prepend "From" address onto message 788 $AdditionalHeaders .=
"\r\nFrom: ".$FromAddress;
791 # send out mail message 792 if (is_Callable(self::$EmailFunc))
794 $Result = call_user_func(self::$EmailFunc,
795 is_null($ToAddress)?$this->
Get(
"EMail"):$ToAddress,
796 $EMailSubject, $EMailBody, $AdditionalHeaders);
800 $Result = mail(is_null($ToAddress)?$this->
Get(
"EMail"):$ToAddress,
802 $EMailBody, $AdditionalHeaders);
805 # report result of mailing attempt to caller 811 # ---- Privilege Functions ----------------------------------------------- 821 public function HasPriv($Privilege, $Privileges = NULL)
823 # return FALSE if not associated with a particular user 824 if ($this->UserId === NULL) {
return FALSE; }
826 # bail out if empty array of privileges passed in 827 if (is_array($Privilege) && !count($Privilege) && (func_num_args() < 2))
830 # set up beginning of database query 831 $Query =
"SELECT COUNT(*) AS PrivCount FROM APUserPrivileges " 832 .
"WHERE UserId='".$this->UserId.
"' AND (";
834 # add first privilege(s) to query (first arg may be single value or array) 835 if (is_array($Privilege))
838 foreach ($Privilege as $Priv)
840 $Query .= $Sep.
"Privilege='".addslashes($Priv).
"'";
846 $Query .=
"Privilege='".$Privilege.
"'";
850 # add any privileges from additional args to query 851 $Args = func_get_args();
853 foreach ($Args as $Arg)
855 $Query .= $Sep.
"Privilege='".$Arg.
"'";
862 # look for privilege in database 863 $PrivCount = $this->DB->Query($Query,
"PrivCount");
865 # return value to caller 866 return ($PrivCount > 0) ? TRUE : FALSE;
879 # set up beginning of database query 880 $Query =
"SELECT DISTINCT UserId FROM APUserPrivileges " 883 # add first privilege(s) to query (first arg may be single value or array) 884 if (is_array($Privilege))
887 foreach ($Privilege as $Priv)
889 $Query .= $Sep.
"Privilege='".addslashes($Priv).
"'";
895 $Query .=
"Privilege='".$Privilege.
"'";
899 # add any privileges from additional args to query 900 $Args = func_get_args();
902 foreach ($Args as $Arg)
904 $Query .= $Sep.
"Privilege='".$Arg.
"'";
908 # return query to caller 922 # set up beginning of database query 923 $Query =
"SELECT DISTINCT UserId FROM APUserPrivileges " 926 # add first privilege(s) to query (first arg may be single value or array) 927 if (is_array($Privilege))
930 foreach ($Privilege as $Priv)
932 $Query .= $Sep.
"Privilege != '".addslashes($Priv).
"'";
938 $Query .=
"Privilege != '".$Privilege.
"'";
942 # add any privileges from additional args to query 943 $Args = func_get_args();
945 foreach ($Args as $Arg)
947 $Query .= $Sep.
"Privilege != '".$Arg.
"'";
951 # return query to caller 957 # return error if not associated with a particular user 960 # if privilege value is invalid 961 if (intval($Privilege) != trim($Privilege))
963 # set code to indicate error 968 # if user does not already have privilege 969 $PrivCount = $this->DB->Query(
"SELECT COUNT(*) AS PrivCount" 970 .
" FROM APUserPrivileges" 971 .
" WHERE UserId='".$this->UserId.
"'" 972 .
" AND Privilege='".$Privilege.
"'",
976 # add privilege for this user to database 977 $this->DB->Query(
"INSERT INTO APUserPrivileges" 978 .
" (UserId, Privilege) VALUES" 979 .
" ('".$this->UserId.
"', ".$Privilege.
")");
982 # set code to indicate success 986 # report result to caller 992 # return error if not associated with a particular user 995 # remove privilege from database (if present) 996 $this->DB->Query(
"DELETE FROM APUserPrivileges" 997 .
" WHERE UserId = '".$this->UserId.
"'" 998 .
" AND Privilege = '".$Privilege.
"'");
1000 # report success to caller 1007 # return empty list if not associated with a particular user 1008 if ($this->UserId === NULL) {
return array(); }
1010 # read privileges from database and return array to caller 1011 $this->DB->Query(
"SELECT Privilege FROM APUserPrivileges" 1012 .
" WHERE UserId='".$this->UserId.
"'");
1013 return $this->DB->FetchColumn(
"Privilege");
1018 # return error if not associated with a particular user 1021 # clear old priv list values 1022 $this->DB->Query(
"DELETE FROM APUserPrivileges" 1023 .
" WHERE UserId='".$this->UserId.
"'");
1025 # for each priv value passed in 1026 foreach ($NewPrivileges as $Privilege)
1041 # if we have a UserId in the session, move it aside 1042 if (isset($_SESSION[
"APUserId"]))
1044 $OldUserId = $_SESSION[
"APUserId"];
1045 unset($_SESSION[
"APUserId"]);
1048 # create a new anonymous user 1049 $CalledClass = get_called_class();
1053 # restore the $_SESSION value 1054 if (isset($OldUserId))
1056 $_SESSION[
"APUserId"] = $OldUserId;
1059 # return our anonymous user 1063 # ---- Miscellaneous Functions ------------------------------------------- 1065 # get unique alphanumeric code for user 1068 # return NULL if not associated with a particular user 1069 if ($this->UserId === NULL) {
return NULL; }
1071 return substr(strtoupper(md5(
1072 $this->
Get(
"UserName").$this->
Get(
"UserPassword").$SeedString)),
1077 # ---- PRIVATE INTERFACE ------------------------------------------------- 1079 protected $DB; # handle to SQL database we use to store user information
1080 protected $UserId = NULL; # user ID number
for reference into database
1082 protected $LoggedIn; # flag indicating whether user is logged in
1083 private $DBFields; # used
for caching user values
1085 # optional mail function to use instead of mail() 1086 private static $EmailFunc = NULL;
1088 # check whether a user name is valid 1089 # (alphanumeric string of 2-24 chars that starts with a letter) 1092 if (preg_match(
"/^[a-zA-Z][a-zA-Z0-9]{1,23}$/", $UserName))
1099 # check whether a password is valid (at least 6 characters) 1101 $Password, $UserName, $Email)
1103 return count(self::CheckPasswordForErrors(
1104 $Password, $UserName, $Email)) == 0 ?
1118 $Password, $UserName = NULL, $Email = NULL)
1120 # start off assuming no errors 1123 # normalize incoming password 1124 $Password = self::NormalizePassword($Password);
1126 # username provided and password contains username 1127 if ($UserName !== NULL &&
1128 stripos($Password, $UserName) !== FALSE)
1133 # email provided and password contains email 1134 if ($Email !== NULL &&
1135 stripos($Password, $Email) !== FALSE)
1140 # length requirement 1141 if (strlen($Password) == 0)
1145 elseif (strlen($Password) < self::$PasswordMinLength)
1150 # unique characters requirement 1151 $UniqueChars = count(array_unique(
1152 preg_split(
'//u', $Password, NULL, PREG_SPLIT_NO_EMPTY)));
1154 if ($UniqueChars < self::$PasswordMinUniqueChars)
1159 # for the following complexity checks, use unicode character properties 1160 # in PCRE as in: http://php.net/manual/en/regexp.reference.unicode.php 1162 # check for punctuation, uppercase letters, and numbers as per the system 1164 if (self::$PasswordRules & self::PW_REQUIRE_PUNCTUATION &&
1165 !preg_match(
'/\p{P}/u', $Password) )
1170 if (self::$PasswordRules & self::PW_REQUIRE_MIXEDCASE &&
1171 (!preg_match(
'/\p{Lu}/u', $Password) ||
1172 !preg_match(
'/\p{Ll}/u', $Password) ) )
1178 if (self::$PasswordRules & self::PW_REQUIRE_DIGITS &&
1179 !preg_match(
'/\p{N}/u', $Password))
1187 # check whether an e-mail address looks valid 1190 if (preg_match(
"/^[a-zA-Z0-9._\-]+@[a-zA-Z0-9._\-]+\.[a-zA-Z]{2,3}$/",
1201 # get normalized version of e-mail address 1204 return strtolower(trim($EMailAddress));
1207 # get normalized version of user name 1210 return trim($UserName);
1213 # get normalized version of password 1216 return trim($Password);
1219 # generate random password 1222 # seed random number generator 1223 mt_srand((
double)microtime() * 1000000);
1225 # generate password of requested length 1226 return sprintf(
"%06d", mt_rand(pow(10, ($PasswordMinLength - 1)),
1227 (pow(10, $PasswordMaxLength) - 1)));
1230 # convenience function to supply parameters to Database->UpdateValue() 1233 return $this->DB->UpdateValue(
"APUsers", $FieldName, $NewValue,
1234 "UserId = '".$this->UserId.
"'", $this->DBFields);
1237 # methods for backward compatibility with earlier versions of User 1250 self::$PasswordRules = $NewValue;
1259 self::$PasswordMinLength = $NewValue;
1268 self::$PasswordMinUniqueChars = $NewValue;
1277 return "Passwords are case-sensitive, cannot contain your username or email, " 1278 .
"must be at least ".self::$PasswordMinLength
1279 .
" characters long, " 1280 .
" have at least ".self::$PasswordMinUniqueChars
1281 .
" different characters" 1282 .(self::$PasswordRules & self::PW_REQUIRE_PUNCTUATION ?
1283 ", include punctuation":
"")
1284 .(self::$PasswordRules & self::PW_REQUIRE_MIXEDCASE ?
1285 ", include capital and lowercase letters":
"")
1286 .(self::$PasswordRules & self::PW_REQUIRE_DIGITS ?
1287 ", include a number":
"").
".";
1293 private static function GetSaltForCrypt()
1295 # generate a password salt by grabbing CRYPT_SALT_LENGTH 1296 # random bytes, then base64 encoding while filtering out 1297 # non-alphanumeric characters to get a string all the hashes 1299 $Salt = preg_replace(
"/[^A-Za-z0-9]/",
"",
1300 base64_encode(openssl_random_pseudo_bytes(
1301 CRYPT_SALT_LENGTH) ));
1303 # select the best available hashing algorithm, provide a salt 1304 # in the correct format for that algorithm 1305 if (CRYPT_SHA512==1)
1307 return '$6$'.substr($Salt, 0, 16);
1309 elseif (CRYPT_SHA256==1)
1311 return '$5$'.substr($Salt, 0, 16);
1313 elseif (CRYPT_BLOWFISH==1)
1315 return '$2y$'.substr($Salt, 0, 22);
1317 elseif (CRYPT_MD5==1)
1319 return '$1$'.substr($Salt, 0, 12);
1321 elseif (CRYPT_EXT_DES==1)
1323 return '_'.substr($Salt, 0, 8);
1327 return substr($Salt, 0, 2);
1331 private static $PasswordMinLength = 6;
1332 private static $PasswordMinUniqueChars = 4;
1334 # default to no additional requirements beyond length 1335 private static $PasswordRules = 0;
GetRandomPassword($PasswordMinLength=6, $PasswordMaxLength=8)
static GetAnonymousUser()
Get the anonymous user (i.e., the User object that exists when no user is logged in), useful when a permission check needs to know if something should be visible to the general public.
static NormalizeUserName($UserName)
IsLoggedIn()
Report whether user is currently logged in.
static IsValidLookingEMailAddress($EMail)
static SetPasswordMinLength($NewValue)
Set password minimum length.
GetUniqueCode($SeedString, $CodeLength)
__construct($UserInfoOne=NULL, $UserInfoTwo=NULL)
SQL database abstraction object with smart query caching.
static CheckPasswordForErrors($Password, $UserName=NULL, $Email=NULL)
Determine if a provided password complies with the configured rules, optionally checking that it does...
IsMailChangeCodeGood($Code)
UpdateValue($FieldName, $NewValue=DB_NOVALUE)
static NormalizePassword($Password)
CreateNewUserAndMailPassword($UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
const U_PASSWORDNEEDSPUNCTUATION
const U_PASSWORDNEEDSDIGIT
Login($UserName, $Password, $IgnorePassword=FALSE)
SetEncryptedPassword($NewEncryptedPassword)
const U_PASSWORDCONTAINSEMAIL
const PW_REQUIRE_MIXEDCASE
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)
static SetPasswordMinUniqueChars($NewValue)
Set password minimum unique characters.
static SetPasswordRules($NewValue)
Set password requirements.
IsActivated($NewValue=DB_NOVALUE)
static GetStatusMessageForCode($StatusCode)
Get text error message for a specified error code.
const PW_REQUIRE_PUNCTUATION
HasPriv($Privilege, $Privileges=NULL)
Check whether user has specified privilege(s).
const U_PASSWORDNEEDSMIXEDCASE
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)
const U_PASSWORDCONTAINSUSERNAME
const U_PASSWORDTOOSIMPLE
Set($FieldName, $NewValue)
IsAnonymous()
Report whether user is anonymous user.
static GetPasswordRulesDescription()
Get a string describing the password rules.
const U_DUPLICATEUSERNAME
static SetEmailFunction($NewValue)
Set email function to use instead of mail().
static IsValidPassword($Password, $UserName, $Email)
static NormalizeEMailAddress($EMailAddress)
GetDate($FieldName, $Format="")
CreateNewUserWithEMailedPassword($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
IsNotLoggedIn()
Report whether user is not currently logged in.
CreateNewUserAndMailPasswordFromFile($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
SetPassword($NewPassword)
SetPrivList($NewPrivileges)
ChangePassword($OldPassword, $NewPassword, $NewPasswordAgain)
Check provided password and set a new one if it war correct.
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