CWIS Developer Documentation
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 
504  $UserName, $EMail, $EMailAgain,
505  $TemplateFile = "Axis--User--EMailTemplate.txt")
506  {
508  $UserName, $EMail, $EMailAgain, $TemplateFile);
509  }
510 
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 
521  $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody);
522  }
523 
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 }
Get($FieldName)
Definition: User.php:246
$DB
Definition: User.php:976
GetRandomPassword($PasswordMinLength=6, $PasswordMaxLength=8)
Definition: User.php:1044
static NormalizeUserName($UserName)
Definition: User.php:1032
const U_TEMPLATENOTFOUND
Definition: User.php:37
IsLoggedIn()
Definition: User.php:433
static IsValidLookingEMailAddress($EMail)
Definition: User.php:1012
GetMailChangeCode()
Definition: User.php:631
GetUniqueCode($SeedString, $CodeLength)
Definition: User.php:963
GivePriv($Privilege)
Definition: User.php:1062
__construct($UserInfoOne=NULL, $UserInfoTwo=NULL)
Definition: User.php:45
GrantPriv($Privilege)
Definition: User.php:881
SQL database abstraction object with smart query caching.
Definition: Database.php:22
IsMailChangeCodeGood($Code)
Definition: User.php:639
const U_EMAILSDONTMATCH
Definition: User.php:23
GetResetCode()
Definition: User.php:616
UpdateValue($FieldName, $NewValue=DB_NOVALUE)
Definition: User.php:1055
static NormalizePassword($Password)
Definition: User.php:1038
CreateNewUserAndMailPassword($UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
Definition: User.php:524
GetActivationCode()
Definition: User.php:595
const U_ERROR
Definition: User.php:19
static IsValidPassword($Password)
Definition: User.php:999
const U_NOTLOGGEDIN
Definition: User.php:35
const U_BADPASSWORD
Definition: User.php:20
const U_ILLEGALEMAIL
Definition: User.php:31
Login($UserName, $Password, $IgnorePassword=FALSE)
Definition: User.php:291
Definition: User.php:41
SetEncryptedPassword($NewEncryptedPassword)
Definition: User.php:497
StatusMessage($StatusCode=NULL)
Definition: User.php:121
Delete()
Definition: User.php:158
IsResetCodeGood($Code)
Definition: User.php:624
static IsValidUserName($UserName)
Definition: User.php:986
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
GetPasswordSalt($UserName)
Definition: User.php:396
LastLocation($NewLocation=NULL)
Definition: User.php:216
GetPrivList()
Definition: User.php:931
IsActivated($NewValue=DB_NOVALUE)
Definition: User.php:610
HasPriv($Privilege, $Privileges=NULL)
Check whether user has specified privilege(s).
Definition: User.php:747
$LoggedIn
Definition: User.php:979
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
SendEMail($TemplateTextOrFileName, $FromAddress=NULL, $MoreSubstitutions=NULL, $ToAddress=NULL)
Definition: User.php:646
Set($FieldName, $NewValue)
Definition: User.php:278
const DB_NOVALUE
Definition: Database.php:1541
const U_MAILINGERROR
Definition: User.php:36
const U_DUPLICATEUSERNAME
Definition: User.php:24
static SetEmailFunction($NewValue)
Set email function to use instead of mail().
Definition: User.php:177
const U_OKAY
Definition: User.php:18
static NormalizeEMailAddress($EMailAddress)
Definition: User.php:1026
GetDate($FieldName, $Format="")
Definition: User.php:255
const U_DUPLICATEEMAIL
Definition: User.php:38
CreateNewUserWithEMailedPassword($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
Definition: User.php:503
Status()
Definition: User.php:115
IsNotLoggedIn()
Definition: User.php:437
Logout()
Definition: User.php:378
LastActiveDate()
Definition: User.php:236
$Result
Definition: User.php:978
CreateNewUserAndMailPasswordFromFile($UserName, $EMail, $EMailAgain, $TemplateFile="Axis--User--EMailTemplate.txt")
Definition: User.php:511
LastIPAddress()
Definition: User.php:240
const U_NOSUCHUSER
Definition: User.php:21
Id()
Definition: User.php:188
SetPassword($NewPassword)
Definition: User.php:487
const U_NOTACTIVATED
Definition: User.php:39
$UserId
Definition: User.php:977
SetPrivList($NewPrivileges)
Definition: User.php:942
ChangePassword($OldPassword, $NewPassword, $NewPasswordAgain)
Definition: User.php:446
IsActivationCodeGood($Code)
Definition: User.php:603
const U_ILLEGALUSERNAME
Definition: User.php:25
RevokePriv($Privilege)
Definition: User.php:916
Name()
Definition: User.php:192
const U_ILLEGALPASSWORD
Definition: User.php:27
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
const U_PASSWORDSDONTMATCH
Definition: User.php:22