root/branches/gbastien/wifidog/classes/User.php @ 1434

Revision 1434, 48.9 KB (checked in by gbastien, 3 years ago)

* New code for node groups
* Login and signup and logout script now can do something with the mac address

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[402]1<?php
[745]2
[1092]3
[866]4/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
[768]5
[866]6// +-------------------------------------------------------------------+
7// | WiFiDog Authentication Server                                     |
8// | =============================                                     |
9// |                                                                   |
10// | The WiFiDog Authentication Server is part of the WiFiDog captive  |
11// | portal suite.                                                     |
12// +-------------------------------------------------------------------+
13// | PHP version 5 required.                                           |
14// +-------------------------------------------------------------------+
15// | Homepage:     http://www.wifidog.org/                             |
16// | Source Forge: http://sourceforge.net/projects/wifidog/            |
17// +-------------------------------------------------------------------+
18// | This program is free software; you can redistribute it and/or     |
19// | modify it under the terms of the GNU General Public License as    |
20// | published by the Free Software Foundation; either version 2 of    |
21// | the License, or (at your option) any later version.               |
22// |                                                                   |
23// | This program is distributed in the hope that it will be useful,   |
24// | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
25// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
26// | GNU General Public License for more details.                      |
27// |                                                                   |
28// | You should have received a copy of the GNU General Public License |
29// | along with this program; if not, contact:                         |
30// |                                                                   |
31// | Free Software Foundation           Voice:  +1-617-542-5942        |
32// | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
33// | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
34// |                                                                   |
35// +-------------------------------------------------------------------+
36
37/**
38 * @package    WiFiDogAuthServer
[1421]39 * @author     Benoit Grégoire <benoitg@coeus.ca>
[1031]40 * @copyright  2005-2006 Benoit Grégoire, Technologies Coeus inc.
[915]41 * @version    Subversion $Id$
42 * @link       http://www.wifidog.org/
[516]43 */
44
[915]45/**
46 * Load required classes
47 */
[1092]48require_once ('classes/Network.php');
49require_once ('classes/InterfaceElements.php');
[1174]50require_once ('classes/ProfileTemplate.php');
51require_once ('classes/Profile.php');
[1249]52require_once ('classes/Permission.php');
[915]53/**
54 * Abstract a User
55 *
56 * @package    WiFiDogAuthServer
[1421]57 * @author     Benoit Grégoire <benoitg@coeus.ca>
[1031]58 * @copyright  2005-2006 Benoit Grégoire, Technologies Coeus inc.
[915]59 */
[1092]60class User implements GenericObject {
[1249]61    private $_row;
[866]62    private $id;
[1147]63    /** Object cache for the object factory (getObject())*/
64    private static $instanceArray = array();
[402]65
[866]66    /** Instantiate a user object
67     * @param $id The user id of the requested user
68     * @return a User object, or null if there was an error
69     */
[1249]70    public static function &getObject($id) {
[1147]71        if(!isset(self::$instanceArray[$id]))
72        {
[1169]73            self::$instanceArray[$id] = new self($id);
[1147]74        }
75        return self::$instanceArray[$id];
[866]76    }
[745]77
[1092]78    static function createNewObject() {
[866]79        echo "<h1>Use User::createUser() instead</h1>";
80    }
81    /** Get an interface to create a new object.
[1192]82     * @return html markup
83     */
[1092]84    public static function getCreateNewObjectUI() {
[866]85        return null;
86    }
[551]87
[866]88    /** Process the new object interface.
89     *  Will       return the new object if the user has the credentials
90     * necessary (Else an exception is thrown) and and the form was fully
91     * filled (Else the object returns null).
92     * @return the node object or null if no new node was created.
93     */
[1092]94    static function processCreateNewObjectUI() {
[866]95        return self :: createNewObject();
96    }
[974]97    /**
98     * Instantiate the current user
99     *
100     * @return mixed A User object, or null if there was an error
[1192]101
[866]102     */
[1092]103    public static function getCurrentUser() {
104        require_once ('classes/Session.php');
[1127]105        $session = Session::getObject();
[1336]106        $sessCurrentUserId = $session->get(SESS_USER_ID_VAR);
[866]107        $user = null;
[1336]108        if(!empty($sessCurrentUserId)){
109            try {
110                $user = self :: getObject($sessCurrentUserId);
111                //$user = new User($session->get(SESS_USER_ID_VAR));
112            } catch (Exception $e) {
113                /**If any problem occurs, the user should be considered logged out*/
114                $session->set(SESS_USER_ID_VAR, null);
115            }
[866]116        }
117        return $user;
118    }
[745]119
[974]120    /**
121     * Associates the user passed in parameter with the session
122     *
123     * This should NOT be called by anything except the Authenticators
124     *
[1304]125     * @param object $user User a user object, or null
[974]126     *
127     * @return bool True if everything went well setting the session
[1192]128
[866]129     */
[1304]130    public static function setCurrentUser($user) {
131
132        if (get_class($user) == 'User'){
133            $userId = $user->getId();
134            $passwordHash = $user->getPasswordHash();
135        }
136        else {
137            $userId = null;
138            $passwordHash = null;
139        }
140
[1092]141        try {
[1127]142            $session = Session::getObject();
[1304]143            $session->set(SESS_USER_ID_VAR, $userId);
144            $session->set(SESS_PASSWORD_HASH_VAR, $passwordHash);
[866]145            return true;
[1092]146        } catch (Exception $e) {
[866]147            return false;
148        }
149    }
[551]150
[866]151    /** Instantiate a user object
152     * @param $username The username of the user
153     * @param $account_origin Network:  The account origin
[1350]154     * @param &$errMsg An error message will be appended to this if the username is not empty, but the user doesn't exist.
[866]155     * @return a User object, or null if there was an error
156     */
[1249]157    public static function getUserByUsernameAndOrigin($username, Network $account_origin, &$errMsg = null) {
[1127]158        $db = AbstractDb::getObject();
[866]159        $object = null;
[517]160
[877]161        $username_str = $db->escapeString($username);
[1428]162        $comparison = ($account_origin->getUsernamesCaseSensitive()? '=': 'ILike');
[877]163        $account_origin_str = $db->escapeString($account_origin->getId());
[1428]164        $db->execSqlUniqueRes("SELECT user_id FROM users WHERE username {$comparison} '$username_str' AND account_origin = '$account_origin_str'", $user_info, false);
[517]165
[1249]166        if ($user_info != null) {
167            $object = self::getObject($user_info['user_id']);
168        }
169        else if (!empty($username)) {
[1406]170            $errMsg .= sprintf(_("There is no user with username %s"),$username);
[1249]171        }
[866]172        return $object;
173    }
[551]174
[866]175    /** Instantiate a user object
[1409]176     * @param $usernameOrEmail The username or the email address of the user
177     * @param &$errMsg An error message will be appended to this if the username is not empty, but the user doesn't exist.
178     * @return a User object, or null if there was an error
179     */
180    public static function getUserByUsernameOrEmail($usernameOrEmail, &$errMsg = null) {
181        $db = AbstractDb::getObject();
182        $object = null;
183
184        $usernameOrEmail_str = $db->escapeString($usernameOrEmail);
[1428]185        $db->execSqlUniqueRes("SELECT user_id FROM users WHERE username = '$usernameOrEmail_str' OR email ILike '$usernameOrEmail_str'", $user_info, false);
[1409]186
187        if ($user_info != null) {
188            $object = self::getObject($user_info['user_id']);
189        }
190        else if (!empty($usernameOrEmail)) {
191            $errMsg .= sprintf(_("There is no user with username or email %s"),$usernameOrEmail);
192        }
193        return $object;
194    }
195 
196
197   /** Instantiate a user object
[1289]198     * @param $url The OpenId url
199     * @return a User object, or null if none matched
200     */
201    public static function getUserByOpenIdUrl($url) {
202        $db = AbstractDb::getObject();
203        $object = null;
204
205        $url_str = $db->escapeString($url);
206        $db->execSqlUniqueRes("SELECT user_id FROM users WHERE open_id_url = '$url_str'", $user_rows, false);
207
208        if ($user_rows != null) {
209            $object = self::getObject($user_rows[0]['user_id']);
210        }
211        return $object;
212    }
213    /** Instantiate a user object
[866]214     * @param $email The email of the user
215     * @param $account_origin Network:  The account origin
216     * @return a User object, or null if there was an error
217     */
[1092]218    public static function getUserByEmailAndOrigin($email, Network $account_origin) {
[1127]219        $db = AbstractDb::getObject();
[866]220        $object = null;
[402]221
[877]222        $email_str = $db->escapeString($email);
223        $account_origin_str = $db->escapeString($account_origin->getId());
[1428]224        $db->execSqlUniqueRes("SELECT user_id FROM users WHERE email ILike '$email_str' AND account_origin = '$account_origin_str'", $user_info, false);
[530]225
[866]226        if ($user_info != null)
[1169]227        $object = self::getObject($user_info['user_id']);
[866]228        return $object;
229    }
[530]230
[866]231    /** Returns the hash of the password suitable for storing or comparing in the database.  This hash is the same one as used in NoCat
232     * @return The 32 character hash.
233     */
[1092]234    public static function passwordHash($password) {
[866]235        /**
236         * utf8_decode is used for backward compatibility with old passwords
237         * containing special characters.
238         * Conversion from UTF-8 to ISO-8859-1 is done to match the MD5 hash
239         */
240        return base64_encode(pack("H*", md5(utf8_decode($password))));
241    }
[402]242
[866]243    /** Create a new User in the database
244     * @param $id The id to be given to the new user
245     * @return the newly created User object, or null if there was an error
246     */
[1092]247    static function createUser($id, $username, Network $account_origin, $email, $password) {
[1127]248        $db = AbstractDb::getObject();
[408]249
[866]250        $object = null;
[877]251        $id_str = $db->escapeString($id);
252        $username_str = $db->escapeString($username);
253        $account_origin_str = $db->escapeString($account_origin->getId());
254        $email_str = $db->escapeString($email);
[717]255
[877]256        $password_hash = $db->escapeString(User :: passwordHash($password));
[866]257        $status = ACCOUNT_STATUS_VALIDATION;
258        $token = User :: generateToken();
[402]259
[1123]260        $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',CURRENT_TIMESTAMP)");
[402]261
[1147]262        $object = self::getObject($id);
[866]263        return $object;
264    }
[768]265
[1092]266    /*    public static function purgeUnvalidatedUsers($days_since_creation)
[1169]267     {
268     $db = AbstractDb::getObject();
269     $days_since_creation = $db->escapeString($days_since_creation);
[768]270
[1169]271     //$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',CURRENT_TIMESTAMP)");
272     }*/
273
[866]274    /** @param $object_id The id of the user */
[1092]275    function __construct($object_id) {
[1127]276        $db = AbstractDb::getObject();
[880]277        $this->mDb = & $db;
[877]278        $object_id_str = $db->escapeString($object_id);
[866]279        $sql = "SELECT * FROM users WHERE user_id='{$object_id_str}'";
[877]280        $db->execSqlUniqueRes($sql, $row, false);
[1092]281        if ($row == null) {
[866]282            throw new Exception(sprintf(_("User id: %s could not be found in the database"), $object_id_str));
283        }
[1249]284        $this->_row = $row;
[866]285        $this->id = $row['user_id'];
286    } //End class
[402]287
[1092]288    function getId() {
[866]289        return $this->id;
290    }
[745]291
[866]292    /** Gets the Network to which the user belongs
293     * @return Network object (never returns null)
294     */
[1092]295    public function getNetwork() {
[1249]296        return Network :: getObject($this->_row['account_origin']);
[866]297    }
[402]298
[866]299    /** Get a user display suitable for a user list.  Will include link to the user profile. */
[1092]300    function getListUI() {
[866]301        $html = '';
[1092]302        if ($this->isSplashOnlyUser()) {
303            $html .= _("Guest");
[1090]304        }
[1093]305        else {
[1192]306            $nickname = null;
307            $avatar = null;
308            $profile = $this->getAllProfiles();
309            if(!empty($profile)) {
310                // Use the first profile for now
311                $profile = $profile[0];
312
313                $nickname_fields = $profile->getFieldsBySemanticId("foaf:nick");
314                // Try using the first nickname available
315                if(!empty($nickname_fields)) {
316                    $nickname_content = $nickname_fields[0]->getContentField();
317                    if(!empty($nickname_content)) {
318                        // Force non-verbose output
319                        $str = $nickname_content->__toString(false);
320                        if(!empty($str))
321                        $nickname = $str;
322                    }
323                }
324
325                $avatar_fields = $profile->getFieldsBySemanticId("foaf:img");
326                // Try using the first avatar available
327                if(!empty($avatar_fields)) {
328                    $avatar_content = $avatar_fields[0]->getContentField();
329                    if(!empty($avatar_content)) {
330                        $avatar = $avatar_content->getUserUI();
331                    }
332                }
333            }
[1226]334
335
336
[1192]337            // Display the avatar
338            if(empty($avatar))
339            $html .= Avatar::getDefaultUserUI();
[1177]340            else
[1192]341            $html .= $avatar;
[1226]342
[1192]343            // Display the nickname or the username
[1194]344            $profiles=$this->getAllProfiles();
345            if($profiles){
[1289]346                $html .= "<a href='".BASE_URL_PATH."profile/?user_id=".$this->getId()."' title='".htmlentities(_("View this user's profile."), ENT_QUOTES)."' class='user_nickname'>";
[1194]347            }
[1192]348            if(empty($nickname))
349            $html .= $this->getUserName();
350            else
351            $html .= $nickname;
[1194]352            if($profiles){
353                $html .= "</a>\n";
354            }
[1202]355            $profileTemplates = $this->getNetwork()->getAllProfileTemplates();
[1226]356            /*if($this==User::getCurrentUser() && $profileTemplates) {
[1249]357             $html .= "<div class='user_edit_profile_link'><br/>(<a href='".BASE_SSL_PATH."admin/generic_object_admin.php?object_id=".$this->getId()."&object_class=User&action=edit'>"._("edit profile")."</a>)</div>";
358             }*/
[1192]359
[1093]360        }
[866]361        return $html;
362    }
[551]363
[1289]364    function getOpenIdUrl() {
365        return $this->_row['open_id_url'];
366    }
[1304]367
[1092]368    function getUsername() {
[1249]369        return $this->_row['username'];
[866]370    }
[1092]371
372    /** Set the user's username
[1192]373     * @param $value The new value
374     * @return true on success, false on failure
375     * @throws exception if the user tries to set a duplicate username
376     */
[1035]377    function setUsername($value) {
378        $retval = true;
379        if ($value != $this->getUsername()) {
[1127]380            $db = AbstractDb::getObject();
[1428]381            $otherUser = User::getUserByUsernameAndOrigin($value, $this->getNetwork());
382            if (!is_null($otherUser)) {
383                throw new exception(sprintf(_("Sorry, the username %s is not available"), $value));
384            }
[1035]385            $value = $db->escapeString($value);
[1092]386            $retval = @ $db->execSqlUpdate("UPDATE users SET username = '{$value}' WHERE user_id='{$this->id}'", false);
[1035]387            $this->refresh();
388        }
389        return $retval;
390    }
[1192]391
[1174]392    /** Add profile template to this user */
393    public function addProfile(Profile $profile) {
394        $db = AbstractDb::getObject();
395        $profile_id = $db->escapeString($profile->getId());
396        $sql = "INSERT INTO user_has_profiles (user_id, profile_id) VALUES ('$this->id','$profile_id')";
397        return $db->execSqlUpdate($sql, false);
398    }
[402]399
[1174]400    /** Remove profile template from this user */
401    public function removeProfile(Profile $profile) {
402        $db = AbstractDb::getObject();
403        $profile_id = $db->escapeString($profile->getId());
404        $sql = "DELETE FROM user_has_profiles WHERE user_id='$this->id' AND profile_id='$profile_id'";
405        return $db->execSqlUpdate($sql, false);
406    }
[1192]407
[1174]408    /**Get an array of all Profiles linked to this user
[1192]409     * @return an array of Profile or an empty arrray */
[1174]410    public function getAllProfiles() {
411        $db = AbstractDb::getObject();
412        $retval = array ();
413        $profile_rows = null;
414        $sql = "SELECT profile_id FROM user_has_profiles NATURAL JOIN profiles WHERE user_id='$this->id' ORDER BY creation_date";
415        $db->execSql($sql, $profile_rows, false);
416        if ($profile_rows != null) {
417            foreach ($profile_rows as $profile_row) {
418                $retval[] = Profile :: getObject($profile_row['profile_id']);
419            }
420        }
421        return $retval;
422    }
423
[1092]424    public function getEmail() {
[1249]425        return $this->_row['email'];
[866]426    }
[402]427
[1092]428    public function setEmail($email) {
429        $email_str = $this->mDb->escapeString($email);
430        if (!($update = $this->mDb->execSqlUpdate("UPDATE users SET email='{$email_str}' WHERE user_id='{$this->id}'"))) {
431            throw new Exception(_("Could not update email address."));
432        }
[1249]433        $this->_row['email'] = $email; // unescaped
[898]434    }
[745]435
[1092]436    function setIsInvisible($value) {
437        $retval = true;
438        if ($value != $this->isAdvertised()) {
[1127]439            $db = AbstractDb::getObject();
[1092]440            $value ? $value = 'TRUE' : $value = 'FALSE';
441            $retval = $db->execSqlUpdate("UPDATE users SET is_invisible = {$value} WHERE user_id = '{$this->getId()}'", false);
442            $this->refresh();
443        }
444        return $retval;
[898]445    }
[745]446
[1092]447    public function isInvisible() {
[1249]448        return (($this->_row['is_invisible'] == 't') ? true : false);
[898]449    }
450
451    /**What locale (language) does the user prefer? */
[1092]452    public function getPreferedLocale() {
[1127]453        $session = Session::getObject();
[1249]454        $locale = $this->_row['prefered_locale'];
[1092]455        if (empty ($locale) && !empty ($session))
[1169]456        $locale = $session->get(SESS_LANGUAGE_VAR);
[1092]457        if (empty ($locale))
[1169]458        $locale = DEFAULT_LANG;
[1092]459        return $locale;
[866]460    }
[545]461
[1092]462    public function setPreferedLocale($locale) {
463        $locale_str = $this->mDb->escapeString($locale);
464        if (!($update = $this->mDb->execSqlUpdate("UPDATE users SET prefered_locale='{$locale_str}' WHERE user_id='{$this->id}'"))) {
465            throw new Exception(_("Could not update username locale."));
466        }
[1249]467        $this->_row['prefered_locale'] = $locale;
[898]468    }
469
[866]470    /** get the hashed password stored in the database */
[1092]471    public function getPasswordHash() {
[1249]472        return $this->_row['pass'];
[866]473    }
[402]474
[866]475    /** Get the account status.
476     * @return Possible values are listed in common.php
[1192]477     */
[1092]478    function getAccountStatus() {
[1249]479        return $this->_row['account_status'];
[866]480    }
[402]481
[1092]482    function setAccountStatus($status) {
[1127]483        $db = AbstractDb::getObject();
[1170]484        if($status != $this->getAccountStatus()) {
485            $status_str = $db->escapeString($status);
486            if (!($update = $db->execSqlUpdate("UPDATE users SET account_status='{$status_str}' WHERE user_id='{$this->id}'"))) {
487                throw new Exception(_("Could not update status."));
488            }
[1249]489            $this->_row['account_status'] = $status;
[866]490        }
491    }
[402]492
[866]493    /** Is the user valid?  Valid means that the account is validated or hasn't exhausted it's validation period.
494     $errmsg: Returs the reason why the account is or isn't valid */
[1092]495    function isUserValid(& $errmsg = null) {
[1285]496        global $account_status_to_text;
[1127]497        $db = AbstractDb::getObject();
[866]498        $retval = false;
499        $account_status = $this->getAccountStatus();
[1092]500        if ($account_status == ACCOUNT_STATUS_ALLOWED) {
[866]501            $retval = true;
[1092]502        } else
[1169]503        if ($account_status == ACCOUNT_STATUS_VALIDATION) {
504            $sql = "SELECT CASE WHEN ((CURRENT_TIMESTAMP - reg_date) > networks.validation_grace_time) THEN true ELSE false END AS validation_grace_time_expired, EXTRACT(EPOCH FROM networks.validation_grace_time) as validation_grace_time FROM users  JOIN networks ON (users.account_origin = networks.network_id) WHERE (user_id='{$this->id}')";
505            $db->execSqlUniqueRes($sql, $user_info, false);
[402]506
[1169]507            if ($user_info['validation_grace_time_expired'] == 't') {
[1220]508                $errmsg = sprintf(_("Sorry, your %.0f 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."), $user_info['validation_grace_time']/60);
[1169]509                $retval = false;
[1092]510            } else {
[1169]511                $errmsg = _("Your account is currently valid.");
512                $retval = true;
[866]513            }
[1169]514        } else {
515            $errmsg = _("Sorry, your account is not valid: ") . $account_status_to_text[$account_status];
516            $retval = false;
517        }
[866]518        return $retval;
519    }
[402]520
[1249]521    public function DEPRECATEDisSuperAdmin() {
[1127]522        $db = AbstractDb::getObject();
[866]523        //$this->session->dump();
[553]524
[1249]525        $db->execSqlUniqueRes("SELECT * FROM users JOIN server_stakeholders USING (user_id) WHERE (users.user_id='$this->id')", $user_info, false);
[1092]526        if (!empty ($user_info)) {
[866]527            return true;
[1092]528        } else {
[866]529            return false;
530        }
[608]531
[866]532    }
[608]533
[1092]534    /** Is this user the Splash Only User() */
535    public function isSplashOnlyUser() {
[1249]536        if ($this->_row['username'] == "SPLASH_ONLY_USER") {
[1092]537            return true;
538        } else {
539            return false;
540        }
541    }
542
543    function getValidationToken() {
[1249]544        return $this->_row['validation_token'];
[866]545    }
[402]546
[1351]547    /** Retrieves the connection history necessary for abuse control
548
549    * @return false if abuse control is disabled */
550
551    static function getAbuseControlConnectionHistory($user = null, $mac = null, $node = null) {
552        if (!$user) {
553            $user = User::getCurrentUser();
554        }
555        if (!$node) {
556            $node = Node::getCurrentNode();//Maybe this should be getCurrentRealNode, but it would make debuging harder
557        }
558        $network = $node->getNetwork();
559
560        $db = AbstractDb::getObject();
561
562        if ($network->getConnectionLimitWindow()) {
563            //$sql =  " SELECT * from connections \n";//For debugging
564            $sql =  " SELECT \n";
565            $sql .= " SUM (incoming+outgoing) AS network_total_bytes, \n";
566            $sql .= " SUM (CASE WHEN node_id = '".$node->getId()."' THEN (incoming+outgoing) END) AS node_total_bytes, \n";
[1415]567            $sql .= " SUM (COALESCE(timestamp_out,last_updated) - timestamp_in) AS network_duration, \n";
[1413]568            $sql .= " SUM (CASE WHEN node_id = '".$node->getId()."' THEN (COALESCE(timestamp_out,last_updated) - timestamp_in) END) AS node_duration \n";//For real //The coalesce is to make sure the substraction returns a value for active conections, since active connections do not yet have a timestamp_out.  Do NOT coalesce with CURRENT_TIMESTAMP, it could cause real problems for users in case of gateway crash.
[1351]569            $sql .= " FROM connections \n";//For real
570            $sql .= " JOIN nodes USING (node_id) \n";
571            $sql .= " JOIN networks USING (network_id) \n";
572            $sql .= " JOIN tokens ON (tokens.token_id = connections.token_id) \n";
573            $sql .= " WHERE 1=1 \n";
574
575            if ($mac) {
576                //Catch some cheaters
577                $mac = $db->escapeString($mac);
578                $mac_sql_or = " OR connections.user_mac = '$mac' ";
579            }
580            else {
581                $mac_sql_or = null;
582            }
583            $sql .= " AND (connections.user_id = '".$user->getId()."' $mac_sql_or ) \n";
584
585            $sql .= " AND (timestamp_in > CURRENT_TIMESTAMP - networks.connection_limit_window OR tokens.token_status = '".TOKEN_INUSE."')";  //Get every connection within the window plus any still active connection, even if it started before the window
586
587            $subselect = $sql;
588            $sql =  " SELECT subselect.*, \n";
589            $sql .= " networks.connection_limit_window, \n";
590            $sql .= " networks.connection_limit_network_max_total_bytes, COALESCE(network_total_bytes>networks.connection_limit_network_max_total_bytes, false) AS network_total_bytes_exceeded_limit, \n";
591            $sql .= " networks.connection_limit_node_max_total_bytes, COALESCE(node_total_bytes>networks.connection_limit_node_max_total_bytes, false) AS node_total_bytes_exceeded_limit, \n";
592            $sql .= " networks.connection_limit_network_max_usage_duration, COALESCE(network_duration>networks.connection_limit_network_max_usage_duration, false) AS network_duration_exceeded_limit, \n";
593            $sql .= " networks.connection_limit_node_max_usage_duration, COALESCE(node_duration>networks.connection_limit_node_max_usage_duration, false) AS node_duration_exceeded_limit \n";
594
595            $sql .= " FROM ($subselect) AS subselect JOIN networks ON (network_id = '".$network->getId()."')";
596
597            $db->execSqlUniqueRes($sql, $connection_limits_report, false);
598            return $connection_limits_report;
599        }
600        else {
601            return false;
602        }
603    }
604
605    /** Takes the same paramaters as getAbuseControlConnectionHistory, and tells you if the abuse limits are busted
606
607    * @return false if abuse control respected, else a string containing the reason(s) for the bust  */
608
609    static function isAbuseControlViolated($user = null, $mac = null, $node = null) {
610        $retval = false;
611        $abuseControlReport = self::getAbuseControlConnectionHistory($user, $mac, $node);
612        if($abuseControlReport) {
[1355]613            if (!$user) {
614                $user = User::getCurrentUser();
615            }
[1351]616            //pretty_print_r($abuseControlReport);
[1355]617            if($node && Security::hasPermission(Permission::P('NODE_PERM_BYPASS_DYNAMIC_ABUSE_CONTROL'), $node, $user)) {
618                $retval = false;
[1351]619            }
[1355]620            else {
621                require_once('classes/Content/UIAllowedBandwidth/UIAllowedBandwidth.php');
622                if($abuseControlReport['network_total_bytes_exceeded_limit']=='t') {
623                    $retval .= sprintf(_("During the last %s period, you transfered %s bytes throughout the network, which exceeds the %s bytes limit for the entire network."), $abuseControlReport['connection_limit_window'], UIAllowedBandwidth::formatSize($abuseControlReport['network_total_bytes']), UIAllowedBandwidth::formatSize($abuseControlReport['connection_limit_network_max_total_bytes']));
624                }
625                if($abuseControlReport['node_total_bytes_exceeded_limit']=='t') {
626                    $retval .= sprintf(_("During the last %s period, you transfered %s bytes at this node, which exceeds the %s bytes limit for this node."), $abuseControlReport['connection_limit_window'], UIAllowedBandwidth::formatSize($abuseControlReport['node_total_bytes']), UIAllowedBandwidth::formatSize($abuseControlReport['connection_limit_node_max_total_bytes']));
627                }
628                if($abuseControlReport['network_duration_exceeded_limit']=='t') {
629                    $retval .= sprintf(_("During the last %s period, you were online for a duration of %s throughout the network, which exceeds the %s limit for the entire network."), $abuseControlReport['connection_limit_window'], $abuseControlReport['network_duration'], $abuseControlReport['connection_limit_network_max_usage_duration']);
630                }
631                if($abuseControlReport['node_duration_exceeded_limit']=='t') {
632                    $retval .= sprintf(_("During the last %s period, you were online for a duration of %s at this node, which exceeds the %s limit for this node."), $abuseControlReport['connection_limit_window'], $abuseControlReport['node_duration'], $abuseControlReport['connection_limit_node_max_usage_duration']);
633                }
[1351]634            }
635        }
636        return $retval;
637    }
[866]638    /** Generate a token in the connection table so the user can actually use the internet
639    @return true on success, false on failure
640    */
[1434]641    function generateConnectionToken($mac = null) {
[1092]642        if ($this->isUserValid()) {
[1127]643            $db = AbstractDb::getObject();
644            $session = Session::getObject();
[745]645
[866]646            $token = self :: generateToken();
[1092]647            if ($_SERVER['REMOTE_ADDR']) {
[877]648                $node_ip = $db->escapeString($_SERVER['REMOTE_ADDR']);
[866]649            }
[1434]650           
[1135]651            if ($session && $node_ip && $session->get(SESS_NODE_ID_VAR)) {
652                //echo "$session && $node_ip && {$session->get(SESS_NODE_ID_VAR)}";
653                $node_id = $db->escapeString($session->get(SESS_NODE_ID_VAR));
[1434]654                $abuseControlFault = User::isAbuseControlViolated($this, $mac, Node::getObject($node_id));
[1351]655                if($abuseControlFault) {
656                    throw new Exception ($abuseControlFault);
657                }
[1434]658                $mac = (is_null($mac)?'': $db->escapeString($mac));
[1350]659                /*
660                 * Delete all unused tokens for this user, so we don't fill the database
661                 * with them
662                 */
663                $sql = "DELETE FROM connections USING tokens "."WHERE tokens.token_id=connections.token_id AND token_status='".TOKEN_UNUSED."' AND user_id = '".$this->getId()."';\n";
664                // TODO:  Try to find a reusable token before creating a brand new one!
[1351]665
[1350]666                $sql .= "INSERT INTO tokens (token_owner, token_issuer, token_id, token_status) VALUES ('" . $this->getId() . "', '" . $this->getId() . "', '$token', '" . TOKEN_UNUSED . "');\n";
[1434]667                $sql .= "INSERT INTO connections (user_id, token_id, timestamp_in, node_id, node_ip, last_updated, user_mac) VALUES ('" . $this->getId() . "', '$token', CURRENT_TIMESTAMP, '$node_id', '$node_ip', CURRENT_TIMESTAMP, '$mac')";
[1350]668                $db->execSqlUpdate($sql, false);
[866]669                $retval = $token;
[1351]670            }
671            else {
672                $retval = false;
673            }
674        }
675        else {
[1169]676            $retval = false;
[866]677        }
678        return $retval;
679    }
[402]680
[1092]681    function setPassword($password) {
[1127]682        $db = AbstractDb::getObject();
[551]683
[866]684        $new_password_hash = User :: passwordHash($password);
[1169]685        if (empty($password)) {
686            throw new Exception(_("Password cannot be empty."));
687        }
688
[1092]689        if (!($update = $db->execSqlUpdate("UPDATE users SET pass='$new_password_hash' WHERE user_id='{$this->id}'"))) {
[866]690            throw new Exception(_("Could not change user's password."));
691        }
[1249]692        $this->_row['pass'] = $password;
[866]693    }
[402]694
[1092]695    function getAccountOrigin() {
[1249]696        return $this->_row['account_origin'];
[866]697    }
[608]698
[866]699    /** Return all the users
700     */
[1092]701    static function getAllUsers() {
[1127]702        $db = AbstractDb::getObject();
[402]703
[877]704        $db->execSql("SELECT * FROM users", $objects, false);
[1092]705        if ($objects == null) {
[866]706            throw new Exception(_("No users could not be found in the database"));
707        }
708        return $objects;
709    }
[402]710
[1092]711    function sendLostUsername() {
[866]712        $network = $this->getNetwork();
[1321]713        require_once ('classes/Mail.php');
[866]714        $mail = new Mail();
715        $mail->setSenderName(_("Registration system"));
716        $mail->setSenderEmail($network->getValidationEmailFromAddress());
717        $mail->setRecipientEmail($this->getEmail());
[1092]718        $mail->setMessageSubject($network->getName() . _(" lost username request"));
719        $mail->setMessageBody(_("Hello,\nYou have requested that the authentication server send you your username:\nUsername: ") . $this->getUsername() . _("\n\nHave a nice day,\nThe Team"));
[866]720        $mail->send();
721    }
[402]722
[1092]723    function sendValidationEmail() {
724        if ($this->getAccountStatus() != ACCOUNT_STATUS_VALIDATION) {
[866]725            throw new Exception(_("The user is not in validation period."));
[1092]726        } else {
727            if ($this->getValidationToken() == "") {
[866]728                throw new Exception(_("The validation token is empty."));
[1092]729            } else {
[866]730                $network = $this->getNetwork();
[1321]731                require_once ('classes/Mail.php');
[866]732                $mail = new Mail();
733                $mail->setSenderName(_("Registration system"));
734                $mail->setSenderEmail($network->getValidationEmailFromAddress());
735                $mail->setRecipientEmail($this->getEmail());
[1092]736                $mail->setMessageSubject($network->getName() . _(" new user validation"));
737                $url = BASE_SSL_PATH . "validate.php?user_id=" . $this->getId() . "&token=" . $this->getValidationToken();
738                $mail->setMessageBody(_("Hello,\nPlease follow the link below to validate your account.\n") . $url . _("\n\nThank you,\nThe Team."));
[866]739                $mail->send();
740            }
741        }
742    }
[402]743
[1092]744    function sendLostPasswordEmail() {
[866]745        $network = $this->getNetwork();
746        $new_password = $this->randomPass();
747        $this->setPassword($new_password);
[1321]748        require_once ('classes/Mail.php');
[866]749        $mail = new Mail();
750        $mail->setSenderName(_("Registration system"));
751        $mail->setSenderEmail($network->getValidationEmailFromAddress());
752        $mail->setRecipientEmail($this->getEmail());
[1092]753        $mail->setMessageSubject($network->getName() . _(" new password request"));
754        $mail->setMessageBody(_("Hello,\nYou have requested that the authentication server send you a new password:\nUsername: ") . $this->getUsername() . _("\nPassword: ") . $new_password . _("\n\nHave a nice day,\nThe Team"));
[866]755        $mail->send();
756    }
[402]757
[1092]758    public static function emailExists($id) {
[1127]759        $db = AbstractDb::getObject();
[877]760        $id_str = $db->escapeString($id);
[866]761        $sql = "SELECT * FROM users WHERE email='{$id_str}'";
[877]762        $db->execSqlUniqueRes($sql, $row, false);
[866]763        return $row;
764    }
[516]765
[1092]766    public static function randomPass() {
[866]767        $rand_pass = ''; // makes sure the $pass var is empty.
[1092]768        for ($j = 0; $j < 3; $j++) {
769            $startnend = array (
[1192]770            'b',
771            'c',
772            'd',
773            'f',
774            'g',
775            'h',
776            'j',
777            'k',
778            'l',
779            'm',
780            'n',
781            'p',
782            'q',
783            'r',
784            's',
785            't',
786            'v',
787            'w',
788            'x',
789            'y',
790            'z',
[1169]791
[1192]792            );
793            $id = array (
794            'a',
795            'e',
796            'i',
797            'o',
798            'u',
799            'y',
[516]800
[1192]801            );
802            $count1 = count($startnend) - 1;
803            $count2 = count($id) - 1;
[1169]804
[1192]805            for ($i = 0; $i < 3; $i++) {
806                if ($i != 1) {
807                    $rand_pass .= $startnend[rand(0, $count1)];
808                } else {
809                    $rand_pass .= $id[rand(0, $count2)];
[866]810                }
[1192]811            }
[866]812        }
813        return $rand_pass;
814    }
[516]815
[1092]816    public static function generateToken() {
[866]817        return md5(uniqid(rand(), 1));
818    }
[516]819
[986]820    /**
821     * Get an interface to add a user to a list
822     *
823     * @param string $user_prefix      A identifier provided by the programmer
824     *                                 to recognise it's generated HTML form
825     * @param string $add_button_name  Name of optional "add" button
826     * @param string $add_button_value Value of optional "add" button
827     *
828     * @return string HTML markup
[1192]829
[986]830     */
[1092]831    public static function getSelectUserUI($user_prefix, $add_button_name = null, $add_button_value = null) {
[1127]832        $db = AbstractDb::getObject();
[1249]833        $networkSelector = Network :: getSelectUI($user_prefix);
[986]834        // Check if we need to add an "add" button
835        if ($add_button_name && $add_button_value) {
[1169]836            $userSelector = _("Username") . ": " . InterfaceElements :: generateInputText("select_user_" . $user_prefix . "_username", "", "", "input_text", array (
[1192]837            "onkeypress" => "if ((event.which ? event.which : event.keyCode) == 13) {form.$add_button_name.click() }"
838            ));
839            $userSelector .= InterfaceElements :: generateInputSubmit($add_button_name, $add_button_value);
[986]840        } else {
[1409]841            $userSelector = _("Search for Username or Email Address") . ": " . InterfaceElements :: generateInputText("select_user_" . $user_prefix . "_username");
[986]842        }
[1409]843        $html = "<div class='user_select_user_ui_container'>".$networkSelector . "<br>" . $userSelector . "</div>\n";
[1169]844        return $html;
[866]845    }
[608]846
[866]847    /** Get the selected user, IF one was selected and is valid
848     * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
[1249]849     * @param &$errMsg An error message will be appended to this is the username is not empty, but the user doesn't exist.
[866]850     * @return the User object, or null if the user is invalid or none was selected
851     */
[1249]852    static function processSelectUserUI($user_prefix, &$errMsg) {
[866]853        $object = null;
[1092]854        try {
[1249]855            $network = Network :: processSelectUI($user_prefix);
[866]856            $name = "select_user_{$user_prefix}_username";
[1092]857            if (!empty ($_REQUEST[$name])) {
[866]858                $username = $_REQUEST[$name];
[1409]859                return self :: getUserByUsernameOrEmail($username, $errMsg);
[1092]860            } else
[1169]861            return null;
[1092]862        } catch (Exception $e) {
[866]863            return null;
864        }
865    }
[551]866
[1092]867    public function getAdminUI() {
[1127]868        $db = AbstractDb::getObject();
[1092]869        $currentUser = self :: getCurrentUser();
[1169]870        $userPreferencesItems = array();
[1170]871        $finalHtml = '';
[1316]872        if(Security::hasPermission(Permission::P('NETWORK_PERM_VIEW_STATISTICS'), $this->getNetwork())) {
[1170]873            /* Statistics */
[1169]874            $content = "<a href='".BASE_SSL_PATH."admin/stats.php?Statistics=".$this->getNetwork()->getId()."&distinguish_users_by=user_id&stats_selected_users=".$this->getUsername()."&UserReport=on&user_id=".$this->getId()."&action=generate'>"._("Get user statistics")."</a>\n";
[1170]875            $administrationItems[] = InterfaceElements::genSectionItem($content);
876
877            /* Account status */
878            $title = _("Account Status");
879            $help = _("Note that Error is for internal use only");
880            $name = "user_" . $this->getId() . "_accountstatus";
881            global $account_status_to_text;
882            $content = FormSelectGenerator::generateFromKeyLabelArray($account_status_to_text, $this->getAccountStatus(), $name, null, false);
883            $administrationItems[] = InterfaceElements::genSectionItem($content, $title, $help);
884
885            $finalHtml .= InterfaceElements::genSection($administrationItems, _("Administrative options"));
[1169]886        }
[1174]887
[1316]888        if (($this == $currentUser && !$this->isSplashOnlyUser() )|| Security::hasPermission(Permission::P('NETWORK_PERM_EDIT_ANY_USER'), $this->getNetwork())) {
[1170]889            /* Username */
[1169]890            $title = _("Username");
[1092]891            $name = "user_" . $this->getId() . "_username";
[1177]892            $content = "<input type='text' name='$name' value='" . htmlentities($this->getUsername()) . "' size=30><br/>\n";
[1409]893            $content .= _("Be careful when changing this: it's the username you use to log in!");
[1169]894            $userPreferencesItems[] = InterfaceElements::genSectionItem($content, $title);
[1192]895
[1409]896
897            /* Email */
898            $title = _("Email");
899            $name = "email_" . $this->getId() . "_email";
900            $content = "<input type='text' name='$name' disabled='disabled' value='" . htmlentities($this->getEmail()) . "' size=30><br/>\n";
901            $content .= _("If you wish to change this address, please Email Support!");
902            $userPreferencesItems[] = InterfaceElements::genSectionItem($content, $title);
903
904
905
[1174]906            /* Change password */
[1192]907            $changePasswordItems=array();
908            if($this == $currentUser) {//Don't enter the old password if changing password for another user
909                $title = _("Your current password");
910                $name = "user_" . $this->getId() . "_oldpassword";
911                $content = "<input type='password' name='$name' size='20'>\n";
912                $changePasswordItems[] = InterfaceElements::genSectionItem($content, $title);
913            }
914
915            $title = _("Your new password");
916            $name = "user_" . $this->getId() . "_newpassword";
917            $content = "<input type='password' name='$name' size='20'>\n";
918            $changePasswordItems[] = InterfaceElements::genSectionItem($content, $title);
919
920            $title = _("Your new password (again)");
921            $name = "user_" . $this->getId() . "_newpassword_again";
922            $content = "<input type='password' name='$name' size='20'>\n";
923            $changePasswordItems[] = InterfaceElements::genSectionItem($content, $title);
924
925            $userPreferencesItems[] = InterfaceElements::genSection($changePasswordItems, _("Change my password"));
926
927            $finalHtml .= InterfaceElements::genSection($userPreferencesItems, _("User preferences"), false, false, get_class($this));
928
[1174]929            //N.B: For now, let pretend we have only one profile per use...
930            $profiles = $this->getAllProfiles();
931            $current_profile = null;
[1192]932            if(!empty($profiles)) {
933                $current_profile = $profiles[0];
[1174]934            }
[1192]935
[1174]936            if($current_profile != null) {
[1192]937                $finalHtml .= $current_profile->getAdminUI();
938                $name = "user_" . $this->getId() . "_delete_profile_".$current_profile->getId();
939                $value = _("Completely delete my public profile");
940                $finalHtml .= "<div class='admin_element_tools'>";
941                $finalHtml .= '<input type="submit" class="submit" name="' . $name . '" value="' . $value . '">';
942                $finalHtml .= "</div>";
[1174]943            }
[1194]944            else {                    // Get the list of profile templates for the users' network
945                $profile_templates = ProfileTemplate::getAllProfileTemplates($this->getNetwork());
946                if(!empty($profile_templates)) {
947                    $name = "user_" . $this->getId() . "_add_profile";
948                    $value = _("Create my public profile");
949                    $finalHtml .= "<div class='admin_element_tools'>";
950                    $finalHtml .= '<input type="submit" class="submit" name="' . $name . '" value="' . $value . '">';
951                    $finalHtml .= "</div>";
952                }
[1192]953            }
[1170]954        }
[1169]955
956        return $finalHtml;
[866]957    }
[745]958
[1092]959    public function processAdminUI() {
[1127]960        $db = AbstractDb::getObject();
[1092]961        $currentUser = self :: getCurrentUser();
[1316]962        if (Security::hasPermission(Permission::P('NETWORK_PERM_EDIT_ANY_USER'), $this->getNetwork())) {
[1170]963            /* Account status */
964            $name = "user_" . $this->getId() . "_accountstatus";
965            $status = FormSelectGenerator::getResult($name, null);
966            $this->setAccountStatus($status);
967        }
968
[1316]969        if ($this == $currentUser || Security::requirePermission(Permission::P('NETWORK_PERM_EDIT_ANY_USER'), $this->getNetwork())) {
[1170]970            /* Username */
[1092]971            $name = "user_" . $this->getId() . "_username";
972            $this->setUsername($_REQUEST[$name]);
[1192]973
[1170]974            /* Change password */
[1169]975            $nameOldpassword = "user_" . $this->getId() . "_oldpassword";
976            $nameNewpassword = "user_" . $this->getId() . "_newpassword";
977            $nameNewpasswordAgain = "user_" . $this->getId() . "_newpassword_again";
[1170]978            if($_REQUEST[$nameNewpassword]!=null){
979                if ($this == $currentUser && $this->getPasswordHash() != User::passwordHash($_REQUEST[$nameOldpassword])) {
980                    throw new Exception(_("Wrong password."));
981                }
982                if ($_REQUEST[$nameNewpassword] != $_REQUEST[$nameNewpasswordAgain]){
983                    throw new Exception(_("Passwords do not match."));
984                }
985                $this->setPassword($_REQUEST[$nameNewpassword]);
986            }
[1169]987
[1174]988            // Pretend there is only one
989            $profiles = $this->getAllProfiles();
[1192]990            if(!empty($profiles)) {
991                $current_profile = $profiles[0];
992                if($current_profile != null) {
993                    $current_profile->processAdminUI();
994                    $name = "user_" . $this->getId() . "_delete_profile_".$current_profile->getId();
995                    if(!empty($_REQUEST[$name])) {
996                        $errmsg=null;
997                        $current_profile->delete($errmsg);
998                    }
999                }
1000            }
[1194]1001            else {
1002                $name = "user_" . $this->getId() . "_add_profile";
1003                if(!empty($_REQUEST[$name])) {
1004                    // Get the list of profile templates for the users' network
1005                    $profile_templates = ProfileTemplate::getAllProfileTemplates($this->getNetwork());
1006                    if(!empty($profile_templates)) {
1007                        // Create a blank profile and link it to the user
1008                        $current_profile = Profile::createNewObject(null, $profile_templates[0]);
1009                        $this->addProfile($current_profile);
[1192]1010                    }
[1194]1011                }
1012
[1192]1013            }
[1174]1014
[1092]1015        }
[866]1016    }
[745]1017
[1092]1018    public function delete(& $errmsg) {
[866]1019    }
[745]1020
[1092]1021    public function getUserUI() {
[880]1022        $html = "";
1023        $html .= $this->getRealName();
[745]1024
[880]1025        return $html;
[1092]1026    }
[880]1027
[866]1028    /** Add content to this user ( subscription ) */
[1092]1029    public function addContent(Content $content) {
[1127]1030        $db = AbstractDb::getObject();
[877]1031        $content_id = $db->escapeString($content->getId());
[866]1032        $sql = "INSERT INTO user_has_content (user_id, content_id) VALUES ('$this->id','$content_id')";
[877]1033        $db->execSqlUpdate($sql, false);
[866]1034        return true;
1035    }
[551]1036
[866]1037    /** Remove content from this node */
[1092]1038    public function removeContent(Content $content) {
[1127]1039        $db = AbstractDb::getObject();
[877]1040        $content_id = $db->escapeString($content->getId());
[866]1041        $sql = "DELETE FROM user_has_content WHERE user_id='$this->id' AND content_id='$content_id'";
[877]1042        $db->execSqlUpdate($sql, false);
[866]1043        return true;
1044    }
[608]1045
[866]1046    /**Get an array of all Content linked to this node
[1169]1047     * @return an array of Content or an empty arrray */
[1092]1048    function getAllContent() {
[1127]1049        $db = AbstractDb::getObject();
[866]1050        $retval = array ();
[1174]1051        $content_rows = null;
[866]1052        $sql = "SELECT * FROM user_has_content WHERE user_id='$this->id' ORDER BY subscribe_timestamp";
[877]1053        $db->execSql($sql, $content_rows, false);
[1092]1054        if ($content_rows != null) {
1055            foreach ($content_rows as $content_row) {
[866]1056                $retval[] = Content :: getObject($content_row['content_id']);
1057            }
1058        }
1059        return $retval;
1060    }
[608]1061
[898]1062    /** Reloads the object from the database.  Should normally be called after a set operation */
[1092]1063    protected function refresh() {
1064        $this->__construct($this->id);
[898]1065    }
[1249]1066    /** Menu hook function */
1067    static public function hookMenu() {
1068        $items = array();
1069        $network = Network::getCurrentNetwork();
1070        $server = Server::getServer();
1071        if(Security::hasAnyPermission(array(array(Permission::P('NETWORK_PERM_VIEW_ONLINE_USERS'), $network))))
1072        {
1073            $items[] = array('path' => 'users/online_users',
1074            'title' => _("Online Users"),
1075            'url' => BASE_URL_PATH."admin/online_users.php");
1076        }
1077        if(Security::hasPermission(Permission::P('SERVER_PERM_EDIT_SERVER_CONFIG'), $server))
1078        {
1079            $items[] = array('path' => 'users/import_nocat',
1080            'title' => _("Import NoCat user database"),
1081            'url' => BASE_URL_PATH."admin/import_user_database.php"
[1304]1082            );
[1249]1083        }
[1304]1084        if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_EDIT_ANY_USER')))
[1249]1085        {
1086            $items[] = array('path' => 'users/user_manager',
1087            'title' => _("User manager"),
1088            'url' => BASE_URL_PATH."admin/user_log.php"
[1304]1089            );
[1249]1090        }
[1304]1091        if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_VIEW_STATISTICS')))
[1249]1092        {
1093            $items[] = array('path' => 'users/statistics',
1094            'title' => _("Statistics"),
1095            'url' => BASE_URL_PATH."admin/stats.php"
[1304]1096            );
[1249]1097        }
1098        $items[] = array('path' => 'users',
1099        'title' => _('User administration'),
1100        'type' => MENU_ITEM_GROUPING);
1101        return $items;
1102    }
[898]1103
[1018]1104    /** Set Smarty template values.  Standardization routine. */
[1092]1105    public static function assignSmartyValues($smarty, $user = null) {
1106        if (!$user)
[1169]1107        $user = User :: getCurrentUser();
[1192]1108        $session = Session :: getObject();
1109        $smarty->assign('userOriginallyRequestedURL', $session ? $session->get(SESS_ORIGINAL_URL_VAR) : '');
[1035]1110        $smarty->assign('userId', $user ? $user->getId() : '');
[1196]1111        $smarty->assign('userName', $user ? $user->getUsername() : '');
[1092]1112        /**
1113         * Define user security levels for the template
1114         *
1115         * These values are used in the default template of WiFoDog but could be
1116         * used in a customized template to restrict certain links to specific
[1192]1117         * user access levels.  Note however that they will all be deprecateb by the
1118         * new roles system.
[1092]1119         */
[1157]1120        $smarty->assign('userIsValid', $user && !$user->isSplashOnlyUser() ? true : false);
[1249]1121        $smarty->assign('userDEPRECATEDisSuperAdmin', $user && $user->DEPRECATEDisSuperAdmin());
[1018]1122
[1249]1123        if (isset ($_REQUEST['debug_request']) && ($user && $user->DEPRECATEDisSuperAdmin())) {
[1018]1124            // Tell Smarty everything it needs to know
1125            $smarty->assign('debugRequested', true);
1126            $smarty->assign('debugOutput', print_r($_REQUEST, true));
1127        }
[1092]1128    }
[866]1129}
1130
1131/*
1132 * Local variables:
1133 * tab-width: 4
1134 * c-basic-offset: 4
1135 * c-hanging-comment-ender-p: nil
1136 * End:
[1409]1137 */
Note: See TracBrowser for help on using the browser.