Followup r64181, rm comment that doesn't fit anymore
[lhc/web/wiklou.git] / includes / User.php
index 941f0bd..3dec040 100644 (file)
@@ -41,57 +41,13 @@ class PasswordError extends MWException {
  * of the database.
  */
 class 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().
-        * @showinitializer
+        * Global constants made accessable as class constants so that autoloader
+        * magic can be used.
         */
-       public static $mToggles = array(
-               'highlightbroken',
-               'justify',
-               'hideminor',
-               'extendwatchlist',
-               'usenewrc',
-               'numberheadings',
-               'showtoolbar',
-               'editondblclick',
-               'editsection',
-               'editsectiononrightclick',
-               'showtoc',
-               'rememberpassword',
-               'watchcreations',
-               'watchdefault',
-               'watchmoves',
-               'watchdeletion',
-               'minordefault',
-               'previewontop',
-               'previewonfirst',
-               'nocache',
-               'enotifwatchlistpages',
-               'enotifusertalkpages',
-               'enotifminoredits',
-               'enotifrevealaddr',
-               'shownumberswatching',
-               'fancysig',
-               'externaleditor',
-               'externaldiff',
-               'showjumplinks',
-               'uselivepreview',
-               'forceeditsummary',
-               'watchlisthideminor',
-               'watchlisthidebots',
-               'watchlisthideown',
-               'watchlisthideanons',
-               'watchlisthideliu',
-               'ccmeonemails',
-               'diffonly',
-               'showhiddencats',
-               'noconvertlink',
-               'norollbackdiff',
-       );
+       const USER_TOKEN_LENGTH = USER_TOKEN_LENGTH;
+       const MW_USER_VERSION = MW_USER_VERSION;
+       const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
 
        /**
         * \type{\arrayof{\string}} List of member variables which are saved to the
@@ -167,6 +123,7 @@ class User {
                'reupload',
                'reupload-shared',
                'rollback',
+               'selenium',
                'sendemail',
                'siteadmin',
                'suppressionlog',
@@ -228,7 +185,7 @@ class User {
         * @see newFromSession()
         * @see newFromRow()
         */
-       function User() {
+       function __construct() {
                $this->clearInstanceCache( 'defaults' );
        }
 
@@ -816,7 +773,7 @@ class User {
        function loadDefaults( $name = false ) {
                wfProfileIn( __METHOD__ );
 
-               global $wgCookiePrefix;
+               global $wgRequest;
 
                $this->mId = 0;
                $this->mName = $name;
@@ -827,8 +784,8 @@ class User {
                $this->mOptionOverrides = null;
                $this->mOptionsLoaded = false;
 
-               if ( isset( $_COOKIE[$wgCookiePrefix.'LoggedOut'] ) ) {
-                       $this->mTouched = wfTimestamp( TS_MW, $_COOKIE[$wgCookiePrefix.'LoggedOut'] );
+               if( $wgRequest->getCookie( 'LoggedOut' ) !== null ) {
+                       $this->mTouched = wfTimestamp( TS_MW, $wgRequest->getCookie( 'LoggedOut' ) );
                } else {
                        $this->mTouched = '0'; # Allow any pages to be cached
                }
@@ -859,7 +816,7 @@ class User {
         * @return \bool True if the user is logged in, false otherwise.
         */
        private function loadFromSession() {
-               global $wgMemc, $wgCookiePrefix, $wgExternalAuthType, $wgAutocreatePolicy;
+               global $wgRequest, $wgExternalAuthType, $wgAutocreatePolicy;
 
                $result = null;
                wfRunHooks( 'UserLoadFromSession', array( $this, &$result ) );
@@ -875,8 +832,8 @@ class User {
                        }
                }
 
-               if ( isset( $_COOKIE["{$wgCookiePrefix}UserID"] ) ) {
-                       $sId = intval( $_COOKIE["{$wgCookiePrefix}UserID"] );
+               if ( $wgRequest->getCookie( 'UserID' ) !== null ) {
+                       $sId = intval( $wgRequest->getCookie( 'UserID' ) );
                        if( isset( $_SESSION['wsUserID'] ) && $sId != $_SESSION['wsUserID'] ) {
                                $this->loadDefaults(); // Possible collision!
                                wfDebugLog( 'loginSessions', "Session user ID ({$_SESSION['wsUserID']}) and
@@ -898,8 +855,8 @@ class User {
 
                if ( isset( $_SESSION['wsUserName'] ) ) {
                        $sName = $_SESSION['wsUserName'];
-               } else if ( isset( $_COOKIE["{$wgCookiePrefix}UserName"] ) ) {
-                       $sName = $_COOKIE["{$wgCookiePrefix}UserName"];
+               } else if ( $wgRequest->getCookie('UserName') !== null ) {
+                       $sName = $wgRequest->getCookie('UserName');
                        $_SESSION['wsUserName'] = $sName;
                } else {
                        $this->loadDefaults();
@@ -923,8 +880,8 @@ class User {
                if ( isset( $_SESSION['wsToken'] ) ) {
                        $passwordCorrect = $_SESSION['wsToken'] == $this->mToken;
                        $from = 'session';
-               } else if ( isset( $_COOKIE["{$wgCookiePrefix}Token"] ) ) {
-                       $passwordCorrect = $this->mToken == $_COOKIE["{$wgCookiePrefix}Token"];
+               } else if ( $wgRequest->getCookie( 'Token' ) !== null ) {
+                       $passwordCorrect = $this->mToken == $wgRequest->getCookie( 'Token' );
                        $from = 'cookie';
                } else {
                        # No session or persistent login cookie
@@ -1090,22 +1047,6 @@ class User {
                }
        }
 
-       /**
-        * Get a list of user toggle names
-        * @return \type{\arrayof{\string}} Array of user toggle names
-        */
-       static function getToggles() {
-               global $wgContLang, $wgUseRCPatrol;
-               $extraToggles = array();
-               wfRunHooks( 'UserToggles', array( &$extraToggles ) );
-               if( $wgUseRCPatrol ) {
-                       $extraToggles[] = 'hidepatrolled';
-                       $extraToggles[] = 'newpageshidepatrolled';
-                       $extraToggles[] = 'watchlisthidepatrolled';
-               }
-               return array_merge( self::$mToggles, $extraToggles, $wgContLang->getExtraUserToggles() );
-       }
-
 
        /**
         * Get blocking information
@@ -1271,10 +1212,34 @@ class User {
                        // Deprecated, but kept for backwards-compatibility config
                        return false;
                }
-               if( in_array( wfGetIP(), $wgRateLimitsExcludedIPs ) ) {
+
+               wfDebug( "Checking the list of IP addresses excluded from rate limit..\n" );
+
+               // Read list of IP addresses from MediaWiki namespace
+               $message = wfMsgForContentNoTrans( 'ratelimit-excluded-ips' );
+               $lines = explode( "\n", $message );
+               foreach( $lines as $line ) {
+                       // Remove comment lines
+                       $comment = substr( trim( $line ), 0, 1 );
+                       if ( $comment == '#' || $comment == '' ) {
+                               continue;
+                       }
+                       // Remove additional comments after an IP address
+                       $comment = strpos( $line, '#' );
+                       if ( $comment > 0 ) {
+                               $line = trim( substr( $line, 0, $comment-1 ) );
+                               if ( IP::isValid( $line ) ) {
+                                       $wgRateLimitsExcludedIPs[] = IP::sanitizeIP( $line );
+                               }
+                       }
+               }
+
+               $ip = IP::sanitizeIP( wfGetIP() );
+               if( in_array( $ip, $wgRateLimitsExcludedIPs ) ) {
                        // No other good way currently to disable rate limits
                        // for specific IPs. :P
                        // But this is a crappy hack and should die.
+                       wfDebug( "IP $ip matches the list of rate limit excluded IPs\n" );
                        return false;
                }
                return !$this->isAllowed('noratelimit');
@@ -2041,7 +2006,7 @@ class User {
 
                if ( $oname == 'skin' ) {
                        # Clear cached skin, so the new one displays immediately in Special:Preferences
-                       unset( $this->mSkin );
+                       $this->mSkin = null;
                }
 
                // Explicitly NULL values should refer to defaults
@@ -2078,6 +2043,20 @@ class User {
                return $this->mDatePreference;
        }
 
+       /**
+        * Get the user preferred stub threshold
+        */
+       function getStubThreshold() {
+               global $wgMaxArticleSize; # Maximum article size, in Kb
+               $threshold = intval( $this->getOption( 'stubthreshold' ) );
+               if ( $threshold > $wgMaxArticleSize * 1024 ) {
+                       # If they have set an impossible value, disable the preference 
+                       # so we can use the parser cache again.
+                       $threshold = 0;
+               }
+               return $threshold;
+       }
+
        /**
         * Get the permissions this user has.
         * @return \type{\arrayof{\string}} Array of permission names
@@ -2261,33 +2240,46 @@ class User {
         * @return Skin The current skin
         * @todo FIXME : need to check the old failback system [AV]
         */
-       function &getSkin( $t = null ) {
-               if ( !isset( $this->mSkin ) ) {
-                       wfProfileIn( __METHOD__ );
-
-                       global $wgHiddenPrefs;
-                       if( !in_array( 'skin', $wgHiddenPrefs ) ) {
-                               # get the user skin
-                               global $wgRequest;
-                               $userSkin = $this->getOption( 'skin' );
-                               $userSkin = $wgRequest->getVal( 'useskin', $userSkin );
-                       } else {
-                               # if we're not allowing users to override, then use the default
-                               global $wgDefaultSkin;
-                               $userSkin = $wgDefaultSkin;
+       function getSkin( $t = null ) {
+               if ( $t ) {
+                       $skin = $this->createSkinObject();
+                       $skin->setTitle( $t );
+                       return $skin;
+               } else {
+                       if ( ! $this->mSkin ) {
+                               $this->mSkin = $this->createSkinObject();
                        }
-
-                       $this->mSkin =& Skin::newFromKey( $userSkin );
-                       wfProfileOut( __METHOD__ );
-               }
-               if( $t || !$this->mSkin->getTitle() ) {
-                       if ( !$t ) {
+                       
+                       if ( ! $this->mSkin->getTitle() ) {
                                global $wgOut;
                                $t = $wgOut->getTitle();
+                               $this->mSkin->setTitle($t);
                        }
-                       $this->mSkin->setTitle( $t );
+                       
+                       return $this->mSkin;
+               }
+       }
+       
+       // Creates a Skin object, for getSkin()
+       private function createSkinObject() {
+               wfProfileIn( __METHOD__ );
+
+               global $wgHiddenPrefs;
+               if( !in_array( 'skin', $wgHiddenPrefs ) ) {
+                       # get the user skin
+                       global $wgRequest;
+                       $userSkin = $this->getOption( 'skin' );
+                       $userSkin = $wgRequest->getVal( 'useskin', $userSkin );
+               } else {
+                       # if we're not allowing users to override, then use the default
+                       global $wgDefaultSkin;
+                       $userSkin = $wgDefaultSkin;
                }
-               return $this->mSkin;
+
+               $skin = Skin::newFromKey( $userSkin );
+               wfProfileOut( __METHOD__ );
+               
+               return $skin;
        }
 
        /**
@@ -2686,11 +2678,12 @@ class User {
                }
 
                // stubthreshold is only included below for completeness,
-               // it will always be 0 when this function is called by parsercache.
+               // since it disables the parser cache, its value will always 
+               // be 0 when this function is called by parsercache.
 
                $confstr =        $this->getOption( 'math' );
-               $confstr .= '!' . $this->getOption( 'stubthreshold' );
-               if ( $wgUseDynamicDates ) {
+               $confstr .= '!' . $this->getStubThreshold();
+               if ( $wgUseDynamicDates ) { # This is wrong (bug 24714)
                        $confstr .= '!' . $this->getDatePreference();
                }
                $confstr .= '!' . ( $this->getOption( 'numberheadings' ) ? '1' : '' );
@@ -2700,6 +2693,9 @@ class User {
                $extra = $wgContLang->getExtraHashOptions();
                $confstr .= $extra;
 
+               // Since the skin could be overloading link(), it should be
+               // included here but in practice, none of our skins do that.
+
                $confstr .= $wgRenderHashAppend;
 
                // Give a chance for extensions to modify the hash, if they have
@@ -2738,13 +2734,6 @@ class User {
                return $this->isAllowed( 'createaccount' ) && !$this->isBlockedFromCreateAccount();
        }
 
-       /**
-        * @deprecated
-        */
-       function setLoaded( $loaded ) {
-               wfDeprecated( __METHOD__ );
-       }
-
        /**
         * Get this user's personal page title.
         *
@@ -2772,9 +2761,9 @@ class User {
        function getMaxID() {
                static $res; // cache
 
-               if ( isset( $res ) )
+               if ( isset( $res ) ) {
                        return $res;
-               else {
+               else {
                        $dbr = wfGetDB( DB_SLAVE );
                        return $res = $dbr->selectField( 'user', 'max(user_id)', false, __METHOD__ );
                }
@@ -3207,8 +3196,6 @@ class User {
         * @return \string Localized descriptive group name
         */
        static function getGroupName( $group ) {
-               global $wgMessageCache;
-               $wgMessageCache->loadAllMessages();
                $key = "group-$group";
                $name = wfMsg( $key );
                return $name == '' || wfEmptyMsg( $key, $name )
@@ -3223,8 +3210,6 @@ class User {
         * @return \string Localized name for group member
         */
        static function getGroupMember( $group ) {
-               global $wgMessageCache;
-               $wgMessageCache->loadAllMessages();
                $key = "group-$group-member";
                $name = wfMsg( $key );
                return $name == '' || wfEmptyMsg( $key, $name )
@@ -3281,8 +3266,6 @@ class User {
         * @return \types{\type{Title},\bool} Title of the page if it exists, false otherwise
         */
        static function getGroupPage( $group ) {
-               global $wgMessageCache;
-               $wgMessageCache->loadAllMessages();
                $page = wfMsgForContent( 'grouppage-' . $group );
                if( !wfEmptyMsg( 'grouppage-' . $group, $page ) ) {
                        $title = Title::newFromText( $page );
@@ -3495,8 +3478,6 @@ class User {
         * @return \string Localized description of the right
         */
        static function getRightDescription( $right ) {
-               global $wgMessageCache;
-               $wgMessageCache->loadAllMessages();
                $key = "right-$right";
                $name = wfMsg( $key );
                return $name == '' || wfEmptyMsg( $key, $name )
@@ -3578,28 +3559,34 @@ class User {
 
        /**
         * Add a newuser log entry for this user
+        *
         * @param $byEmail Boolean: account made by email?
+        * @param $reason String: user supplied reason
         */
-       public function addNewUserLogEntry( $byEmail = false ) {
-               global $wgUser, $wgNewUserLog;
+       public function addNewUserLogEntry( $byEmail = false, $reason = '' ) {
+               global $wgUser, $wgContLang, $wgNewUserLog;
                if( empty( $wgNewUserLog ) ) {
                        return true; // disabled
                }
 
                if( $this->getName() == $wgUser->getName() ) {
                        $action = 'create';
-                       $message = '';
                } else {
                        $action = 'create2';
-                       $message = $byEmail
-                               ? wfMsgForContent( 'newuserlog-byemail' )
-                               : '';
+                       if ( $byEmail ) {
+                               if ( $reason === '' ) {
+                                       $reason = wfMsgForContent( 'newuserlog-byemail' );
+                               } else {
+                                       $reason = $wgContLang->commaList( array(
+                                               $reason, wfMsgForContent( 'newuserlog-byemail' ) ) );
+                               }
+                       }
                }
                $log = new LogPage( 'newusers' );
                $log->addEntry(
                        $action,
                        $this->getUserPage(),
-                       $message,
+                       $reason,
                        array( $this->getId() )
                );
                return true;
@@ -3714,6 +3701,10 @@ class User {
         *
         * Obviously, you still need to do server-side checking.
         *
+        * NOTE: A combination of bugs in various browsers means that this function
+        * actually just returns array() unconditionally at the moment.  May as
+        * well keep it around for when the browser bugs get fixed, though.
+        *
         * @return array Array of HTML attributes suitable for feeding to
         *   Html::element(), directly or indirectly.  (Don't feed to Xml::*()!
         *   That will potentially output invalid XHTML 1.0 Transitional, and will
@@ -3728,7 +3719,14 @@ class User {
 
                # Note that the pattern requirement will always be satisfied if the
                # input is empty, so we need required in all cases.
-               $ret = array( 'required' );
+               #
+               # FIXME (bug 23769): This needs to not claim the password is required
+               # if e-mail confirmation is being used.  Since HTML5 input validation
+               # is b0rked anyway in some browsers, just return nothing.  When it's
+               # re-enabled, fix this code to not output required for e-mail
+               # registration.
+               #$ret = array( 'required' );
+               $ret = array();
 
                # We can't actually do this right now, because Opera 9.6 will print out
                # the entered password visibly in its error message!  When other
@@ -3763,7 +3761,7 @@ class User {
                        if ( !$template
                                        || $template->getNamespace() !== NS_TEMPLATE
                                        || !$template->exists() ) {
-                               $text = "== $subject ==\n\n$text\n\n-- $signature";
+                               $text = "\n== $subject ==\n\n$text\n\n-- $signature";
                        } else {
                                $text = '{{'. $template->getText()
                                        . " | subject=$subject | body=$text | signature=$signature }}";
@@ -3780,8 +3778,6 @@ class User {
         * @param $signature String Text to leave in the signature
         * @param $summary String the summary for this change, defaults to
         *                        "Leave system message."
-        * @param $article Article The article to update, defaults to the
-        *                        user's talk page.
         * @param $editor User The user leaving the message, defaults to
         *                        "{{MediaWiki:usermessage-editor}}"
         * @param $flags Int default edit flags
@@ -3810,7 +3806,7 @@ class User {
                $flags = $article->checkFlags( $flags );
 
                if ( $flags & EDIT_UPDATE ) {
-                       $text .= $article->getContent();
+                       $text = $article->getContent() . $text;
                }
 
                $dbw = wfGetDB( DB_MASTER );