CWIS Developer Documentation
Axis--User.php
Go to the documentation of this file.
1 <?PHP
2 
3 #
4 # Axis--User.php
5 # An Object for Handling User Information
6 #
7 # Copyright 1999-2001 Axis Data
8 # This code is free software that can be used or redistributed under the
9 # terms of Version 2 of the GNU General Public License, as published by the
10 # Free Software Foundation (http://www.fsf.org).
11 #
12 # Author: Edward Almasy (almasy@axisdata.com)
13 #
14 # Part of the AxisPHP library v1.2.4
15 # For more information see http://www.axisdata.com/AxisPHP/
16 #
17 
18 # status values (error codes)
19 define("U_OKAY", 0);
20 define("U_ERROR", 1);
21 define("U_BADPASSWORD", 2);
22 define("U_NOSUCHUSER", 3);
23 define("U_PASSWORDSDONTMATCH", 4);
24 define("U_EMAILSDONTMATCH", 5);
25 define("U_DUPLICATEUSERNAME", 6);
26 define("U_ILLEGALUSERNAME", 7);
27 define("U_EMPTYUSERNAME", 8);
28 define("U_ILLEGALPASSWORD", 9);
29 define("U_ILLEGALPASSWORDAGAIN",10);
30 define("U_EMPTYPASSWORD", 11);
31 define("U_EMPTYPASSWORDAGAIN", 12);
32 define("U_ILLEGALEMAIL", 13);
33 define("U_ILLEGALEMAILAGAIN", 14);
34 define("U_EMPTYEMAIL", 15);
35 define("U_EMPTYEMAILAGAIN", 16);
36 define("U_NOTLOGGEDIN", 17);
37 define("U_MAILINGERROR", 18);
38 define("U_TEMPLATENOTFOUND", 19);
39 define("U_DUPLICATEEMAIL", 20);
40 define("U_NOTACTIVATED", 21);
41 
42 
43 class User {
44 
45  # ---- PUBLIC INTERFACE --------------------------------------------------
46 
47  function User($UserInfoOne = NULL, $UserInfoTwo = NULL)
48  {
49  # assume constructor will succeed and user is not logged in
50  $this->Result = U_OKAY;
51  $this->LoggedIn = FALSE;
52 
53  # create database connection
54  $this->DB = new Database();
55 
56  # if user info passed in
57  if (is_int($UserInfoOne) || is_string($UserInfoOne)
58  || is_int($UserInfoTwo) || is_string($UserInfoTwo))
59  {
60  # if user ID was passed in
61  if (is_int($UserInfoOne) || is_int($UserInfoTwo))
62  {
63  # save user ID
64  $this->UserId = is_int($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
65  }
66  else
67  {
68  # look up user ID in database
69  $UserInfoTwo = is_string($UserInfoOne) ? $UserInfoOne : $UserInfoTwo;
70  $this->DB->Query("SELECT UserId, LoggedIn FROM APUsers"
71  ." WHERE UserName='".addslashes($UserInfoTwo)."'");
72  $Record = $this->DB->FetchRow();
73  if ($Record)
74  {
75  $this->UserId = $Record["UserId"];
76  $this->LoggedIn = $Record["LoggedIn"];
77  }
78 
79  # if user ID was not found
80  if ($Record === FALSE)
81  {
82  # if name looks like it could actually be a user ID
83  if (preg_match("/^[-]*[0-9]+$/", $UserInfoTwo))
84  {
85  # assume name was user ID
86  $this->UserId = intval($UserInfoTwo);
87  }
88  else
89  {
90  # set code indicating no user found
91  $this->Result = U_NOSUCHUSER;
92  unset($this->UserId);
93  }
94  }
95  }
96  }
97  else
98  {
99  # if user ID is available from session
100  if (isset($_SESSION["APUserId"]))
101  {
102  # save user ID
103  $this->UserId = $_SESSION["APUserId"];
104 
105  # set flag indicating user is currently logged in
106  $this->LoggedIn = TRUE;
107  }
108  }
109  }
110 
111  function Status()
112  {
113  return $this->Result;
114  }
115 
116  # return text message corresponding to current (or specified) status code
117  function StatusMessage($StatusCode = NULL)
118  {
119  $APUserStatusMessages = array(
120  U_OKAY => "The operation was successful.",
121  U_ERROR => "There has been an error.",
122  U_BADPASSWORD => "The password you entered was"
123  ." incorrect.",
124  U_NOSUCHUSER => "No such user name was found.",
125  U_PASSWORDSDONTMATCH => "The new passwords you entered do"
126  ." not match.",
127  U_EMAILSDONTMATCH => "The e-mail addresses you entered"
128  ." do not match.",
129  U_DUPLICATEUSERNAME => "The user name you requested is"
130  ." already in use.",
131  U_ILLEGALUSERNAME => "The user name you requested is too"
132  ." short, too long, or contains"
133  ." illegal characters.",
134  U_ILLEGALPASSWORD => "The new password you requested is"
135  ." too short, too long, or"
136  ." contains illegal characters.",
137  U_ILLEGALEMAIL => "The e-mail address you entered"
138  ." appears to be invalid.",
139  U_NOTLOGGEDIN => "The user is not logged in.",
140  U_MAILINGERROR => "An error occurred while attempting"
141  ." to send e-mail. Please notify"
142  ." the system administrator.",
143  U_TEMPLATENOTFOUND => "An error occurred while attempting"
144  ." to generate e-mail. Please"
145  ." notify the system administrator.",
146  U_DUPLICATEEMAIL => "The e-mail address you supplied already"
147  ." has an account associated with it.",
148  );
149 
150  return ($StatusCode === NULL) ? $APUserStatusMessages[$this->Result]
151  : $APUserStatusMessages[$StatusCode];
152  }
153 
154  function Delete()
155  {
156  # clear priv list values
157  $this->DB->Query("DELETE FROM APUserPrivileges WHERE UserId = '".$this->UserId."'");
158 
159  # delete user record from database
160  $this->DB->Query("DELETE FROM APUsers WHERE UserId = '".$this->UserId."'");
161 
162  # report to caller that everything succeeded
163  $this->Result = U_OKAY;
164  return $this->Result;
165  }
166 
172  static function SetEmailFunction($NewValue)
173  {
174  if (is_callable($NewValue))
175  {
176  self::$EmailFunc = $NewValue;
177  }
178  }
179 
180 
181  # ---- Getting/Setting Values --------------------------------------------
182 
183  function Id()
184  {
185  return $this->UserId;
186  }
187  function Name()
188  {
189  return $this->Get("UserName");
190  }
191  function LastLocation($NewLocation = NULL)
192  {
193  if ($NewLocation)
194  {
195  $this->DB->Query("UPDATE APUsers SET"
196  ." LastLocation = '".addslashes($NewLocation)."',"
197  ." LastActiveDate = NOW(),"
198  ." LastIPAddress = '".$_SERVER["REMOTE_ADDR"]."'"
199  ." WHERE UserId = '".addslashes($this->UserId)."'");
200  if (isset($this->DBFields))
201  {
202  $this->DBFields["LastLocation"] = $NewLocation;
203  $this->DBFields["LastActiveDate"] = date("Y-m-d H:i:s");
204  }
205  }
206  return $this->Get("LastLocation");
207  }
208  function LastActiveDate()
209  {
210  return $this->Get("LastActiveDate");
211  }
212  function LastIPAddress()
213  {
214  return $this->Get("LastIPAddress");
215  }
216 
217  # get value from specified field
218  function Get($FieldName)
219  {
220  return $this->UpdateValue($FieldName);
221  }
222 
223  # get value (formatted as a date) from specified field
224  function GetDate($FieldName, $Format = "")
225  {
226  # retrieve specified value from database
227  if (strlen($Format) > 0)
228  {
229  $this->DB->Query("SELECT DATE_FORMAT(`".addslashes($FieldName)."`, '".addslashes($Format)."') AS `".addslashes($FieldName)."` FROM APUsers WHERE UserId='".$this->UserId."'");
230  }
231  else
232  {
233  $this->DB->Query("SELECT `".addslashes($FieldName)."` FROM APUsers WHERE UserId='".$this->UserId."'");
234  }
235  $Record = $this->DB->FetchRow();
236 
237  # return value to caller
238  return $Record[$FieldName];
239  }
240 
241  # set value in specified field
242  function Set($FieldName, $NewValue)
243  {
244  $this->UpdateValue($FieldName, $NewValue);
245  $this->Result = U_OKAY;
246  return $this->Result;
247  }
248 
249 
250  # ---- Login Functions ---------------------------------------------------
251 
252  function Login($UserName, $Password, $IgnorePassword = FALSE)
253  {
254  # if user not found in DB
255  $this->DB->Query("SELECT * FROM APUsers"
256  ." WHERE UserName = '"
257  .addslashes(self::NormalizeUserName($UserName))."'");
258  if ($this->DB->NumRowsSelected() < 1)
259  {
260  # result is no user by that name
261  $this->Result = U_NOSUCHUSER;
262  }
263  else
264  {
265  # if user account not yet activated
266  $Record = $this->DB->FetchRow();
267  if (!$Record["RegistrationConfirmed"])
268  {
269  # result is user registration not confirmed
270  $this->Result = U_NOTACTIVATED;
271  }
272  else
273  {
274  # grab password from DB
275  $StoredPassword = $Record["UserPassword"];
276 
277  if (isset($Password[0]) && $Password[0] == " ")
278  {
279  $Challenge = md5(date("Ymd").$_SERVER["REMOTE_ADDR"]);
280  $StoredPassword = md5( $Challenge . $StoredPassword );
281 
282  $EncryptedPassword = trim($Password);
283  }
284  else
285  {
286  # if supplied password matches encrypted password
287  $EncryptedPassword = crypt($Password, $StoredPassword);
288  }
289 
290  if (($EncryptedPassword == $StoredPassword) || $IgnorePassword)
291  {
292  # result is success
293  $this->Result = U_OKAY;
294 
295  # store user ID for session
296  $this->UserId = $Record["UserId"];
297  $_SESSION["APUserId"] = $this->UserId;
298 
299  # update last login date
300  $this->DB->Query("UPDATE APUsers SET LastLoginDate = NOW(),"
301  ." LoggedIn = '1'"
302  ." WHERE UserId = '".$this->UserId."'");
303 
304  # Check for old format hashes, and rehash if possible
305  if ($EncryptedPassword === $StoredPassword &&
306  substr($StoredPassword,0,3) !== "$1$" &&
307  $Password[0] !== " " &&
308  CRYPT_MD5 )
309  {
310  $NewPassword = crypt($Password);
311  $this->DB->Query(
312  "UPDATE APUsers SET UserPassword='".addslashes($NewPassword)."' "
313  ."WHERE UserId='".$this->UserId."'");
314  }
315 
316  # since self::DBFields might already have been set to false if
317  # the user wasn't logged in when this is called, populate it
318  # with user data so that a call to self::UpdateValue will be
319  # able to properly fetch the data associated with the user
320  $this->DBFields = $Record;
321 
322  # set flag to indicate we are logged in
323  $this->LoggedIn = TRUE;
324  }
325  else
326  {
327  # result is bad password
328  $this->Result = U_BADPASSWORD;
329  }
330  }
331  }
332 
333  # return result to caller
334  return $this->Result;
335  }
336 
337  # log this user out
338  function Logout()
339  {
340  # clear user ID (if any) for session
341  unset($_SESSION["APUserId"]);
342 
343  # if user is marked as logged in
344  if ($this->LoggedIn)
345  {
346  # set flag to indicate user is no longer logged in
347  $this->LoggedIn = FALSE;
348 
349  # clear login flag in database
350  $this->DB->Query(
351  "UPDATE APUsers SET LoggedIn = '0' "
352  ."WHERE UserId='".$this->UserId."'");
353  }
354  }
355 
356  function GetPasswordSalt($UserName)
357  {
358  $this->DB->Query(
359  "SELECT * FROM APUsers WHERE UserName = '"
360  .addslashes(self::NormalizeUserName($UserName))."'");
361 
362  if ($this->DB->NumRowsSelected() < 1)
363  {
364  # result is no user by that name, generate a fake salt
365  # to discourage user enumeration. Make it be an old-format
366  # crypt() salt so that it's harder.
367  $SaltString = $_SERVER["SERVER_ADDR"].$UserName;
368  $Result = substr(base64_encode(md5($SaltString)),0,2);
369  }
370  else
371  {
372  # grab password from DB
373  # Assumes that we used php's crypt() for the passowrd
374  # management stuff, and will need to be changed if we
375  # go to something else.
376  $Record = $this->DB->FetchRow();
377  $StoredPassword = $Record["UserPassword"];
378 
379  if (substr($StoredPassword,0,3)==="$1$")
380  {
381  $Result = substr($StoredPassword, 0,12);
382  }
383  else
384  {
385  $Result = substr($StoredPassword, 0,2);
386  }
387  }
388 
389  return $Result;
390  }
391 
392  # report whether this user is or is not currently logged in
393  function IsLoggedIn() { return $this->LoggedIn; }
394  function IsNotLoggedIn() { return !$this->LoggedIn; }
395 
396 
397  # ---- Password Functions ------------------------------------------------
398 
399  # set new password (with checks against old password)
400  function ChangePassword($OldPassword, $NewPassword, $NewPasswordAgain)
401  {
402  # make sure a user is logged in
403  if ($this->IsLoggedIn() !== TRUE)
404  {
405  $this->Result = U_NOTLOGGEDIN;
406  return $this->Result;
407  }
408 
409  # if old password is not correct
410  $StoredPassword = $this->DB->Query("SELECT UserPassword FROM APUsers"
411  ." WHERE UserId='".$this->UserId."'", "UserPassword");
412  $EncryptedPassword = crypt($OldPassword, $StoredPassword);
413  if ($EncryptedPassword != $StoredPassword)
414  {
415  # set status to indicate error
416  $this->Result = U_BADPASSWORD;
417  }
418  # else if new password is not legal
419  elseif (!$this->IsValidPassword($NewPassword))
420  {
421  # set status to indicate error
422  $this->Result = U_ILLEGALPASSWORD;
423  }
424  # else if both instances of new password do not match
425  elseif (self::NormalizePassword($NewPassword)
426  != self::NormalizePassword($NewPasswordAgain))
427  {
428  # set status to indicate error
429  $this->Result = U_PASSWORDSDONTMATCH;
430  }
431  else
432  {
433  # set new password
434  $this->SetPassword($NewPassword);
435 
436  # set status to indicate password successfully changed
437  $this->Result = U_OKAY;
438  }
439 
440  # report to caller that everything succeeded
441  return $this->Result;
442  }
443 
444  # set new password
445  function SetPassword($NewPassword)
446  {
447  # generate encrypted password
448  $EncryptedPassword = crypt(self::NormalizePassword($NewPassword));
449 
450  # save encrypted password
451  $this->UpdateValue("UserPassword", $EncryptedPassword);
452  }
453 
455  $UserName, $EMail, $EMailAgain,
456  $TemplateFile = "Axis--User--EMailTemplate.txt")
457  {
459  $UserName, $EMail, $EMailAgain, $TemplateFile);
460  }
461 
463  $UserName, $EMail, $EMailAgain,
464  $TemplateFile = "Axis--User--EMailTemplate.txt")
465  {
466  # load e-mail template from file (first line is subject)
467  $Template = file($TemplateFile, 1);
468  $EMailSubject = array_shift($Template);
469  $EMailBody = join("", $Template);
470 
472  $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody);
473  }
474 
476  $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody)
477  {
478  # make sure e-mail addresses match
479  if ($EMail != $EMailAgain)
480  {
481  $this->Result = U_EMAILSDONTMATCH;
482  return $this->Result;
483  }
484 
485  # make sure e-mail address looks valid
486  if ($this->IsValidLookingEMailAddress($EMail) == FALSE)
487  {
488  $this->Result = U_ILLEGALEMAIL;
489  return $this->Result;
490  }
491 
492  # generate random password
493  $Password = $this->GetRandomPassword();
494 
495  # attempt to create new user with password
496  $Result = $this->CreateNewUser($UserName, $Password, $Password);
497 
498  # if user creation failed
499  if ($Result != U_OKAY)
500  {
501  # report error result to caller
502  return $Result;
503  }
504  # else
505  else
506  {
507  # set e-mail address in user record
508  $this->Set("EMail", $EMail);
509 
510  # plug appropriate values into subject and body of e-mail message
511  $EMailSubject = str_replace("X-USERNAME-X", $UserName, $EMailSubject);
512  $EMailBody = str_replace("X-USERNAME-X", $UserName, $EMailBody);
513  $EMailBody = str_replace("X-PASSWORD-X", $Password, $EMailBody);
514 
515  # send out e-mail message with new account info
516  if (is_Callable(self::$EmailFunc))
517  {
518  $Result = call_user_func(self::$EmailFunc,
519  $EMail, $EMailSubject, $EMailBody,
520  "Auto-Submitted: auto-generated");
521  }
522  else
523  {
524  $Result = mail($EMail, $EMailSubject, $EMailBody,
525  "Auto-Submitted: auto-generated");
526  }
527 
528  # if mailing attempt failed
529  if ($Result != TRUE)
530  {
531  # report error to caller
532  $this->Result = U_MAILINGERROR;
533  return $this->Result;
534  }
535  # else
536  else
537  {
538  # report success to caller
539  $this->Result = U_OKAY;
540  return $this->Result;
541  }
542  }
543  }
544 
545  # get code for user to submit to confirm registration
546  function GetActivationCode()
547  {
548  # code is MD5 sum based on user name and encrypted password
549  $ActivationCodeLength = 6;
550  return $this->GetUniqueCode("Activation", $ActivationCodeLength);
551  }
552 
553  # check whether confirmation code is valid
554  function IsActivationCodeGood($Code)
555  {
556  return (strtoupper(trim($Code)) == $this->GetActivationCode())
557  ? TRUE : FALSE;
558  }
559 
560  # get/set whether user registration has been confirmed
561  function IsActivated($NewValue = DB_NOVALUE)
562  {
563  return $this->UpdateValue("RegistrationConfirmed", $NewValue);
564  }
565 
566  # get code for user to submit to confirm password reset
567  function GetResetCode()
568  {
569  # code is MD5 sum based on user name and encrypted password
570  $ResetCodeLength = 10;
571  return $this->GetUniqueCode("Reset", $ResetCodeLength);
572  }
573 
574  # check whether password reset code is valid
575  function IsResetCodeGood($Code)
576  {
577  return (strtoupper(trim($Code)) == $this->GetResetCode())
578  ? TRUE : FALSE;
579  }
580 
581  # get code for user to submit to confirm mail change request
582  function GetMailChangeCode()
583  {
584  $ResetCodeLength = 10;
585 
586  return $this->GetUniqueCode("MailChange".$this->Get("EMail").$this->Get("NewEMail"),
587  $ResetCodeLength);
588  }
589 
590  function IsMailChangeCodeGood($Code)
591  {
592  return (strtoupper(trim($Code)) == $this->GetMailChangeCode())
593  ? TRUE : FALSE;
594  }
595 
596  # send e-mail to user (returns TRUE on success)
597  function SendEMail(
598  $TemplateTextOrFileName, $FromAddress = NULL, $MoreSubstitutions = NULL,
599  $ToAddress = NULL)
600  {
601  # if template is file name
602  if (@is_file($TemplateTextOrFileName))
603  {
604  # load in template from file
605  $Template = file($TemplateTextOrFileName, 1);
606 
607  # report error to caller if template load failed
608  if ($Template == FALSE)
609  {
610  $this->Status = U_TEMPLATENOTFOUND;
611  return $this->Status;
612  }
613 
614  # join into one text block
615  $TemplateTextOrFileName = join("", $Template);
616  }
617 
618  # split template into lines
619  $Template = explode("\n", $TemplateTextOrFileName);
620 
621  # strip any comments out of template
622  $FilteredTemplate = array();
623  foreach ($Template as $Line)
624  {
625  if (!preg_match("/^[\\s]*#/", $Line))
626  {
627  $FilteredTemplate[] = $Line;
628  }
629  }
630 
631  # split subject line out of template (first non-comment line in file)
632  $EMailSubject = array_shift($FilteredTemplate);
633  $EMailBody = join("\n", $FilteredTemplate);
634 
635  # set up our substitutions
636  $Substitutions = array(
637  "X-USERNAME-X" => $this->Get("UserName"),
638  "X-EMAILADDRESS-X" => $this->Get("EMail"),
639  "X-ACTIVATIONCODE-X" => $this->GetActivationCode(),
640  "X-RESETCODE-X" => $this->GetResetCode(),
641  "X-CHANGECODE-X" => $this->GetMailChangeCode(),
642  "X-IPADDRESS-X" => @$_SERVER["REMOTE_ADDR"],
643  );
644 
645  # if caller provided additional substitutions
646  if (is_array($MoreSubstitutions))
647  {
648  # add in entries from caller to substitution list
649  $Substitutions = array_merge(
650  $Substitutions, $MoreSubstitutions);
651  }
652 
653  # perform substitutions on subject and body of message
654  $EMailSubject = str_replace(array_keys($Substitutions),
655  array_values($Substitutions), $EMailSubject);
656  $EMailBody = str_replace(array_keys($Substitutions),
657  array_values($Substitutions), $EMailBody);
658 
659  $AdditionalHeaders = "Auto-Submitted: auto-generated";
660 
661  # if caller provided "From" address
662  if ($FromAddress)
663  {
664  # prepend "From" address onto message
665  $AdditionalHeaders .= "\r\nFrom: ".$FromAddress;
666  }
667 
668  # send out mail message
669  if (is_Callable(self::$EmailFunc))
670  {
671  $Result = call_user_func(self::$EmailFunc,
672  is_null($ToAddress)?$this->Get("EMail"):$ToAddress,
673  $EMailSubject, $EMailBody, $AdditionalHeaders);
674  }
675  else
676  {
677  $Result = mail(is_null($ToAddress)?$this->Get("EMail"):$ToAddress,
678  $EMailSubject,
679  $EMailBody, $AdditionalHeaders);
680  }
681 
682  # report result of mailing attempt to caller
683  $this->Status = ($Result == TRUE) ? U_OKAY : U_MAILINGERROR;
684  return ($this->Status == U_OKAY);
685  }
686 
687 
688  # ---- Privilege Functions -----------------------------------------------
689 
698  function HasPriv($Privilege, $Privileges = NULL)
699  {
700  # make sure a user is logged in (no privileges if not logged in)
701  if ($this->IsLoggedIn() == FALSE) { return FALSE; }
702 
703  # bail out if empty array of privileges passed in
704  if (is_array($Privilege) && !count($Privilege) && (func_num_args() < 2))
705  { return FALSE; }
706 
707  # set up beginning of database query
708  $Query = "SELECT COUNT(*) AS PrivCount FROM APUserPrivileges "
709  ."WHERE UserId='".$this->UserId."' AND (";
710 
711  # add first privilege(s) to query (first arg may be single value or array)
712  if (is_array($Privilege))
713  {
714  $Sep = "";
715  foreach ($Privilege as $Priv)
716  {
717  $Query .= $Sep."Privilege='".addslashes($Priv)."'";
718  $Sep = " OR ";
719  }
720  }
721  else
722  {
723  $Query .= "Privilege='".$Privilege."'";
724  $Sep = " OR ";
725  }
726 
727  # add any privileges from additional args to query
728  $Args = func_get_args();
729  array_shift($Args);
730  foreach ($Args as $Arg)
731  {
732  $Query .= $Sep."Privilege='".$Arg."'";
733  $Sep = " OR ";
734  }
735 
736  # close out query
737  $Query .= ")";
738 
739  # look for privilege in database
740  $PrivCount = $this->DB->Query($Query, "PrivCount");
741 
742  # return value to caller
743  return ($PrivCount > 0) ? TRUE : FALSE;
744  }
745 
754  static function GetSqlQueryForUsersWithPriv($Privilege, $Privileges = NULL)
755  {
756  # set up beginning of database query
757  $Query = "SELECT UserId FROM APUserPrivileges "
758  ."WHERE ";
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  # return query to caller
786  return $Query;
787  }
788 
789  function GrantPriv($Privilege)
790  {
791  # if privilege value is invalid
792  if (intval($Privilege) != trim($Privilege))
793  {
794  # set code to indicate error
795  $this->Result = U_ERROR;
796  }
797  else
798  {
799  # if user does not already have privilege
800  $PrivCount = $this->DB->Query("SELECT COUNT(*) AS PrivCount"
801  ." FROM APUserPrivileges"
802  ." WHERE UserId='".$this->UserId."'"
803  ." AND Privilege='".$Privilege."'",
804  "PrivCount");
805  if ($PrivCount == 0)
806  {
807  # add privilege for this user to database
808  $this->DB->Query("INSERT INTO APUserPrivileges"
809  ." (UserId, Privilege) VALUES"
810  ." ('".$this->UserId."', ".$Privilege.")");
811  }
812 
813  # set code to indicate success
814  $this->Result = U_OKAY;
815  }
816 
817  # report result to caller
818  return $this->Result;
819  }
820 
821  function RevokePriv($Privilege)
822  {
823  # remove privilege from database (if present)
824  $this->DB->Query("DELETE FROM APUserPrivileges"
825  ." WHERE UserId = '".$this->UserId."'"
826  ." AND Privilege = '".$Privilege."'");
827 
828  # report success to caller
829  $this->Result = U_OKAY;
830  return $this->Result;
831  }
832 
833  function GetPrivList()
834  {
835  # read privileges from database and return array to caller
836  $this->DB->Query("SELECT Privilege FROM APUserPrivileges"
837  ." WHERE UserId='".$this->UserId."'");
838  return $this->DB->FetchColumn("Privilege");
839  }
840 
841  function SetPrivList($NewPrivileges)
842  {
843  # clear old priv list values
844  $this->DB->Query("DELETE FROM APUserPrivileges"
845  ." WHERE UserId='".$this->UserId."'");
846 
847  # for each priv value passed in
848  foreach ($NewPrivileges as $Privilege)
849  {
850  # set priv for user
851  $this->GrantPriv($Privilege);
852  }
853  }
854 
855 
856  # ---- Miscellaneous Functions -------------------------------------------
857 
858  # get unique alphanumeric code for user
859  function GetUniqueCode($SeedString, $CodeLength)
860  {
861  return substr(strtoupper(md5(
862  $this->Get("UserName").$this->Get("UserPassword").$SeedString)),
863  0, $CodeLength);
864  }
865 
866 
867  # ---- PRIVATE INTERFACE -------------------------------------------------
868 
869  protected $DB; # handle to SQL database we use to store user information
870  private $UserId; # user ID number for reference into database
871  private $Result; # result of last operation
872  private $LoggedIn; # flag indicating whether user is logged in
873  private $DBFields; # used for caching user values
874 
875  # optional mail function to use instead of mail()
876  private static $EmailFunc = NULL;
877 
878  # check whether a user name is valid (alphanumeric string of 2-24 chars)
879  static function IsValidUserName($UserName)
880  {
881  if (preg_match("/^[a-zA-Z0-9]{2,24}$/", $UserName)) { return TRUE; } else { return FALSE; }
882  }
883 
884  # check whether a password is valid (at least 6 characters)
885  static function IsValidPassword($Password)
886  {
887  if (strlen(self::NormalizePassword($Password)) < 6)
888  { return FALSE; } else { return TRUE; }
889  }
890 
891  # check whether an e-mail address looks valid
892  static function IsValidLookingEMailAddress($EMail)
893  {
894  if (preg_match("/^[a-zA-Z0-9._\-]+@[a-zA-Z0-9._\-]+\.[a-zA-Z]{2,3}$/", $EMail)) { return TRUE; } else { return FALSE; }
895  }
896 
897  # get normalized version of e-mail address
898  static function NormalizeEMailAddress($EMailAddress)
899  {
900  return strtolower(trim($EMailAddress));
901  }
902 
903  # get normalized version of user name
904  static function NormalizeUserName($UserName)
905  {
906  return trim($UserName);
907  }
908 
909  # get normalized version of password
910  static function NormalizePassword($Password)
911  {
912  return trim($Password);
913  }
914 
915  # generate random password
916  function GetRandomPassword($PasswordMinLength = 6, $PasswordMaxLength = 8)
917  {
918  # seed random number generator
919  mt_srand((double)microtime() * 1000000);
920 
921  # generate password of requested length
922  return sprintf("%06d", mt_rand(pow(10, ($PasswordMinLength - 1)),
923  (pow(10, $PasswordMaxLength) - 1)));
924  }
925 
926  # convenience function to supply parameters to Database->UpdateValue()
927  function UpdateValue($FieldName, $NewValue = DB_NOVALUE)
928  {
929  return $this->DB->UpdateValue("APUsers", $FieldName, $NewValue,
930  "UserId = '".$this->UserId."'", $this->DBFields);
931  }
932 
933  # methods for backward compatibility with earlier versions of User
934  function GivePriv($Privilege) { $this->GrantPriv($Privilege); }
935 
936 }