Localisation updates for core messages from Betawiki (2008-06-23 22:55 CEST)
[lhc/web/wiklou.git] / includes / User.php
index 5a36eea..61fa69f 100644 (file)
@@ -133,6 +133,7 @@ class User {
                'minoredit',
                'move',
                'nominornewtalk',
+               'noratelimit',
                'patrol',
                'protect',
                'proxyunbannable',
@@ -431,34 +432,7 @@ class User {
         * @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);
        }
 
        /**
@@ -962,11 +936,9 @@ class User {
         *
         * @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 {
@@ -1102,7 +1074,11 @@ class User {
         */
        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');
        }
 
        /**
@@ -1509,18 +1485,6 @@ class User {
                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;
@@ -1545,7 +1509,7 @@ class User {
 
                        if( !$this->isValidPassword( $str ) ) {
                                global $wgMinimalPasswordLength;
-                               throw new PasswordError( wfMsg( 'passwordtooshort',
+                               throw new PasswordError( wfMsgExt( 'passwordtooshort', array( 'parsemag' ),
                                        $wgMinimalPasswordLength ) );
                        }
                }
@@ -1573,7 +1537,7 @@ class User {
                        // Save an invalid hash...
                        $this->mPassword = '';
                } else {
-                       $this->mPassword = $this->encryptPassword( $str );
+                       $this->mPassword = self::crypt( $str );
                }
                $this->mNewpassword = '';
                $this->mNewpassTime = null;
@@ -1617,7 +1581,7 @@ class User {
         */
        function setNewpassword( $str, $throttle = true ) {
                $this->load();
-               $this->mNewpassword = $this->encryptPassword( $str );
+               $this->mNewpassword = self::crypt( $str );
                if ( $throttle ) {
                        $this->mNewpassTime = wfTimestampNow();
                }
@@ -2445,6 +2409,32 @@ class User {
        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
@@ -2473,14 +2463,13 @@ class User {
                        /* 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;
                        }
                }
@@ -2493,8 +2482,7 @@ class User {
         * @return bool
         */
        function checkTemporaryPassword( $plaintext ) {
-               $hash = $this->encryptPassword( $plaintext );
-               return $hash === $this->mNewpassword;
+               return self::comparePasswords( $this->mNewpassword, $plaintext, $this->getId() );
        }
 
        /**
@@ -2969,4 +2957,62 @@ class User {
                        ? $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;
+               }
+       }
 }