Source for file users.class.inc.php
Documentation is available at users.class.inc.php
* This file is part of Group-Office. You should have received a copy of the
* Group-Office license along with Group-Office. See the file /LICENSE.TXT
* If you have questions write an e-mail to info@intermesh.nl
* @copyright Copyright Intermesh
* @version $Id: users.class.inc.php 1294 2008-10-30 13:07:15Z mschering $
* @author Merijn Schering <mschering@intermesh.nl>
* This class is used to manage users in Group-Office.
* @copyright Copyright Intermesh
* @version $Id: users.class.inc.php 1294 2008-10-30 13:07:15Z mschering $
* @author Merijn Schering <mschering@intermesh.nl>
* @since Group-Office 2.05
* The constructor initializes the SQL database connection.
* Some functionality is global and therefore implemented in this class,
* and not in the child classes. For this functions a database connection
* is needed, so we initialize it in the constructor. There is no need to
if(!isset ($_SESSION['GO_SESSION']['decimal_seperator']))
$_SESSION['GO_SESSION']['decimal_seperator'] = $GO_CONFIG->default_decimal_seperator;
if(!isset ($_SESSION['GO_SESSION']['thousands_seperator']))
$_SESSION['GO_SESSION']['thousands_seperator'] = $GO_CONFIG->default_thousands_seperator;
if(!isset ($_SESSION['GO_SESSION']['date_seperator']))
$_SESSION['GO_SESSION']['date_seperator'] = $GO_CONFIG->default_date_seperator;
if(!isset ($_SESSION['GO_SESSION']['date_format']))
$_SESSION['GO_SESSION']['date_format'] = Date::get_dateformat( $GO_CONFIG->default_date_format, $_SESSION['GO_SESSION']['date_seperator']);
if(!isset ($_SESSION['GO_SESSION']['time_format']))
$_SESSION['GO_SESSION']['time_format'] = $GO_CONFIG->default_time_format;
if(!isset ($_SESSION['GO_SESSION']['currency']))
$_SESSION['GO_SESSION']['currency'] = $GO_CONFIG->default_currency;
if(!isset ($_SESSION['GO_SESSION']['timezone']))
$_SESSION['GO_SESSION']['timezone'] = $GO_CONFIG->default_timezone;
if(!isset ($_SESSION['GO_SESSION']['country']))
$_SESSION['GO_SESSION']['country'] = $GO_CONFIG->default_country;
if(!isset ($_SESSION['GO_SESSION']['sort_name']))
$_SESSION['GO_SESSION']['sort_name'] = 'first_name';
* Updates the session data corresponding to the user_id.
global $GO_LANGUAGE, $GO_CONFIG;
if ($userdata = $this->get_user($user_id)) {
$middle_name = $userdata['middle_name'] == '' ? '' : $userdata['middle_name']. ' ';
if($update_language && $GO_LANGUAGE->language != $userdata['language'])
$userdata['language'] = $up_user['language'] = $GO_LANGUAGE->language;
$GO_LANGUAGE->set_language($userdata['language']);
$_SESSION['GO_SESSION']['user_id'] = $user_id;
$_SESSION['GO_SESSION']['username'] = $userdata['username'];
$_SESSION['GO_SESSION']['name'] = $userdata['first_name']. ' '. $middle_name. $userdata['last_name'];
$_SESSION['GO_SESSION']['function'] = $userdata['function'];
$_SESSION['GO_SESSION']['department'] = $userdata['department'];
$_SESSION['GO_SESSION']['first_name'] = $userdata['first_name'];
$_SESSION['GO_SESSION']['middle_name'] = $userdata['middle_name'];
$_SESSION['GO_SESSION']['last_name'] = $userdata['last_name'];
$_SESSION['GO_SESSION']['country'] = $userdata['country'];
$_SESSION['GO_SESSION']['email'] = $userdata['email'];
$_SESSION['GO_SESSION']['thousands_seperator'] = $userdata['thousands_seperator'];
$_SESSION['GO_SESSION']['decimal_seperator'] = $userdata['decimal_seperator'];
$_SESSION['GO_SESSION']['date_format'] = Date::get_dateformat($userdata['date_format'], $userdata['date_seperator']);
$_SESSION['GO_SESSION']['date_seperator'] = $userdata['date_seperator'];
$_SESSION['GO_SESSION']['time_format'] = $userdata['time_format'];
$_SESSION['GO_SESSION']['currency'] = $userdata['currency'];
$_SESSION['GO_SESSION']['lastlogin'] = isset ($userdata['lastlogin']) ? $userdata['lastlogin'] : time();
$_SESSION['GO_SESSION']['max_rows_list'] = $userdata['max_rows_list'];
$_SESSION['GO_SESSION']['timezone'] = $userdata['timezone'];
$_SESSION['GO_SESSION']['start_module'] = isset ($userdata['start_module']) ? $userdata['start_module'] : 'summary';
//$_SESSION['GO_SESSION']['language'] = $userdata['language'];
$_SESSION['GO_SESSION']['theme'] = $userdata['theme'];
$_SESSION['GO_SESSION']['mute_sound'] = $userdata['mute_sound'];
$_SESSION['GO_SESSION']['first_weekday'] = $userdata['first_weekday'];
$_SESSION['GO_SESSION']['sort_name'] = !empty($userdata['sort_name']) ? $userdata['sort_name'] : 'first_name';
* This function returns an array of the fields that can be used as search
$searchfields[] = array( '', $lang['common']['SearchAll'] );
$searchfields[] = array( 'first_name', $lang['common']['firstName'] );
$searchfields[] = array( 'last_name', $lang['common']['lastName'] );
$searchfields[] = array( 'email', $lang['common']['email'] );
$searchfields[] = array( 'company', $lang['common']['company'] );
$searchfields[] = array( 'department', $lang['common']['department'] );
$searchfields[] = array( 'function', $lang['common']['function'] );
$searchfields[] = array( 'address', $lang['common']['address'] );
$searchfields[] = array( 'city', $lang['common']['city'] );
$searchfields[] = array( 'zip', $lang['common']['zip'] );
$searchfields[] = array( 'state', $lang['common']['state'] );
$searchfields[] = array( 'country', $lang['common']['country'] );
$searchfields[] = array( 'work_address',$lang['common']['workAddress'] );
$searchfields[] = array( 'work_cip', $lang['common']['workZip'] );
$searchfields[] = array( 'work_city', $lang['common']['workCity'] );
$searchfields[] = array( 'work_state', $lang['common']['workState'] );
$searchfields[] = array( 'work_country',$lang['common']['workCountry'] );
* This function searches for users with the given search field.
function search($query, $field, $user_id= 0, $start= 0, $offset= 0, $sort= "name", $sort_direction= 'ASC')
if(!isset ($_SESSION['GO_SESSION']['sort_name']) || $_SESSION['GO_SESSION']['sort_name'] == 'first_name')
$sort = 'first_name '. $sort_direction. ', last_name ';
$sort = 'last_name '. $sort_direction. ', first_name ';
$sql = "SELECT DISTINCT go_users.*";
/* if(isset($GO_MODULES->modules['customfields']) && $GO_MODULES->modules['customfields']['read_permission'])
$sql .= " FROM go_users INNER JOIN go_acl ON go_users.acl_id = go_acl.acl_id ".
"LEFT JOIN go_users_groups ON go_acl.group_id = go_users_groups.group_id ";
/* if(isset($GO_MODULES->modules['customfields']) && $GO_MODULES->modules['customfields']['read_permission'])
$sql .= "LEFT JOIN cf_8 ON cf_8.link_id=users.link_id ";
$sql .= "WHERE (go_acl.user_id=". $this->escape($user_id). " ".
"OR go_users_groups.user_id=". $this->escape($user_id). ") AND ";
$sql = "SELECT * FROM go_users ";
/*if(isset($GO_MODULES->modules['customfields']) && $GO_MODULES->modules['customfields']['read_permission'])
$sql .= "LEFT JOIN cf_8 ON cf_8.link_id=users.link_id ";
$fields_sql = "SHOW FIELDS FROM go_users";
$this->query($fields_sql);
if(eregi('varchar', $this->f('Type')))
$fields[]= 'go_users.'. $this->f('Field');
/*if(isset($GO_MODULES->modules['customfields']) && $GO_MODULES->modules['customfields']['read_permission'])
$fields_sql = "SHOW FIELDS FROM cf_8";
$this->query($fields_sql);
while ($this->next_record()) {
$fields[]='cf_8.'.$this->f('Field');
foreach($fields as $field)
$sql .= "CONCAT(first_name,middle_name,last_name) LIKE '". $this->escape(str_replace(' ','%', $query)). "' ";
$sql .= "$field LIKE '". $this->escape($query). "' ";
$sql .= " ORDER BY $sort $sort_direction";
$sql .= " LIMIT ". $this->escape($start. ",". $offset);
$links = $GO_LINKS->get_links($link_id, 8);
$sql = "SELECT go_users.* FROM go_users INNER JOIN go_acl ON go_users.acl_id = go_acl.acl_id ".
"LEFT JOIN go_users_groups ON go_acl.group_id = go_users_groups.group_id WHERE (go_acl.user_id=". $this->escape($user_id). " ".
"OR go_users_groups.user_id=". $this->escape($user_id). ") AND link_id IN (". implode(',',$links). ") ORDER BY last_name ASC, first_name ASC";
* Fetch all users from the user management backend.
* This function retrieves all users from the database and returns their
* number. After that you are able to process each user via next_record.
* over the different user accounts. next_user() should be considered.
* @param string $sort The field to sort on
* @param string $direction The sort direction
* @param int $start Return results starting from this row
* @param int $offset Return this number of rows
* @return int The number of users
function get_users($sort= "name",$direction= "ASC", $start= 0, $offset= 0)
if(!isset ($_SESSION['GO_SESSION']['sort_name']) || $_SESSION['GO_SESSION']['sort_name'] == 'first_name')
$sort = 'first_name '. $direction. ', last_name';
$sort = 'last_name '. $direction. ', first_name';
// $sort = 'first_name '.$direction.', last_name';
$this->query("SELECT id FROM go_users");
$sql = "SELECT * FROM go_users ORDER BY ". $sort. " ". $direction;
$sql .= " LIMIT ". $this->escape($start. ",". $offset);
* This function retrieves all users that are visible to a user.
* This function fetches all users that should be visible to the given
* user. next_record() can be used to iterate over the result set.
* @param string $sort The field to sort on
* @param string $direction The sort direction
* @param int $start Return results starting from this row
* @param int $offset Return this number of rows
* @return int The number of users
if ($sort == 'users.name' || $sort== 'name')
if($_SESSION['GO_SESSION']['sort_name'] == 'first_name')
$sort = 'users.first_name '. $direction. ', go_users.last_name';
$sort = 'users.last_name '. $direction. ', go_users.first_name';
// $sort = 'users.first_name '.$direction.', go_users.last_name';
$sql = "SELECT DISTINCT go_users.* FROM go_users ".
"INNER JOIN go_acl ON go_users.acl_id= go_acl.acl_id ".
"LEFT JOIN go_users_groups ON (go_acl.group_id = go_users_groups.group_id) ".
"WHERE go_users_groups.user_id=". $this->escape($user_id). " OR ".
"go_acl.user_id = ". $this->escape($user_id). " ORDER BY ". $sort. " ". $direction;
* This function searches for a user by his email address.
* This function retrieves all userdata based on the users email address.
* @param string $email The e-mail address of a user
$sql = "SELECT * FROM go_users WHERE email='". $this->escape($email). "'";
//return false if there is more then one result
* This function returns all userdata based on the user's name.
* @param int $user_id The user to check access for
* @param string $username
* @return array The user profile
$sql = "SELECT DISTINCT go_users.* FROM go_users ".
"INNER JOIN go_acl ON go_users.acl_id= go_acl.acl_id ".
"LEFT JOIN go_users_groups ON (go_acl.group_id = go_users_groups.group_id) ".
"WHERE (go_users_groups.user_id=". $this->escape($user_id). " OR ".
"go_acl.user_id = ". $this->escape($user_id). ") AND email='". $this->escape($email). "'";
* This function checks if the password the user supplied is valid.
* @param string $password
$this->query("SELECT id FROM go_users WHERE password='". md5($password).
"' AND id='". $_SESSION['GO_SESSION']['user_id']. "'");
* This function searches for a user by his ID andreturns all userdata based on the users ID.
$sql = "SELECT * FROM go_users WHERE id='". $this->escape($user_id). "'";
if($this->record['date_seperator']== '')
$this->record['date_seperator']= ' ';
* This function updates all userdata based on the given parameters.
* @return bool True on success
$visible_user_groups= null,
global $GO_MODULES, $GO_SECURITY, $GO_GROUPS;
$GO_MODULES->get_modules();
while ($GO_MODULES->next_record())
$could_read = $GO_SECURITY->has_permission($user['id'], $GO_MODULES->f('acl_read'));
$can_read = in_array($GO_MODULES->f('id'), $modules_read);
if ($could_read && !$can_read)
$GO_SECURITY->delete_user_from_acl($user['id'], $GO_MODULES->f('acl_read'));
if ($can_read && !$could_read)
$GO_SECURITY->add_user_to_acl($user['id'], $GO_MODULES->f('acl_read'));
if(isset ($modules_write))
$could_write = $GO_SECURITY->has_permission($user['id'], $GO_MODULES->f('acl_write'));
$can_write = in_array($GO_MODULES->f('id'), $modules_write);
if ($could_write && !$can_write)
$GO_SECURITY->delete_user_from_acl($user['id'], $GO_MODULES->f('acl_write'));
if ($can_write && !$could_write)
$GO_SECURITY->add_user_to_acl($user['id'], $GO_MODULES->f('acl_write'));
//make sure we have user['acl_id']
$GO_GROUPS->get_groups();
while($GO_GROUPS->next_record())
$is_in_group = $groups2->is_in_group($user['id'], $GO_GROUPS->f('id'));
$should_be_in_group = in_array($GO_GROUPS->f('id'), $user_groups);
if ($is_in_group && !$should_be_in_group)
$groups2->delete_user_from_group($user['id'], $GO_GROUPS->f('id'));
if (!$is_in_group && $should_be_in_group)
$groups2->add_user_to_group($user['id'], $GO_GROUPS->f('id'));
if(isset ($visible_user_groups))
$group_is_visible = $GO_SECURITY->group_in_acl($GO_GROUPS->f('id'), $user['acl_id']);
$group_should_be_visible = in_array($GO_GROUPS->f('id'), $visible_user_groups);
if ($group_is_visible && !$group_should_be_visible)
$GO_SECURITY->delete_group_from_acl($GO_GROUPS->f('id'), $user['acl_id']);
if (!$group_is_visible && $group_should_be_visible)
$GO_SECURITY->add_group_to_acl($GO_GROUPS->f('id'), $user['acl_id']);
* This function updates a the profile of a user.
* Using an SQL update record, this function actualizes the profile of the
* @param Array $user is an array of all data that should be updated.
* @return Boolean to indicate the success of the operation.
$params = array('user'=> $user);
if(!empty($user['password']))
$user['password']= md5($user['password']);
if(isset ($_SESSION['GO_SESSION']['user_id']) && $user['id'] == $_SESSION['GO_SESSION']['user_id'])
$params['user']= $this->get_user($user['id']);
$GO_MODULES->fire_event('add_user', $params);
$GO_MODULES->fire_event('update_user', $params);
* This function updates the user's password.
* @param string $password
* @return bool True on success
function update_password($user_id, $password)
$sql = "UPDATE go_users SET password='".md5($password)."' WHERE id='$user_id'";
$params = array('user_id'=>$user_id, 'password'=>$password);
$GO_MODULES->fire_event('change_user_password', $params);
* This function returns all userdata based on the user's name.
* @param string $username
* @return array The user profile
$sql = "SELECT * FROM go_users WHERE username='". $this->escape($username). "'";
* This function checks, if there is already a user with the given email
* @return bool True if exists
$sql = "SELECT id FROM go_users WHERE email='". $this->escape($email). "'";
* This function adds a new user to the database.
* @param string $user Array of all columns of table 'go_users'
* @param string $user_groups The user group id's the user will be member of
* @param string $visible_user_groups The user group id's where the user will be visible to
* @param string $modules_read The modules the user will have read permissions for
* @param string $modules_write The modules the user will have write permissions for
* @param string $acl Some custom ACL id's the user will have access to (Be careful)
* @return bool True on success
$visible_user_groups= array(),
global $GO_CONFIG, $GO_LANGUAGE, $GO_SECURITY, $GO_GROUPS, $GO_MODULES;
// We check if we are able to add a new user. If we already have too much
// of them we do not want new ones ;)
// We check if a user with this email address already exists. Since the
// email address is used as key for the acl_id, no two users may have the
// same address. It also should not be possible to have multiple users
if(!$GO_CONFIG->allow_duplicate_email)
$this->query( "SELECT id FROM go_users WHERE email='". $this->escape($user['email']). "' OR username='". $this->escape($user['username']). "'");
if(!isset ($user['start_module']))
$user['start_module']= 'summary';
if(!isset ($user['language']))
$user['language'] = $GO_LANGUAGE->language;
if(!isset ($user['currency']))
$user['currency'] = $GO_CONFIG->default_currency;
if(!isset ($user['decimal_seperator']))
$user['decimal_seperator'] = $GO_CONFIG->default_decimal_seperator;
if(!isset ($user['thousands_seperator']))
$user['thousands_seperator'] = $GO_CONFIG->default_thousands_seperator;
if(!isset ($user['time_format']))
$user['time_format'] = $GO_CONFIG->default_time_format;
if(!isset ($user['date_format']))
$user['date_format'] = $GO_CONFIG->default_date_format;
if(!isset ($user['date_seperator']))
$user['date_seperator'] = $GO_CONFIG->default_date_seperator;
if(!isset ($user['first_weekday']))
$user['first_weekday'] = $GO_CONFIG->default_first_weekday;
if(!isset ($user['timezone']))
$user['timezone'] = $GO_CONFIG->default_timezone;
if(!isset ($user['theme']))
$user['theme'] = $GO_CONFIG->theme;
if(!isset ($user['max_rows_list']))
$user['max_rows_list'] = 30;
$user['id'] = $this->nextid("go_users");
// When the acl_id is already given, we do not have to create a new one,
// but it may be neccessary to change the owner of the acl - this is
// needed when the authentication framework "accidentially" creates the
// acl id for this user (which happens in the case, when the user is
// authenticated against an LDAP directory, where the id is generated
// when the LDAP entry is converted to the $user entry, which is given
// as parameter to this function).
if ( isset ( $user['acl_id'] ) ) {
$GO_SECURITY->set_acl_owner( $user['acl_id'], $user['id'] );
$user['acl_id'] = $GO_SECURITY->get_new_acl( $user['email'] );
$user['registration_time'] = $user['mtime']= time();
$params = array('user'=> $user);
$GO_MODULES->fire_event('before_add_user', $params);
$unencrypted_password = $user['password'];
if(!empty($user['password']))
$unencrypted_password = $user['password'];
$user['password'] = md5($user['password']);
if ($user['id'] > 0 && $this->insert_row('go_users', $user))
$GO_SECURITY->set_acl_owner( $user['acl_id'], $user['id'] );
$GO_GROUPS->add_user_to_group( $user['id'], $GO_CONFIG->group_everyone);
foreach($user_groups as $group_id)
if($group_id > 0 && $group_id != $GO_CONFIG->group_everyone && !$GO_GROUPS->is_in_group($user['id'], $group_id))
$GO_GROUPS->add_user_to_group($user['id'], $group_id);
foreach($visible_user_groups as $group_id)
if($group_id > 0 && !$GO_SECURITY->group_in_acl($group_id, $user['acl_id']))
$GO_SECURITY->add_group_to_acl($group_id, $user['acl_id']);
foreach($modules_read as $module_name)
$module = $GO_MODULES->get_module($module_name);
if($module && !$GO_SECURITY->user_in_acl($user['id'], $module['acl_read']))
$GO_SECURITY->add_user_to_acl($user['id'], $module['acl_read']);
foreach($modules_write as $module_name)
$module = $GO_MODULES->get_module($module_name);
if($module && !$GO_SECURITY->user_in_acl($user['id'], $module['acl_write']))
$GO_SECURITY->add_user_to_acl($user['id'], $module['acl_write']);
if(!$GO_SECURITY->user_in_acl($user['id'], $acl_id))
$GO_SECURITY->add_user_to_acl($user['id'], $acl_id);
$user['password']= $unencrypted_password;
//delay add user event because name must be supplied first.
if(!empty($user['first_name']) && !empty($user['first_name']))
$GO_MODULES->fire_event('add_user', $params);
$GO_SECURITY->delete_acl( $user['id'] );
* This function tells us if we exceeded the maximum number of users if set in
if($this->get_users() < $GO_CONFIG->max_users || $GO_CONFIG->max_users == 0)
* This function deletes a user from the database.
global $GO_CONFIG,$GO_SECURITY, $GO_MODULES, $GO_GROUPS;
$acl_id = $this->f("acl_id");
$username = $this->f("username");
$sql = "DELETE FROM go_users WHERE id='". $this->escape($user_id). "'";
$GO_SECURITY->delete_acl($acl_id);
$GO_SECURITY->delete_user($user_id);
require_once($GO_CONFIG->class_path. 'base/search.class.inc.php');
$search->delete_search_result($user_id, 8);
$GO_MODULES->fire_event('user_delete', $user);
//$GO_GROUPS->__on_user_delete($user_id);
$sql = "DELETE FROM go_acl WHERE user_id=". $this->escape($user_id). ";";
// system('rm -Rf '.$GO_CONFIG->file_storage_path.'users/'.$user_id);
throw new Exception('An error has occured while deleting the user');
$sql = "UPDATE go_users SET logins=logins+1, lastlogin='". time().
* This function generates a randomized password.
* @param string $characters_allow
* @param string $characters_disallow
* @param int $password_length
function random_password( $characters_allow = 'a-z,1-9', $characters_disallow = 'i,o', $password_length = 4, $repeat = 0 ) {
// Generate array of allowable characters.
$characters_allow = explode(',', $characters_allow);
for ($i = 0; $i < count($characters_allow); $i ++ ) {
$character_range = explode('-', $characters_allow[$i]);
for ($j = ord($character_range[0]); $j <= ord($character_range[1]); $j ++ ) {
$array_allow[] = chr($j);
$array_allow[] = $characters_allow[$i];
// Generate array of disallowed characters.
$characters_disallow = explode(',', $characters_disallow);
for ($i = 0; $i < count($characters_disallow); $i ++ ) {
$character_range = explode('-', $characters_disallow[$i]);
for ($j = ord($character_range[0]); $j <= ord($character_range[1]); $j ++ ) {
$array_disallow[] = chr($j);
$array_disallow[] = $characters_disallow[$i];
// Generate array of allowed characters by removing disallowed
// characters from array.
$array_allow = array_diff($array_allow, $array_disallow);
// Resets the keys since they won't be consecutive after
// removing the disallowed characters.
while (list ($key, $val) = each($array_allow)) {
$array_allow_tmp[$new_key] = $val;
$array_allow = $array_allow_tmp;
while (strlen($password) < $password_length) {
// If characters are not allowed to repeat,
// only add character if not found in partial password string.
if (substr_count($password, $array_allow[$character]) == 0) {
$password .= $array_allow[$character];
$password .= $array_allow[$character];
* When a global search action is performed this function will be called for each module
* @param int $last_sync_time The time this function was called last
global $GO_MODULES, $GO_CONFIG, $GO_LANGUAGE;
require_once($GO_CONFIG->class_path. '/base/search.class.inc.php');
require ($GO_LANGUAGE->get_language_file('users'));
$sql = "SELECT DISTINCT * FROM go_users WHERE id=?";
$this->query($sql, 'i', $user_id);
$cache['id']= $this->f('id');
$cache['name'] = String::format_name($this->f('last_name'),$this->f('first_name'),$this->f('middle_name'));
$cache['description']= '';
$cache['keywords']= $search->record_to_keywords($this->record). ','. $cache['type'];
$cache['mtime']= $this->f('mtime');
$cache['module']= 'users';
$cache['acl_read']= $GO_MODULES->modules['users']['acl_read'];
$cache['acl_write']= $GO_MODULES->modules['users']['acl_write'];
$search->cache_search_result($cache);
|