From 0356402c78d4b07d78ca0433e76a406e0d35ce27 Mon Sep 17 00:00:00 2001 From: dave Date: Thu, 1 Jan 2009 18:07:54 +0000 Subject: bug #634 fixed git-svn-id: https://code.elgg.org/elgg/trunk@2528 36083f99-b078-4883-b0ff-0f9b5a30f544 --- engine/lib/users.php | 1071 +++++++++++++++++++++++++------------------------- 1 file changed, 536 insertions(+), 535 deletions(-) diff --git a/engine/lib/users.php b/engine/lib/users.php index aba76cec0..ec3165a8d 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -11,19 +11,19 @@ * @copyright Curverider Ltd 2008 * @link http://elgg.org/ */ - - /// Map a username to a cached GUID - $USERNAME_TO_GUID_MAP_CACHE = array(); - - /// Map a user code to a cached GUID - $CODE_TO_GUID_MAP_CACHE = array(); + + /// Map a username to a cached GUID + $USERNAME_TO_GUID_MAP_CACHE = array(); + + /// Map a user code to a cached GUID + $CODE_TO_GUID_MAP_CACHE = array(); /** * ElggUser - * - * Representation of a "user" in the system. - * - * @package Elgg + * + * Representation of a "user" in the system. + * + * @package Elgg * @subpackage Core */ class ElggUser extends ElggEntity @@ -42,7 +42,7 @@ $this->attributes['type'] = "user"; $this->attributes['name'] = ""; $this->attributes['username'] = ""; - $this->attributes['password'] = ""; + $this->attributes['password'] = ""; $this->attributes['salt'] = ""; $this->attributes['email'] = ""; $this->attributes['language'] = ""; @@ -93,9 +93,9 @@ // We assume if we have got this far, $guid is an int else if (is_numeric($guid)) { if (!$this->load($guid)) IOException(sprintf(elgg_echo('IOException:FailedToLoadGUID'), get_class(), $guid)); - } - - else + } + + else throw new InvalidParameterException(elgg_echo('InvalidParameterException:UnrecognisedValue')); } } @@ -119,8 +119,8 @@ throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $guid, get_class())); // Load missing data - $row = get_user_entity_as_row($guid); - if (($row) && (!$this->isFullyLoaded())) $this->attributes['tables_loaded'] ++; // If $row isn't a cached copy then increment the counter + $row = get_user_entity_as_row($guid); + if (($row) && (!$this->isFullyLoaded())) $this->attributes['tables_loaded'] ++; // If $row isn't a cached copy then increment the counter // Now put these into the attributes array as core values $objarray = (array) $row; @@ -141,7 +141,7 @@ return false; // Now save specific stuff - return create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'), $this->get('password'), $this->get('salt'), $this->get('email'), $this->get('language'), $this->get('code')); + return create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'), $this->get('password'), $this->get('salt'), $this->get('email'), $this->get('language'), $this->get('code')); } /** @@ -149,9 +149,9 @@ * @return true|false */ public function delete() - { - if (!delete_user_entity($this->get('guid'))) - return false; + { + if (!delete_user_entity($this->get('guid'))) + return false; return parent::delete(); @@ -292,23 +292,23 @@ */ function getOwner() { if ($this->owner_guid == 0) - return $this->getGUID(); - + return $this->getGUID(); + return $this->owner_guid; } - - // EXPORTABLE INTERFACE //////////////////////////////////////////////////////////// - - /** - * Return an array of fields which can be exported. - */ - public function getExportableValues() - { - return array_merge(parent::getExportableValues(), array( - 'name', - 'username', - 'language', - )); + + // EXPORTABLE INTERFACE //////////////////////////////////////////////////////////// + + /** + * Return an array of fields which can be exported. + */ + public function getExportableValues() + { + return array_merge(parent::getExportableValues(), array( + 'name', + 'username', + 'language', + )); } } @@ -320,25 +320,25 @@ function get_user_entity_as_row($guid) { global $CONFIG; - - $row = retrieve_cached_entity_row($guid); - if ($row) - { - // We have already cached this object, so retrieve its value from the cache - if (isset($CONFIG->debug) && $CONFIG->debug == true) - error_log("** Retrieving sub part of GUID:$guid from cache"); - - return $row; - } - else - { - // Object not cached, load it. - if (isset($CONFIG->debug) && $CONFIG->debug == true) - error_log("** Sub part of GUID:$guid loaded from DB"); + + $row = retrieve_cached_entity_row($guid); + if ($row) + { + // We have already cached this object, so retrieve its value from the cache + if (isset($CONFIG->debug) && $CONFIG->debug == true) + error_log("** Retrieving sub part of GUID:$guid from cache"); + + return $row; + } + else + { + // Object not cached, load it. + if (isset($CONFIG->debug) && $CONFIG->debug == true) + error_log("** Sub part of GUID:$guid loaded from DB"); $guid = (int)$guid; - return get_data_row("SELECT * from {$CONFIG->dbprefix}users_entity where guid=$guid"); + return get_data_row("SELECT * from {$CONFIG->dbprefix}users_entity where guid=$guid"); } } @@ -353,12 +353,12 @@ */ function create_user_entity($guid, $name, $username, $password, $salt, $email, $language, $code) { - global $CONFIG; + global $CONFIG; $guid = (int)$guid; $name = sanitise_string($name); $username = sanitise_string($username); - $password = sanitise_string($password); + $password = sanitise_string($password); $salt = sanitise_string($salt); $email = sanitise_string($email); $language = sanitise_string($language); @@ -367,34 +367,34 @@ $row = get_entity_as_row($guid); if ($row) { - // Exists and you have access to it + // Exists and you have access to it - if ($exists = get_data_row("SELECT guid from {$CONFIG->dbprefix}users_entity where guid = {$guid}")) { - $result = update_data("UPDATE {$CONFIG->dbprefix}users_entity set name='$name', username='$username', password='$password', email='$email', language='$language', code='$code', last_action = ". time() ." where guid = {$guid}"); - if ($result != false) - { - // Update succeeded, continue - $entity = get_entity($guid); - if (trigger_elgg_event('update',$entity->type,$entity)) { - return $guid; - } else { - $entity->delete(); - } + if ($exists = get_data_row("SELECT guid from {$CONFIG->dbprefix}users_entity where guid = {$guid}")) { + $result = update_data("UPDATE {$CONFIG->dbprefix}users_entity set name='$name', username='$username', password='$password', email='$email', language='$language', code='$code', last_action = ". time() ." where guid = {$guid}"); + if ($result != false) + { + // Update succeeded, continue + $entity = get_entity($guid); + if (trigger_elgg_event('update',$entity->type,$entity)) { + return $guid; + } else { + $entity->delete(); + } } - } - else - { - // Update failed, attempt an insert. - $result = insert_data("INSERT into {$CONFIG->dbprefix}users_entity (guid, name, username, password, salt, email, language, code) values ($guid, '$name', '$username', '$password', '$salt', '$email', '$language', '$code')"); - if ($result!==false) { - $entity = get_entity($guid); - if (trigger_elgg_event('create',$entity->type,$entity)) { - return $guid; - } else { - delete_entity($guid); - } - } - } + } + else + { + // Update failed, attempt an insert. + $result = insert_data("INSERT into {$CONFIG->dbprefix}users_entity (guid, name, username, password, salt, email, language, code) values ($guid, '$name', '$username', '$password', '$salt', '$email', '$language', '$code')"); + if ($result!==false) { + $entity = get_entity($guid); + if (trigger_elgg_event('create',$entity->type,$entity)) { + return $guid; + } else { + delete_entity($guid); + } + } + } } @@ -451,6 +451,7 @@ function user_add_friend($user_guid, $friend_guid) { $user_guid = (int) $user_guid; $friend_guid = (int) $friend_guid; + if ($user_guid == $friend_guid) return false; if (!$friend = get_entity($friend_guid)) return false; if (!$user = get_entity($user_guid)) return false; if ( (!($user instanceof ElggUser)) || (!($friend instanceof ElggUser)) ) return false; @@ -552,7 +553,7 @@ $entities = get_user_objects($user_guid, $subtype, $limit, $offset); return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview); - + } /** @@ -665,17 +666,17 @@ { global $CONFIG, $USERNAME_TO_GUID_MAP_CACHE; - $username = sanitise_string($username); - $access = get_access_sql_suffix('e'); - - // Caching - if ( (isset($USERNAME_TO_GUID_MAP_CACHE[$username])) && (retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username])) ) - return retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]); + $username = sanitise_string($username); + $access = get_access_sql_suffix('e'); + + // Caching + if ( (isset($USERNAME_TO_GUID_MAP_CACHE[$username])) && (retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username])) ) + return retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]); $row = get_data_row("SELECT e.* from {$CONFIG->dbprefix}users_entity u join {$CONFIG->dbprefix}entities e on e.guid=u.guid where u.username='$username' "); - if ($row) { + if ($row) { $USERNAME_TO_GUID_MAP_CACHE[$username] = $row->guid; - return new ElggUser($row); + return new ElggUser($row); } return false; @@ -691,87 +692,87 @@ { global $CONFIG, $CODE_TO_GUID_MAP_CACHE; - $code = sanitise_string($code); - - $access = get_access_sql_suffix('e'); - - // Caching - if ( (isset($CODE_TO_GUID_MAP_CACHE[$code])) && (retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code])) ) - return retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]); + $code = sanitise_string($code); + + $access = get_access_sql_suffix('e'); + + // Caching + if ( (isset($CODE_TO_GUID_MAP_CACHE[$code])) && (retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code])) ) + return retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]); $row = get_data_row("SELECT e.* from {$CONFIG->dbprefix}users_entity u join {$CONFIG->dbprefix}entities e on e.guid=u.guid where u.code='$code' and $access"); - if ($row) { + if ($row) { $CODE_TO_GUID_MAP_CACHE[$code] = $row->guid; - return new ElggUser($row); + return new ElggUser($row); } return false; } - - /** - * Get an array of users from their - * - * @param string $email Email address. - * @return Array of users - */ - function get_user_by_email($email) - { - global $CONFIG; - - $email = sanitise_string($email); - - $access = get_access_sql_suffix('e'); - - $query = "SELECT e.* from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid where email='$email' and $access"; - - return get_data($query, 'entity_row_to_elggstar'); - } - - /** - * Searches for a user based on a complete or partial name or username using full text searching. - * - * IMPORTANT NOTE: With MySQL's default setup: - * 1) $criteria must be 4 or more characters long - * 2) If $criteria matches greater than 50% of results NO RESULTS ARE RETURNED! - * - * @param string $criteria The partial or full name or username. - * @param int $limit Limit of the search. - * @param int $offset Offset. - * @param string $order_by The order. - * @param boolean $count Whether to return the count of results or just the results. - */ - function search_for_user($criteria, $limit = 10, $offset = 0, $order_by = "", $count = false) - { - global $CONFIG; - - $criteria = sanitise_string($criteria); - $limit = (int)$limit; - $offset = (int)$offset; - $order_by = sanitise_string($order_by); - - $access = get_access_sql_suffix("e"); - - if ($order_by == "") $order_by = "e.time_created desc"; - - if ($count) { - $query = "SELECT count(e.guid) as total "; - } else { - $query = "SELECT e.* "; - } + + /** + * Get an array of users from their + * + * @param string $email Email address. + * @return Array of users + */ + function get_user_by_email($email) + { + global $CONFIG; + + $email = sanitise_string($email); + + $access = get_access_sql_suffix('e'); + + $query = "SELECT e.* from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid where email='$email' and $access"; + + return get_data($query, 'entity_row_to_elggstar'); + } + + /** + * Searches for a user based on a complete or partial name or username using full text searching. + * + * IMPORTANT NOTE: With MySQL's default setup: + * 1) $criteria must be 4 or more characters long + * 2) If $criteria matches greater than 50% of results NO RESULTS ARE RETURNED! + * + * @param string $criteria The partial or full name or username. + * @param int $limit Limit of the search. + * @param int $offset Offset. + * @param string $order_by The order. + * @param boolean $count Whether to return the count of results or just the results. + */ + function search_for_user($criteria, $limit = 10, $offset = 0, $order_by = "", $count = false) + { + global $CONFIG; + + $criteria = sanitise_string($criteria); + $limit = (int)$limit; + $offset = (int)$offset; + $order_by = sanitise_string($order_by); + + $access = get_access_sql_suffix("e"); + + if ($order_by == "") $order_by = "e.time_created desc"; + + if ($count) { + $query = "SELECT count(e.guid) as total "; + } else { + $query = "SELECT e.* "; + } $query .= "from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid where "; // $query .= " match(u.name,u.username) against ('$criteria') "; $query .= "(u.name like \"%{$criteria}%\" or u.username like \"%{$criteria}%\")"; - $query .= " and $access"; - - if (!$count) { - $query .= " order by $order_by limit $offset, $limit"; // Add order and limit - return get_data($query, "entity_row_to_elggstar"); - } else { - if ($count = get_data_row($query)) { - return $count->total; - } - } - return false; + $query .= " and $access"; + + if (!$count) { + $query .= " order by $order_by limit $offset, $limit"; // Add order and limit + return get_data($query, "entity_row_to_elggstar"); + } else { + if ($count = get_data_row($query)) { + return $count->total; + } + } + return false; } /** @@ -794,277 +795,277 @@ return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview, false); - } - - /** - * A function that returns a maximum of $limit users who have done something within the last - * $seconds seconds. - * - * @param int $seconds Number of seconds (default 600 = 10min) - * @param int $limit Limit, default 10. - * @param int $offset Offset, defualt 0. - */ - function find_active_users($seconds = 600, $limit = 10, $offset = 0) - { - global $CONFIG; - - $seconds = (int)$seconds; - $limit = (int)$limit; - $offset = (int)$offset; - - $time = time() - $seconds; - - $access = get_access_sql_suffix("e"); - - $query = "SELECT distinct e.* from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid = u.guid where u.last_action >= {$time} and $access order by u.last_action desc limit {$offset},{$limit}"; - - return get_data($query, "entity_row_to_elggstar"); - } - - /** - * Generate and send a password request email to a given user's registered email address. - * - * @param int $user_guid - */ - function send_new_password_request($user_guid) - { - global $CONFIG; - - $user_guid = (int)$user_guid; - - $user = get_entity($user_guid); - if ($user) - { - // generate code - $code = generate_random_cleartext_password(); - //create_metadata($user_guid, 'conf_code', $code,'', 0, 0); - set_private_setting($user_guid, 'passwd_conf_code', $code); - - // generate link - $link = $CONFIG->site->url . "action/user/passwordreset?u=$user_guid&c=$code"; - - // generate email - $email = sprintf(elgg_echo('email:resetreq:body'), $user->name, $_SERVER['REMOTE_ADDR'], $link); - - return notify_user($user->guid, $CONFIG->site->guid, elgg_echo('email:resetreq:subject'), $email, NULL, 'email'); - - } - - return false; - } - - /** - * Low level function to reset a given user's password. - * - * This can only be called from execute_new_password_request(). - * - * @param int $user_guid The user. - * @param string $password password text (which will then be converted into a hash and stored) - */ - function force_user_password_reset($user_guid, $password) - { - global $CONFIG; - - if (call_gatekeeper('execute_new_password_request', __FILE__)) - { - $user = get_entity($user_guid); - - if ($user) - { - $hash = generate_user_password($user, $password); - - return update_data("UPDATE {$CONFIG->dbprefix}users_entity set password='$hash' where guid=$user_guid"); - } - } - - return false; - } - - /** - * Validate and execute a password reset for a user. - * - * @param int $user_guid The user id - * @param string $conf_code Confirmation code as sent in the request email. - */ - function execute_new_password_request($user_guid, $conf_code) - { - global $CONFIG; - - $user_guid = (int)$user_guid; - - $user = get_entity($user_guid); - if (($user) && (get_private_setting($user_guid, 'passwd_conf_code') == $conf_code)) - { - $password = generate_random_cleartext_password(); - - if (force_user_password_reset($user_guid, $password)) - { - //remove_metadata($user_guid, 'conf_code'); - remove_private_setting($user_guid, 'passwd_conf_code'); - - $email = sprintf(elgg_echo('email:resetpassword:body'), $user->name, $password); - - return notify_user($user->guid, $CONFIG->site->guid, elgg_echo('email:resetpassword:subject'), $email, NULL, 'email'); - } - } - - return false; - } - - /** - * Set the validation status for a user. - * - * @param bool $status Validated (true) or false - * @param string $method Optional method to say how a user was validated - * @return bool - */ - function set_user_validation_status($user_guid, $status, $method = '') - { - if (!$status) $method = ''; - - create_metadata($user_guid, 'validated', $status,'', 0, 2); - create_metadata($user_guid, 'validated_method', $method,'', 0, 2); - - return true; - } - - /** - * Trigger an event requesting that a user guid be validated somehow - either by email address or some other way. - * - * This event invalidates any existing values and returns - * - * @param unknown_type $user_guid - */ - function request_user_validation($user_guid) - { - $user = get_entity($user_guid); - - if (($user) && ($user instanceof ElggUser)) - { - // invalidate any existing validations - set_user_validation_status($user_guid, false); - - // request validation - trigger_elgg_event('validate', 'user', $user); - - } - } - - /** - * Validates an email address. - * - * @param string $address Email address. - * @return bool - */ - function is_email_address($address) - { - // TODO: Make this better! - - if (strpos($address, '@')=== false) - return false; - - if (strpos($address, '.')=== false) - return false; - - return true; - } - - /** - * Simple function that will generate a random clear text password suitable for feeding into generate_user_password(). - * - * @see generate_user_password - * @return string - */ - function generate_random_cleartext_password() - { - return substr(md5(microtime() . rand()), 0, 8); - } - - /** - * Generate a password for a user, currently uses MD5. - * - * Later may introduce salting etc. - * - * @param ElggUser $user The user this is being generated for. - * @param string $password Password in clear text - */ - function generate_user_password(ElggUser $user, $password) - { - return md5($password . $user->salt); - } - - /** - * Simple function which ensures that a username contains only valid characters. - * - * This should only permit chars that are valid on the file system as well. - * - * @param string $username - * @throws RegistrationException on invalid - */ - function validate_username($username) - { - // Basic, check length - if (strlen($username)<4) throw new RegistrationException(elgg_echo('registration:usernametooshort')); - - // Blacklist for bad characters (partially nicked from mediawiki) - - $blacklist = '/[' . - '\x{0080}-\x{009f}' . # iso-8859-1 control chars - '\x{00a0}' . # non-breaking space - '\x{2000}-\x{200f}' . # various whitespace - '\x{2028}-\x{202f}' . # breaks and control chars - '\x{3000}' . # ideographic space - '\x{e000}-\x{f8ff}' . # private use - ']/u'; - - if ( - preg_match($blacklist, $username) || - - // Belts and braces TODO: Tidy into main unicode - //(strpos($username, '.')!==false) || - (strpos($username, '/')!==false) || - (strpos($username, '\\')!==false) || - (strpos($username, '"')!==false) || - (strpos($username, '\'')!==false) || - (strpos($username, '*')!==false) || - (strpos($username, '&')!==false) || - (strpos($username, ' ')!==false) - ) - throw new RegistrationException(elgg_echo('registration:invalidchars')); - - $result = true; - return $result = trigger_plugin_hook('registeruser:validate:username', 'all', array('username' => $username), $result); - } - - /** - * Simple validation of a password. - * - * @param string $password - * @throws RegistrationException on invalid - */ - function validate_password($password) - { - if (strlen($password)<6) throw new RegistrationException(elgg_echo('registration:passwordtooshort')); - - $result = true; - return $result = trigger_plugin_hook('registeruser:validate:password', 'all', array('password' => $password), $result); - } - - /** - * Simple validation of a email. - * - * @param string $address - * @throws RegistrationException on invalid - * @return bool - */ - function validate_email_address($address) - { - if (!is_email_address($address)) throw new RegistrationException(elgg_echo('registration:notemail')); - - // Got here, so lets try a hook (defaulting to ok) - $result = true; - return $result = trigger_plugin_hook('registeruser:validate:email', 'all', array('email' => $address), $result); - } + } + + /** + * A function that returns a maximum of $limit users who have done something within the last + * $seconds seconds. + * + * @param int $seconds Number of seconds (default 600 = 10min) + * @param int $limit Limit, default 10. + * @param int $offset Offset, defualt 0. + */ + function find_active_users($seconds = 600, $limit = 10, $offset = 0) + { + global $CONFIG; + + $seconds = (int)$seconds; + $limit = (int)$limit; + $offset = (int)$offset; + + $time = time() - $seconds; + + $access = get_access_sql_suffix("e"); + + $query = "SELECT distinct e.* from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid = u.guid where u.last_action >= {$time} and $access order by u.last_action desc limit {$offset},{$limit}"; + + return get_data($query, "entity_row_to_elggstar"); + } + + /** + * Generate and send a password request email to a given user's registered email address. + * + * @param int $user_guid + */ + function send_new_password_request($user_guid) + { + global $CONFIG; + + $user_guid = (int)$user_guid; + + $user = get_entity($user_guid); + if ($user) + { + // generate code + $code = generate_random_cleartext_password(); + //create_metadata($user_guid, 'conf_code', $code,'', 0, 0); + set_private_setting($user_guid, 'passwd_conf_code', $code); + + // generate link + $link = $CONFIG->site->url . "action/user/passwordreset?u=$user_guid&c=$code"; + + // generate email + $email = sprintf(elgg_echo('email:resetreq:body'), $user->name, $_SERVER['REMOTE_ADDR'], $link); + + return notify_user($user->guid, $CONFIG->site->guid, elgg_echo('email:resetreq:subject'), $email, NULL, 'email'); + + } + + return false; + } + + /** + * Low level function to reset a given user's password. + * + * This can only be called from execute_new_password_request(). + * + * @param int $user_guid The user. + * @param string $password password text (which will then be converted into a hash and stored) + */ + function force_user_password_reset($user_guid, $password) + { + global $CONFIG; + + if (call_gatekeeper('execute_new_password_request', __FILE__)) + { + $user = get_entity($user_guid); + + if ($user) + { + $hash = generate_user_password($user, $password); + + return update_data("UPDATE {$CONFIG->dbprefix}users_entity set password='$hash' where guid=$user_guid"); + } + } + + return false; + } + + /** + * Validate and execute a password reset for a user. + * + * @param int $user_guid The user id + * @param string $conf_code Confirmation code as sent in the request email. + */ + function execute_new_password_request($user_guid, $conf_code) + { + global $CONFIG; + + $user_guid = (int)$user_guid; + + $user = get_entity($user_guid); + if (($user) && (get_private_setting($user_guid, 'passwd_conf_code') == $conf_code)) + { + $password = generate_random_cleartext_password(); + + if (force_user_password_reset($user_guid, $password)) + { + //remove_metadata($user_guid, 'conf_code'); + remove_private_setting($user_guid, 'passwd_conf_code'); + + $email = sprintf(elgg_echo('email:resetpassword:body'), $user->name, $password); + + return notify_user($user->guid, $CONFIG->site->guid, elgg_echo('email:resetpassword:subject'), $email, NULL, 'email'); + } + } + + return false; + } + + /** + * Set the validation status for a user. + * + * @param bool $status Validated (true) or false + * @param string $method Optional method to say how a user was validated + * @return bool + */ + function set_user_validation_status($user_guid, $status, $method = '') + { + if (!$status) $method = ''; + + create_metadata($user_guid, 'validated', $status,'', 0, 2); + create_metadata($user_guid, 'validated_method', $method,'', 0, 2); + + return true; + } + + /** + * Trigger an event requesting that a user guid be validated somehow - either by email address or some other way. + * + * This event invalidates any existing values and returns + * + * @param unknown_type $user_guid + */ + function request_user_validation($user_guid) + { + $user = get_entity($user_guid); + + if (($user) && ($user instanceof ElggUser)) + { + // invalidate any existing validations + set_user_validation_status($user_guid, false); + + // request validation + trigger_elgg_event('validate', 'user', $user); + + } + } + + /** + * Validates an email address. + * + * @param string $address Email address. + * @return bool + */ + function is_email_address($address) + { + // TODO: Make this better! + + if (strpos($address, '@')=== false) + return false; + + if (strpos($address, '.')=== false) + return false; + + return true; + } + + /** + * Simple function that will generate a random clear text password suitable for feeding into generate_user_password(). + * + * @see generate_user_password + * @return string + */ + function generate_random_cleartext_password() + { + return substr(md5(microtime() . rand()), 0, 8); + } + + /** + * Generate a password for a user, currently uses MD5. + * + * Later may introduce salting etc. + * + * @param ElggUser $user The user this is being generated for. + * @param string $password Password in clear text + */ + function generate_user_password(ElggUser $user, $password) + { + return md5($password . $user->salt); + } + + /** + * Simple function which ensures that a username contains only valid characters. + * + * This should only permit chars that are valid on the file system as well. + * + * @param string $username + * @throws RegistrationException on invalid + */ + function validate_username($username) + { + // Basic, check length + if (strlen($username)<4) throw new RegistrationException(elgg_echo('registration:usernametooshort')); + + // Blacklist for bad characters (partially nicked from mediawiki) + + $blacklist = '/[' . + '\x{0080}-\x{009f}' . # iso-8859-1 control chars + '\x{00a0}' . # non-breaking space + '\x{2000}-\x{200f}' . # various whitespace + '\x{2028}-\x{202f}' . # breaks and control chars + '\x{3000}' . # ideographic space + '\x{e000}-\x{f8ff}' . # private use + ']/u'; + + if ( + preg_match($blacklist, $username) || + + // Belts and braces TODO: Tidy into main unicode + //(strpos($username, '.')!==false) || + (strpos($username, '/')!==false) || + (strpos($username, '\\')!==false) || + (strpos($username, '"')!==false) || + (strpos($username, '\'')!==false) || + (strpos($username, '*')!==false) || + (strpos($username, '&')!==false) || + (strpos($username, ' ')!==false) + ) + throw new RegistrationException(elgg_echo('registration:invalidchars')); + + $result = true; + return $result = trigger_plugin_hook('registeruser:validate:username', 'all', array('username' => $username), $result); + } + + /** + * Simple validation of a password. + * + * @param string $password + * @throws RegistrationException on invalid + */ + function validate_password($password) + { + if (strlen($password)<6) throw new RegistrationException(elgg_echo('registration:passwordtooshort')); + + $result = true; + return $result = trigger_plugin_hook('registeruser:validate:password', 'all', array('password' => $password), $result); + } + + /** + * Simple validation of a email. + * + * @param string $address + * @throws RegistrationException on invalid + * @return bool + */ + function validate_email_address($address) + { + if (!is_email_address($address)) throw new RegistrationException(elgg_echo('registration:notemail')); + + // Got here, so lets try a hook (defaulting to ok) + $result = true; + return $result = trigger_plugin_hook('registeruser:validate:email', 'all', array('email' => $address), $result); + } /** * Registers a user, returning false if the username already exists @@ -1072,7 +1073,7 @@ * @param string $username The username of the new user * @param string $password The password * @param string $name The user's display name - * @param string $email Their email address + * @param string $email Their email address * @param bool $allow_multiple_emails Allow the same email address to be registered multiple times? * @param int $friend_guid Optionally, GUID of a user this user will friend once fully registered * @return int|false The new user's GUID; false on failure @@ -1080,11 +1081,11 @@ function register_user($username, $password, $name, $email, $allow_multiple_emails = false, $friend_guid = 0, $invitecode = '') { // Load the configuration - global $CONFIG; + global $CONFIG; - $username = sanitise_string($username); - $password = sanitise_string($password); - $name = sanitise_string($name); + $username = sanitise_string($username); + $password = sanitise_string($password); + $name = sanitise_string($name); $email = sanitise_string($email); // A little sanity checking @@ -1094,32 +1095,32 @@ || empty($email)) { return false; } - - // See if it exists and is disabled - $access_status = access_get_show_hidden_status(); - access_show_hidden_entities(true); - - // Validate email address - if (!validate_email_address($email)) throw new RegistrationException(elgg_echo('registration:emailnotvalid')); - - // Validate password - if (!validate_password($password)) throw new RegistrationException(elgg_echo('registration:passwordnotvalid')); - - // Validate the username - if (!validate_username($username)) throw new RegistrationException(elgg_echo('registration:usernamenotvalid')); + + // See if it exists and is disabled + $access_status = access_get_show_hidden_status(); + access_show_hidden_entities(true); + + // Validate email address + if (!validate_email_address($email)) throw new RegistrationException(elgg_echo('registration:emailnotvalid')); + + // Validate password + if (!validate_password($password)) throw new RegistrationException(elgg_echo('registration:passwordnotvalid')); + + // Validate the username + if (!validate_username($username)) throw new RegistrationException(elgg_echo('registration:usernamenotvalid')); // Check to see if $username exists already if ($user = get_user_by_username($username)) { - //return false; + //return false; throw new RegistrationException(elgg_echo('registration:userexists')); - } - - // If we're not allowed multiple emails then see if this address has been used before - if ((!$allow_multiple_emails) && (get_user_by_email($email))) - { - throw new RegistrationException(elgg_echo('registration:dupeemail')); - } - + } + + // If we're not allowed multiple emails then see if this address has been used before + if ((!$allow_multiple_emails) && (get_user_by_email($email))) + { + throw new RegistrationException(elgg_echo('registration:dupeemail')); + } + access_show_hidden_entities($access_status); // Check to see if we've registered the first admin yet. @@ -1131,8 +1132,8 @@ $user->username = $username; $user->email = $email; $user->name = $name; - $user->access_id = 2; - $user->salt = generate_random_cleartext_password(); // Note salt generated before password! + $user->access_id = 2; + $user->salt = generate_random_cleartext_password(); // Note salt generated before password! $user->password = generate_user_password($user, $password); $user->save(); @@ -1149,10 +1150,10 @@ if (!$admin) { $user->admin = true; datalist_set('admin_registered',1); - } - - // Turn on email notifications by default - set_user_notification_setting($user->getGUID(), 'email', true); + } + + // Turn on email notifications by default + set_user_notification_setting($user->getGUID(), 'email', true); return $user->getGUID(); } @@ -1175,7 +1176,7 @@ * */ function collections_submenu_items() { - global $CONFIG; + global $CONFIG; $user = get_loggedin_user(); add_submenu_item(elgg_echo('friends:collections'), $CONFIG->wwwroot . "pg/collections/" . $user->username); add_submenu_item(elgg_echo('friends:collections:add'),$CONFIG->wwwroot."pg/collections/add"); @@ -1254,53 +1255,53 @@ $user_guid = (int) $user_guid; global $CONFIG; $time = time(); - + execute_delayed_write_query("UPDATE {$CONFIG->dbprefix}users_entity set prev_last_action = last_action, last_action = {$time} where guid = {$user_guid}"); - } - - /** - * Sets the last logon time of the given user to right now. - * - * @param int $user_guid The user GUID - */ - function set_last_login($user_guid) { - - $user_guid = (int) $user_guid; - global $CONFIG; - $time = time(); - - execute_delayed_write_query("UPDATE {$CONFIG->dbprefix}users_entity set prev_last_login = last_login, last_login = {$time} where guid = {$user_guid}"); - - } - - /** - * A permissions plugin hook that grants access to users if they are newly created - allows - * for email activation. - * - * TODO: Do this in a better way! - * - * @param unknown_type $hook - * @param unknown_type $entity_type - * @param unknown_type $returnvalue - * @param unknown_type $params - */ - function new_user_enable_permissions_check($hook, $entity_type, $returnvalue, $params) - { - $entity = $params['entity']; - $user = $params['user']; - if (($entity) && ($entity instanceof ElggUser)) - { - if ( - (($entity->disable_reason == 'new_user') || ( - $entity->last_action == 0 && $entity->last_login == 0 - )) - && (!isloggedin())) - return true; - - } - - return $returnvalue; + } + + /** + * Sets the last logon time of the given user to right now. + * + * @param int $user_guid The user GUID + */ + function set_last_login($user_guid) { + + $user_guid = (int) $user_guid; + global $CONFIG; + $time = time(); + + execute_delayed_write_query("UPDATE {$CONFIG->dbprefix}users_entity set prev_last_login = last_login, last_login = {$time} where guid = {$user_guid}"); + + } + + /** + * A permissions plugin hook that grants access to users if they are newly created - allows + * for email activation. + * + * TODO: Do this in a better way! + * + * @param unknown_type $hook + * @param unknown_type $entity_type + * @param unknown_type $returnvalue + * @param unknown_type $params + */ + function new_user_enable_permissions_check($hook, $entity_type, $returnvalue, $params) + { + $entity = $params['entity']; + $user = $params['user']; + if (($entity) && ($entity instanceof ElggUser)) + { + if ( + (($entity->disable_reason == 'new_user') || ( + $entity->last_action == 0 && $entity->last_login == 0 + )) + && (!isloggedin())) + return true; + + } + + return $returnvalue; } /** @@ -1332,9 +1333,9 @@ global $CONFIG; // Set up menu for logged in users - if (isloggedin()) { + if (isloggedin()) { $user = get_loggedin_user(); - add_menu(elgg_echo('friends'), $CONFIG->wwwroot . "pg/friends/" . $user->username); + add_menu(elgg_echo('friends'), $CONFIG->wwwroot . "pg/friends/" . $user->username); } register_page_handler('friends','friends_page_handler'); @@ -1342,33 +1343,33 @@ register_page_handler('collections','collections_page_handler'); register_page_handler('dashboard','dashboard_page_handler'); register_action("register",true); - register_action("useradd",true); + register_action("useradd",true); register_action("friends/add"); register_action("friends/remove"); register_action('friends/addcollection'); register_action('friends/deletecollection'); register_action('friends/editcollection'); - register_action("user/spotlight"); + register_action("user/spotlight"); - register_action("usersettings/save"); - - register_action("user/passwordreset"); + register_action("usersettings/save"); + + register_action("user/passwordreset"); register_action("user/requestnewpassword"); - - // User name change - extend_elgg_settings_page('user/settings/name', 'usersettings/user', 1); - //register_action("user/name"); - - // User password change - extend_elgg_settings_page('user/settings/password', 'usersettings/user', 1); - //register_action("user/password"); - - // Add email settings - extend_elgg_settings_page('user/settings/email', 'usersettings/user', 1); - //register_action("email/save"); - - // Add language settings - extend_elgg_settings_page('user/settings/language', 'usersettings/user', 1); + + // User name change + extend_elgg_settings_page('user/settings/name', 'usersettings/user', 1); + //register_action("user/name"); + + // User password change + extend_elgg_settings_page('user/settings/password', 'usersettings/user', 1); + //register_action("user/password"); + + // Add email settings + extend_elgg_settings_page('user/settings/email', 'usersettings/user', 1); + //register_action("email/save"); + + // Add language settings + extend_elgg_settings_page('user/settings/language', 'usersettings/user', 1); //register_action("user/language"); // Register the user type @@ -1376,10 +1377,10 @@ register_plugin_hook('usersettings:save','user','users_settings_save'); register_plugin_hook('search','all','search_list_users_by_name'); - - - // Handle a special case for newly created users when the user is not logged in - // TODO: handle this better! + + + // Handle a special case for newly created users when the user is not logged in + // TODO: handle this better! register_plugin_hook('permissions_check','all','new_user_enable_permissions_check'); } -- cgit v1.2.3