class User {
/**
- * \arrayof{\string} A list of default user toggles, i.e., boolean user
+ * \type{\arrayof{\string}} A list of default user toggles, i.e., boolean user
* preferences that are displayed by Special:Preferences as checkboxes.
* This list can be extended via the UserToggles hook or by
* $wgContLang::getExtraUserToggles().
'showjumplinks',
'uselivepreview',
'forceeditsummary',
- 'watchlisthideown',
- 'watchlisthidebots',
'watchlisthideminor',
+ 'watchlisthidebots',
+ 'watchlisthideown',
+ 'watchlisthideanons',
+ 'watchlisthideliu',
'ccmeonemails',
'diffonly',
'showhiddencats',
+ 'noconvertlink',
);
/**
- * \arrayof{\string} List of member variables which are saved to the
+ * \type{\arrayof{\string}} List of member variables which are saved to the
* shared cache (memcached). Any operation which changes the
* corresponding database fields must call a cache-clearing function.
* @showinitializer
);
/**
- * \arrayof{\string} Core rights.
+ * \type{\arrayof{\string}} Core rights.
* Each of these should have a corresponding message of the form
* "right-$right".
* @showinitializer
'reupload',
'reupload-shared',
'rollback',
+ 'siteadmin',
'suppressredirect',
'trackback',
'undelete',
* addresses like this, if we allowed accounts like this to be created
* new users could get the old edits of these anonymous users.
*
- * @param $name \type{\string}
- * @return \type{\bool}
+ * @param $name \type{\string} String to match
+ * @return \type{\bool} True or false
*/
static function isIP( $name ) {
return preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.(?:xxx|\d{1,3})$/',$name) || IP::isIPv6($name);
* is longer than the maximum allowed username size or doesn't begin with
* a capital letter.
*
- * @param $name \type{\string}
- * @return \type{\bool}
+ * @param $name \type{\string} String to match
+ * @return \type{\bool} True or false
*/
static function isValidUserName( $name ) {
global $wgContLang, $wgMaxNameChars;
* If an account already exists in this form, login will be blocked
* by a failure to pass this function.
*
- * @param $name \type{\string}
- * @return \type{\bool}
+ * @param $name \type{\string} String to match
+ * @return \type{\bool} True or false
*/
static function isUsableName( $name ) {
global $wgReservedUsernames;
* rather than in isValidUserName() to avoid disrupting
* existing accounts.
*
- * @param $name \type{\string}
- * @return \type{\bool}
+ * @param $name \type{\string} String to match
+ * @return \type{\bool} True or false
*/
static function isCreatableName( $name ) {
return
* Is the input a valid password for this user?
*
* @param $password \type{\string} Desired password
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
function isValidPassword( $password ) {
global $wgMinimalPasswordLength, $wgContLang;
* @todo Check for RFC 2822 compilance (bug 959)
*
* @param $addr \type{\string} E-mail address
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
public static function isValidEmailAddr( $addr ) {
$result = null;
return false;
# Clean up name according to title rules
- $t = Title::newFromText( $name );
+ $t = ($validate === 'valid') ?
+ Title::newFromText( $name ) : Title::makeTitle( NS_USER, $name );
+ # Check for invalid titles
if( is_null( $t ) ) {
return false;
}
* Return a random password. Sourced from mt_rand, so it's not particularly secure.
* @todo hash random numbers to improve security, like generateToken()
*
- * @return \type{\string}
+ * @return \type{\string} New random password
*/
static function randomPassword() {
global $wgMinimalPasswordLength;
/**
* Initialize this object from a row from the user table.
*
- * @param $row \arrayof{\mixed} Row from the user table to load.
+ * @param $row \type{\arrayof{\mixed}} Row from the user table to load.
*/
function loadFromRow( $row ) {
$this->mDataLoaded = true;
* Combine the language default options with any site-specific options
* and add the default language variants.
*
- * @return \arrayof{\string} Array of options
+ * @return \type{\arrayof{\string}} Array of options
*/
static function getDefaultOptions() {
global $wgNamespacesToBeSearchedDefault;
* Get a given default option value.
*
* @param $opt \type{\string} Name of option to retrieve
- * @return \type{\string}
+ * @return \type{\string} Default option value
*/
public static function getDefaultOption( $opt ) {
$defOpts = self::getDefaultOptions();
/**
* Get a list of user toggle names
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of user toggle names
*/
static function getToggles() {
global $wgContLang;
$this->mBlockedby = 0;
$this->mHideName = 0;
+ $this->mAllowUsertalk = 0;
$ip = wfGetIP();
if ($this->isAllowed( 'ipblock-exempt' ) ) {
$this->mBlockedby = $this->mBlock->mBy;
$this->mBlockreason = $this->mBlock->mReason;
$this->mHideName = $this->mBlock->mHideName;
+ $this->mAllowUsertalk = $this->mBlock->mAllowUsertalk;
if ( $this->isLoggedIn() ) {
$this->spreadBlock();
}
} else {
- $this->mBlock = null;
- wfDebug( __METHOD__.": No block.\n" );
+ // Bug 13611: don't remove mBlock here, to allow account creation blocks to
+ // apply to users. Note that the existence of $this->mBlock is not used to
+ // check for edit blocks, $this->mBlockedby is instead.
}
# Proxy blocking
* Whether the given IP is in the SORBS blacklist.
*
* @param $ip \type{\string} IP to check
- * @return \type{\bool}
+ * @return \type{\bool} True if blacklisted
*/
function inSorbsBlacklist( $ip ) {
global $wgEnableSorbs, $wgSorbsUrl;
*
* @param $ip \type{\string} IP to check
* @param $base \type{\string} URL of the DNS blacklist
- * @return \type{\bool}
+ * @return \type{\bool} True if blacklisted
*/
function inDnsBlacklist( $ip, $base ) {
wfProfileIn( __METHOD__ );
$found = false;
$host = '';
- // FIXME: IPv6 ???
- $m = array();
- if ( preg_match( '/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip, $m ) ) {
+ // FIXME: IPv6 ??? (http://bugs.php.net/bug.php?id=33170)
+ if( IP::isIPv4($ip) ) {
# Make hostname
- for ( $i=4; $i>=1; $i-- ) {
- $host .= $m[$i] . '.';
- }
- $host .= $base;
+ $host = "$ip.$base";
# Send query
$ipList = gethostbynamel( $host );
- if ( $ipList ) {
+ if( $ipList ) {
wfDebug( "Hostname $host is {$ipList[0]}, it's a proxy says $base!\n" );
$found = true;
} else {
/**
* Is this user subject to rate limiting?
*
- * @return \type{\bool}
+ * @return \type{\bool} True if rate limited
*/
public function isPingLimitable() {
global $wgRateLimitsExcludedGroups;
wfDebug( __METHOD__.": asking isBlocked()\n" );
$blocked = $this->isBlocked( $bFromSlave );
# If a user's name is suppressed, they cannot make edits anywhere
- if ( !$this->mHideName && $wgBlockAllowsUTEdit && $title->getText() === $this->getName() &&
+ if ( !$this->mHideName && $this->mAllowUsertalk && $title->getText() === $this->getName() &&
$title->getNamespace() == NS_USER_TALK ) {
$blocked = false;
wfDebug( __METHOD__.": self-talk page, ignoring any blocks\n" );
/**
* Get the user name, or the IP of an anonymous user
- * @return \type{\string}
+ * @return \type{\string} User's name or IP address
*/
function getName() {
if ( !$this->mDataLoaded && $this->mFrom == 'name' ) {
/**
* Get the user's name escaped by underscores.
- * @return \type{\string}
+ * @return \type{\string} Username escaped by underscores
*/
function getTitleKey() {
return str_replace( ' ', '_', $this->getName() );
/**
* Return the talk page(s) this user has new messages on.
- * @return \arrayof{\string} Array of page URLs
+ * @return \type{\arrayof{\string}} Array of page URLs
*/
function getNewMessageLinks() {
$talks = array();
return ($timestamp >= $this->mTouched);
}
+ /**
+ * Get the user touched timestamp
+ */
+ function getTouched() {
+ $this->load();
+ return $this->mTouched;
+ }
+
/**
* Set the password and reset the random token.
* Calls through to authentication plugin if necessary;
/**
* Get the user's current token.
- * @return \type{\string}
+ * @return \type{\string} Token
*/
function getToken() {
$this->load();
/**
* Has password reminder email been sent within the last
* $wgPasswordReminderResendTime hours?
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
function isPasswordReminderThrottled() {
global $wgPasswordReminderResendTime;
/**
* Get the user's e-mail address
- * @return \type{\string}
+ * @return \type{\string} User's e-mail address
*/
function getEmail() {
$this->load();
/**
* Get the user's real name
- * @return \type{\string}
+ * @return \type{\string} User's real name
*/
function getRealName() {
$this->load();
/**
* Get the user's preferred date format.
- * @return \type{\string}
+ * @return \type{\string} User's preferred date format
*/
function getDatePreference() {
// Important migration for old data rows
/**
* Get the permissions this user has.
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of permission names
*/
function getRights() {
if ( is_null( $this->mRights ) ) {
/**
* Get the list of explicit group memberships this user has.
* The implicit * and user groups are not included.
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of internal group names
*/
function getGroups() {
$this->load();
* Get the list of implicit group memberships this user has.
* This includes all explicit groups, plus 'user' if logged in,
* '*' for all accounts and autopromoted groups
+ *
* @param $recache \type{\bool} Whether to avoid the cache
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of internal group names
*/
function getEffectiveGroups( $recache = false ) {
if ( $recache || is_null( $this->mEffectiveGroups ) ) {
/**
* Get the user's edit count.
- * @return \type{\int}
+ * @return \type{\int} User's edit count
*/
function getEditCount() {
if ($this->mId) {
/**
* Get whether the user is logged in
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
function isLoggedIn() {
return $this->getID() != 0;
/**
* Get whether the user is anonymous
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
function isAnon() {
return !$this->isLoggedIn();
/**
* Get whether the user is a bot
- * @return \type{\bool}
+ * @return \type{\bool} True or false
* @deprecated
*/
function isBot() {
// In the spirit of DWIM
return true;
- return in_array( $action, $this->getRights() );
+ # Use strict parameter to avoid matching numeric 0 accidentally inserted
+ # by misconfiguration: 0 == 'foo'
+ return in_array( $action, $this->getRights(), true );
}
/**
* Check whether to enable recent changes patrol features for this user
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
public function useRCPatrol() {
global $wgUseRCPatrol;
/**
* Check whether to enable new pages patrol features for this user
- * @return \type{\bool}
+ * @return \type{\bool} True or false
*/
public function useNPPatrol() {
global $wgUseRCPatrol, $wgUseNPPatrol;
/**
* Get the current skin, loading it if required
- * @return \type{Skin}
+ * @return \type{Skin} Current skin
* @todo FIXME : need to check the old failback system [AV]
*/
function &getSkin() {
}
/**
- * Set a cookie on the user's client
- * @param $name \type{\string} Name of the cookie to set
- * @param $name \type{\string} Value to set
- * @param $name \type{\int} Expiration time, as a UNIX time value;
- * if 0 or not specified, use the default $wgCookieExpiration
+ * Set a cookie on the user's client. Wrapper for
+ * WebResponse::setCookie
*/
protected function setCookie( $name, $value, $exp=0 ) {
- global $wgCookiePrefix,$wgCookieDomain,$wgCookieSecure,$wgCookieExpiration, $wgCookieHttpOnly;
- if( $exp == 0 ) {
- $exp = time() + $wgCookieExpiration;
- }
- $httpOnlySafe = wfHttpOnlySafe();
- wfDebugLog( 'cookie',
- 'setcookie: "' . implode( '", "',
- array(
- $wgCookiePrefix . $name,
- $value,
- $exp,
- '/',
- $wgCookieDomain,
- $wgCookieSecure,
- $httpOnlySafe && $wgCookieHttpOnly ) ) . '"' );
- if( $httpOnlySafe && isset( $wgCookieHttpOnly ) ) {
- setcookie( $wgCookiePrefix . $name,
- $value,
- $exp,
- '/',
- $wgCookieDomain,
- $wgCookieSecure,
- $wgCookieHttpOnly );
- } else {
- // setcookie() fails on PHP 5.1 if you give it future-compat paramters.
- // stab stab!
- setcookie( $wgCookiePrefix . $name,
- $value,
- $exp,
- '/',
- $wgCookieDomain,
- $wgCookieSecure );
- }
+ global $wgRequest;
+ $wgRequest->response()->setcookie( $name, $value, $exp );
}
/**
* Add a user to the database, return the user object
*
* @param $name \type{\string} Username to add
- * @param $params \arrayof{\string} Non-default parameters to save to the database:
+ * @param $params \type{\arrayof{\string}} Non-default parameters to save to the database:
* - password The user's password. Password logins will be disabled if this is omitted.
* - newpassword A temporary password mailed to the user
* - email The user's email address
* which will give them a chance to modify this key based on their own
* settings.
*
- * @return \type{\string}
+ * @return \type{\string} Page rendering hash
*/
function getPageRenderingHash() {
- global $wgContLang, $wgUseDynamicDates, $wgLang;
+ global $wgUseDynamicDates, $wgRenderHashAppend, $wgLang, $wgContLang;
if( $this->mHash ){
return $this->mHash;
}
$extra = $wgContLang->getExtraHashOptions();
$confstr .= $extra;
+ $confstr .= $wgRenderHashAppend;
+
// Give a chance for extensions to modify the hash, if they have
// extra options or other effects on the parser cache.
wfRunHooks( 'PageRenderingHash', array( &$confstr ) );
/**
* Get whether the user is explicitly blocked from account creation.
- * @return \type{\bool}
+ * @return \type{\bool} True if blocked
*/
function isBlockedFromCreateAccount() {
$this->getBlockedStatus();
/**
* Get whether the user is blocked from using Special:Emailuser.
- * @return \type{\bool}
+ * @return \type{\bool} True if blocked
*/
function isBlockedFromEmailuser() {
$this->getBlockedStatus();
/**
* Get whether the user is allowed to create an account.
- * @return \type{\bool}
+ * @return \type{\bool} True if allowed
*/
function isAllowedToCreateAccount() {
return $this->isAllowed( 'createaccount' ) && !$this->isBlockedFromCreateAccount();
/**
* Get this user's personal page title.
*
- * @return \type{Title}
+ * @return \type{Title} User's personal page title
*/
function getUserPage() {
return Title::makeTitle( NS_USER, $this->getName() );
/**
* Get this user's talk page title.
*
- * @return \type{Title}
+ * @return \type{Title} User's talk page title
*/
function getTalkPage() {
$title = $this->getUserPage();
/**
* Get the maximum valid user ID.
- * @return \type{\int}
+ * @return \type{\int} %User ID
* @static
*/
function getMaxID() {
/**
* Check if the given clear-text password matches the temporary password
* sent by e-mail for password reset operations.
- * @return \type{\bool}
+ * @return \type{\bool} True if matches, false otherwise
*/
function checkTemporaryPassword( $plaintext ) {
return self::comparePasswords( $this->mNewpassword, $plaintext, $this->getId() );
* @param $subject \type{\string} Message subject
* @param $body \type{\string} Message body
* @param $from \type{\string} Optional From address; if unspecified, default $wgPasswordSender will be used
- * @param $replyto \type{\string}
+ * @param $replyto \type{\string} Reply-to address
* @return \twotypes{\bool,WikiError} True on success, a WikiError object on failure
*/
function sendMail( $subject, $body, $from = null, $replyto = null ) {
* this change to the database.
*
* @param[out] &$expiration \type{\mixed} Accepts the expiration time
- * @return \type{\string}
+ * @return \type{\string} New token
* @private
*/
function confirmationToken( &$expiration ) {
/**
* Return a URL the user can use to confirm their email address.
* @param $token \type{\string} Accepts the email confirmation token
- * @return \type{\string}
+ * @return \type{\string} New token URL
* @private
*/
function confirmationTokenUrl( $token ) {
}
/**
* Return a URL the user can use to invalidate their email address.
+ *
* @param $token \type{\string} Accepts the email confirmation token
- * @return \type{\string}
+ * @return \type{\string} New token URL
* @private
*/
function invalidationTokenUrl( $token ) {
/**
* Is this user allowed to send e-mails within limits of current
* site configuration?
- * @return \type{\bool}
+ * @return \type{\bool} True if allowed
*/
function canSendEmail() {
$canSend = $this->isEmailConfirmed();
/**
* Is this user allowed to receive e-mails within limits of current
* site configuration?
- * @return \type{\bool}
+ * @return \type{\bool} True if allowed
*/
function canReceiveEmail() {
return $this->isEmailConfirmed() && !$this->getOption( 'disablemail' );
* confirmed their address by returning a code or using a password
* sent to the address from the wiki.
*
- * @return \type{\bool}
+ * @return \type{\bool} True if confirmed
*/
function isEmailConfirmed() {
global $wgEmailAuthentication;
/**
* Check whether there is an outstanding request for e-mail confirmation.
- * @return \type{\bool}
+ * @return \type{\bool} True if pending
*/
function isEmailConfirmationPending() {
global $wgEmailAuthentication;
/**
* Get the permissions associated with a given list of groups
*
- * @param $groups \arrayof{\string} List of internal group names
- * @return \arrayof{\string} List of permission key names for given groups combined
+ * @param $groups \type{\arrayof{\string}} List of internal group names
+ * @return \type{\arrayof{\string}} List of permission key names for given groups combined
*/
static function getGroupPermissions( $groups ) {
global $wgGroupPermissions;
* Get all the groups who have a given permission
*
* @param $role \type{\string} Role to check
- * @return \arrayof{\string} List of internal group names with the given permission
+ * @return \type{\arrayof{\string}} List of internal group names with the given permission
*/
static function getGroupsWithPermission( $role ) {
global $wgGroupPermissions;
* Get the localized descriptive name for a group, if it exists
*
* @param $group \type{\string} Internal group name
- * @return \type{\string}
+ * @return \type{\string} Localized descriptive group name
*/
static function getGroupName( $group ) {
global $wgMessageCache;
* Get the localized descriptive name for a member of a group, if it exists
*
* @param $group \type{\string} Internal group name
- * @return \type{\string}
+ * @return \type{\string} Localized name for group member
*/
static function getGroupMember( $group ) {
global $wgMessageCache;
* Return the set of defined explicit groups.
* The implicit groups (by default *, 'user' and 'autoconfirmed')
* are not included, as they are defined automatically, not in the database.
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of internal group names
*/
static function getAllGroups() {
global $wgGroupPermissions;
/**
* Get a list of all available permissions.
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of permission names
*/
static function getAllRights() {
if ( self::$mAllRights === false ) {
/**
* Get a list of implicit groups
- * @return \arrayof{\string}
+ * @return \type{\arrayof{\string}} Array of internal group names
*/
public static function getImplicitGroups() {
global $wgImplicitGroups;
* Get the description of a given right
*
* @param $right \type{\string} Right to query
- * @return \type{\string}
+ * @return \type{\string} Localized description of the right
*/
static function getRightDescription( $right ) {
global $wgMessageCache;
* @param $hash \type{\string} Password hash
* @param $password \type{\string} Plain-text password to compare
* @param $userId \type{\string} %User ID for old-style password salt
- * @return \type{\bool}
+ * @return \type{\bool} True if matches, false otherwise
*/
static function comparePasswords( $hash, $password, $userId = false ) {
$m = false;
return self::oldCrypt( $password, $userId ) === $hash;
}
}
+
+ /**
+ * Add a newuser log entry for this user
+ * @param bool $byEmail, account made by email?
+ */
+ public function addNewUserLogEntry( $byEmail = false ) {
+ global $wgUser, $wgContLang, $wgNewUserLog;
+ if( empty($wgNewUserLog) ) {
+ return true; // disabled
+ }
+ $talk = $wgContLang->getFormattedNsText( NS_TALK );
+ if( $this->getName() == $wgUser->getName() ) {
+ $action = 'create';
+ $message = '';
+ } else {
+ $action = 'create2';
+ $message = $byEmail ? wfMsgForContent( 'newuserlog-byemail' ) : '';
+ }
+ $log = new LogPage( 'newusers' );
+ $log->addEntry( $action, $this->getUserPage(), $message, array( $this->getId() ) );
+ return true;
+ }
+
+ /**
+ * Add an autocreate newuser log entry for this user
+ * Used by things like CentralAuth and perhaps other authplugins.
+ */
+ public function addNewUserLogEntryAutoCreate() {
+ global $wgNewUserLog;
+ if( empty($wgNewUserLog) ) {
+ return true; // disabled
+ }
+ $log = new LogPage( 'newusers', false );
+ $log->addEntry( 'autocreate', $this->getUserPage(), '', array( $this->getId() ) );
+ return true;
+ }
+
}