root/trunk/wifidog-auth/wifidog/classes/User.php @ 566

Revision 566, 16.7 KB (checked in by benoitg, 8 years ago)

2005-04-25 Benoit Gr�goire <bock@…>

  • Integration merge, should work, but there will be display problems everywhere. Expect further commits today.
  • Almost 100% complete Network abstraction
  • Much better object encapsulation. Deprecated methods not removed yet.
  • Add MainUI class. Used to display the interface. Inner workings still need work.
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2
3/********************************************************************\
4 * This program is free software; you can redistribute it and/or    *
5 * modify it under the terms of the GNU General Public License as   *
6 * published by the Free Software Foundation; either version 2 of   *
7 * the License, or (at your option) any later version.              *
8 *                                                                  *
9 * This program is distributed in the hope that it will be useful,  *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
12 * GNU General Public License for more details.                     *
13 *                                                                  *
14 * You should have received a copy of the GNU General Public License*
15 * along with this program; if not, contact:                        *
16 *                                                                  *
17 * Free Software Foundation           Voice:  +1-617-542-5942       *
18 * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
19 * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
20 *                                                                  *
21 \********************************************************************/
22/**@file User.php
23 * @author Copyright (C) 2005 Benoit Grégoire <bock@step.polymtl.ca>
24 */
25
26require_once BASEPATH.'include/common.php';
27require_once BASEPATH.'classes/Network.php';
28/** Abstract a User. */
29class User
30{
31        private $mRow;
32        private $id;
33
34        /** Instantiate a user object
35         * @param $id The user id of the requested user
36         * @return a User object, or null if there was an error
37         */
38        public static function getObject($id)
39        {
40                $object = null;
41                $object = new self($id);
42                return $object;
43        }
44
45        /** Instantiate the current user
46         * @return a User object, or null if there was an error
47         */
48        public static function getCurrentUser()
49        {
50                require_once BASEPATH.'classes/Session.php';
51                $session = new Session();
52                $user = null;
53                try
54                {
55                        $user = new User($session->get(SESS_USER_ID_VAR));
56                }
57                catch (Exception $e)
58                {
59                        /**If any problem occurs, the user should be considered logged out*/
60                        $session->set(SESS_USER_ID_VAR, null);
61                }
62                return $user;
63        }
64
65        /** Instantiate a user object
66         * @param $username The username of the user
67         * @param $account_origin The account origin
68         * @return a User object, or null if there was an error
69         */
70        public static function getUserByUsernameAndOrigin($username, $account_origin)
71        {
72                global $db;
73                $object = null;
74
75                $username_str = $db->EscapeString($username);
76                $account_origin_str = $db->EscapeString($account_origin);
77                $db->ExecSqlUniqueRes("SELECT user_id FROM users WHERE username = '$username_str' AND account_origin = '$account_origin_str'", $user_info, false);
78
79                if ($user_info != null)
80                        $object = new self($user_info['user_id']);
81                return $object;
82        }
83
84        /** Instantiate a user object
85         * @param $email The email of the user
86         * @param $account_origin The account origin
87         * @return a User object, or null if there was an error
88         */
89        public static function getUserByEmailAndOrigin($email, $account_origin)
90        {
91                global $db;
92                $object = null;
93
94                $email_str = $db->EscapeString($email);
95                $account_origin_str = $db->EscapeString($account_origin);
96                $db->ExecSqlUniqueRes("SELECT user_id FROM users WHERE email = '$email_str' AND account_origin = '$account_origin_str'", $user_info, false);
97
98                if ($user_info != null)
99                        $object = new self($user_info['user_id']);
100                return $object;
101        }
102
103        /**
104         * Get the list of users associated with a username
105         * Since we cannot guarantee the uniqueness of (user, e-mail) key this will
106         * return an array.
107         *
108         * NB : This function will only extract users who authenticate
109         * through a LocalUserAuthenticator
110         * (see AuthenticatorLocalUser::getAllLocalUserAccountOrigins)
111         *
112         * @param $username : the username criterion
113         * @return array : array of User objects
114         */
115        public static function getUsersByUsername($username)
116        {
117                $users_list = array ();
118
119                // E-mail cannot be empty, will return an empty array.
120                if (!empty ($username))
121                {
122                        // Build SQL query, excluding users who do not authenticate through LocalUserAuth
123                        global $db;
124                        $username_str = $db->EscapeString($username);
125                        $sql = "SELECT user_id FROM users WHERE username = '$username_str'";
126                        $first = true;
127                        foreach (array_keys(AuthenticatorLocalUser :: getAllLocalUserAccountOrigins()) as $account_origin)
128                        {
129                                if ($first === true)
130                                {
131                                        $sql .= " AND (account_origin = '$account_origin'";
132                                        $first = false;
133                                }
134                                else
135                                        $sql .= " OR account_origin = '$account_origin'";
136                        }
137                        if ($first === false)
138                                $sql .= ")";
139                        $db->ExecSql($sql, $users_rows, false);
140
141                        // Fill an array with User objects corresponding to those we just got
142                        if (!empty ($users_rows))
143                                foreach ($users_rows as $user_row)
144                                        $users_list[] = new User($user_row['user_id']);
145                }
146
147                return $users_list;
148        }
149
150        /**
151         * Get the list of users associated with an e-mail address
152         * Since we cannot guarantee the unicity of (user, e-mail) key
153         * this will return an array.
154         *
155         * NB : This function will only extract users who authenticate
156         * through a LocalUserAuthenticator
157         * (see AuthenticatorLocalUser::getAllLocalUserAccountOrigins)
158         *
159         * @param $email : the e-mail criterion
160         * @return array : array of User objects
161         */
162        public static function getUsersByEmail($email)
163        {
164                $users_list = array ();
165
166                // E-mail cannot be empty, will return an empty array.
167                if (!empty ($email))
168                {
169                        // Build SQL query, excluding users who do not authenticate through LocalUserAuth
170                        global $db;
171                        $email_str = $db->EscapeString($email);
172                        $sql = "SELECT user_id FROM users WHERE email = '$email_str'";
173                        $first = true;
174                        foreach (array_keys(AuthenticatorLocalUser :: getAllLocalUserAccountOrigins()) as $account_origin)
175                        {
176                                if ($first === true)
177                                {
178                                        $sql .= " AND (account_origin = '$account_origin'";
179                                        $first = false;
180                                }
181                                else
182                                        $sql .= " OR account_origin = '$account_origin'";
183                        }
184                        if ($first === false)
185                                $sql .= ")";
186                        $db->ExecSql($sql, $users_rows, false);
187
188                        // Fill an array with User objects corresponding to those we just got
189                        if (!empty ($users_rows))
190                                foreach ($users_rows as $user_row)
191                                        $users_list[] = new User($user_row['user_id']);
192                }
193
194                return $users_list;
195        }
196
197        /** Returns the hash of the password suitable for storing or comparing in the database.  This hash is the same one as used in NoCat
198         * @return The 32 character hash.
199         */
200        public static function passwordHash($password)
201        {
202                return base64_encode(pack("H*", md5($password)));
203        }
204
205        /** Create a new User in the database
206         * @param $id The id to be given to the new user
207         * @return the newly created User object, or null if there was an error
208         */
209        static function createUser($id, $username, $account_origin, $email, $password)
210        {
211                global $db;
212
213                $object = null;
214                $id_str = $db->EscapeString($id);
215                $username_str = $db->EscapeString($username);
216                $account_origin_str = $db->EscapeString($account_origin);
217                $email_str = $db->EscapeString($email);
218                /**
219                 * utf8_decode is used for backward compatibility with old passwords
220                 * containing special characters.
221                 * Conversion from UTF-8 to ISO-8859-1 is done to match the MD5 hash
222                 */
223                $password_hash = $db->EscapeString(User :: passwordHash(utf8_decode($password)));
224                $status = ACCOUNT_STATUS_VALIDATION;
225                $token = User :: generateToken();
226
227                $db->ExecSqlUpdate("INSERT INTO users (user_id,username, account_origin,email,pass,account_status,validation_token,reg_date) VALUES ('$id_str','$username_str','$account_origin_str','$email_str','$password_hash','$status','$token',NOW())");
228
229                $object = new self($id);
230                return $object;
231        }
232
233        /** @param $object_id The id of the user */
234        function __construct($object_id)
235        {
236                global $db;
237                $object_id_str = $db->EscapeString($object_id);
238                $sql = "SELECT * FROM users WHERE user_id='{$object_id_str}'";
239                $db->ExecSqlUniqueRes($sql, $row, false);
240                if ($row == null)
241                {
242                        throw new Exception(_("User id: ").$object_id_str._(" could not be found in the database"));
243                }
244                $this->mRow = $row;
245                $this->id = $row['user_id'];
246        } //End class
247
248        function getId()
249        {
250                return $this->id;
251        }
252
253/** Get a user display suitable for a user list.  Will include link to the user profile. */
254        function getUserListUI()
255        {
256                                                $html = '';
257                                                $html .= $this->getUserName();
258                                                return $html;
259        }
260
261        function getUsername()
262        {
263                return $this->mRow['username'];
264        }
265
266        public function getEmail()
267        {
268                return $this->mRow['email'];
269        }
270
271        /**What locale (language) does the user prefer?
272         * @todo Save in the database */
273        public function getPreferedLocale()
274        {
275                global $session;
276                //return $this->mRow['prefered_locale'];
277                $locale = $session->get('SESS_LANGUAGE_VAR');
278                if (empty ($locale))
279                {
280                        $locale = DEFAULT_LANG;
281                }
282                return $locale;
283        }
284
285        public function getPasswordHash()
286        {
287                return $this->mRow['pass'];
288        }
289
290        /** Get the account status. 
291         * @return Possible values are listed in common.php
292        */
293        function getAccountStatus()
294        {
295                return $this->mRow['account_status'];
296        }
297
298        function setAccountStatus($status)
299        {
300                global $db;
301
302                $status_str = $db->EscapeString($status);
303                if (!($update = $db->ExecSqlUpdate("UPDATE users SET account_status='{$status_str}' WHERE user_id='{$this->id}'")))
304                {
305                        throw new Exception(_("Could not update status."));
306                }
307                $this->mRow['account_status'] = $status;
308        }
309
310        /** Is the user valid?  Valid means that the account is validated or hasn't exhausted it's validation period.
311         $errmsg: Returs the reason why the account is or isn't valid */
312        function isUserValid(& $errmsg = null)
313        {
314                global $db;
315                $retval = false;
316                $account_status = $this->getAccountStatus();
317                if ($account_status == ACCOUNT_STATUS_ALLOWED)
318                {
319                        $retval = true;
320                }
321                else
322                        if ($account_status == ACCOUNT_STATUS_VALIDATION)
323                        {
324                                $sql = "SELECT CASE WHEN ((NOW() - reg_date) > interval '".VALIDATION_GRACE_TIME." minutes') THEN true ELSE false END AS validation_grace_time_expired FROM users WHERE (user_id='{$this->id}')";
325                                $db->ExecSqlUniqueRes($sql, $user_info, false);
326
327                                if ($user_info['validation_grace_time_expired'] == 't')
328                                {
329                                        $errmsg = _("Sorry, your ").$validation_grace_time._(" minutes grace period to retrieve your email and validate your account has now expired. You will have to connect to the internet and validate your account from another location or create a new account. For help, please ").'<a href="'.BASEPATH.'faq.php'.'">'._("click here.").'</a>';
330                                        $retval = false;
331                                }
332                                else
333                                {
334                                        $errmsg = _("Your account is currently valid.");
335                                        $retval = true;
336                                }
337                        }
338                        else
339                        {
340                                $errmsg = _("Sorry, your account is not valid: ").$account_status_to_text[$account_status];
341                                $retval = false;
342                        }
343                return $retval;
344        }
345
346  public function isSuperAdmin() {
347    global $db;
348    //$this->session->dump();
349   
350    $db->ExecSqlUniqueRes("SELECT * FROM users NATURAL JOIN administrators WHERE (users.user_id='$this->id')", $user_info, false);
351    if (!empty($user_info)) {
352     return true;
353    } else {
354     return false;
355    }
356
357  }
358        function getValidationToken()
359        {
360                return $this->mRow['validation_token'];
361        }
362
363        function getInfoArray()
364        {
365                return $this->mRow;
366        }
367
368        /** Generate a token in the connection table so the user can actually use the internet
369        @return true on success, false on failure
370        */
371        function generateConnectionToken()
372        {
373                if ($this->isUserValid())
374                {
375                        global $db;
376                        $token = self :: generateToken();
377                        if ($_SERVER['REMOTE_ADDR'])
378                        {
379                                $node_ip = $db->EscapeString($_SERVER['REMOTE_ADDR']);
380                        }
381                        if (isset ($_REQUEST['gw_id']) && $_REQUEST['gw_id'])
382                        {
383                                $node_id = $db->EscapeString($_REQUEST['gw_id']);
384                                $db->ExecSqlUpdate("INSERT INTO connections (user_id, token, token_status, timestamp_in, node_id, node_ip, last_updated) VALUES ('".$this->getId()."', '$token', '".TOKEN_UNUSED."', NOW(), '$node_id', '$node_ip', NOW())", false);
385                                $retval = $token;
386                        }
387                        else
388                                $retval = false;
389                }
390                else
391                {
392                        $retval = false;
393                }
394                return $retval;
395        }
396
397        function setPassword($password)
398        {
399                global $db;
400
401                $new_password_hash = User :: passwordHash(utf8_decode($password));
402                if (!($update = $db->ExecSqlUpdate("UPDATE users SET pass='$new_password_hash' WHERE user_id='{$this->id}'")))
403                {
404                        throw new Exception(_("Could not change user's password."));
405                }
406                $this->mRow['pass'] = $password;
407        }
408
409        function getConnections()
410        {
411                global $db;
412                $db->ExecSql("SELECT * FROM connections,nodes WHERE user_id='{$this->id}' AND nodes.node_id=connections.node_id ORDER BY timestamp_in", $connections, false);
413                return $connections;
414        }
415
416        /** Return all the users
417         */
418        static function getAllUsers()
419        {
420                global $db;
421
422                $db->ExecSql("SELECT * FROM users", $objects, false);
423                if ($objects == null)
424                {
425                        throw new Exception(_("No users could not be found in the database"));
426                }
427                return $objects;
428        }
429
430        function sendLostUsername()
431        {
432                $username = $this->getUsername();
433                $headers = 'MIME-Version: 1.0'."\r\n";
434                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
435                $headers .= "From: ".VALIDATION_EMAIL_FROM_ADDRESS;
436                $subject = HOTSPOT_NETWORK_NAME._(" lost username request");
437                $body = _("Hello,\nYou have requested that the authentication server send you your username:\nUsername: ").$username._("\n\nHave a nice day,\nThe Team");
438
439                mail($this->getEmail(), $subject, $body, $headers);
440        }
441
442        function sendValidationEmail()
443        {
444                if ($this->getAccountStatus() != ACCOUNT_STATUS_VALIDATION)
445                {
446                        throw new Exception(_("The user is not in validation period."));
447                }
448                else
449                {
450                        if ($this->getValidationToken() == "")
451                        {
452                                throw new Exception(_("The validation token is empty."));
453                        }
454                        else
455                        {
456                                $headers = 'MIME-Version: 1.0'."\r\n";
457                                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
458                                $headers .= "From: ".VALIDATION_EMAIL_FROM_ADDRESS;
459                                $subject = HOTSPOT_NETWORK_NAME._(" new user validation");
460                                $url = "http://".$_SERVER["SERVER_NAME"]."/validate.php?user_id=".$this->getId()."&token=".$this->getValidationToken();
461                                $body = _("Hello,\nPlease follow the link below to validate your account.\n").$url._("\n\nThank you,\nThe Team.");
462
463                                mail($this->getEmail(), $subject, $body, $headers);
464                        }
465                }
466        }
467
468        function sendLostPasswordEmail()
469        {
470                global $db;
471
472                $new_password = $this->randomPass();
473                $this->setPassword($new_password);
474                $username = $this->getUsername();
475
476                $headers = 'MIME-Version: 1.0'."\r\n";
477                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
478                $headers .= "From: ".VALIDATION_EMAIL_FROM_ADDRESS;
479                $subject = HOTSPOT_NETWORK_NAME._(" new password request");
480                $body = _("Hello,\nYou have requested that the authentication server send you a new password:\nUsername: ").$username._("\nPassword: ").$new_password._("\n\nHave a nice day,\nThe Team");
481
482                mail($this->getEmail(), $subject, $body, $headers);
483        }
484
485        static function userExists($id)
486        {
487                global $db;
488                $id_str = $db->EscapeString($id);
489                $sql = "SELECT * FROM users WHERE user_id='{$id_str}'";
490                $db->ExecSqlUniqueRes($sql, $row, false);
491                return $row;
492        }
493
494        public static function emailExists($id)
495        {
496                global $db;
497                $id_str = $db->EscapeString($id);
498                $sql = "SELECT * FROM users WHERE email='{$id_str}'";
499                $db->ExecSqlUniqueRes($sql, $row, false);
500                return $row;
501        }
502
503        public static function randomPass()
504        {
505                $rand_pass = ''; // makes sure the $pass var is empty.
506                for ($j = 0; $j < 3; $j ++)
507                {
508                        $startnend = array ('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z',);
509                        $id = array ('a', 'e', 'i', 'o', 'u', 'y',);
510                        $count1 = count($startnend) - 1;
511                        $count2 = count($id) - 1;
512
513                        for ($i = 0; $i < 3; $i ++)
514                        {
515                                if ($i != 1)
516                                {
517                                        $rand_pass .= $startnend[rand(0, $count1)];
518                                }
519                                else
520                                {
521                                        $rand_pass .= $id[rand(0, $count2)];
522                                }
523                        }
524                }
525                return $rand_pass;
526        }
527
528        public static function generateToken()
529        {
530                return md5(uniqid(rand(), 1));
531        }
532
533        /** Get an interface to add a user to a list
534        * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
535        * @return html markup
536        */
537        static function getSelectUserUI($user_prefix)
538        {
539                global $db;
540                $html = '';
541                $html .= Network :: getSelectNetworkUI($user_prefix);
542                $name = "select_user_{$user_prefix}_username";
543                $html .= "Username: \n";
544                $html .= "<input type='text' name='$name' value=''>\n";
545                return $html;
546        }
547        /** Get the selected user, IF one was selected and is valid
548         * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
549         * @return the User object, or null if the user is invalid or none was selected
550         */
551        static function processSelectUserUI($user_prefix)
552        {
553                $object = null;
554                $network = Network :: processSelectNetworkUI($user_prefix);
555                $name = "select_user_{$user_prefix}_username";
556                $username = $_REQUEST[$name];
557                return self::getUserByUsernameAndOrigin($username, $network->GetId());
558        }
559
560
561} // End class
562?>
Note: See TracBrowser for help on using the browser.