diff --git a/class2.php b/class2.php index 649b5e1e4..202e9bc5d 100644 --- a/class2.php +++ b/class2.php @@ -1561,7 +1561,6 @@ function init_session() global $user_pref, $currentUser; - $sql = e107::getDb(); $e107 = e107::getInstance(); // New user model @@ -1629,20 +1628,6 @@ function init_session() { e107::getRedirect()->setPreviousUrl(); } - - // DB - $update_ip = ($user->get('user_ip') != USERIP ? ", user_ip = '".USERIP."'" : ""); - if($user->get('user_currentvisit') + 3600 < time() || !$user->get('user_lastvisit')) - { - $user->set('user_lastvisit', (integer) $user->get('user_currentvisit')); - $user->set('user_currentvisit', time()); - $sql->db_Update('user', "user_visits = user_visits + 1, user_lastvisit = ".$user->get('user_lastvisit').", user_currentvisit = ".$user->get('user_currentvisit')."{$update_ip} WHERE user_id='".USERID."' "); - } - else - { - $user->set('user_currentvisit', time()); - $sql->db_Update('user', "user_currentvisit = ".$user->get('user_currentvisit')."{$update_ip} WHERE user_id='".USERID."' "); - } define('USERLV', $user->get('user_lastvisit')); // BC - FIXME - get rid of them! @@ -1650,6 +1635,7 @@ function init_session() $currentUser['user_realname'] = $result['user_login']; // Used by force_userupdate $e107->currentUser = &$currentUser; + // XXX could go to e_user class as well if ($user->checkClass(e107::getPref('allow_theme_select', false), false)) { // User can set own theme if (isset($_POST['settheme'])) @@ -1684,6 +1670,7 @@ function init_session() ->remove('sitetheme_deflayout') ->save(false); } + // XXX could go to e_user class as well END define('USERTHEME', ($user->getPref('sitetheme') && file_exists(e_THEME.$user->getPref('sitetheme')."/theme.php") ? $user->getPref('sitetheme') : false)); @@ -1691,7 +1678,7 @@ function init_session() } define('USERCLASS_LIST', $user->getClassList(true)); - define('e_CLASS_REGEXP', '(^|,)('.str_replace(',', '|', USERCLASS_LIST).')(,|$)'); + define('e_CLASS_REGEXP', $user->getClassRegex()); define('e_NOBODY_REGEXP', '(^|,)'.e_UC_NOBODY.'(,|$)'); /* XXX - remove it after everything is working well!! @@ -1839,7 +1826,7 @@ function init_session() $sql->db_Mark_Time('Start: Go online'); if(!isset($_E107['no_online']) && varset($pref['track_online'])) { - e107::getOnline()->online($pref['track_online'], $pref['flood_protect']); + e107::getOnline()->goOnline($pref['track_online'], $pref['flood_protect']); } function cookie($name, $value, $expire=0, $path = '/', $domain = '', $secure = 0) diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index 94915196d..b7667bafa 100644 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -1760,6 +1760,10 @@ class e107 if(isset($GLOBALS['_E107']['minimal']) || e_AJAX_REQUEST) { $_e107vars = array('forceuserupdate', 'online', 'theme', 'menus', 'prunetmp'); + + // lame but quick - allow online when ajax request only, additonal checks are made in e_online class + if(e_AJAX_REQUEST && !isset($GLOBALS['_E107']['online']) && !isset($GLOBALS['_E107']['minimal'])) unset($_e107vars[1]); + foreach($_e107vars as $v) { $noname = 'no_'.$v; diff --git a/e107_handlers/online_class.php b/e107_handlers/online_class.php index 420b99535..bdc7bb236 100755 --- a/e107_handlers/online_class.php +++ b/e107_handlers/online_class.php @@ -2,16 +2,14 @@ /* * e107 website system * - * Copyright (C) 2008-2009 e107 Inc (e107.org) + * Copyright (C) 2008-2010 e107 Inc (e107.org) * Released under the terms and conditions of the * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * e107 Main * - * $Source: /cvs_backup/e107_0.8/e107_handlers/online_class.php,v $ - * $Revision$ - * $Date$ - * $Author$ + * $URL$ + * $Id$ */ @@ -32,11 +30,11 @@ online_pagecount tinyint(3) unsigned NOT NULL default '0', Number of page accesses (within most recent timeout interval?) online_active int(10) unsigned NOT NULL default '0', Not used? Actually added in the update routines, version 0.7.6. (Also displayed in admin log) online_agent varchar(255) NOT NULL default '' User agent - use for bot identification - + Current count() queries: a) Total b) $sql->db_Count('online', '(*)', "WHERE `online_location` = '{$page}' ")); - + Also forum_viewforum.php: $member_users = $sql->db_Count('online', '(*)', "WHERE online_location REGEXP('viewforum.php.id=$forumId\$') AND online_user_id != 0"); $guest_users = $sql->db_Count('online', '(*)', "WHERE online_location REGEXP('viewforum.php.id=$forumId\$') AND online_user_id = 0"); @@ -58,40 +56,50 @@ SELECT COUNT(`online_user_id`) AS ol_count, `online_user_id` FROM `#online` GROU * @todo Eliminate other globals * @todo Can we simplify counts into one query? */ -class e_online +class e_online { - function online($online_tracking = false, $flood_control = false) + /** + * Go online + * @param boolean $online_tracking + * @param boolean $flood_control + * @return void + */ + public function goOnline($online_tracking = false, $flood_control = false) { - global $pref, $e_event; + // global $pref, $e_event; // Not needed as globals //global $online_timeout, $online_warncount, $online_bancount; // Not needed as globals //global $members_online, $total_online; // Not needed as globals - global $listuserson; + global $listuserson; // FIXME - remove it, make it property, call e_online signleton - e107::getOnline() $e107 = e107::getInstance(); $sql = e107::getDb(); + $user = e107::getUser(); - if($online_tracking == true || $flood_control == true) + if($online_tracking || $flood_control) { - if(!isset($online_timeout)) $online_timeout = 300; - if(!isset($online_bancount)) + $online_timeout = 300; + + list($ban_access_guest,$ban_access_member) = explode(',',e107::getPref('ban_max_online_access', '100,200')); + $online_bancount = max($ban_access_guest,50); // Safety net for incorrect values + if ($user->isUser()) { - list($ban_access_guest,$ban_access_member) = explode(',',varset($pref['ban_max_online_access'],'100,200')); - $online_bancount = max($ban_access_guest,50); // Safety net for incorrect values - if (USER) - { - $online_bancount = max($online_bancount,$ban_access_member); - } + $online_bancount = max($online_bancount,$ban_access_member); } + $online_warncount = $online_bancount * 0.9; // Set warning threshold at 90% of ban threshold - //TODO Add support for all queries. + //TODO Add support for all queries. $page = (strpos(e_SELF, 'forum_') !== FALSE) ? e_SELF.'.'.e_QUERY : e_SELF; $page = (strpos(e_SELF, 'comment') !== FALSE) ? e_SELF.'.'.e_QUERY : $page; $page = (strpos(e_SELF, 'content') !== FALSE) ? e_SELF.'.'.e_QUERY : $page; $page = $e107->tp->toDB($page, true); $ip = $e107->getip(); - $udata = (USER === true ? USERID.'.'.USERNAME : '0'); + $udata = ($user->isUser() ? $user->getId().'.'.$user->getName() : '0'); $agent = $_SERVER['HTTP_USER_AGENT']; - + + // XXX - more exceptions, e.g. hide online location for admins/users (pref), e_jlsib.php, etc + // XXX - more advanced flod timing when e_AJAX_REQUEST, e.g. $ban_access_ajax = 300 + $update_page = deftrue('e_AJAX_REQUEST') ? '' : ", online_location='{$page}'"; + $insert_query = array( 'online_timestamp' => time(), 'online_flag' => 0, @@ -102,93 +110,97 @@ class e_online 'online_active' => 0, 'online_agent' => $agent ); - - if (USER) + + // !deftrue('e_AJAX_REQUEST') + // TODO add option to hide users from online list? boolean online_hide field? + // don't do anything if main admin logged in as another user + if ($user->isUser() && !$user->getParentId()) { // Find record that matches IP or visitor, or matches user info - if ($sql->db_Select('online', '*', "(`online_ip` = '{$ip}' AND `online_user_id` = '0') OR `online_user_id` = '{$udata}'")) + if ($sql->db_Select('online', '*', "(`online_ip` = '{$ip}' AND `online_user_id` = '0') OR `online_user_id` = '{$udata}'")) { $row = $sql->db_Fetch(); - if ($row['online_user_id'] == $udata) + if ($row['online_user_id'] == $udata) { //Matching user record - if ($row['online_timestamp'] < (time() - $online_timeout)) + if ($row['online_timestamp'] < (time() - $online_timeout)) { //It has been at least 'online_timeout' seconds since this user's info last logged //Update user record with timestamp, current IP, current page and set pagecount to 1 - $query = "online_timestamp='".time()."', online_ip='{$ip}', online_location='{$page}', online_pagecount=1 WHERE online_user_id='{$row['online_user_id']}' LIMIT 1"; - } - else + $query = "online_timestamp='".time()."', online_ip='{$ip}'{$update_page}, online_pagecount=1 WHERE online_user_id='{$row['online_user_id']}' LIMIT 1"; + } + else { - if (!ADMIN) + if (!$user->isAdmin()) { $row['online_pagecount'] ++; } // Update user record with current IP, current page and increment pagecount - $query = "online_ip='{$ip}', `online_location` = '{$page}', `online_pagecount` = '".intval($row['online_pagecount'])."' WHERE `online_user_id` = '{$row['online_user_id']}' LIMIT 1"; + $query = "online_ip='{$ip}'{$update_page}, `online_pagecount` = '".intval($row['online_pagecount'])."' WHERE `online_user_id` = '{$row['online_user_id']}' LIMIT 1"; } - } - else + } + else { //Found matching visitor record (ip only) for this user - if ($row['online_timestamp'] < (time() - $online_timeout)) + if ($row['online_timestamp'] < (time() - $online_timeout)) { // It has been at least 'timeout' seconds since this user has connected // Update record with timestamp, current IP, current page and set pagecount to 1 - $query = "`online_timestamp` = '".time()."', `online_user_id` = '{$udata}', `online_location` = '{$page}', `online_pagecount` = 1 WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; - } - else + $query = "`online_timestamp` = '".time()."', `online_user_id` = '{$udata}'{$update_page}, `online_pagecount` = 1 WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; + } + else { // Another visit within the timeout period - if (!ADMIN) + if (!$user->isAdmin()) { $row['online_pagecount'] ++; } //Update record with current IP, current page and increment pagecount - $query = "`online_user_id` = '{$udata}', `online_location` = '{$page}', `online_pagecount` = ".intval($row['online_pagecount'])." WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; + $query = "`online_user_id` = '{$udata}'{$update_page}, `online_pagecount` = ".intval($row['online_pagecount'])." WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; } } $sql->db_Update('online', $query); - } - else + } + else { $sql->db_Insert('online',$insert_query); } } - else + // don't do anything if main admin logged in as another user + elseif(!$user->getParentId()) { - //Current page request is from a visitor - if ($sql->db_Select('online', '*', "`online_ip` = '{$ip}' AND `online_user_id` = '0'")) + //Current page request is from a guest + if ($sql->db_Select('online', '*', "`online_ip` = '{$ip}' AND `online_user_id` = '0'")) { // Recent visitor $row = $sql->db_Fetch(); if ($row['online_timestamp'] < (time() - $online_timeout)) //It has been at least 'timeout' seconds since this ip has connected { //Update record with timestamp, current page, and set pagecount to 1 - $query = "`online_timestamp` = '".time()."', `online_location` = '{$page}', `online_pagecount` = 1 WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; - } - else + $query = "`online_timestamp` = '".time()."'{$update_page}, `online_pagecount` = 1 WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; + } + else { //Update record with current page and increment pagecount $row['online_pagecount'] ++; // echo "here {$online_pagecount}"; - $query="`online_location` = '{$page}', `online_pagecount` = {$row['online_pagecount']} WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; + $query="`online_pagecount` = {$row['online_pagecount']}{$update_page} WHERE `online_ip` = '{$ip}' AND `online_user_id` = '0' LIMIT 1"; } $sql->db_Update('online', $query); - } - else + } + else { // New visitor $sql->db_Insert('online',$insert_query); } } - if (ADMIN || ($pref['autoban'] != 1 && $pref['autoban'] != 2) || (!isset($row['online_pagecount']))) // Auto-Ban is switched off. (0 or 3) + if ($user->isAdmin() || (e107::getPref('autoban') != 1 && e107::getPref('autoban') != 2) || (!isset($row['online_pagecount']))) // Auto-Ban is switched off. (0 or 3) { $row['online_pagecount'] = 1; } // Always allow localhost - any problems are usually semi-intentional! - if (($row['online_ip'] != '127.0.0.1') && ($row['online_ip'] != e107::LOCALHOST_IP)) + if (($row['online_ip'] != '127.0.0.1') && ($row['online_ip'] != e107::LOCALHOST_IP)) { // Check for excessive access if ($row['online_pagecount'] > $online_bancount) @@ -196,11 +208,11 @@ class e_online include_lan(e_LANGUAGEDIR.e_LANGUAGE.'/admin/lan_banlist.php'); if ($e107->add_ban(2,str_replace('--HITS--',$row['online_pagecount'],BANLAN_78),$ip,0)) { - $e_event->trigger('flood', $ip); + e107::getEvent()->trigger('flood', $ip); exit; } } - elseif ($row['online_pagecount'] >= $online_warncount) + elseif ($row['online_pagecount'] >= $online_warncount) { echo "
".LAN_WARNING."

