CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
454 function CreateNewUserWithEMailedPassword(
455 $UserName, $EMail, $EMailAgain,
456 $TemplateFile = "Axis--User--EMailTemplate.txt")
457 {
458 return CreateNewUserAndMailPasswordFromFile(
459 $UserName, $EMail, $EMailAgain, $TemplateFile);
460 }
461
462 function CreateNewUserAndMailPasswordFromFile(
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
471 return CreateNewUserAndMailPassword(
472 $UserName, $EMail, $EMailAgain, $EMailSubject, $EMailBody);
473 }
474
475 function CreateNewUserAndMailPassword(
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 }