Simpler method for mixing and clipping when computing a second-try hash value
[lhc/web/wiklou.git] / includes / User.php
index b7efd25..f7d7880 100644 (file)
@@ -43,7 +43,7 @@ class PasswordError extends MWException {
 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().
@@ -82,9 +82,11 @@ class User {
                'showjumplinks',
                'uselivepreview',
                'forceeditsummary',
-               'watchlisthideown',
-               'watchlisthidebots',
                'watchlisthideminor',
+               'watchlisthidebots',
+               'watchlisthideown',
+               'watchlisthideanons',
+               'watchlisthideliu',
                'ccmeonemails',
                'diffonly',
                'showhiddencats',
@@ -92,7 +94,7 @@ class User {
        );
 
        /**
-        * \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
@@ -119,7 +121,7 @@ class User {
        );
 
        /**
-        * \arrayof{\string} Core rights.
+        * \type{\arrayof{\string}} Core rights.
         * Each of these should have a corresponding message of the form 
         * "right-$right".
         * @showinitializer
@@ -157,6 +159,7 @@ class User {
                'reupload',
                'reupload-shared',
                'rollback',
+               'siteadmin',
                'suppressredirect',
                'trackback',
                'undelete',
@@ -643,7 +646,9 @@ class User {
                        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;
                }
@@ -886,7 +891,7 @@ class User {
        /**
         * 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;
@@ -953,7 +958,7 @@ class User {
         * 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;
@@ -993,7 +998,7 @@ class User {
 
        /**
         * Get a list of user toggle names
-        * @return \arrayof{\string} Array of user toggle names
+        * @return \type{\arrayof{\string}} Array of user toggle names
         */
        static function getToggles() {
                global $wgContLang;
@@ -1031,6 +1036,7 @@ class User {
                
                $this->mBlockedby = 0;
                $this->mHideName = 0;
+               $this->mAllowUsertalk = 0;
                $ip = wfGetIP();
 
                if ($this->isAllowed( 'ipblock-exempt' ) ) {
@@ -1046,12 +1052,14 @@ class User {
                        $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
@@ -1102,19 +1110,15 @@ class User {
 
                $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 {
@@ -1264,7 +1268,7 @@ class User {
                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" );
@@ -1395,7 +1399,7 @@ class User {
 
        /**
         * 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();
@@ -1565,6 +1569,14 @@ class User {
                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;
@@ -1847,7 +1859,7 @@ class User {
 
        /**
         * Get the permissions this user has.
-        * @return \arrayof{\string} Array of permission names
+        * @return \type{\arrayof{\string}} Array of permission names
         */
        function getRights() {
                if ( is_null( $this->mRights ) ) {
@@ -1862,7 +1874,7 @@ class User {
        /**
         * Get the list of explicit group memberships this user has.
         * The implicit * and user groups are not included.
-        * @return \arrayof{\string} Array of internal group names
+        * @return \type{\arrayof{\string}} Array of internal group names
         */
        function getGroups() {
                $this->load();
@@ -1875,7 +1887,7 @@ class User {
         * '*' for all accounts and autopromoted groups
         *
         * @param $recache \type{\bool} Whether to avoid the cache
-        * @return \arrayof{\string} Array of internal group names
+        * @return \type{\arrayof{\string}} Array of internal group names
         */
        function getEffectiveGroups( $recache = false ) {
                if ( $recache || is_null( $this->mEffectiveGroups ) ) {
@@ -1996,7 +2008,9 @@ class User {
                        // 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 );
        }
 
        /**
@@ -2317,7 +2331,7 @@ class User {
         * 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
@@ -2427,7 +2441,7 @@ class User {
         * @return \type{\string} Page rendering hash
         */
        function getPageRenderingHash() {
-               global $wgContLang, $wgUseDynamicDates, $wgLang;
+               global $wgUseDynamicDates, $wgRenderHashAppend, $wgLang, $wgContLang;
                if( $this->mHash ){
                        return $this->mHash;
                }
@@ -2447,6 +2461,8 @@ class User {
                $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 ) );
@@ -2895,8 +2911,8 @@ class User {
        /**
         * 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;
@@ -2914,7 +2930,7 @@ class User {
         * 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;
@@ -2963,7 +2979,7 @@ class User {
         * 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} Array of internal group names
+        * @return \type{\arrayof{\string}} Array of internal group names
         */
        static function getAllGroups() {
                global $wgGroupPermissions;
@@ -2975,7 +2991,7 @@ class User {
 
        /**
         * Get a list of all available permissions.
-        * @return \arrayof{\string} Array of permission names
+        * @return \type{\arrayof{\string}} Array of permission names
         */
        static function getAllRights() {
                if ( self::$mAllRights === false ) {
@@ -2992,7 +3008,7 @@ class User {
 
        /**
         * Get a list of implicit groups
-        * @return \arrayof{\string} Array of internal group names
+        * @return \type{\arrayof{\string}} Array of internal group names
         */
        public static function getImplicitGroups() {
                global $wgImplicitGroups;
@@ -3183,4 +3199,41 @@ class User {
                        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;
+       }
+
 }