".CORE_LAN6."
"; exit; @@ -208,34 +220,41 @@ class e_online } // Delete records for users (and guests) not seen for a while - $sql->db_Delete('online', '`online_timestamp` < '.(time() - $online_timeout)); + // FIXME - DB optimization - mark records as deleted (online_deleted=1), delete once per hour (could be pref) via e_cron + // FIXME - Additional prefs for this (it does 2-3 more queries no matter someone need them), could be also separate method + // Speed up ajax requests + if(!deftrue('e_AJAX_REQUEST')) + { + $sql->db_Delete('online', '`online_timestamp` < '.(time() - $online_timeout)); - $total_online = $sql->db_Count('online'); - if ($members_online = $sql->db_Select('online', 'online_user_id, online_location', 'online_user_id != 0')) - { - $member_list = ''; - $listuserson = array(); - while ($row = $sql->db_Fetch()) + // FIXME - don't use constants below, save data in class vars, call e_online signleton - e107::getOnline() + $total_online = $sql->db_Count('online'); + if ($members_online = $sql->db_Select('online', 'online_user_id, online_location', 'online_user_id != 0')) { - $vals = explode('.', $row['online_user_id'], 2); - $member_list .= "{$vals[1]} "; - $listuserson[$row['online_user_id']] = $row['online_location']; + $member_list = ''; + $listuserson = array(); + while ($row = $sql->db_Fetch()) + { + $vals = explode('.', $row['online_user_id'], 2); + $member_list .= "{$vals[1]} "; + $listuserson[$row['online_user_id']] = $row['online_location']; + } + } + define('TOTAL_ONLINE', $total_online); + define('MEMBERS_ONLINE', $members_online); + define('GUESTS_ONLINE', $total_online - $members_online); + define('ON_PAGE', $sql->db_Count('online', '(*)', "WHERE `online_location` = '{$page}' ")); + define('MEMBER_LIST', $member_list); + + //update most ever online + $olCountPrefs = e107::getConfig('history'); // Get historic counts of members on line + if ($total_online > ($olCountPrefs->get('most_members_online') + $olCountPrefs->get('most_guests_online'))) + { + $olCountPrefs->set('most_members_online', MEMBERS_ONLINE); + $olCountPrefs->set('most_guests_online', GUESTS_ONLINE); + $olCountPrefs->set('most_online_datestamp', time()); + $olCountPrefs->save(false, true, false); } - } - define('TOTAL_ONLINE', $total_online); - define('MEMBERS_ONLINE', $members_online); - define('GUESTS_ONLINE', $total_online - $members_online); - define('ON_PAGE', $sql->db_Count('online', '(*)', "WHERE `online_location` = '{$page}' ")); - define('MEMBER_LIST', $member_list); - - //update most ever online - $olCountPrefs = e107::getConfig('history'); // Get historic counts of members on line - if ($total_online > ($olCountPrefs->get('most_members_online') + $olCountPrefs->get('most_guests_online'))) - { - $olCountPrefs->set('most_members_online', MEMBERS_ONLINE); - $olCountPrefs->set('most_guests_online', GUESTS_ONLINE); - $olCountPrefs->set('most_online_datestamp', time()); - $olCountPrefs->save(false, true, false); } } else diff --git a/e107_handlers/user_model.php b/e107_handlers/user_model.php index 994dd4a1d..feed0fec2 100644 --- a/e107_handlers/user_model.php +++ b/e107_handlers/user_model.php @@ -99,6 +99,13 @@ class e_user_model extends e_front_model */ protected $_message_stack = 'user'; + /** + * User class as set in user Adminsitration + * + * @var integer + */ + protected $_memberlist_access = null; + /** * Extended data * @@ -125,6 +132,17 @@ class e_user_model extends e_front_model */ protected $_editor = null; + /** + * Constructor + * @param array $data + * @return void + */ + public function __construct($data = array()) + { + $this->_memberlist_access = e107::getPref('memberlist_access'); + parent::__construct($data); + } + /** * Always return integer * @@ -135,6 +153,11 @@ class e_user_model extends e_front_model return (integer) parent::getId(); } + final public function getName($anon = false) + { + return ($this->isUser() ? $this->get('user_name') : $anon); + } + final public function getAdminId() { return ($this->isAdmin() ? $this->getId() : false); @@ -205,9 +228,9 @@ class e_user_model extends e_front_model $this->_class_list = array(); if ($this->isUser()) { - if ($this->getValue('class')) + if ($this->get('user_class')) { - $this->_class_list = explode(',', $this->getValue('class')); + $this->_class_list = explode(',', $this->get('user_class')); } $this->_class_list[] = e_UC_MEMBER; if ($this->isAdmin()) @@ -238,6 +261,11 @@ class e_user_model extends e_front_model return ($toString ? implode(',', $this->_class_list) : $this->_class_list); } + final public function getClassRegex() + { + return '(^|,)('.str_replace(',', '|', $this->getClassList(true)).')(,|$)'; + } + final public function checkClass($class, $allowMain = true) { // FIXME - replace check_class() here @@ -427,10 +455,10 @@ class e_user_model extends e_front_model } /** - * Get current user editor model + * Set current user editor model * @return e_user_model */ - public function setEditor($user_model) + public function setEditor(e_user_model $user_model) { $this->_editor = $user_model; return $this; @@ -450,6 +478,20 @@ class e_user_model extends e_front_model return ($perm && !in_array($field, array($this->getFieldIdName(), 'user_admin', 'user_perms', 'user_prefs'))); } + /** + * Check if passed field is readable by the Editor + * @param string $field + * @return boolean + */ + public function isReadable($field) + { + $perm = false; + $editor = $this->getEditor(); + if($this->getId() === $editor->getId() || $editor->isMainAdmin() || $editor->checkAdminPerms('4')) + $perm = true; + return ($perm || (!in_array($field, array('user_admin', 'user_perms', 'user_prefs', 'user_password') && $editor->checkClass($this->_memberlist_access)))); + } + /** * Set current object as a target * @@ -805,6 +847,10 @@ class e_user extends e_user_model // NEW - try 'logged in as' feature if(!$denyAs) $this->loadAs(); + // update lastvisit field + $this->updateVisit(); + + // currently does nothing $this->_initConstants(); return $this; } @@ -857,6 +903,34 @@ class e_user extends e_user_model return $this; } + /** + * Update user visit timestamp + * @return void + */ + protected function updateVisit() + { + // Don't update if main admin is logged in as current (non main admin) user + if(!$this->getParentId()) + { + $sql = e107::getDb(); + $this->set('last_ip', $this->get('user_ip')); + $current_ip = e107::getInstance()->getip(); + $update_ip = $this->get('user_ip' != $current_ip ? ", user_ip = '".$current_ip."'" : ""); + $this->set('user_ip', $current_ip); + if($this->get('user_currentvisit') + 3600 < time() || !$this->get('user_lastvisit')) + { + $this->set('user_lastvisit', (integer) $this->get('user_currentvisit')); + $this->set('user_currentvisit', time()); + $sql->db_Update('user', "user_visits = user_visits + 1, user_lastvisit = ".$this->get('user_lastvisit').", user_currentvisit = ".$this->get('user_currentvisit')."{$update_ip} WHERE user_id='".$this->getId()."' "); + } + else + { + $this->set('user_currentvisit', time()); + $sql->db_Update('user', "user_currentvisit = ".$this->get('user_currentvisit')."{$update_ip} WHERE user_id='".$this->getId()."' "); + } + } + } + final protected function _destroySession() { cookie($this->_session_key, '', (time() - 2592000)); @@ -989,6 +1063,13 @@ class e_user_extended_model extends e_front_model */ protected $_message_stack = 'user'; + /** + * User class as set in user Adminsitration + * + * @var integer + */ + protected $_memberlist_access = null; + /** * @var e_user_extended_structure_tree */ @@ -1000,12 +1081,6 @@ class e_user_extended_model extends e_front_model */ protected $_user = null; - /** - * User model - * @var e_user_model - */ - protected $_editor = null; - /** * Stores access classes and default value per custom field * @var array @@ -1019,9 +1094,9 @@ class e_user_extended_model extends e_front_model */ public function __construct(e_user_model $user_model) { + $this->_memberlist_access = e107::getPref('memberlist_access'); $this->setUser($user_model) - ->setEditor(e107::getUser()) // current by default - ->load(); + ->load(); } /** @@ -1058,17 +1133,7 @@ class e_user_extended_model extends e_front_model */ public function getEditor() { - return $this->_editor; - } - - /** - * Get current user editor model - * @return e_user_model - */ - public function setEditor($user_model) - { - $this->_editor = $user_model; - return $this; + return $this->getUser()->getEditor(); } /** @@ -1157,9 +1222,10 @@ class e_user_extended_model extends e_front_model public function checkRead($field) { $hidden = $this->get('user_hidden_fields'); - if($this->getId() !== $this->getEditor()->getId() && !empty($hidden) && strpos($hidden, $field) !== false) return false; + $editor = $this->getEditor(); + if($this->getId() !== $editor->getId() && !empty($hidden) && strpos($hidden, $field) !== false) return false; - return ($this->checkApplicable($field) && $this->getEditor()->checkClass(varset($this->_struct_index[$field]['read']))); + return ($this->checkApplicable($field) && $editor->checkClass($this->_memberlist_access) && $editor->checkClass(varset($this->_struct_index[$field]['read']))); } /** @@ -1635,9 +1701,11 @@ class e_user_pref extends e_front_model /** * Save and apply user preferences + * @param boolean $from_post + * @param boolean $force * @return boolean success */ - public function save($from_post = false) + public function save($from_post = false, $force = false) { if($this->_user->getId()) { @@ -1645,9 +1713,13 @@ class e_user_pref extends e_front_model { $this->mergePostedData(false, true, false); } - $data = $this->toString(true); - $this->apply(); - return (e107::getDb('user_prefs')->db_Update('user', "user_prefs='{$data}' WHERE user_id=".$this->_user->getId()) ? true : false); + if($force || $this->dataHasChanged()) + { + $data = $this->toString(true); + $this->apply(); + return (e107::getDb('user_prefs')->db_Update('user', "user_prefs='{$data}' WHERE user_id=".$this->_user->getId()) ? true : false); + } + return 0; } return false; }