* @package MediaWiki
*/
class User {
- /**#@+
- * @access private
- */
- var $mId, $mName, $mPassword, $mEmail, $mNewtalk;
- var $mEmailAuthenticated;
- var $mRights, $mOptions;
- var $mDataLoaded, $mNewpassword;
- var $mSkin;
- var $mBlockedby, $mBlockreason;
- var $mTouched;
- var $mToken;
- var $mRealName;
- var $mHash;
- var $mGroups;
- var $mVersion; // serialized version
- var $mRegistration;
-
- /** Construct using User:loadDefaults() */
+ /*
+ * When adding a new private variable, dont forget to add it to __sleep()
+ */
+ /**@{{
+ * @private
+ */
+ private $mBlockedby; //!<
+ private $mBlockreason; //!<
+ private $mDataLoaded; //!<
+ private $mEmail; //!<
+ private $mEmailAuthenticated; //!<
+ private $mGroups; //!<
+ private $mHash; //!<
+ private $mId; //!<
+ private $mName; //!<
+ private $mNewpassword; //!<
+ private $mNewtalk; //!<
+ private $mOptions; //!<
+ private $mPassword; //!<
+ private $mRealName; //!<
+ private $mRegistration; //!<
+ private $mRights; //!<
+ private $mSkin; //!<
+ private $mToken; //!<
+ private $mTouched; //!<
+ private $mVersion; //!< serialized version
+ /**@}} */
+
+ /** Constructor using User:loadDefaults() */
function User() {
$this->loadDefaults();
$this->mVersion = MW_USER_VERSION;
/**
* Serialze sleep function, for better cache efficiency and avoidance of
- * silly "incomplete type" errors when skins are cached
+ * silly "incomplete type" errors when skins are cached. The array should
+ * contain names of private variables (see at top of User.php).
*/
function __sleep() {
- return array( 'mId', 'mName', 'mPassword', 'mEmail', 'mNewtalk',
- 'mEmailAuthenticated', 'mRights', 'mOptions', 'mDataLoaded',
- 'mNewpassword', 'mBlockedby', 'mBlockreason', 'mTouched',
- 'mToken', 'mRealName', 'mHash', 'mGroups', 'mRegistration' );
+ return array(
+'mBlockedby',
+'mBlockreason',
+'mDataLoaded',
+'mEmail',
+'mEmailAuthenticated',
+'mGroups',
+'mHash',
+'mId',
+'mName',
+'mNewpassword',
+'mNewtalk',
+'mOptions',
+'mPassword',
+'mRealName',
+'mRegistration',
+'mRights',
+'mToken',
+'mTouched',
+'mVersion',
+);
}
/**
|| $parsed->getNamespace()
|| strcmp( $name, $parsed->getPrefixedText() ) )
return false;
- else
- return true;
+
+ // Check an additional blacklist of troublemaker characters.
+ // Should these be merged into the title char list?
+ $unicodeBlacklist = '/[' .
+ '\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( $unicodeBlacklist, $name ) ) {
+ return false;
+ }
+
+ return true;
}
/**
$fname = 'User::loadDefaults' . $n;
wfProfileIn( $fname );
- global $wgContLang, $wgDBname;
+ global $wgCookiePrefix;
global $wgNamespacesToBeSearchedDefault;
$this->mId = 0;
$this->setToken(); # Random
$this->mHash = false;
- if ( isset( $_COOKIE[$wgDBname.'LoggedOut'] ) ) {
- $this->mTouched = wfTimestamp( TS_MW, $_COOKIE[$wgDBname.'LoggedOut'] );
+ if ( isset( $_COOKIE[$wgCookiePrefix.'LoggedOut'] ) ) {
+ $this->mTouched = wfTimestamp( TS_MW, $_COOKIE[$wgCookiePrefix.'LoggedOut'] );
}
else {
$this->mTouched = '0'; # Allow any pages to be cached
*
* @return array
* @static
- * @access private
+ * @private
*/
function getDefaultOptions() {
/**
* @param string $opt
* @return string
* @static
- * @access public
+ * @public
*/
function getDefaultOption( $opt ) {
$defOpts = User::getDefaultOptions();
/**
* Get blocking information
- * @access private
+ * @private
* @param bool $bFromSlave Specify whether to check slave or master. To improve performance,
* non-critical checks are done against slaves. Check when actually saving should be done against
* master.
}
# Proxy blocking
- if ( !$this->isSysop() && !in_array( $ip, $wgProxyWhitelist ) ) {
+ # FIXME ? proxyunbannable is to deprecate the old isSysop()
+ if ( !$this->isAllowed('proxyunbannable') && !in_array( $ip, $wgProxyWhitelist ) ) {
# Local list
if ( wfIsLocallyBlockedProxy( $ip ) ) {
* last-hit counters will be shared across wikis.
*
* @return bool true if a rate limiter was tripped
- * @access public
+ * @public
*/
function pingLimiter( $action='edit' ) {
global $wgRateLimits;
/**
* Initialise php session
+ * @static
*/
- function SetupSession() {
+ static function SetupSession() {
global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain;
if( $wgSessionsInMemcached ) {
require_once( 'MemcachedSessions.php' );
* Create a new user object using data from session
* @static
*/
- function loadFromSession() {
- global $wgMemc, $wgDBname;
+ static function loadFromSession() {
+ global $wgMemc, $wgDBname, $wgCookiePrefix;
if ( isset( $_SESSION['wsUserID'] ) ) {
if ( 0 != $_SESSION['wsUserID'] ) {
} else {
return new User();
}
- } else if ( isset( $_COOKIE["{$wgDBname}UserID"] ) ) {
- $sId = intval( $_COOKIE["{$wgDBname}UserID"] );
+ } else if ( isset( $_COOKIE["{$wgCookiePrefix}UserID"] ) ) {
+ $sId = intval( $_COOKIE["{$wgCookiePrefix}UserID"] );
$_SESSION['wsUserID'] = $sId;
} else {
return new User();
}
if ( isset( $_SESSION['wsUserName'] ) ) {
$sName = $_SESSION['wsUserName'];
- } else if ( isset( $_COOKIE["{$wgDBname}UserName"] ) ) {
- $sName = $_COOKIE["{$wgDBname}UserName"];
+ } else if ( isset( $_COOKIE["{$wgCookiePrefix}UserName"] ) ) {
+ $sName = $_COOKIE["{$wgCookiePrefix}UserName"];
$_SESSION['wsUserName'] = $sName;
} else {
return new User();
if ( isset( $_SESSION['wsToken'] ) ) {
$passwordCorrect = $_SESSION['wsToken'] == $user->mToken;
- } else if ( isset( $_COOKIE["{$wgDBname}Token"] ) ) {
- $passwordCorrect = $user->mToken == $_COOKIE["{$wgDBname}Token"];
+ } else if ( isset( $_COOKIE["{$wgCookiePrefix}Token"] ) ) {
+ $passwordCorrect = $user->mToken == $_COOKIE["{$wgCookiePrefix}Token"];
} else {
return new User(); # Can't log in from session
}
/**
* Return the title dbkey form of the name, for eg user pages.
* @return string
- * @access public
+ * @public
*/
function getTitleKey() {
return str_replace( ' ', '_', $this->getName() );
return (bool)$this->mNewtalk;
}
+ /**
+ * Return the talk page(s) this user has new messages on.
+ */
+ function getNewMessageLinks() {
+ global $wgDBname;
+ $talks = array();
+ if (!wfRunHooks('UserRetrieveNewTalks', array(&$this, &$talks)))
+ return $talks;
+
+ if (!$this->getNewtalk())
+ return array();
+ $up = $this->getUserPage();
+ $utp = $up->getTalkPage();
+ return array(array("wiki" => $wgDBname, "link" => $utp->getLocalURL()));
+ }
+
+
/**
* Perform a user_newtalk check on current slaves; if the memcached data
* is funky we don't want newtalk state to get stuck on save, as that's
* @param string $field
* @param mixed $id
* @return bool
- * @access private
+ * @private
*/
function checkNewtalk( $field, $id ) {
$fname = 'User::checkNewtalk';
* Add or update the
* @param string $field
* @param mixed $id
- * @access private
+ * @private
*/
function updateNewtalk( $field, $id ) {
$fname = 'User::updateNewtalk';
* Clear the new messages flag for the given user
* @param string $field
* @param mixed $id
- * @access private
+ * @private
*/
function deleteNewtalk( $field, $id ) {
$fname = 'User::deleteNewtalk';
}
/**
- * Check if a user is sysop
+ * Deprecated in 1.6, die in 1.7, to be removed in 1.8
* @deprecated
*/
function isSysop() {
- return $this->isAllowed( 'protect' );
+ wfDebugDieBacktrace( "Call to deprecated (v1.7) User::isSysop() method\n" );
+ #return $this->isAllowed( 'protect' );
}
- /** @deprecated */
+ /**
+ * Deprecated in 1.6, die in 1.7, to be removed in 1.8
+ * @deprecated
+ */
function isDeveloper() {
- return $this->isAllowed( 'siteadmin' );
+ wfDebugDieBacktrace( "Call to deprecated (v1.7) User::isDeveloper() method\n" );
+ #return $this->isAllowed( 'siteadmin' );
}
- /** @deprecated */
+ /**
+ * Deprecated in 1.6, die in 1.7, to be removed in 1.8
+ * @deprecated
+ */
function isBureaucrat() {
- return $this->isAllowed( 'makesysop' );
+ wfDebugDieBacktrace( "Call to deprecated (v1.7) User::isBureaucrat() method\n" );
+ #return $this->isAllowed( 'makesysop' );
}
/**
function clearNotification( &$title ) {
global $wgUser, $wgUseEnotif;
+
if ($title->getNamespace() == NS_USER_TALK &&
$title->getText() == $this->getName() ) {
+ if (!wfRunHooks('UserClearNewTalkNotification', array(&$this)))
+ return;
$this->setNewtalk( false );
}
* the next change of any watched page.
*
* @param int $currentUser user ID number
- * @access public
+ * @public
*/
function clearAllNotifications( $currentUser ) {
global $wgUseEnotif;
}
/**
- * @access private
+ * @private
* @return string Encoding options
*/
function encodeOptions() {
}
/**
- * @access private
+ * @private
*/
function decodeOptions( $str ) {
$a = explode( "\n", $str );
}
function setCookies() {
- global $wgCookieExpiration, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgDBname;
+ global $wgCookieExpiration, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookiePrefix;
if ( 0 == $this->mId ) return;
$this->loadFromDatabase();
$exp = time() + $wgCookieExpiration;
$_SESSION['wsUserID'] = $this->mId;
- setcookie( $wgDBname.'UserID', $this->mId, $exp, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
+ setcookie( $wgCookiePrefix.'UserID', $this->mId, $exp, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
$_SESSION['wsUserName'] = $this->getName();
- setcookie( $wgDBname.'UserName', $this->getName(), $exp, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
+ setcookie( $wgCookiePrefix.'UserName', $this->getName(), $exp, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
$_SESSION['wsToken'] = $this->mToken;
if ( 1 == $this->getOption( 'rememberpassword' ) ) {
- setcookie( $wgDBname.'Token', $this->mToken, $exp, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
+ setcookie( $wgCookiePrefix.'Token', $this->mToken, $exp, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
} else {
- setcookie( $wgDBname.'Token', '', time() - 3600 );
+ setcookie( $wgCookiePrefix.'Token', '', time() - 3600 );
}
}
* It will clean the session cookie
*/
function logout() {
- global $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgDBname;
+ global $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookiePrefix;
$this->loadDefaults();
$this->setLoaded( true );
$_SESSION['wsUserID'] = 0;
- setcookie( $wgDBname.'UserID', '', time() - 3600, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
- setcookie( $wgDBname.'Token', '', time() - 3600, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
+ setcookie( $wgCookiePrefix.'UserID', '', time() - 3600, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
+ setcookie( $wgCookiePrefix.'Token', '', time() - 3600, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
# Remember when user logged out, to prevent seeing cached pages
- setcookie( $wgDBname.'LoggedOut', wfTimestampNow(), time() + 86400, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
+ setcookie( $wgCookiePrefix.'LoggedOut', wfTimestampNow(), time() + 86400, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
}
/**
* Save object settings into database
*/
function saveSettings() {
- global $wgMemc, $wgDBname, $wgUseEnotif;
+ global $wgMemc, $wgDBname;
$fname = 'User::saveSettings';
if ( wfReadOnly() ) { return; }
* Get this user's personal page title.
*
* @return Title
- * @access public
+ * @public
*/
function getUserPage() {
return Title::makeTitle( NS_USER, $this->getName() );
* Get this user's talk page title.
*
* @return Title
- * @access public
+ * @public
*/
function getTalkPage() {
$title = $this->getUserPage();
* @param mixed $salt - Optional function-specific data for hash.
* Use a string or an array of strings.
* @return string
- * @access public
+ * @public
*/
function editToken( $salt = '' ) {
if( !isset( $_SESSION['wsEditToken'] ) ) {
* @param string $val - the input value to compare
* @param string $salt - Optional function-specific data for hash
* @return bool
- * @access public
+ * @public
*/
function matchEditToken( $val, $salt = '' ) {
global $wgMemc;
-
-/*
- if ( !isset( $_SESSION['wsEditToken'] ) ) {
- $logfile = '/home/wikipedia/logs/session_debug/session.log';
- $mckey = memsess_key( session_id() );
- $uname = @posix_uname();
- $msg = "wsEditToken not set!\n" .
- 'apache server=' . $uname['nodename'] . "\n" .
- 'session_id = ' . session_id() . "\n" .
- '$_SESSION=' . var_export( $_SESSION, true ) . "\n" .
- '$_COOKIE=' . var_export( $_COOKIE, true ) . "\n" .
- "mc get($mckey) = " . var_export( $wgMemc->get( $mckey ), true ) . "\n\n\n";
-
- @error_log( $msg, 3, $logfile );
+ $sessionToken = $this->editToken( $salt );
+ if ( $val != $sessionToken ) {
+ wfDebug( "User::matchEditToken: broken session data\n" );
}
-*/
- return ( $val == $this->editToken( $salt ) );
+ return $val == $sessionToken;
}
/**
* A hash (unsalted since it's used as a key) is stored.
* @param &$expiration mixed output: accepts the expiration time
* @return string
- * @access private
+ * @private
*/
function confirmationToken( &$expiration ) {
$fname = 'User::confirmationToken';
* the URL the user can use to confirm.
* @param &$expiration mixed output: accepts the expiration time
* @return string
- * @access private
+ * @private
*/
function confirmationTokenUrl( &$expiration ) {
$token = $this->confirmationToken( $expiration );
function isEmailConfirmed() {
global $wgEmailAuthentication;
$this->loadFromDatabase();
- if( $this->isAnon() )
- return false;
- if( !$this->isValidEmailAddr( $this->mEmail ) )
- return false;
- if( $wgEmailAuthentication && !$this->getEmailAuthenticationTimestamp() )
- return false;
- return true;
+ $confirmed = true;
+ if( wfRunHooks( 'EmailConfirmed', array( &$this, &$confirmed ) ) ) {
+ if( $this->isAnon() )
+ return false;
+ if( !$this->isValidEmailAddr( $this->mEmail ) )
+ return false;
+ if( $wgEmailAuthentication && !$this->getEmailAuthenticationTimestamp() )
+ return false;
+ return true;
+ } else {
+ return $confirmed;
+ }
}
/**
/**
* @param string $group key name
- * @return string localized descriptive name, if provided
+ * @return string localized descriptive name for group, if provided
* @static
*/
function getGroupName( $group ) {
- $key = "group-$group-name";
+ $key = "group-$group";
$name = wfMsg( $key );
if( $name == '' || $name == "<$key>" ) {
return $group;
}
}
+ /**
+ * @param string $group key name
+ * @return string localized descriptive name for member of a group, if provided
+ * @static
+ */
+ function getGroupMember( $group ) {
+ $key = "group-$group-member";
+ $name = wfMsg( $key );
+ if( $name == '' || $name == "<$key>" ) {
+ return $group;
+ } else {
+ return $name;
+ }
+ }
+
+
/**
* Return the set of defined explicit groups.
* The * and 'user' groups are not included.
array_keys( $wgGroupPermissions ),
array( '*', 'user', 'autoconfirmed' ) );
}
-
+
+ /**
+ * Get the title of a page describing a particular group
+ *
+ * @param $group Name of the group
+ * @return mixed
+ */
+ function getGroupPage( $group ) {
+ $page = wfMsgForContent( 'grouppage-' . $group );
+ if( !wfEmptyMsg( 'grouppage-' . $group, $page ) ) {
+ $title = Title::newFromText( $page );
+ if( is_object( $title ) )
+ return $title;
+ }
+ return false;
+ }
+
+
}
?>