2007-04-16 11:58:25 +00:00
< ? php
2009-07-21 06:36:12 +00:00
/** @private */
2009-05-30 13:47:35 +00:00
function _new_user ( $row ) {
return new User ( $row );
}
2012-02-07 13:44:54 +00:00
2009-07-19 07:38:13 +00:00
/**
2007-12-06 11:01:18 +00:00
* An object representing a row in the " users " table .
2009-07-19 07:38:13 +00:00
*
2014-04-26 09:01:49 +00:00
* The currently logged in user will always be accessible via the global variable $user
2007-12-06 11:01:18 +00:00
*/
2007-04-16 11:58:25 +00:00
class User {
2014-04-26 09:01:49 +00:00
/** @var int */
2014-04-24 08:36:05 +00:00
public $id ;
2014-04-26 09:01:49 +00:00
/** @var string */
2014-04-24 08:36:05 +00:00
public $name ;
2014-04-26 09:01:49 +00:00
/** @var string */
2014-04-24 08:36:05 +00:00
public $email ;
2014-04-26 09:01:49 +00:00
2014-04-24 08:36:05 +00:00
public $join_date ;
2014-04-26 09:01:49 +00:00
2014-04-27 19:33:57 +00:00
/** @var string */
2014-04-24 08:36:05 +00:00
public $passhash ;
2014-03-30 12:26:48 +00:00
2014-04-26 09:01:49 +00:00
/** @var UserClass */
2014-04-27 19:33:57 +00:00
public $class ;
2008-08-23 12:05:24 +00:00
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Initialisation *
* *
* User objects shouldn ' t be created directly , they should be *
* fetched from the database like so : *
* *
2009-05-30 13:47:35 +00:00
* $user = User :: by_name ( " bob " ); *
2008-08-23 12:05:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-19 07:38:13 +00:00
/**
* One will very rarely construct a user directly , more common
2014-04-27 19:33:57 +00:00
* would be to use User :: by_id , User :: by_session , etc .
*
* @ param mixed $row
2009-07-19 07:38:13 +00:00
*/
2014-03-22 09:00:59 +00:00
public function __construct ( $row ) {
2012-02-14 20:38:19 +00:00
global $_user_classes ;
2007-04-16 11:58:25 +00:00
$this -> id = int_escape ( $row [ 'id' ]);
$this -> name = $row [ 'name' ];
$this -> email = $row [ 'email' ];
$this -> join_date = $row [ 'joindate' ];
2010-05-28 12:04:57 +00:00
$this -> passhash = $row [ 'pass' ];
2012-02-14 20:38:19 +00:00
$this -> class = $_user_classes [ $row [ " class " ]];
2007-04-16 11:58:25 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* Construct a User by session .
*
* @ param string $name
* @ param string $session
* @ return null | User
*/
2012-02-02 13:58:48 +00:00
public static function by_session ( /*string*/ $name , /*string*/ $session ) {
2009-05-11 14:04:33 +00:00
global $config , $database ;
2012-06-23 22:38:28 +00:00
$row = $database -> cache -> get ( " user-session- $name - $session " );
if ( ! $row ) {
2012-06-23 23:57:55 +00:00
if ( $database -> get_driver_name () === " mysql " ) {
2012-06-23 23:25:47 +00:00
$query = " SELECT * FROM users WHERE name = :name AND md5(concat(pass, :ip)) = :sess " ;
}
else {
$query = " SELECT * FROM users WHERE name = :name AND md5(pass || :ip) = :sess " ;
}
2012-06-23 22:38:28 +00:00
$row = $database -> get_row ( $query , array ( " name " => $name , " ip " => get_session_ip ( $config ), " sess " => $session ));
2012-06-24 00:57:06 +00:00
$database -> cache -> set ( " user-session- $name - $session " , $row , 600 );
2012-06-23 22:38:28 +00:00
}
2009-05-11 14:04:33 +00:00
return is_null ( $row ) ? null : new User ( $row );
2008-08-23 12:05:24 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* Construct a User by session .
* @ param int $id
* @ return null | User
*/
2012-02-02 13:58:48 +00:00
public static function by_id ( /*int*/ $id ) {
2008-08-23 12:05:24 +00:00
assert ( is_numeric ( $id ));
2009-05-11 14:04:33 +00:00
global $database ;
2012-01-11 20:57:00 +00:00
if ( $id === 1 ) {
$cached = $database -> cache -> get ( 'user-id:' . $id );
2011-03-23 11:26:11 +00:00
if ( $cached ) return new User ( $cached );
}
2011-01-01 15:58:09 +00:00
$row = $database -> get_row ( " SELECT * FROM users WHERE id = :id " , array ( " id " => $id ));
2012-06-24 00:57:06 +00:00
if ( $id === 1 ) $database -> cache -> set ( 'user-id:' . $id , $row , 600 );
2009-05-11 14:04:33 +00:00
return is_null ( $row ) ? null : new User ( $row );
2008-08-23 12:05:24 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* Construct a User by name .
* @ param string $name
* @ return null | User
*/
2012-02-02 13:58:48 +00:00
public static function by_name ( /*string*/ $name ) {
2008-08-23 12:05:24 +00:00
assert ( is_string ( $name ));
2009-05-11 14:04:33 +00:00
global $database ;
2012-12-10 21:28:41 +00:00
$row = $database -> get_row ( $database -> scoreql_to_sql ( " SELECT * FROM users WHERE SCORE_STRNORM(name) = SCORE_STRNORM(:name) " ), array ( " name " => $name ));
2009-05-11 14:04:33 +00:00
return is_null ( $row ) ? null : new User ( $row );
2008-08-23 12:05:24 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* Construct a User by name and hash .
* @ param string $name
* @ param string $hash
* @ return null | User
*/
2012-02-02 13:58:48 +00:00
public static function by_name_and_hash ( /*string*/ $name , /*string*/ $hash ) {
2008-08-23 12:05:24 +00:00
assert ( is_string ( $name ));
assert ( is_string ( $hash ));
assert ( strlen ( $hash ) == 32 );
2009-05-11 14:04:33 +00:00
global $database ;
2012-12-10 21:28:41 +00:00
$row = $database -> get_row ( $database -> scoreql_to_sql ( " SELECT * FROM users WHERE SCORE_STRNORM(name) = SCORE_STRNORM(:name) AND pass = :hash " ), array ( " name " => $name , " hash " => $hash ));
2009-05-11 14:04:33 +00:00
return is_null ( $row ) ? null : new User ( $row );
2008-08-23 12:05:24 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* @ param int $offset
* @ param int $limit
* @ return array
*/
2012-02-02 13:58:48 +00:00
public static function by_list ( /*int*/ $offset , /*int*/ $limit = 50 ) {
2009-05-30 13:47:35 +00:00
assert ( is_numeric ( $offset ));
assert ( is_numeric ( $limit ));
global $database ;
2011-01-01 15:58:09 +00:00
$rows = $database -> get_all ( " SELECT * FROM users WHERE id >= :start AND id < :end " , array ( " start " => $offset , " end " => $offset + $limit ));
2009-05-30 13:47:35 +00:00
return array_map ( " _new_user " , $rows );
}
2008-08-23 12:05:24 +00:00
2014-04-26 09:01:49 +00:00
/* useful user object functions start here */
/**
* @ param string $ability
* @ return bool
2008-08-23 12:05:24 +00:00
*/
2012-02-07 13:44:54 +00:00
public function can ( $ability ) {
2012-02-14 20:38:19 +00:00
return $this -> class -> can ( $ability );
2012-02-07 13:44:54 +00:00
}
2008-08-23 12:05:24 +00:00
2009-07-19 07:38:13 +00:00
/**
2014-04-27 19:33:57 +00:00
* Test if this user is anonymous ( not logged in ) .
2009-07-19 07:38:13 +00:00
*
2014-04-24 23:08:23 +00:00
* @ return bool
2009-07-19 07:38:13 +00:00
*/
2007-04-16 11:58:25 +00:00
public function is_anonymous () {
2009-05-11 14:04:33 +00:00
global $config ;
2012-01-12 19:46:58 +00:00
return ( $this -> id === $config -> get_int ( 'anon_id' ));
2007-04-16 11:58:25 +00:00
}
2010-01-12 15:01:34 +00:00
/**
2014-04-27 19:33:57 +00:00
* Test if this user is logged in .
2010-01-12 15:01:34 +00:00
*
2014-04-24 23:08:23 +00:00
* @ return bool
2010-01-12 15:01:34 +00:00
*/
public function is_logged_in () {
global $config ;
2012-01-12 19:46:58 +00:00
return ( $this -> id !== $config -> get_int ( 'anon_id' ));
2010-01-12 15:01:34 +00:00
}
2009-07-19 07:38:13 +00:00
/**
2014-04-27 19:33:57 +00:00
* Test if this user is an administrator .
2009-07-19 07:38:13 +00:00
*
2014-04-24 23:08:23 +00:00
* @ return bool
2009-07-19 07:38:13 +00:00
*/
2007-04-16 11:58:25 +00:00
public function is_admin () {
2012-02-14 21:15:19 +00:00
return ( $this -> class -> name === " admin " );
2007-04-16 11:58:25 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* @ param string $class
*/
2012-02-14 20:38:19 +00:00
public function set_class ( /*string*/ $class ) {
assert ( is_string ( $class ));
2009-05-11 14:04:33 +00:00
global $database ;
2012-02-14 20:38:19 +00:00
$database -> Execute ( " UPDATE users SET class=:class WHERE id=:id " , array ( " class " => $class , " id " => $this -> id ));
log_info ( " core-user " , 'Set class for ' . $this -> name . ' to ' . $class );
2007-04-16 11:58:25 +00:00
}
2014-04-26 09:01:49 +00:00
/**
* @ param string $password
*/
2012-02-02 13:58:48 +00:00
public function set_password ( /*string*/ $password ) {
2009-05-11 14:04:33 +00:00
global $database ;
2007-11-04 03:51:41 +00:00
$hash = md5 ( strtolower ( $this -> name ) . $password );
2011-01-01 15:58:09 +00:00
$database -> Execute ( " UPDATE users SET pass=:hash WHERE id=:id " , array ( " hash " => $hash , " id " => $this -> id ));
2012-01-12 19:46:58 +00:00
log_info ( " core-user " , 'Set password for ' . $this -> name );
2007-11-04 03:51:41 +00:00
}
2009-08-11 16:07:03 +00:00
2014-04-27 19:33:57 +00:00
/**
* @ param string $address
*/
2012-02-02 13:58:48 +00:00
public function set_email ( /*string*/ $address ) {
2009-08-11 16:07:03 +00:00
global $database ;
2011-01-01 15:58:09 +00:00
$database -> Execute ( " UPDATE users SET email=:email WHERE id=:id " , array ( " email " => $address , " id " => $this -> id ));
2012-01-12 19:46:58 +00:00
log_info ( " core-user " , 'Set email for ' . $this -> name );
2009-08-11 16:07:03 +00:00
}
2009-10-08 01:57:28 +00:00
/**
* Get a snippet of HTML which will render the user ' s avatar , be that
2014-04-27 19:33:57 +00:00
* a local file , a remote file , a gravatar , a something else , etc .
*
2014-04-24 23:08:23 +00:00
* @ return String of HTML
2009-10-08 01:57:28 +00:00
*/
public function get_avatar_html () {
// FIXME: configurable
2009-10-08 11:40:52 +00:00
global $config ;
2012-01-11 20:57:00 +00:00
if ( $config -> get_string ( " avatar_host " ) === " gravatar " ) {
2009-10-08 11:40:52 +00:00
if ( ! empty ( $this -> email )) {
$hash = md5 ( strtolower ( $this -> email ));
2010-04-21 16:56:01 +00:00
$s = $config -> get_string ( " avatar_gravatar_size " );
2012-02-09 17:37:41 +00:00
$d = urlencode ( $config -> get_string ( " avatar_gravatar_default " ));
2010-04-21 16:56:01 +00:00
$r = $config -> get_string ( " avatar_gravatar_rating " );
2012-12-30 18:08:58 +00:00
$cb = date ( " Y-m-d " );
return " <img class= \" avatar gravatar \" src= \" http://www.gravatar.com/avatar/ $hash .jpg?s= $s &d= $d &r= $r &cacheBreak= $cb\ " > " ;
2009-10-08 11:40:52 +00:00
}
2009-10-08 01:57:28 +00:00
}
return " " ;
}
2010-05-28 12:04:57 +00:00
/**
* Get an auth token to be used in POST forms
*
* password = secret , avoid storing directly
* passhash = md5 ( password ), so someone who gets to the database can ' t get passwords
* sesskey = md5 ( passhash . IP ), so if it gets sniffed it can ' t be used from another IP ,
* and it can ' t be used to get the passhash to generate new sesskeys
* authtok = md5 ( sesskey , salt ), presented to the user in web forms , to make sure that
* the form was generated within the session . Salted and re - hashed so that
* reading a web page from the user 's cache doesn' t give access to the session key
2012-02-08 01:05:38 +00:00
*
2014-04-27 19:33:57 +00:00
* @ return string A string containing auth token ( MD5sum )
2010-05-28 12:04:57 +00:00
*/
public function get_auth_token () {
global $config ;
2012-02-02 03:53:18 +00:00
$salt = DATABASE_DSN ;
2010-05-28 12:04:57 +00:00
$addr = get_session_ip ( $config );
2010-09-22 12:20:08 +00:00
return md5 ( md5 ( $this -> passhash . $addr ) . " salty-csrf- " . $salt );
2010-05-28 12:04:57 +00:00
}
public function get_auth_html () {
$at = $this -> get_auth_token ();
2012-01-11 20:57:00 +00:00
return '<input type="hidden" name="auth_token" value="' . $at . '">' ;
2010-05-28 12:04:57 +00:00
}
public function check_auth_token () {
2012-01-26 17:36:22 +00:00
return ( isset ( $_POST [ " auth_token " ]) && $_POST [ " auth_token " ] == $this -> get_auth_token ());
2010-05-28 12:04:57 +00:00
}
2007-04-16 11:58:25 +00:00
}
2012-10-16 21:58:47 +00:00
class MockUser extends User {
public function __construct ( $name ) {
$row = array (
" name " => $name ,
" id " => 1 ,
" email " => " " ,
" joindate " => " " ,
" pass " => " " ,
" class " => " admin " ,
);
parent :: __construct ( $row );
}
}
2014-04-24 23:01:47 +00:00