'minoredit',
'move',
'nominornewtalk',
+ 'noratelimit',
'patrol',
'protect',
'proxyunbannable',
* @return bool
*/
static function isIP( $name ) {
- return preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.(?:xxx|\d{1,3})$/',$name) || User::isIPv6($name);
- /*return preg_match("/^
- (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
- (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
- (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
- (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))
- $/x", $name);*/
- }
-
- /**
- * Check if $name is an IPv6 IP.
- */
- static function isIPv6($name) {
- /*
- * if it has any non-valid characters, it can't be a valid IPv6
- * address.
- */
- if (preg_match("/[^:a-fA-F0-9]/", $name))
- return false;
-
- $parts = explode(":", $name);
- if (count($parts) < 3)
- return false;
- foreach ($parts as $part) {
- if (!preg_match("/^[0-9a-fA-F]{0,4}$/", $part))
- return false;
- }
- return true;
+ return preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.(?:xxx|\d{1,3})$/',$name) || IP::isIPv6($name);
}
/**
*
* @param string $opt
* @return string
- * @static
- * @public
*/
- function getDefaultOption( $opt ) {
- $defOpts = User::getDefaultOptions();
+ public static function getDefaultOption( $opt ) {
+ $defOpts = self::getDefaultOptions();
if( isset( $defOpts[$opt] ) ) {
return $defOpts[$opt];
} else {
*/
public function isPingLimitable() {
global $wgRateLimitsExcludedGroups;
- return array_intersect($this->getEffectiveGroups(), $wgRateLimitsExcludedGroups) == array();
+ if( array_intersect( $this->getEffectiveGroups(), $wgRateLimitsExcludedGroups ) ) {
+ // Deprecated, but kept for backwards-compatibility config
+ return false;
+ }
+ return !$this->isAllowed('noratelimit');
}
/**
return ($timestamp >= $this->mTouched);
}
- /**
- * Encrypt a password.
- * It can eventually salt a password.
- * @see User::addSalt()
- * @param string $p clear Password.
- * @return string Encrypted password.
- */
- function encryptPassword( $p ) {
- $this->load();
- return wfEncryptPassword( $this->mId, $p );
- }
-
/**
* Set the password and reset the random token
* Calls through to authentication plugin if necessary;
if( !$this->isValidPassword( $str ) ) {
global $wgMinimalPasswordLength;
- throw new PasswordError( wfMsg( 'passwordtooshort',
+ throw new PasswordError( wfMsgExt( 'passwordtooshort', array( 'parsemag' ),
$wgMinimalPasswordLength ) );
}
}
// Save an invalid hash...
$this->mPassword = '';
} else {
- $this->mPassword = $this->encryptPassword( $str );
+ $this->mPassword = self::crypt( $str );
}
$this->mNewpassword = '';
$this->mNewpassTime = null;
*/
function setNewpassword( $str, $throttle = true ) {
$this->load();
- $this->mNewpassword = $this->encryptPassword( $str );
+ $this->mNewpassword = self::crypt( $str );
if ( $throttle ) {
$this->mNewpassTime = wfTimestampNow();
}
function isNewbie() {
return !$this->isAllowed( 'autoconfirmed' );
}
+
+ /**
+ * Is the user active? We check to see if they've made at least
+ * X number of edits in the last Y days.
+ *
+ * @return bool true if the user is active, false if not
+ */
+ public function isActiveEditor() {
+ global $wgActiveUserEditCount, $wgActiveUserDays;
+ $dbr = wfGetDB( DB_SLAVE );
+
+ // Stolen without shame from RC
+ $cutoff_unixtime = time() - ( $wgActiveUserDays * 86400 );
+ $cutoff_unixtime = $cutoff_unixtime - ( $cutoff_unixtime % 86400 );
+ $oldTime = $dbr->addQuotes( $dbr->timestamp( $cutoff_unixtime ) );
+
+ $res = $dbr->select( 'revision', '1',
+ array( 'rev_user_text' => $this->getName(), "rev_timestamp > $oldTime"),
+ __METHOD__,
+ array('LIMIT' => $wgActiveUserEditCount ) );
+
+ $count = $dbr->numRows($res);
+ $dbr->freeResult($res);
+
+ return $count == $wgActiveUserEditCount;
+ }
/**
* Check to see if the given clear-text password is one of the accepted passwords
/* Auth plugin doesn't allow local authentication for this user name */
return false;
}
- $ep = $this->encryptPassword( $password );
- if ( 0 == strcmp( $ep, $this->mPassword ) ) {
+ if ( self::comparePasswords( $this->mPassword, $password, $this->mId ) ) {
return true;
} elseif ( function_exists( 'iconv' ) ) {
# Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
# Check for this with iconv
- $cp1252hash = $this->encryptPassword( iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password ) );
- if ( 0 == strcmp( $cp1252hash, $this->mPassword ) ) {
+ $cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password );
+ if ( self::comparePasswords( $this->mPassword, $cp1252Password, $this->mId ) ) {
return true;
}
}
* @return bool
*/
function checkTemporaryPassword( $plaintext ) {
- $hash = $this->encryptPassword( $plaintext );
- return $hash === $this->mNewpassword;
+ return self::comparePasswords( $this->mNewpassword, $plaintext, $this->getId() );
}
/**
? $right
: $name;
}
+
+ /**
+ * Make an old-style password hash
+ *
+ * @param string $password Plain-text password
+ * @param string $userId User ID
+ */
+ static function oldCrypt( $password, $userId ) {
+ global $wgPasswordSalt;
+ if ( $wgPasswordSalt ) {
+ return md5( $userId . '-' . md5( $password ) );
+ } else {
+ return md5( $password );
+ }
+ }
+
+ /**
+ * Make a new-style password hash
+ *
+ * @param string $password Plain-text password
+ * @param string $salt Salt, may be random or the user ID. False to generate a salt.
+ */
+ static function crypt( $password, $salt = false ) {
+ global $wgPasswordSalt;
+
+ if($wgPasswordSalt) {
+ if ( $salt === false ) {
+ $salt = substr( wfGenerateToken(), 0, 8 );
+ }
+ return ':B:' . $salt . ':' . md5( $salt . '-' . md5( $password ) );
+ } else {
+ return ':A:' . md5( $password);
+ }
+ }
+
+ /**
+ * Compare a password hash with a plain-text password. Requires the user
+ * ID if there's a chance that the hash is an old-style hash.
+ *
+ * @param string $hash Password hash
+ * @param string $password Plain-text password to compare
+ * @param string $userId User ID for old-style password salt
+ */
+ static function comparePasswords( $hash, $password, $userId = false ) {
+ $m = false;
+ $type = substr( $hash, 0, 3 );
+ if ( $type == ':A:' ) {
+ # Unsalted
+ return md5( $password ) === substr( $hash, 3 );
+ } elseif ( $type == ':B:' ) {
+ # Salted
+ list( $salt, $realHash ) = explode( ':', substr( $hash, 3 ), 2 );
+ return md5( $salt.'-'.md5( $password ) ) == $realHash;
+ } else {
+ # Old-style
+ return self::oldCrypt( $password, $userId ) === $hash;
+ }
+ }
}