CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

User.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # User.php
4 # An Object for Handling User Information
5 #
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).
10 #
11 # Author: Edward Almasy (almasy@axisdata.com)
12 #
13 # Part of the AxisPHP library v1.2.4
14 # For more information see http://www.axisdata.com/AxisPHP/
15 #
16
17 # status values (error codes)
18 define("U_OKAY", 0);
19 define("U_ERROR", 1);
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
41 class User
42 {
43 # ---- PUBLIC INTERFACE --------------------------------------------------
44
45 public function __construct($UserInfoOne = NULL, $UserInfoTwo = NULL)
46 {
47 # assume constructor will succeed and user is not logged in
48 $this->Result = U_OKAY;
49 $this->LoggedIn = FALSE;
50
51 # create database connection
52 $this->DB = new Database();
53
54 # if user info passed in
55 if (is_int($UserInfoOne) || is_string($UserInfoOne)
56 || is_int($UserInfoTwo) || is_string($UserInfoTwo))
57 {
58 # if user ID was passed in
59 if (is_int($UserInfoOne) || is_int($UserInfoTwo))
60 {
61 # save user ID
62 $this->UserId = is_int($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
63
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)."'",
68 "LoggedIn");
69 }
70 else
71 {
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();
77 if ($Record)
78 {
79 $this->UserId = $Record["UserId"];
80 $this->LoggedIn = $Record["LoggedIn"];
81 }
82
83 # if user ID was not found
84 if ($Record === FALSE)
85 {
86 # if name looks like it could actually be a user ID
87 if (preg_match("/^[-]*[0-9]+$/", $UserInfoTwo))
88 {
89 # assume name was user ID
90 $this->UserId = intval($UserInfoTwo);
91 }
92 else
93 {
94 # set code indicating no user found
95 $this->Result = U_NOSUCHUSER;
96 unset($this->UserId);
97 }
98 }
99 }
100 }
101 else
102 {
103 # if user ID is available from session
104 if (isset($_SESSION["APUserId"]))
105 {
106 # save user ID
107 $this->UserId = $_SESSION["APUserId"];
108
109 # set flag indicating user is currently logged in
110 $this->LoggedIn = TRUE;
111 }
112 }
113 }
114
115 public function Status()
116 {
117 return $this->Result;
118 }
119
120 # return text message corresponding to current (or specified) status code
121 public function StatusMessage($StatusCode = NULL)
122 {
123 $APUserStatusMessages = array(
124 U_OKAY => "The operation was successful.",
125 U_ERROR => "There has been an error.",
126 U_BADPASSWORD => "The password you entered was"
127 ." incorrect.",
128 U_NOSUCHUSER => "No such user name was found.",
129 U_PASSWORDSDONTMATCH => "The new passwords you entered do"
130 ." not match.",
131 U_EMAILSDONTMATCH => "The e-mail addresses you entered"
132 ." do not match.",
133 U_DUPLICATEUSERNAME => "The user name you requested is"
134 ." already in use.",
135 U_ILLEGALUSERNAME => "The user name you requested is too"
136 ." short, too long, or contains"
137 ." illegal characters.",
138 U_ILLEGALPASSWORD => "The new password you requested is"
139 ." too short, too long, or"
140 ." contains illegal characters.",
141 U_ILLEGALEMAIL => "The e-mail address you entered"
142 ." appears to be invalid.",
143 U_NOTLOGGEDIN => "The user is not logged in.",
144 U_MAILINGERROR => "An error occurred while attempting"
145 ." to send e-mail. Please notify"
146 ." the system administrator.",
147 U_TEMPLATENOTFOUND => "An error occurred while attempting"
148 ." to generate e-mail. Please"
149 ." notify the system administrator.",
150 U_DUPLICATEEMAIL => "The e-mail address you supplied already"
151 ." has an account associated with it.",
152 );
153
154 return ($StatusCode === NULL) ? $APUserStatusMessages[$this->Result]
155 : $APUserStatusMessages[$StatusCode];
156 }
157
158 public function Delete()
159 {
160 # clear priv list values
161 $this->DB->Query("DELETE FROM APUserPrivileges WHERE UserId = '"
162 .$this->UserId."'");
163
164 # delete user record from database
165 $this->DB->Query("DELETE FROM APUsers WHERE UserId = '".$this->UserId."'");
166
167 # report to caller that everything succeeded
168 $this->Result = U_OKAY;
169 return $this->Result;
170 }
171
177 public static function SetEmailFunction($NewValue)
178 {
179 if (is_callable($NewValue))
180 {
181 self::$EmailFunc = $NewValue;
182 }
183 }
184
185
186 # ---- Getting/Setting Values --------------------------------------------
187
188 public function Id()
189 {
190 return $this->UserId;
191 }
192 public function Name()
193 {
194 return $this->Get("UserName");
195 }
196
202 public function GetBestName()
203 {
204 $RealName = $this->Get("RealName");
205
206 # the real name is available, so use it
207 if (strlen(trim($RealName)))
208 {
209 return $RealName;
210 }
211
212 # the real name isn't available, so use the user name
213 return $this->Get("UserName");
214 }
215
216 public function LastLocation($NewLocation = NULL)
217 {
218 # return NULL if not associated with a particular user
219 if ($this->UserId === NULL) { return NULL; }
220
221 if ($NewLocation)
222 {
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))
229 {
230 $this->DBFields["LastLocation"] = $NewLocation;
231 $this->DBFields["LastActiveDate"] = date("Y-m-d H:i:s");
232 }
233 }
234 return $this->Get("LastLocation");
235 }
236 public function LastActiveDate()
237 {
238 return $this->Get("LastActiveDate");
239 }
240 public function LastIPAddress()
241 {
242 return $this->Get("LastIPAddress");
243 }
244
245 # get value from specified field
246 public function Get($FieldName)
247 {
248 # return NULL if not associated with a particular user
249 if ($this->UserId === NULL) { return NULL; }
250
251 return $this->UpdateValue($FieldName);
252 }
253
254 # get value (formatted as a date) from specified field
255 public function GetDate($FieldName, $Format = "")
256 {
257 # return NULL if not associated with a particular user
258 if ($this->UserId === NULL) { return NULL; }
259
260 # retrieve specified value from database
261 if (strlen($Format) > 0)
262 {
263 $this->DB->Query("SELECT DATE_FORMAT(`".addslashes($FieldName)
264 ."`, '".addslashes($Format)."') AS `".addslashes($FieldName)
265 ."` FROM APUsers WHERE UserId='".$this->UserId."'");
266 }
267 else
268 {
269 $this->DB->Query("SELECT `".addslashes($FieldName)."` FROM APUsers WHERE UserId='".$this->UserId."'");
270 }
271 $Record = $this->DB->FetchRow();
272
273 # return value to caller
274 return $Record[$FieldName];
275 }
276
277 # set value in specified field
278 public function Set($FieldName, $NewValue)
279 {
280 # return error if not associated with a particular user
281 if ($this->UserId === NULL) { return U_NOTLOGGEDIN; }
282
283 $this->UpdateValue($FieldName, $NewValue);
284 $this->Result = U_OKAY;
285 return $this->Result;
286 }
287
288
289 # ---- Login Functions ---------------------------------------------------
290
291 public function Login($UserName, $Password, $IgnorePassword = FALSE)
292 {
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)
298 {
299 # result is no user by that name
300 $this->Result = U_NOSUCHUSER;
301 }
302 else
303 {
304 # if user account not yet activated
305 $Record = $this->DB->FetchRow();
306 if (!$Record["RegistrationConfirmed"])
307 {
308 # result is user registration not confirmed
309 $this->Result = U_NOTACTIVATED;
310 }
311 else
312 {
313 # grab password from DB
314 $StoredPassword = $Record["UserPassword"];
315
316 if (isset($Password[0]) && $Password[0] == " ")
317 {
318 $Challenge = md5(date("Ymd").$_SERVER["REMOTE_ADDR"]);
319 $StoredPassword = md5( $Challenge . $StoredPassword );
320
321 $EncryptedPassword = trim($Password);
322 }
323 else
324 {
325 # if supplied password matches encrypted password
326 $EncryptedPassword = crypt($Password, $StoredPassword);
327 }
328
329 if (($EncryptedPassword == $StoredPassword) || $IgnorePassword)
330 {
331 # result is success
332 $this->Result = U_OKAY;
333
334 # store user ID for session
335 $this->UserId = $Record["UserId"];
336 $_SESSION["APUserId"] = $this->UserId;
337
338 # update last login date
339 $this->DB->Query("UPDATE APUsers SET LastLoginDate = NOW(),"
340 ." LoggedIn = '1'"
341 ." WHERE UserId = '".$this->UserId."'");
342
343 # Check for old format hashes, and rehash if possible
344 if ($EncryptedPassword === $StoredPassword &&
345 substr($StoredPassword, 0, 3) !== "$1$" &&
346 $Password[0] !== " " &&
347 CRYPT_MD5 )
348 {
349 $NewPassword = crypt($Password, self::GetSaltForCrypt() );
350 $this->DB->Query(
351 "UPDATE APUsers SET UserPassword='"
352 .addslashes($NewPassword)."' "
353 ."WHERE UserId='".$this->UserId."'");
354 }
355
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;
361
362 # set flag to indicate we are logged in
363 $this->LoggedIn = TRUE;
364 }
365 else
366 {
367 # result is bad password
368 $this->Result = U_BADPASSWORD;
369 }
370 }
371 }
372
373 # return result to caller
374 return $this->Result;
375 }
376
377 # log this user out
378 public function Logout()
379 {
380 # clear user ID (if any) for session
381 unset($_SESSION["APUserId"]);
382
383 # if user is marked as logged in
384 if ($this->LoggedIn)
385 {
386 # set flag to indicate user is no longer logged in
387 $this->LoggedIn = FALSE;
388
389 # clear login flag in database
390 $this->DB->Query(
391 "UPDATE APUsers SET LoggedIn = '0' "
392 ."WHERE UserId='".$this->UserId."'");
393 }
394 }
395
396 public function GetPasswordSalt($UserName)
397 {
398 $this->DB->Query(
399 "SELECT * FROM APUsers WHERE UserName = '"
400 .addslashes(self::NormalizeUserName($UserName))."'");
401
402 if ($this->DB->NumRowsSelected() < 1)
403 {
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);
409 }
410 else
411 {
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"];
418
419 if (substr($StoredPassword, 0, 3) === "$1$")
420 {
421 $Result = substr($StoredPassword, 0, 12);
422 }
423 else
424 {
425 $Result = substr($StoredPassword, 0, 2);
426 }
427 }
428
429 return $Result;
430 }
431
432 # report whether this user is or is not currently logged in
433 public function IsLoggedIn()
434 {
435 return $this->LoggedIn;
436 }
437 public function IsNotLoggedIn()
438 {
439 return !$this->LoggedIn;
440 }
441
442
443 # ---- Password Functions ------------------------------------------------
444
445 # set new password (with checks against old password)
446 public function ChangePassword($OldPassword, $NewPassword, $NewPasswordAgain)
447 {
448 # return error if not associated with a particular user
449 if ($this->UserId === NULL) { return U_NOTLOGGEDIN; }
450
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)
456 {
457 # set status to indicate error
458 $this->Result = U_BADPASSWORD;
459 }
460 # else if new password is not legal
461 elseif (!$this->IsValidPassword($NewPassword))
462 {
463 # set status to indicate error
464 $this->Result = U_ILLEGALPASSWORD;
465 }
466 # else if both instances of new password do not match
467 elseif (self::NormalizePassword($NewPassword)
468 != self::NormalizePassword($NewPasswordAgain))
469 {
470 # set status to indicate error
471 $this->Result = U_PASSWORDSDONTMATCH;
472 }
473 else
474 {
475 # set new password
476 $this->SetPassword($NewPassword);
477
478 # set status to indicate password successfully changed
479 $this->Result = U_OKAY;
480 }
481
482 # report to caller that everything succeeded
483 return $this->Result;
484 }
485
486 # set new password
487 public function SetPassword($NewPassword)
488 {
489 # generate encrypted password
490 $EncryptedPassword = crypt(self::NormalizePassword($NewPassword),
491 self::GetSaltForCrypt() );
492
493 # save encrypted password
494 $this->UpdateValue("UserPassword", $EncryptedPassword);
495 }
496
497 public function SetEncryptedPassword($NewEncryptedPassword)
498 {
499 # save encrypted password
500 $this->UpdateValue("UserPassword", $NewEncryptedPassword);
501 }
502
503 public function CreateNewUserWithEMailedPassword(
504 $UserName, $EMail, $EMailAgain,
505 $TemplateFile = "Axis--User--EMailTemplate.txt")
506 {
507 return CreateNewUserAndMailPasswordFromFile(
508 $UserName, $EMail, $EMailAgain, $TemplateFile);
509 }
510
511 public function CreateNewUserAndMailPasswordFromFile(
512 $UserName, $EMail, $EMailAgain,
513 $TemplateFile = "Axis--User--EMailTemplate.txt")
514 {
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);
519
520 return CreateNewUserAndMailPassword(
521 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody);
522 }
523
524 public function CreateNewUserAndMailPassword(
525 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
526 {
527 # make sure e-mail addresses match
528 if ($EMail != $EMailAgain)
529 {
530 $this->Result = U_EMAILSDONTMATCH;
531 return $this->Result;
532 }
533
534 # make sure e-mail address looks valid
535 if ($this->IsValidLookingEMailAddress($EMail) == FALSE)
536 {
537 $this->Result = U_ILLEGALEMAIL;
538 return $this->Result;
539 }
540
541 # generate random password
542 $Password = $this->GetRandomPassword();
543
544 # attempt to create new user with password
545 $Result = $this->CreateNewUser($UserName, $Password, $Password);
546
547 # if user creation failed
548 if ($Result != U_OKAY)
549 {
550 # report error result to caller
551 return $Result;
552 }
553 # else
554 else
555 {
556 # set e-mail address in user record
557 $this->Set("EMail", $EMail);
558
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);
563
564 # send out e-mail message with new account info
565 if (is_Callable(self::$EmailFunc))
566 {
567 $Result = call_user_func(self::$EmailFunc,
568 $EMail, $EMailSubject, $EMailBody,
569 "Auto-Submitted: auto-generated");
570 }
571 else
572 {
573 $Result = mail($EMail, $EMailSubject, $EMailBody,
574 "Auto-Submitted: auto-generated");
575 }
576
577 # if mailing attempt failed
578 if ($Result != TRUE)
579 {
580 # report error to caller
581 $this->Result = U_MAILINGERROR;
582 return $this->Result;
583 }
584 # else
585 else
586 {
587 # report success to caller
588 $this->Result = U_OKAY;
589 return $this->Result;
590 }
591 }
592 }
593
594 # get code for user to submit to confirm registration
595 public function GetActivationCode()
596 {
597 # code is MD5 sum based on user name and encrypted password
598 $ActivationCodeLength = 6;
599 return $this->GetUniqueCode("Activation", $ActivationCodeLength);
600 }
601
602 # check whether confirmation code is valid
603 public function IsActivationCodeGood($Code)
604 {
605 return (strtoupper(trim($Code)) == $this->GetActivationCode())
606 ? TRUE : FALSE;
607 }
608
609 # get/set whether user registration has been confirmed
610 public function IsActivated($NewValue = DB_NOVALUE)
611 {
612 return $this->UpdateValue("RegistrationConfirmed", $NewValue);
613 }
614
615 # get code for user to submit to confirm password reset
616 public function GetResetCode()
617 {
618 # code is MD5 sum based on user name and encrypted password
619 $ResetCodeLength = 10;
620 return $this->GetUniqueCode("Reset", $ResetCodeLength);
621 }
622
623 # check whether password reset code is valid
624 public function IsResetCodeGood($Code)
625 {
626 return (strtoupper(trim($Code)) == $this->GetResetCode())
627 ? TRUE : FALSE;
628 }
629
630 # get code for user to submit to confirm mail change request
631 public function GetMailChangeCode()
632 {
633 $ResetCodeLength = 10;
634 return $this->GetUniqueCode("MailChange".$this->Get("EMail")
635 .$this->Get("NewEMail"),
636 $ResetCodeLength);
637 }
638
639 public function IsMailChangeCodeGood($Code)
640 {
641 return (strtoupper(trim($Code)) == $this->GetMailChangeCode())
642 ? TRUE : FALSE;
643 }
644
645 # send e-mail to user (returns TRUE on success)
646 public function SendEMail(
647 $TemplateTextOrFileName, $FromAddress = NULL, $MoreSubstitutions = NULL,
648 $ToAddress = NULL)
649 {
650 # if template is file name
651 if (@is_file($TemplateTextOrFileName))
652 {
653 # load in template from file
654 $Template = file($TemplateTextOrFileName, 1);
655
656 # report error to caller if template load failed
657 if ($Template == FALSE)
658 {
659 $this->Status = U_TEMPLATENOTFOUND;
660 return $this->Status;
661 }
662
663 # join into one text block
664 $TemplateTextOrFileName = join("", $Template);
665 }
666
667 # split template into lines
668 $Template = explode("\n", $TemplateTextOrFileName);
669
670 # strip any comments out of template
671 $FilteredTemplate = array();
672 foreach ($Template as $Line)
673 {
674 if (!preg_match("/^[\\s]*#/", $Line))
675 {
676 $FilteredTemplate[] = $Line;
677 }
678 }
679
680 # split subject line out of template (first non-comment line in file)
681 $EMailSubject = array_shift($FilteredTemplate);
682 $EMailBody = join("\n", $FilteredTemplate);
683
684 # set up our substitutions
685 $Substitutions = array(
686 "X-USERNAME-X" => $this->Get("UserName"),
687 "X-EMAILADDRESS-X" => $this->Get("EMail"),
688 "X-ACTIVATIONCODE-X" => $this->GetActivationCode(),
689 "X-RESETCODE-X" => $this->GetResetCode(),
690 "X-CHANGECODE-X" => $this->GetMailChangeCode(),
691 "X-IPADDRESS-X" => @$_SERVER["REMOTE_ADDR"],
692 );
693
694 # if caller provided additional substitutions
695 if (is_array($MoreSubstitutions))
696 {
697 # add in entries from caller to substitution list
698 $Substitutions = array_merge(
699 $Substitutions, $MoreSubstitutions);
700 }
701
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);
707
708 $AdditionalHeaders = "Auto-Submitted: auto-generated";
709
710 # if caller provided "From" address
711 if ($FromAddress)
712 {
713 # prepend "From" address onto message
714 $AdditionalHeaders .= "\r\nFrom: ".$FromAddress;
715 }
716
717 # send out mail message
718 if (is_Callable(self::$EmailFunc))
719 {
720 $Result = call_user_func(self::$EmailFunc,
721 is_null($ToAddress)?$this->Get("EMail"):$ToAddress,
722 $EMailSubject, $EMailBody, $AdditionalHeaders);
723 }
724 else
725 {
726 $Result = mail(is_null($ToAddress)?$this->Get("EMail"):$ToAddress,
727 $EMailSubject,
728 $EMailBody, $AdditionalHeaders);
729 }
730
731 # report result of mailing attempt to caller
732 $this->Status = ($Result == TRUE) ? U_OKAY : U_MAILINGERROR;
733 return ($this->Status == U_OKAY);
734 }
735
736
737 # ---- Privilege Functions -----------------------------------------------
738
747 public function HasPriv($Privilege, $Privileges = NULL)
748 {
749 # return FALSE if not associated with a particular user
750 if ($this->UserId === NULL) { return FALSE; }
751
752 # bail out if empty array of privileges passed in
753 if (is_array($Privilege) && !count($Privilege) && (func_num_args() < 2))
754 { return FALSE; }
755
756 # set up beginning of database query
757 $Query = "SELECT COUNT(*) AS PrivCount FROM APUserPrivileges "
758 ."WHERE UserId='".$this->UserId."' AND (";
759
760 # add first privilege(s) to query (first arg may be single value or array)
761 if (is_array($Privilege))
762 {
763 $Sep = "";
764 foreach ($Privilege as $Priv)
765 {
766 $Query .= $Sep."Privilege='".addslashes($Priv)."'";
767 $Sep = " OR ";
768 }
769 }
770 else
771 {
772 $Query .= "Privilege='".$Privilege."'";
773 $Sep = " OR ";
774 }
775
776 # add any privileges from additional args to query
777 $Args = func_get_args();
778 array_shift($Args);
779 foreach ($Args as $Arg)
780 {
781 $Query .= $Sep."Privilege='".$Arg."'";
782 $Sep = " OR ";
783 }
784
785 # close out query
786 $Query .= ")";
787
788 # look for privilege in database
789 $PrivCount = $this->DB->Query($Query, "PrivCount");
790
791 # return value to caller
792 return ($PrivCount > 0) ? TRUE : FALSE;
793 }
794
803 public static function GetSqlQueryForUsersWithPriv($Privilege, $Privileges = NULL)
804 {
805 # set up beginning of database query
806 $Query = "SELECT DISTINCT UserId FROM APUserPrivileges "
807 ."WHERE ";
808
809 # add first privilege(s) to query (first arg may be single value or array)
810 if (is_array($Privilege))
811 {
812 $Sep = "";
813 foreach ($Privilege as $Priv)
814 {
815 $Query .= $Sep."Privilege='".addslashes($Priv)."'";
816 $Sep = " OR ";
817 }
818 }
819 else
820 {
821 $Query .= "Privilege='".$Privilege."'";
822 $Sep = " OR ";
823 }
824
825 # add any privileges from additional args to query
826 $Args = func_get_args();
827 array_shift($Args);
828 foreach ($Args as $Arg)
829 {
830 $Query .= $Sep."Privilege='".$Arg."'";
831 $Sep = " OR ";
832 }
833
834 # return query to caller
835 return $Query;
836 }
837
846 public static function GetSqlQueryForUsersWithoutPriv($Privilege, $Privileges = NULL)
847 {
848 # set up beginning of database query
849 $Query = "SELECT DISTINCT UserId FROM APUserPrivileges "
850 ."WHERE ";
851
852 # add first privilege(s) to query (first arg may be single value or array)
853 if (is_array($Privilege))
854 {
855 $Sep = "";
856 foreach ($Privilege as $Priv)
857 {
858 $Query .= $Sep."Privilege != '".addslashes($Priv)."'";
859 $Sep = " AND ";
860 }
861 }
862 else
863 {
864 $Query .= "Privilege != '".$Privilege."'";
865 $Sep = " AND ";
866 }
867
868 # add any privileges from additional args to query
869 $Args = func_get_args();
870 array_shift($Args);
871 foreach ($Args as $Arg)
872 {
873 $Query .= $Sep."Privilege != '".$Arg."'";
874 $Sep = " AND ";
875 }
876
877 # return query to caller
878 return $Query;
879 }
880
881 public function GrantPriv($Privilege)
882 {
883 # return error if not associated with a particular user
884 if ($this->UserId === NULL) { return U_NOTLOGGEDIN; }
885
886 # if privilege value is invalid
887 if (intval($Privilege) != trim($Privilege))
888 {
889 # set code to indicate error
890 $this->Result = U_ERROR;
891 }
892 else
893 {
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."'",
899 "PrivCount");
900 if ($PrivCount == 0)
901 {
902 # add privilege for this user to database
903 $this->DB->Query("INSERT INTO APUserPrivileges"
904 ." (UserId, Privilege) VALUES"
905 ." ('".$this->UserId."', ".$Privilege.")");
906 }
907
908 # set code to indicate success
909 $this->Result = U_OKAY;
910 }
911
912 # report result to caller
913 return $this->Result;
914 }
915
916 public function RevokePriv($Privilege)
917 {
918 # return error if not associated with a particular user
919 if ($this->UserId === NULL) { return U_NOTLOGGEDIN; }
920
921 # remove privilege from database (if present)
922 $this->DB->Query("DELETE FROM APUserPrivileges"
923 ." WHERE UserId = '".$this->UserId."'"
924 ." AND Privilege = '".$Privilege."'");
925
926 # report success to caller
927 $this->Result = U_OKAY;
928 return $this->Result;
929 }
930
931 public function GetPrivList()
932 {
933 # return empty list if not associated with a particular user
934 if ($this->UserId === NULL) { return array(); }
935
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");
940 }
941
942 public function SetPrivList($NewPrivileges)
943 {
944 # return error if not associated with a particular user
945 if ($this->UserId === NULL) { return U_NOTLOGGEDIN; }
946
947 # clear old priv list values
948 $this->DB->Query("DELETE FROM APUserPrivileges"
949 ." WHERE UserId='".$this->UserId."'");
950
951 # for each priv value passed in
952 foreach ($NewPrivileges as $Privilege)
953 {
954 # set priv for user
955 $this->GrantPriv($Privilege);
956 }
957 }
958
959
960 # ---- Miscellaneous Functions -------------------------------------------
961
962 # get unique alphanumeric code for user
963 public function GetUniqueCode($SeedString, $CodeLength)
964 {
965 # return NULL if not associated with a particular user
966 if ($this->UserId === NULL) { return NULL; }
967
968 return substr(strtoupper(md5(
969 $this->Get("UserName").$this->Get("UserPassword").$SeedString)),
970 0, $CodeLength);
971 }
972
973
974 # ---- PRIVATE INTERFACE -------------------------------------------------
975
976 protected $DB; # handle to SQL database we use to store user information
977 protected $UserId = NULL; # user ID number for reference into database
978 protected $Result; # result of last operation
979 protected $LoggedIn; # flag indicating whether user is logged in
980 private $DBFields; # used for caching user values
981
982 # optional mail function to use instead of mail()
983 private static $EmailFunc = NULL;
984
985 # check whether a user name is valid (alphanumeric string of 2-24 chars)
986 public static function IsValidUserName($UserName)
987 {
988 if (preg_match("/^[a-zA-Z0-9]{2,24}$/", $UserName))
989 {
990 return TRUE;
991 }
992 else
993 {
994 return FALSE;
995 }
996 }
997
998 # check whether a password is valid (at least 6 characters)
999 public static function IsValidPassword($Password)
1000 {
1001 if (strlen(self::NormalizePassword($Password)) < 6)
1002 {
1003 return FALSE;
1004 }
1005 else
1006 {
1007 return TRUE;
1008 }
1009 }
1010
1011 # check whether an e-mail address looks valid
1012 public static function IsValidLookingEMailAddress($EMail)
1013 {
1014 if (preg_match("/^[a-zA-Z0-9._\-]+@[a-zA-Z0-9._\-]+\.[a-zA-Z]{2,3}$/",
1015 $EMail))
1016 {
1017 return TRUE;
1018 }
1019 else
1020 {
1021 return FALSE;
1022 }
1023 }
1024
1025 # get normalized version of e-mail address
1026 public static function NormalizeEMailAddress($EMailAddress)
1027 {
1028 return strtolower(trim($EMailAddress));
1029 }
1030
1031 # get normalized version of user name
1032 public static function NormalizeUserName($UserName)
1033 {
1034 return trim($UserName);
1035 }
1036
1037 # get normalized version of password
1038 public static function NormalizePassword($Password)
1039 {
1040 return trim($Password);
1041 }
1042
1043 # generate random password
1044 public function GetRandomPassword($PasswordMinLength = 6, $PasswordMaxLength = 8)
1045 {
1046 # seed random number generator
1047 mt_srand((double)microtime() * 1000000);
1048
1049 # generate password of requested length
1050 return sprintf("%06d", mt_rand(pow(10, ($PasswordMinLength - 1)),
1051 (pow(10, $PasswordMaxLength) - 1)));
1052 }
1053
1054 # convenience function to supply parameters to Database->UpdateValue()
1055 public function UpdateValue($FieldName, $NewValue = DB_NOVALUE)
1056 {
1057 return $this->DB->UpdateValue("APUsers", $FieldName, $NewValue,
1058 "UserId = '".$this->UserId."'", $this->DBFields);
1059 }
1060
1061 # methods for backward compatibility with earlier versions of User
1062 public function GivePriv($Privilege)
1063 {
1064 $this->GrantPriv($Privilege);
1065 }
1066
1070 private static function GetSaltForCrypt()
1071 {
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
1075 # accept as a salt
1076 $Salt = preg_replace("/[^A-Za-z0-9]/","",
1077 base64_encode(openssl_random_pseudo_bytes(
1078 CRYPT_SALT_LENGTH) ));
1079
1080 # select the best available hashing algorithm, provide a salt
1081 # in the correct format for that algorithm
1082 if (CRYPT_SHA512==1)
1083 {
1084 return '$6$'.substr($Salt, 0, 16);
1085 }
1086 elseif (CRYPT_SHA256==1)
1087 {
1088 return '$5$'.substr($Salt, 0, 16);
1089 }
1090 elseif (CRYPT_BLOWFISH==1)
1091 {
1092 return '$2y$'.substr($Salt, 0, 22);
1093 }
1094 elseif (CRYPT_MD5==1)
1095 {
1096 return '$1$'.substr($Salt, 0, 12);
1097 }
1098 elseif (CRYPT_EXT_DES==1)
1099 {
1100 return '_'.substr($Salt, 0, 8);
1101 }
1102 else
1103 {
1104 return substr($Salt, 0, 2);
1105 }
1106 }
1107 }
User\Get
Get($FieldName)
Definition: User.php:246
User\$DB
$DB
Definition: User.php:976
User\GetRandomPassword
GetRandomPassword($PasswordMinLength=6, $PasswordMaxLength=8)
Definition: User.php:1044
User\NormalizeUserName
static NormalizeUserName($UserName)
Definition: User.php:1032
U_TEMPLATENOTFOUND
const U_TEMPLATENOTFOUND
Definition: User.php:37
User\IsLoggedIn
IsLoggedIn()
Definition: User.php:433
User\IsValidLookingEMailAddress
static IsValidLookingEMailAddress($EMail)
Definition: User.php:1012
User\GetMailChangeCode
GetMailChangeCode()
Definition: User.php:631
User\GetUniqueCode
GetUniqueCode($SeedString, $CodeLength)
Definition: User.php:963
User\GivePriv
GivePriv($Privilege)
Definition: User.php:1062
User\__construct
__construct($UserInfoOne=NULL, $UserInfoTwo=NULL)
Definition: User.php:45
User\GrantPriv
GrantPriv($Privilege)
Definition: User.php:881
Database
SQL database abstraction object with smart query caching.
Definition: Database.php:22
User\IsMailChangeCodeGood
IsMailChangeCodeGood($Code)
Definition: User.php:639
U_EMAILSDONTMATCH
const U_EMAILSDONTMATCH
Definition: User.php:23
User\GetResetCode
GetResetCode()
Definition: User.php:616
User\UpdateValue
UpdateValue($FieldName, $NewValue=DB_NOVALUE)
Definition: User.php:1055
User\NormalizePassword
static NormalizePassword($Password)
Definition: User.php:1038
User\CreateNewUserAndMailPassword
CreateNewUserAndMailPassword($UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
Definition: User.php:524
User\GetActivationCode
GetActivationCode()
Definition: User.php:595
U_ERROR
const U_ERROR
Definition: User.php:19
User\IsValidPassword
static IsValidPassword($Password)
Definition: User.php:999
U_NOTLOGGEDIN
const U_NOTLOGGEDIN
Definition: User.php:35
U_BADPASSWORD
const U_BADPASSWORD
Definition: User.php:20
U_ILLEGALEMAIL
const U_ILLEGALEMAIL
Definition: User.php:31
User\Login
Login($UserName, $Password, $IgnorePassword=FALSE)
Definition: User.php:291
User
Definition: User.php:41
User\SetEncryptedPassword
SetEncryptedPassword($NewEncryptedPassword)
Definition: User.php:497
User\StatusMessage
StatusMessage($StatusCode=NULL)
Definition: User.php:121
User\Delete
Delete()
Definition: User.php:158
User\IsResetCodeGood
IsResetCodeGood($Code)
Definition: User.php:624
User\IsValidUserName
static IsValidUserName($UserName)
Definition: User.php:986
User\GetSqlQueryForUsersWithPriv
static GetSqlQueryForUsersWithPriv($Privilege, $Privileges=NULL)
Get an SQL query that will return IDs of all users that have the specified privilege flags...
Definition: User.php:803
User\GetPasswordSalt
GetPasswordSalt($UserName)
Definition: User.php:396
User\LastLocation
LastLocation($NewLocation=NULL)
Definition: User.php:216
User\GetPrivList
GetPrivList()
Definition: User.php:931
User\IsActivated
IsActivated($NewValue=DB_NOVALUE)
Definition: User.php:610
User\HasPriv
HasPriv($Privilege, $Privileges=NULL)
Check whether user has specified privilege(s).
Definition: User.php:747
User\$LoggedIn
$LoggedIn
Definition: User.php:979
User\GetBestName
GetBestName()
Get the best available name associated with a user, i.e., the real name or, if it isn&#39;t available...
Definition: User.php:202
User\SendEMail
SendEMail($TemplateTextOrFileName, $FromAddress=NULL, $MoreSubstitutions=NULL, $ToAddress=NULL)
Definition: User.php:646
PHP
PHP
Definition: RSSClient--Test.php:12
User\Set
Set($FieldName, $NewValue)
Definition: User.php:278
DB_NOVALUE
const DB_NOVALUE
Definition: Database.php:1541
U_MAILINGERROR
const U_MAILINGERROR
Definition: User.php:36
U_DUPLICATEUSERNAME
const U_DUPLICATEUSERNAME
Definition: User.php:24
User\SetEmailFunction
static SetEmailFunction($NewValue)
Set email function to use instead of mail().
Definition: User.php:177
U_OKAY
const U_OKAY
Definition: User.php:18
User\NormalizeEMailAddress
static NormalizeEMailAddress($EMailAddress)
Definition: User.php:1026
User\GetDate
GetDate($FieldName, $Format="")
Definition: User.php:255
U_DUPLICATEEMAIL
const U_DUPLICATEEMAIL
Definition: User.php:38
User\CreateNewUserWithEMailedPassword
CreateNewUserWithEMailedPassword($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
Definition: User.php:503
User\Status
Status()
Definition: User.php:115
User\IsNotLoggedIn
IsNotLoggedIn()
Definition: User.php:437
User\Logout
Logout()
Definition: User.php:378
User\LastActiveDate
LastActiveDate()
Definition: User.php:236
User\$Result
$Result
Definition: User.php:978
User\CreateNewUserAndMailPasswordFromFile
CreateNewUserAndMailPasswordFromFile($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
Definition: User.php:511
User\LastIPAddress
LastIPAddress()
Definition: User.php:240
U_NOSUCHUSER
const U_NOSUCHUSER
Definition: User.php:21
User\Id
Id()
Definition: User.php:188
User\SetPassword
SetPassword($NewPassword)
Definition: User.php:487
U_NOTACTIVATED
const U_NOTACTIVATED
Definition: User.php:39
User\$UserId
$UserId
Definition: User.php:977
User\SetPrivList
SetPrivList($NewPrivileges)
Definition: User.php:942
User\ChangePassword
ChangePassword($OldPassword, $NewPassword, $NewPasswordAgain)
Definition: User.php:446
User\IsActivationCodeGood
IsActivationCodeGood($Code)
Definition: User.php:603
U_ILLEGALUSERNAME
const U_ILLEGALUSERNAME
Definition: User.php:25
User\RevokePriv
RevokePriv($Privilege)
Definition: User.php:916
User\Name
Name()
Definition: User.php:192
U_ILLEGALPASSWORD
const U_ILLEGALPASSWORD
Definition: User.php:27
User\GetSqlQueryForUsersWithoutPriv
static GetSqlQueryForUsersWithoutPriv($Privilege, $Privileges=NULL)
Get an SQL query that will return IDs of all users that do not have the specified privilege flags...
Definition: User.php:846
U_PASSWORDSDONTMATCH
const U_PASSWORDSDONTMATCH
Definition: User.php:22