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

Revision 739, 19.8 KB (checked in by aprilp, 8 years ago)

*** empty log message ***

  • 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 * This program is free software; you can redistribute it and/or    *
4 * modify it under the terms of the GNU General Public License as   *
5 * published by the Free Software Foundation; either version 2 of   *
6 * the License, or (at your option) any later version.              *
7 *                                                                  *
8 * This program is distributed in the hope that it will be useful,  *
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
11 * GNU General Public License for more details.                     *
12 *                                                                  *
13 * You should have received a copy of the GNU General Public License*
14 * along with this program; if not, contact:                        *
15 *                                                                  *
16 * Free Software Foundation           Voice:  +1-617-542-5942       *
17 * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
18 * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
19 *                                                                  *
20 \********************************************************************/
21/**@file User.php
22 * @author Copyright (C) 2005 Benoit Grégoire <bock@step.polymtl.ca>
23 */
24
25require_once BASEPATH.'include/common.php';
26require_once BASEPATH.'classes/Network.php';
27
28/** Abstract a User. */
29class User implements GenericObject
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    static function createNewObject()
46    {
47        echo "<h1>Use User::createUser() instead</h1>";
48    }
49
50        /** Instantiate the current user
51         * @return a User object, or null if there was an error
52         */
53        public static function getCurrentUser()
54        {
55                require_once BASEPATH.'classes/Session.php';
56                $session = new Session();
57                $user = null;
58                try
59                {
60                        $user = self :: getObject($session->get(SESS_USER_ID_VAR));
61                        //$user = new User($session->get(SESS_USER_ID_VAR));
62                }
63                catch (Exception $e)
64                {
65                        /**If any problem occurs, the user should be considered logged out*/
66                        $session->set(SESS_USER_ID_VAR, null);
67                }
68                return $user;
69        }
70       
71        /** Associates the user passed in parameter with the session.  This should NOT be called by anything except the Authenticators
72         * @param User a user object
73         * @return boolean true if everything went well setting the session...
74         */
75        public static function setCurrentUser(User $user)
76        {
77                try
78                {
79                        $session = new Session();
80                        $session->set(SESS_USER_ID_VAR, $user->getId());
81                        $session->set(SESS_PASSWORD_HASH_VAR, $user->getPasswordHash());
82                        return true;
83                }
84                catch(Exception $e)
85                {
86                        return false;
87                }
88        }
89
90        /** Instantiate a user object
91         * @param $username The username of the user
92         * @param $account_origin Network:  The account origin
93         * @return a User object, or null if there was an error
94         */
95        public static function getUserByUsernameAndOrigin($username, Network $account_origin)
96        {
97                global $db;
98                $object = null;
99
100                $username_str = $db->EscapeString($username);
101                $account_origin_str = $db->EscapeString($account_origin->getId());
102                $db->ExecSqlUniqueRes("SELECT user_id FROM users WHERE username = '$username_str' AND account_origin = '$account_origin_str'", $user_info, false);
103
104                if ($user_info != null)
105                        $object = new self($user_info['user_id']);
106                return $object;
107        }
108
109        /** Instantiate a user object
110         * @param $email The email of the user
111         * @param $account_origin Network:  The account origin
112         * @return a User object, or null if there was an error
113         */
114        public static function getUserByEmailAndOrigin($email, Network $account_origin)
115        {
116                global $db;
117                $object = null;
118
119                $email_str = $db->EscapeString($email);
120                $account_origin_str = $db->EscapeString($account_origin->getId());
121                $db->ExecSqlUniqueRes("SELECT user_id FROM users WHERE email = '$email_str' AND account_origin = '$account_origin_str'", $user_info, false);
122
123                if ($user_info != null)
124                        $object = new self($user_info['user_id']);
125                return $object;
126        }
127
128        /** Returns the hash of the password suitable for storing or comparing in the database.  This hash is the same one as used in NoCat
129         * @return The 32 character hash.
130         */
131        public static function passwordHash($password)
132        {
133                /**
134                 * utf8_decode is used for backward compatibility with old passwords
135                 * containing special characters.
136                 * Conversion from UTF-8 to ISO-8859-1 is done to match the MD5 hash
137                 */
138                return base64_encode(pack("H*", md5(utf8_decode($password))));
139        }
140
141        /** Create a new User in the database
142         * @param $id The id to be given to the new user
143         * @return the newly created User object, or null if there was an error
144         */
145        static function createUser($id, $username, Network $account_origin, $email, $password)
146        {
147                global $db;
148
149                $object = null;
150                $id_str = $db->EscapeString($id);
151                $username_str = $db->EscapeString($username);
152                $account_origin_str = $db->EscapeString($account_origin->getId());
153                $email_str = $db->EscapeString($email);
154
155                $password_hash = $db->EscapeString(User :: passwordHash($password));
156                $status = ACCOUNT_STATUS_VALIDATION;
157                $token = User :: generateToken();
158
159                $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())");
160
161                $object = new self($id);
162                return $object;
163        }
164
165        /** @param $object_id The id of the user */
166        function __construct($object_id)
167        {
168                global $db;
169                $object_id_str = $db->EscapeString($object_id);
170                $sql = "SELECT * FROM users WHERE user_id='{$object_id_str}'";
171                $db->ExecSqlUniqueRes($sql, $row, false);
172                if ($row == null)
173                {
174                        throw new Exception(_("User id: ").$object_id_str._(" could not be found in the database"));
175                }
176                $this->mRow = $row;
177                $this->id = $row['user_id'];
178        } //End class
179
180        function getId()
181        {
182                return $this->id;
183        }
184       
185        /** Gets the Network to which the user belongs
186         * @return Network object (never returns null)
187         */
188        public function getNetwork()
189        {
190                return Network::getObject($this->mRow['account_origin']);
191        }
192
193
194        /** Get a user display suitable for a user list.  Will include link to the user profile. */
195        function getUserListUI()
196        {
197                $html = '';
198                $html .= $this->getUserName();
199                return $html;
200        }
201
202        function getUsername()
203        {
204                return $this->mRow['username'];
205        }
206
207        public function getEmail()
208        {
209                return $this->mRow['email'];
210        }
211   
212    public function getRealName()
213    {
214        return $this->mRow['real_name'];
215    }
216   
217    public function setRealName()
218    {
219    }
220   
221    public function getWebsiteURL()
222    {
223        return $this->mRow['website'];
224    }
225   
226    public function setWebsiteURL()
227    {
228    }
229
230        /**What locale (language) does the user prefer?
231         * @todo Save in the database */
232        public function getPreferedLocale()
233        {
234                global $session;
235                //return $this->mRow['prefered_locale'];
236                $locale = $session->get('SESS_LANGUAGE_VAR');
237                if (empty ($locale))
238                {
239                        $locale = DEFAULT_LANG;
240                }
241                return $locale;
242        }
243
244/** get the hashed password stored in the database */
245        public function getPasswordHash()
246        {
247                return $this->mRow['pass'];
248        }
249
250        /** Get the account status. 
251         * @return Possible values are listed in common.php
252        */
253        function getAccountStatus()
254        {
255                return $this->mRow['account_status'];
256        }
257
258        function setAccountStatus($status)
259        {
260                global $db;
261
262                $status_str = $db->EscapeString($status);
263                if (!($update = $db->ExecSqlUpdate("UPDATE users SET account_status='{$status_str}' WHERE user_id='{$this->id}'")))
264                {
265                        throw new Exception(_("Could not update status."));
266                }
267                $this->mRow['account_status'] = $status;
268        }
269
270        /** Is the user valid?  Valid means that the account is validated or hasn't exhausted it's validation period.
271         $errmsg: Returs the reason why the account is or isn't valid */
272        function isUserValid(& $errmsg = null)
273        {
274                global $db;
275                $retval = false;
276                $account_status = $this->getAccountStatus();
277                if ($account_status == ACCOUNT_STATUS_ALLOWED)
278                {
279                        $retval = true;
280                }
281                else
282                        if ($account_status == ACCOUNT_STATUS_VALIDATION)
283                        {
284                                $sql = "SELECT CASE WHEN ((NOW() - reg_date) > interval networks.validation_grace_time) THEN true ELSE false END AS validation_grace_time_expired, networks.validation_grace_time FROM users  JOIN networks ON (users.account_origin = networks.network_id) WHERE (user_id='{$this->id}')";
285                                $db->ExecSqlUniqueRes($sql, $user_info, false);
286
287                                if ($user_info['validation_grace_time_expired'] == 't')
288                                {
289                                        $errmsg = sprintf(_("Sorry, your %s 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 %s click here %s."), $user_info['validation_grace_time_expired'], '<a href="'.BASEPATH.'faq.php'.'">', '</a>');
290                                        $retval = false;
291                                }
292                                else
293                                {
294                                        $errmsg = _("Your account is currently valid.");
295                                        $retval = true;
296                                }
297                        }
298                        else
299                        {
300                                $errmsg = _("Sorry, your account is not valid: ").$account_status_to_text[$account_status];
301                                $retval = false;
302                        }
303                return $retval;
304        }
305
306        public function isSuperAdmin()
307        {
308                global $db;
309                //$this->session->dump();
310
311                $db->ExecSqlUniqueRes("SELECT * FROM users NATURAL JOIN administrators WHERE (users.user_id='$this->id')", $user_info, false);
312                if (!empty ($user_info))
313                {
314                        return true;
315                }
316                else
317                {
318                        return false;
319                }
320
321        }
322
323        /**
324         * Tells if the current user is owner of at least one hotspot.
325         */
326        public function isOwner()
327        {
328                global $db;
329                $db->ExecSqlUniqueRes("SELECT * FROM node_stakeholders WHERE is_owner = true AND user_id='{$this->getId()}'", $row, false);
330                if ($row != null)
331                        return true;
332                return false;
333
334        }
335
336    public function isNobody() {
337                global $db;
338                $db->ExecSqlUniqueRes("SELECT DISTINCT user_id FROM (SELECT user_id FROM network_stakeholders WHERE user_id='{$this->getId()}' UNION SELECT user_id FROM node_stakeholders WHERE user_id='{$this->getId()}' UNION SELECT user_id FROM administrators WHERE user_id='{$this->getId()}') as tmp", $row, false);
339                if ($row == null)
340                        return true;
341                return false;
342    }
343
344        function getValidationToken()
345        {
346                return $this->mRow['validation_token'];
347        }
348
349        function getInfoArray()
350        {
351                return $this->mRow;
352        }
353
354        /** Generate a token in the connection table so the user can actually use the internet
355        @return true on success, false on failure
356        */
357        function generateConnectionToken()
358        {
359                if ($this->isUserValid())
360                {
361                        global $db;
362                        global $session;
363                       
364                        $token = self :: generateToken();
365                        if ($_SERVER['REMOTE_ADDR'])
366                        {
367                                $node_ip = $db->EscapeString($_SERVER['REMOTE_ADDR']);
368                        }
369                       
370                        if ($session && $node_ip && $session->get(SESS_GW_ID_VAR))
371                        {
372                                $node_id = $db->EscapeString($session->get(SESS_GW_ID_VAR));
373                                $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);
374                                $retval = $token;
375                        }
376                        else
377                                $retval = false;
378                }
379                else
380                {
381                        $retval = false;
382                }
383                return $retval;
384        }
385
386        function setPassword($password)
387        {
388                global $db;
389
390                $new_password_hash = User :: passwordHash($password);
391                if (!($update = $db->ExecSqlUpdate("UPDATE users SET pass='$new_password_hash' WHERE user_id='{$this->id}'")))
392                {
393                        throw new Exception(_("Could not change user's password."));
394                }
395                $this->mRow['pass'] = $password;
396        }
397
398        function getAccountOrigin()
399        {
400                return $this->mRow['account_origin'];
401        }
402
403        /** Return all the users
404         */
405        static function getAllUsers()
406        {
407                global $db;
408
409                $db->ExecSql("SELECT * FROM users", $objects, false);
410                if ($objects == null)
411                {
412                        throw new Exception(_("No users could not be found in the database"));
413                }
414                return $objects;
415        }
416
417        function sendLostUsername()
418        {
419                $network = $this->getNetwork();
420                $username = $this->getUsername();
421                $headers = 'MIME-Version: 1.0'."\r\n";
422                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
423                $headers .= "From: ".$network->getValidationEmailFromAddress();
424                $subject = $network->getName()._(" lost username request");
425                $body = _("Hello,\nYou have requested that the authentication server send you your username:\nUsername: ").$username._("\n\nHave a nice day,\nThe Team");
426
427                //TODO: Find a way to use correctly mb_encode_mimeheader
428                $subject = mb_convert_encoding($subject, "ISO-8859-1", "AUTO");
429
430                mail($this->getEmail(), $subject, $body, $headers);
431        }
432
433        function sendValidationEmail()
434        {
435                if ($this->getAccountStatus() != ACCOUNT_STATUS_VALIDATION)
436                {
437                        throw new Exception(_("The user is not in validation period."));
438                }
439                else
440                {
441                        if ($this->getValidationToken() == "")
442                        {
443                                throw new Exception(_("The validation token is empty."));
444                        }
445                        else
446                        {
447                                $network = $this->getNetwork();
448                                $headers = 'MIME-Version: 1.0'."\r\n";
449                                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
450                                $headers .= "From: ".$network->getValidationEmailFromAddress();
451                                $subject = $network->getName()._(" new user validation");
452                                $url = "http://".$_SERVER["SERVER_NAME"]."/validate.php?user_id=".$this->getId()."&token=".$this->getValidationToken();
453                                $body = _("Hello,\nPlease follow the link below to validate your account.\n").$url._("\n\nThank you,\nThe Team.");
454
455                                //TODO: Find a way to use correctly mb_encode_mimeheader
456                                $subject = mb_convert_encoding($subject, "ISO-8859-1", "AUTO");
457
458                                mail($this->getEmail(), $subject, $body, $headers);
459                        }
460                }
461        }
462
463        function sendLostPasswordEmail()
464        {
465                global $db;
466                $network = $this->getNetwork();
467                $new_password = $this->randomPass();
468                $this->setPassword($new_password);
469                $username = $this->getUsername();
470
471                $headers = 'MIME-Version: 1.0'."\r\n";
472                $headers .= 'Content-type: text/plain; charset=UTF-8'."\r\n";
473                $headers .= "From: ".$network->getValidationEmailFromAddress();
474                $subject = $network->getName()._(" new password request");
475                $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");
476
477                //TODO: Find a way to use correctly mb_encode_mimeheader
478                $subject = mb_convert_encoding($subject, "ISO-8859-1", "AUTO");
479
480                mail($this->getEmail(), $subject, $body, $headers);
481        }
482
483        static function userExists($id)
484        {
485                global $db;
486                $id_str = $db->EscapeString($id);
487                $sql = "SELECT * FROM users WHERE user_id='{$id_str}'";
488                $db->ExecSqlUniqueRes($sql, $row, false);
489                return $row;
490        }
491
492        public static function emailExists($id)
493        {
494                global $db;
495                $id_str = $db->EscapeString($id);
496                $sql = "SELECT * FROM users WHERE email='{$id_str}'";
497                $db->ExecSqlUniqueRes($sql, $row, false);
498                return $row;
499        }
500
501        public static function randomPass()
502        {
503                $rand_pass = ''; // makes sure the $pass var is empty.
504                for ($j = 0; $j < 3; $j ++)
505                {
506                        $startnend = array ('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z',);
507                        $id = array ('a', 'e', 'i', 'o', 'u', 'y',);
508                        $count1 = count($startnend) - 1;
509                        $count2 = count($id) - 1;
510
511                        for ($i = 0; $i < 3; $i ++)
512                        {
513                                if ($i != 1)
514                                {
515                                        $rand_pass .= $startnend[rand(0, $count1)];
516                                }
517                                else
518                                {
519                                        $rand_pass .= $id[rand(0, $count2)];
520                                }
521                        }
522                }
523                return $rand_pass;
524        }
525
526        public static function generateToken()
527        {
528                return md5(uniqid(rand(), 1));
529        }
530
531        /** Get an interface to add a user to a list
532        * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
533        * @return html markup
534        */
535        static function getSelectUserUI($user_prefix)
536        {
537                global $db;
538                $html = '';
539                $html .= Network :: getSelectNetworkUI($user_prefix);
540                $html .= "<br>";
541                $name = "select_user_{$user_prefix}_username";
542                $html .= "Username: \n";
543                $html .= "<input type='text' name='$name' value=''>\n";
544                return $html;
545        }
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                try {
555                        $network = Network :: processSelectNetworkUI($user_prefix);
556                        $name = "select_user_{$user_prefix}_username";
557                        if(!empty($_REQUEST[$name]))
558                        {
559                                $username = $_REQUEST[$name];
560                                return self :: getUserByUsernameAndOrigin($username, $network);
561                        }
562                        else
563                                return null;
564                }
565                catch(Exception $e)
566                {
567                        return null;
568                }
569        }
570   
571    public function getAdminUI()
572    {
573        global $db;
574        $html = '';
575        $html .= "<div class='admin_container'>\n";
576        $html .= "<div class='admin_class'>User instance</div>\n";
577       
578        $html .= "<div class='admin_section_container'>\n";
579        $html .= "<div class='admin_section_title'>"._("Username")." : </div>\n";
580        $html .= "<div class='admin_section_data'>\n";
581        //$name = "user_".$this->getId()."_username";
582        //$html .= "<input type='text' name='$name' value='".htmlentities($this->getUsername())."' size=30 readonly>\n";
583        $html .= $this->getUsername()."\n";
584        $html .= "</div>\n";
585        $html .= "</div>\n";
586       
587        //TODO: implement this when Network abstraction is completed
588        /*
589        $html .= "<div class='admin_section_container'>\n";
590        $html .= "<div class='admin_section_title'>"._("Network")." : </div>\n";
591        $html .= "<div class='admin_section_data'>\n";
592        $name = "user_".$this->getId()."_username";
593        // Show network name here
594        $html .= "</div>\n";
595        $html .= "</div>\n";*/
596       
597        $html .= "<div class='admin_section_container'>\n";
598        $html .= "<div class='admin_section_title'>"._("Real name")." : </div>\n";
599        $html .= "<div class='admin_section_data'>\n";
600        $name = "user_".$this->getId()."_real_name";
601        $html .= "<input type='text' name='$name' value='".htmlentities($this->getRealName())."' size=30 readonly>\n";
602        $html .= "</div>\n";
603        $html .= "</div>\n";
604       
605        $html .= "<div class='admin_section_container'>\n";
606        $html .= "<div class='admin_section_title'>"._("Website URL")." : </div>\n";
607        $html .= "<div class='admin_section_data'>\n";
608        $name = "user_".$this->getId()."_website";
609        $html .= "<input type='text' name='$name' value='".htmlentities($this->getWebsiteURL())."' size=30 readonly>\n";
610        $html .= "</div>\n";
611        $html .= "</div>\n";
612       
613        $html .= "</div>\n";
614        return $html;
615    }
616   
617    public function processAdminUI()
618    {
619    }
620   
621    public function delete(& $errmsg)
622    {
623    }
624   
625    public function getUserUI()
626    {
627    }
628
629        /** Add content to this user ( subscription ) */
630        public function addContent(Content $content)
631        {
632                global $db;
633                $content_id = $db->EscapeString($content->getId());
634                $sql = "INSERT INTO user_has_content (user_id, content_id) VALUES ('$this->id','$content_id')";
635                $db->ExecSqlUpdate($sql, false);
636                return true;
637        }
638
639        /** Remove content from this node */
640        public function removeContent(Content $content)
641        {
642                global $db;
643                $content_id = $db->EscapeString($content->getId());
644                $sql = "DELETE FROM user_has_content WHERE user_id='$this->id' AND content_id='$content_id'";
645                $db->ExecSqlUpdate($sql, false);
646                return true;
647        }
648
649        /**Get an array of all Content linked to this node
650        * @return an array of Content or an empty arrray */
651        function getAllContent()
652        {
653                global $db;
654                $retval = array ();
655                $sql = "SELECT * FROM user_has_content WHERE user_id='$this->id' ORDER BY subscribe_timestamp";
656                $db->ExecSql($sql, $content_rows, false);
657                if ($content_rows != null)
658                {
659                        foreach ($content_rows as $content_row)
660                        {
661                                $retval[] = Content :: getObject($content_row['content_id']);
662                        }
663                }
664                return $retval;
665        }
666
667} // End class
668?>
Note: See TracBrowser for help on using the browser.