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

Revision 568, 17.2 KB (checked in by fproulx, 8 years ago)

2005-04-25 Fran�ois Proulx <francois.proulx@…

  • More interface 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        //TODO: Find a way to use correctly mb_encode_mimeheader
440        $subject = mb_convert_encoding($subject, "ISO-8859-1","AUTO");
441       
442                mail($this->getEmail(), $subject, $body, $headers);
443        }
444
445        function sendValidationEmail()
446        {
447                if ($this->getAccountStatus() != ACCOUNT_STATUS_VALIDATION)
448                {
449                        throw new Exception(_("The user is not in validation period."));
450                }
451                else
452                {
453                        if ($this->getValidationToken() == "")
454                        {
455                                throw new Exception(_("The validation token is empty."));
456                        }
457                        else
458                        {
459                                $headers = 'MIME-Version: 1.0'."\r\n";
460                                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
461                                $headers .= "From: ".VALIDATION_EMAIL_FROM_ADDRESS;
462                                $subject = HOTSPOT_NETWORK_NAME._(" new user validation");
463                                $url = "http://".$_SERVER["SERVER_NAME"]."/validate.php?user_id=".$this->getId()."&token=".$this->getValidationToken();
464                                $body = _("Hello,\nPlease follow the link below to validate your account.\n").$url._("\n\nThank you,\nThe Team.");
465               
466                //TODO: Find a way to use correctly mb_encode_mimeheader
467                $subject = mb_convert_encoding($subject, "ISO-8859-1","AUTO");
468       
469                                mail($this->getEmail(), $subject, $body, $headers);
470                        }
471                }
472        }
473
474        function sendLostPasswordEmail()
475        {
476                global $db;
477
478                $new_password = $this->randomPass();
479                $this->setPassword($new_password);
480                $username = $this->getUsername();
481
482                $headers = 'MIME-Version: 1.0'."\r\n";
483                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
484        $headers .= "From: ".VALIDATION_EMAIL_FROM_ADDRESS;
485                $subject = HOTSPOT_NETWORK_NAME._(" new password request");
486                $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");
487       
488        //TODO: Find a way to use correctly mb_encode_mimeheader
489        $subject = mb_convert_encoding($subject, "ISO-8859-1","AUTO");
490       
491                mail($this->getEmail(), $subject, $body, $headers);
492        }
493
494        static function userExists($id)
495        {
496                global $db;
497                $id_str = $db->EscapeString($id);
498                $sql = "SELECT * FROM users WHERE user_id='{$id_str}'";
499                $db->ExecSqlUniqueRes($sql, $row, false);
500                return $row;
501        }
502
503        public static function emailExists($id)
504        {
505                global $db;
506                $id_str = $db->EscapeString($id);
507                $sql = "SELECT * FROM users WHERE email='{$id_str}'";
508                $db->ExecSqlUniqueRes($sql, $row, false);
509                return $row;
510        }
511
512        public static function randomPass()
513        {
514                $rand_pass = ''; // makes sure the $pass var is empty.
515                for ($j = 0; $j < 3; $j ++)
516                {
517                        $startnend = array ('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z',);
518                        $id = array ('a', 'e', 'i', 'o', 'u', 'y',);
519                        $count1 = count($startnend) - 1;
520                        $count2 = count($id) - 1;
521
522                        for ($i = 0; $i < 3; $i ++)
523                        {
524                                if ($i != 1)
525                                {
526                                        $rand_pass .= $startnend[rand(0, $count1)];
527                                }
528                                else
529                                {
530                                        $rand_pass .= $id[rand(0, $count2)];
531                                }
532                        }
533                }
534                return $rand_pass;
535        }
536
537        public static function generateToken()
538        {
539                return md5(uniqid(rand(), 1));
540        }
541
542        /** Get an interface to add a user to a list
543        * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
544        * @return html markup
545        */
546        static function getSelectUserUI($user_prefix)
547        {
548                global $db;
549                $html = '';
550                $html .= Network :: getSelectNetworkUI($user_prefix);
551                $name = "select_user_{$user_prefix}_username";
552                $html .= "Username: \n";
553                $html .= "<input type='text' name='$name' value=''>\n";
554                return $html;
555        }
556        /** Get the selected user, IF one was selected and is valid
557         * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
558         * @return the User object, or null if the user is invalid or none was selected
559         */
560        static function processSelectUserUI($user_prefix)
561        {
562                $object = null;
563                $network = Network :: processSelectNetworkUI($user_prefix);
564                $name = "select_user_{$user_prefix}_username";
565                $username = $_REQUEST[$name];
566                return self::getUserByUsernameAndOrigin($username, $network->GetId());
567        }
568
569
570} // End class
571?>
Note: See TracBrowser for help on using the browser.