X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fspecials%2FSpecialUserlogin.php;h=4882058f4ddbeddf91ac36c162fe6dc6fd62af39;hb=eac38f23a305244db9787ccedd2d3a1007330592;hp=84f8fdded7e72b9cf1af8b32e9266c0f201d7db8;hpb=68ec61e7691988160293bd12cf39aae305ea2a06;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/specials/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php index 84f8fdded7..4882058f4d 100644 --- a/includes/specials/SpecialUserlogin.php +++ b/includes/specials/SpecialUserlogin.php @@ -1,27 +1,32 @@ execute(); -} - -/** - * implements Special:Login + * Implements Special:UserLogin + * * @ingroup SpecialPage */ -class LoginForm { +class LoginForm extends SpecialPage { const SUCCESS = 0; const NO_NAME = 1; @@ -38,41 +43,72 @@ class LoginForm { const NEED_TOKEN = 12; const WRONG_TOKEN = 13; - var $mName, $mPassword, $mRetype, $mReturnTo, $mCookieCheck, $mPosted; - var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword; + var $mUsername, $mPassword, $mRetype, $mReturnTo, $mCookieCheck, $mPosted; + var $mAction, $mCreateaccount, $mCreateaccountMail; var $mLoginattempt, $mRemember, $mEmail, $mDomain, $mLanguage; - var $mSkipCookieCheck, $mReturnToQuery, $mToken; + var $mSkipCookieCheck, $mReturnToQuery, $mToken, $mStickHTTPS; + var $mType, $mReason, $mRealName; + var $mAbortLoginErrorMsg = 'login-abort-generic'; + private $mLoaded = false; + /** + * @var ExternalUser + */ private $mExtUser = null; /** - * Constructor - * @param $request WebRequest: a WebRequest object passed by reference - * @param $par String: subpage parameter + * @ var WebRequest + */ + private $mOverrideRequest = null; + + /** + * @param WebRequest $request + */ + public function __construct( $request = null ) { + parent::__construct( 'Userlogin' ); + + $this->mOverrideRequest = $request; + } + + /** + * Loader + * + * @param $request WebRequest object */ - function LoginForm( &$request, $par = '' ) { + function load() { global $wgAuth, $wgHiddenPrefs, $wgEnableEmail, $wgRedirectOnLogin; - $this->mType = ( $par == 'signup' ) ? $par : $request->getText( 'type' ); # Check for [[Special:Userlogin/signup]] - $this->mName = $request->getText( 'wpName' ); + if ( $this->mLoaded ) { + return; + } + $this->mLoaded = true; + + if ( $this->mOverrideRequest === null ) { + $request = $this->getRequest(); + } else { + $request = $this->mOverrideRequest; + } + + $this->mType = $request->getText( 'type' ); + $this->mUsername = $request->getText( 'wpName' ); $this->mPassword = $request->getText( 'wpPassword' ); $this->mRetype = $request->getText( 'wpRetype' ); $this->mDomain = $request->getText( 'wpDomain' ); + $this->mReason = $request->getText( 'wpReason' ); $this->mReturnTo = $request->getVal( 'returnto' ); $this->mReturnToQuery = $request->getVal( 'returntoquery' ); $this->mCookieCheck = $request->getVal( 'wpCookieCheck' ); $this->mPosted = $request->wasPosted(); $this->mCreateaccount = $request->getCheck( 'wpCreateaccount' ); $this->mCreateaccountMail = $request->getCheck( 'wpCreateaccountMail' ) - && $wgEnableEmail; - $this->mMailmypassword = $request->getCheck( 'wpMailmypassword' ) - && $wgEnableEmail; + && $wgEnableEmail; $this->mLoginattempt = $request->getCheck( 'wpLoginattempt' ); $this->mAction = $request->getVal( 'action' ); $this->mRemember = $request->getCheck( 'wpRemember' ); + $this->mStickHTTPS = $request->getCheck( 'wpStickHTTPS' ); $this->mLanguage = $request->getText( 'uselang' ); $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' ); - $this->mToken = ($this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' ); + $this->mToken = ( $this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' ); if ( $wgRedirectOnLogin ) { $this->mReturnTo = $wgRedirectOnLogin; @@ -85,13 +121,17 @@ class LoginForm { $this->mEmail = ''; } if( !in_array( 'realname', $wgHiddenPrefs ) ) { - $this->mRealName = $request->getText( 'wpRealName' ); + $this->mRealName = $request->getText( 'wpRealName' ); } else { - $this->mRealName = ''; + $this->mRealName = ''; } if( !$wgAuth->validDomain( $this->mDomain ) ) { - $this->mDomain = 'invaliddomain'; + if ( isset( $_SESSION['wsDomain'] ) ) { + $this->mDomain = $_SESSION['wsDomain']; + } else { + $this->mDomain = 'invaliddomain'; + } } $wgAuth->setDomain( $this->mDomain ); @@ -103,18 +143,32 @@ class LoginForm { } } - function execute() { + function getDescription() { + return $this->msg( $this->getUser()->isAllowed( 'createaccount' ) ? + 'userlogin' : 'userloginnocreate' )->text(); + } + + public function execute( $par ) { + if ( session_id() == '' ) { + wfSetupSession(); + } + + $this->load(); + $this->setHeaders(); + + if ( $par == 'signup' ) { # Check for [[Special:Userlogin/signup]] + $this->mType = 'signup'; + } + if ( !is_null( $this->mCookieCheck ) ) { $this->onCookieRedirectCheck( $this->mCookieCheck ); return; - } else if( $this->mPosted ) { + } elseif( $this->mPosted ) { if( $this->mCreateaccount ) { return $this->addNewAccount(); - } else if ( $this->mCreateaccountMail ) { + } elseif ( $this->mCreateaccountMail ) { return $this->addNewAccountMailPassword(); - } else if ( $this->mMailmypassword ) { - return $this->mailPassword(); - } else if ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) { + } elseif ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) { return $this->processLogin(); } } @@ -125,16 +179,14 @@ class LoginForm { * @private */ function addNewAccountMailPassword() { - global $wgOut; - if ( $this->mEmail == '' ) { - $this->mainLoginForm( wfMsgExt( 'noemail', array( 'parsemag', 'escape' ), $this->mName ) ); + $this->mainLoginForm( $this->msg( 'noemailcreate' )->escaped() ); return; } $u = $this->addNewaccountInternal(); - if ($u == null) { + if ( $u == null ) { return; } @@ -144,47 +196,46 @@ class LoginForm { $result = $this->mailPasswordInternal( $u, false, 'createaccount-title', 'createaccount-text' ); wfRunHooks( 'AddNewAccount', array( $u, true ) ); - $u->addNewUserLogEntry(); + $u->addNewUserLogEntry( true, $this->mReason ); - $wgOut->setPageTitle( wfMsg( 'accmailtitle' ) ); - $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->setArticleRelated( false ); + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'accmailtitle' ) ); - if( WikiError::isError( $result ) ) { - $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) ); + if( !$result->isGood() ) { + $this->mainLoginForm( $this->msg( 'mailerror', $result->getWikiText() )->text() ); } else { - $wgOut->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() ); - $wgOut->returnToMain( false ); + $out->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() ); + $out->returnToMain( false ); } - $u = 0; } - /** * @private */ function addNewAccount() { - global $wgUser, $wgEmailAuthentication; + global $wgUser, $wgEmailAuthentication, $wgLoginLanguageSelector; # Create the account and abort if there's a problem doing so $u = $this->addNewAccountInternal(); - if( $u == null ) + if( $u == null ) { return; + } # If we showed up language selection links, and one was in use, be # smart (and sensible) and save that language as the user's preference - global $wgLoginLanguageSelector; - if( $wgLoginLanguageSelector && $this->mLanguage ) + if( $wgLoginLanguageSelector && $this->mLanguage ) { $u->setOption( 'language', $this->mLanguage ); + } + + $out = $this->getOutput(); # Send out an email authentication message if needed - if( $wgEmailAuthentication && User::isValidEmailAddr( $u->getEmail() ) ) { - global $wgOut; - $error = $u->sendConfirmationMail(); - if( WikiError::isError( $error ) ) { - $wgOut->addWikiMsg( 'confirmemail_sendfailed', $error->getMessage() ); + if( $wgEmailAuthentication && Sanitizer::validateEmail( $u->getEmail() ) ) { + $status = $u->sendConfirmationMail(); + if( $status->isGood() ) { + $out->addWikiMsg( 'confirmemail_oncreate' ); } else { - $wgOut->addWikiMsg( 'confirmemail_oncreate' ); + $out->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) ); } } @@ -194,11 +245,15 @@ class LoginForm { # If not logged in, assume the new account as the current one and set # session cookies then show a "welcome" message or a "need cookies" # message as needed - if( $wgUser->isAnon() ) { + if( $this->getUser()->isAnon() ) { + $u->setCookies(); $wgUser = $u; - $wgUser->setCookies(); - wfRunHooks( 'AddNewAccount', array( $wgUser, false ) ); - $wgUser->addNewUserLogEntry(); + // This should set it for OutputPage and the Skin + // which is needed or the personal links will be + // wrong. + $this->getContext()->setUser( $u ); + wfRunHooks( 'AddNewAccount', array( $u, false ) ); + $u->addNewUserLogEntry(); if( $this->hasSessionCookie() ) { return $this->successfulCreation(); } else { @@ -206,15 +261,11 @@ class LoginForm { } } else { # Confirm that the account was created - global $wgOut; - $self = SpecialPage::getTitleFor( 'Userlogin' ); - $wgOut->setPageTitle( wfMsgHtml( 'accountcreated' ) ); - $wgOut->setArticleRelated( false ); - $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->addHTML( wfMsgWikiHtml( 'accountcreatedtext', $u->getName() ) ); - $wgOut->returnToMain( false, $self ); + $out->setPageTitle( $this->msg( 'accountcreated' ) ); + $out->addWikiMsg( 'accountcreatedtext', $u->getName() ); + $out->returnToMain( false, $this->getTitle() ); wfRunHooks( 'AddNewAccount', array( $u, false ) ); - $u->addNewUserLogEntry(); + $u->addNewUserLogEntry( false, $this->mReason ); return true; } } @@ -223,14 +274,12 @@ class LoginForm { * @private */ function addNewAccountInternal() { - global $wgUser, $wgOut; - global $wgMemc, $wgAccountCreationThrottle; - global $wgAuth, $wgMinimalPasswordLength; - global $wgEmailConfirmToEdit; + global $wgAuth, $wgMemc, $wgAccountCreationThrottle, + $wgMinimalPasswordLength, $wgEmailConfirmToEdit; // If the user passes an invalid domain, something is fishy if( !$wgAuth->validDomain( $this->mDomain ) ) { - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); return false; } @@ -240,66 +289,66 @@ class LoginForm { // create a local account and login as any domain user). We only need // to check this for domains that aren't local. if( 'local' != $this->mDomain && $this->mDomain != '' ) { - if( !$wgAuth->canCreateAccounts() && ( !$wgAuth->userExists( $this->mName ) || !$wgAuth->authenticate( $this->mName, $this->mPassword ) ) ) { - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + if( !$wgAuth->canCreateAccounts() && ( !$wgAuth->userExists( $this->mUsername ) + || !$wgAuth->authenticate( $this->mUsername, $this->mPassword ) ) ) { + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); return false; } } if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return false; + throw new ReadOnlyError; } # Request forgery checks. if ( !self::getCreateaccountToken() ) { self::setCreateaccountToken(); - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'nocookiesfornew' )->parse() ); return false; } - + # The user didn't pass a createaccount token if ( !$this->mToken ) { - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'sessionfailure' )->text() ); return false; } - + # Validate the createaccount token if ( $this->mToken !== self::getCreateaccountToken() ) { - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'sessionfailure' )->text() ); return false; } # Check permissions - if ( !$wgUser->isAllowed( 'createaccount' ) ) { - $this->userNotPrivilegedMessage(); - return false; - } elseif ( $wgUser->isBlockedFromCreateAccount() ) { - $this->userBlockedMessage(); + $currentUser = $this->getUser(); + if ( !$currentUser->isAllowed( 'createaccount' ) ) { + throw new PermissionsError( 'createaccount' ); + } elseif ( $currentUser->isBlockedFromCreateAccount() ) { + $this->userBlockedMessage( $currentUser->isBlockedFromCreateAccount() ); return false; } - $ip = wfGetIP(); - if ( $wgUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) { - $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $ip ) . ')' ); + $ip = $this->getRequest()->getIP(); + if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) { + $this->mainLoginForm( $this->msg( 'sorbs_create_account_reason' )->text() . ' (' . htmlspecialchars( $ip ) . ')' ); return false; } # Now create a dummy user ($u) and check if it is valid - $name = trim( $this->mName ); + $name = trim( $this->mUsername ); $u = User::newFromName( $name, 'creatable' ); if ( !is_object( $u ) ) { - $this->mainLoginForm( wfMsg( 'noname' ) ); + $this->mainLoginForm( $this->msg( 'noname' )->text() ); return false; } if ( 0 != $u->idForName() ) { - $this->mainLoginForm( wfMsg( 'userexists' ) ); + $this->mainLoginForm( $this->msg( 'userexists' )->text() ); return false; } if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) { - $this->mainLoginForm( wfMsg( 'badretype' ) ); + $this->mainLoginForm( $this->msg( 'badretype' )->text() ); return false; } @@ -307,7 +356,14 @@ class LoginForm { $valid = $u->getPasswordValidity( $this->mPassword ); if ( $valid !== true ) { if ( !$this->mCreateaccountMail ) { - $this->mainLoginForm( wfMsgExt( $valid, array( 'parsemag' ), $wgMinimalPasswordLength ) ); + if ( is_array( $valid ) ) { + $message = array_shift( $valid ); + $params = $valid; + } else { + $message = $valid; + $params = array( $wgMinimalPasswordLength ); + } + $this->mainLoginForm( $this->msg( $message, $params )->text() ); return false; } else { # do not force a password for account creation by email @@ -319,12 +375,12 @@ class LoginForm { # if you need a confirmed email address to edit, then obviously you # need an email address. if ( $wgEmailConfirmToEdit && empty( $this->mEmail ) ) { - $this->mainLoginForm( wfMsg( 'noemailtitle' ) ); + $this->mainLoginForm( $this->msg( 'noemailtitle' )->text() ); return false; } - if( !empty( $this->mEmail ) && !User::isValidEmailAddr( $this->mEmail ) ) { - $this->mainLoginForm( wfMsg( 'invalidemailaddress' ) ); + if( !empty( $this->mEmail ) && !Sanitizer::validateEmail( $this->mEmail ) ) { + $this->mainLoginForm( $this->msg( 'invalidemailaddress' )->text() ); return false; } @@ -341,25 +397,30 @@ class LoginForm { return false; } - if ( $wgAccountCreationThrottle && $wgUser->isPingLimitable() ) { - $key = wfMemcKey( 'acctcreate', 'ip', $ip ); - $value = $wgMemc->get( $key ); - if ( !$value ) { - $wgMemc->set( $key, 0, 86400 ); - } - if ( $value >= $wgAccountCreationThrottle ) { - $this->throttleHit( $wgAccountCreationThrottle ); - return false; + // Hook point to check for exempt from account creation throttle + if ( !wfRunHooks( 'ExemptFromAccountCreationThrottle', array( $ip ) ) ) { + wfDebug( "LoginForm::exemptFromAccountCreationThrottle: a hook allowed account creation w/o throttle\n" ); + } else { + if ( ( $wgAccountCreationThrottle && $currentUser->isPingLimitable() ) ) { + $key = wfMemcKey( 'acctcreate', 'ip', $ip ); + $value = $wgMemc->get( $key ); + if ( !$value ) { + $wgMemc->set( $key, 0, 86400 ); + } + if ( $value >= $wgAccountCreationThrottle ) { + $this->throttleHit( $wgAccountCreationThrottle ); + return false; + } + $wgMemc->incr( $key ); } - $wgMemc->incr( $key ); } if( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) { - $this->mainLoginForm( wfMsg( 'externaldberror' ) ); + $this->mainLoginForm( $this->msg( 'externaldberror' )->text() ); return false; } - self::clearCreateaccountToken(); + self::clearCreateaccountToken(); return $this->initUser( $u, false ); } @@ -414,66 +475,65 @@ class LoginForm { */ public function authenticateUserData() { global $wgUser, $wgAuth; - if ( $this->mName == '' ) { + + $this->load(); + + if ( $this->mUsername == '' ) { + wfRunHooks( 'LoginAuthenticateAudit', array( new User, $this->mPassword, self::NO_NAME ) ); return self::NO_NAME; } - + // We require a login token to prevent login CSRF // Handle part of this before incrementing the throttle so // token-less login attempts don't count towards the throttle // but wrong-token attempts do. - + // If the user doesn't have a login token yet, set one. if ( !self::getLoginToken() ) { self::setLoginToken(); + wfRunHooks( 'LoginAuthenticateAudit', array( new User, $this->mPassword, self::NEED_TOKEN ) ); return self::NEED_TOKEN; } // If the user didn't pass a login token, tell them we need one if ( !$this->mToken ) { + wfRunHooks( 'LoginAuthenticateAudit', array( new User, $this->mPassword, self::NEED_TOKEN ) ); return self::NEED_TOKEN; } - - global $wgPasswordAttemptThrottle; - $throttleCount = 0; - if ( is_array( $wgPasswordAttemptThrottle ) ) { - $throttleKey = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mName ) ); - $count = $wgPasswordAttemptThrottle['count']; - $period = $wgPasswordAttemptThrottle['seconds']; - - global $wgMemc; - $throttleCount = $wgMemc->get( $throttleKey ); - if ( !$throttleCount ) { - $wgMemc->add( $throttleKey, 1, $period ); // start counter - } else if ( $throttleCount < $count ) { - $wgMemc->incr($throttleKey); - } else if ( $throttleCount >= $count ) { - return self::THROTTLED; - } + $throttleCount = self::incLoginThrottle( $this->mUsername ); + if ( $throttleCount === true ) { + wfRunHooks( 'LoginAuthenticateAudit', array( new User, $this->mPassword, self::THROTTLED ) ); + return self::THROTTLED; } - + // Validate the login token if ( $this->mToken !== self::getLoginToken() ) { + wfRunHooks( 'LoginAuthenticateAudit', array( new User, $this->mPassword, self::WRONG_TOKEN ) ); return self::WRONG_TOKEN; } - // Load $wgUser now, and check to see if we're logging in as the same - // name. This is necessary because loading $wgUser (say by calling - // getName()) calls the UserLoadFromSession hook, which potentially - // creates the user in the database. Until we load $wgUser, checking - // for user existence using User::newFromName($name)->getId() below + // Load the current user now, and check to see if we're logging in as + // the same name. This is necessary because loading the current user + // (say by calling getName()) calls the UserLoadFromSession hook, which + // potentially creates the user in the database. Until we load $wgUser, + // checking for user existence using User::newFromName($name)->getId() below // will effectively be using stale data. - if ( $wgUser->getName() === $this->mName ) { - wfDebug( __METHOD__.": already logged in as {$this->mName}\n" ); + if ( $this->getUser()->getName() === $this->mUsername ) { + wfDebug( __METHOD__ . ": already logged in as {$this->mUsername}\n" ); return self::SUCCESS; } - $this->mExtUser = ExternalUser::newFromName( $this->mName ); + $this->mExtUser = ExternalUser::newFromName( $this->mUsername ); # TODO: Allow some magic here for invalid external names, e.g., let the # user choose a different wiki name. - $u = User::newFromName( $this->mName ); - if( !( $u instanceof User ) || !User::isUsableName( $u->getName() ) ) { + $u = User::newFromName( $this->mUsername ); + if( !( $u instanceof User ) ) { + wfRunHooks( 'LoginAuthenticateAudit', array( new User, $this->mPassword, self::ILLEGAL ) ); + return self::ILLEGAL; + } + if( !User::isUsableName( $u->getName() ) ) { + wfRunHooks( 'LoginAuthenticateAudit', array( $u, $this->mPassword, self::ILLEGAL ) ); return self::ILLEGAL; } @@ -481,6 +541,7 @@ class LoginForm { if ( 0 == $u->getID() ) { $status = $this->attemptAutoCreate( $u ); if ( $status !== self::SUCCESS ) { + wfRunHooks( 'LoginAuthenticateAudit', array( $u, $this->mPassword, $status ) ); return $status; } else { $isAutoCreated = true; @@ -500,12 +561,13 @@ class LoginForm { // Give general extensions, such as a captcha, a chance to abort logins $abort = self::ABORTED; - if( !wfRunHooks( 'AbortLogin', array( $u, $this->mPassword, &$abort ) ) ) { + if( !wfRunHooks( 'AbortLogin', array( $u, $this->mPassword, &$abort, &$this->mAbortLoginErrorMsg ) ) ) { + wfRunHooks( 'LoginAuthenticateAudit', array( $u, $this->mPassword, $abort ) ); return $abort; } global $wgBlockDisablesLogin; - if (!$u->checkPassword( $this->mPassword )) { + if ( !$u->checkPassword( $this->mPassword ) ) { if( $u->checkTemporaryPassword( $this->mPassword ) ) { // The e-mailed temporary password should not be used for actu- // al logins; that's a very sloppy habit, and insecure if an @@ -533,7 +595,7 @@ class LoginForm { // faces etc will probably just fail cleanly here. $retval = self::RESET_PASS; } else { - $retval = ($this->mPassword == '') ? self::EMPTY_PASS : self::WRONG_PASS; + $retval = ( $this->mPassword == '' ) ? self::EMPTY_PASS : self::WRONG_PASS; } } elseif ( $wgBlockDisablesLogin && $u->isBlocked() ) { // If we've enabled it, make it so that a blocked user cannot login @@ -541,15 +603,19 @@ class LoginForm { } else { $wgAuth->updateUser( $u ); $wgUser = $u; + // This should set it for OutputPage and the Skin + // which is needed or the personal links will be + // wrong. + $this->getContext()->setUser( $u ); // Please reset throttle for successful logins, thanks! - if($throttleCount) { - $wgMemc->delete($throttleKey); + if ( $throttleCount ) { + self::clearLoginThrottle( $this->mUsername ); } if ( $isAutoCreated ) { // Must be run after $wgUser is set, for correct new user log - wfRunHooks( 'AuthPluginAutoCreate', array( $wgUser ) ); + wfRunHooks( 'AuthPluginAutoCreate', array( $u ) ); } $retval = self::SUCCESS; @@ -558,16 +624,61 @@ class LoginForm { return $retval; } + /** + * Increment the login attempt throttle hit count for the (username,current IP) + * tuple unless the throttle was already reached. + * @param $username string The user name + * @return Bool|Integer The integer hit count or True if it is already at the limit + */ + public static function incLoginThrottle( $username ) { + global $wgPasswordAttemptThrottle, $wgMemc, $wgRequest; + $username = trim( $username ); // sanity + + $throttleCount = 0; + if ( is_array( $wgPasswordAttemptThrottle ) ) { + $throttleKey = wfMemcKey( 'password-throttle', $wgRequest->getIP(), md5( $username ) ); + $count = $wgPasswordAttemptThrottle['count']; + $period = $wgPasswordAttemptThrottle['seconds']; + + $throttleCount = $wgMemc->get( $throttleKey ); + if ( !$throttleCount ) { + $wgMemc->add( $throttleKey, 1, $period ); // start counter + } elseif ( $throttleCount < $count ) { + $wgMemc->incr( $throttleKey ); + } elseif ( $throttleCount >= $count ) { + return true; + } + } + + return $throttleCount; + } + + /** + * Clear the login attempt throttle hit count for the (username,current IP) tuple. + * @param $username string The user name + * @return void + */ + public static function clearLoginThrottle( $username ) { + global $wgMemc, $wgRequest; + $username = trim( $username ); // sanity + + $throttleKey = wfMemcKey( 'password-throttle', $wgRequest->getIP(), md5( $username ) ); + $wgMemc->delete( $throttleKey ); + } + /** * Attempt to automatically create a user on login. Only succeeds if there * is an external authentication method which allows it. + * + * @param $user User + * * @return integer Status code */ function attemptAutoCreate( $user ) { - global $wgAuth, $wgUser, $wgAutocreatePolicy; + global $wgAuth, $wgAutocreatePolicy; - if ( $wgUser->isBlockedFromCreateAccount() ) { - wfDebug( __METHOD__.": user is blocked from account creation\n" ); + if ( $this->getUser()->isBlockedFromCreateAccount() ) { + wfDebug( __METHOD__ . ": user is blocked from account creation\n" ); return self::CREATE_BLOCKED; } @@ -591,219 +702,147 @@ class LoginForm { return self::NOT_EXISTS; } if ( !$wgAuth->userExists( $user->getName() ) ) { - wfDebug( __METHOD__.": user does not exist\n" ); + wfDebug( __METHOD__ . ": user does not exist\n" ); return self::NOT_EXISTS; } if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) { - wfDebug( __METHOD__.": \$wgAuth->authenticate() returned false, aborting\n" ); + wfDebug( __METHOD__ . ": \$wgAuth->authenticate() returned false, aborting\n" ); return self::WRONG_PLUGIN_PASS; } } - wfDebug( __METHOD__.": creating account\n" ); - $user = $this->initUser( $user, true ); + $abortError = ''; + if( !wfRunHooks( 'AbortAutoAccount', array( $user, &$abortError ) ) ) { + // Hook point to add extra creation throttles and blocks + wfDebug( "LoginForm::attemptAutoCreate: a hook blocked creation: $abortError\n" ); + $this->mAbortLoginErrorMsg = $abortError; + return self::ABORTED; + } + + wfDebug( __METHOD__ . ": creating account\n" ); + $this->initUser( $user, true ); return self::SUCCESS; } function processLogin() { - global $wgUser, $wgAuth; + global $wgMemc, $wgLang; switch ( $this->authenticateUserData() ) { case self::SUCCESS: # We've verified now, update the real record - if( (bool)$this->mRemember != (bool)$wgUser->getOption( 'rememberpassword' ) ) { - $wgUser->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 ); - $wgUser->saveSettings(); + $user = $this->getUser(); + if( (bool)$this->mRemember != (bool)$user->getOption( 'rememberpassword' ) ) { + $user->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 ); + $user->saveSettings(); } else { - $wgUser->invalidateCache(); + $user->invalidateCache(); } - $wgUser->setCookies(); + $user->setCookies(); self::clearLoginToken(); // Reset the throttle - $key = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mName ) ); - global $wgMemc; + $request = $this->getRequest(); + $key = wfMemcKey( 'password-throttle', $request->getIP(), md5( $this->mUsername ) ); $wgMemc->delete( $key ); if( $this->hasSessionCookie() || $this->mSkipCookieCheck ) { /* Replace the language object to provide user interface in * correct language immediately on this first page load. */ - global $wgLang, $wgRequest; - $code = $wgRequest->getVal( 'uselang', $wgUser->getOption( 'language' ) ); - $wgLang = Language::factory( $code ); + $code = $request->getVal( 'uselang', $user->getOption( 'language' ) ); + $userLang = Language::factory( $code ); + $wgLang = $userLang; + $this->getContext()->setLanguage( $userLang ); return $this->successfulLogin(); } else { return $this->cookieRedirectCheck( 'login' ); } break; - + case self::NEED_TOKEN: + $this->mainLoginForm( $this->msg( 'nocookiesforlogin' )->parse() ); + break; case self::WRONG_TOKEN: - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); + $this->mainLoginForm( $this->msg( 'sessionfailure' )->text() ); break; case self::NO_NAME: case self::ILLEGAL: - $this->mainLoginForm( wfMsg( 'noname' ) ); + $this->mainLoginForm( $this->msg( 'noname' )->text() ); break; case self::WRONG_PLUGIN_PASS: - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); break; case self::NOT_EXISTS: - if( $wgUser->isAllowed( 'createaccount' ) ){ - $this->mainLoginForm( wfMsgWikiHtml( 'nosuchuser', htmlspecialchars( $this->mName ) ) ); + if( $this->getUser()->isAllowed( 'createaccount' ) ) { + $this->mainLoginForm( $this->msg( 'nosuchuser', + wfEscapeWikiText( $this->mUsername ) )->parse() ); } else { - $this->mainLoginForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->mName ) ) ); + $this->mainLoginForm( $this->msg( 'nosuchusershort', + wfEscapeWikiText( $this->mUsername ) )->text() ); } break; case self::WRONG_PASS: - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); + $this->mainLoginForm( $this->msg( 'wrongpassword' )->text() ); break; case self::EMPTY_PASS: - $this->mainLoginForm( wfMsg( 'wrongpasswordempty' ) ); + $this->mainLoginForm( $this->msg( 'wrongpasswordempty' )->text() ); break; case self::RESET_PASS: - $this->resetLoginForm( wfMsg( 'resetpass_announce' ) ); + $this->resetLoginForm( $this->msg( 'resetpass_announce' )->text() ); break; case self::CREATE_BLOCKED: - $this->userBlockedMessage(); + $this->userBlockedMessage( $this->getUser()->mBlock ); break; case self::THROTTLED: - $this->mainLoginForm( wfMsg( 'login-throttled' ) ); + $this->mainLoginForm( $this->msg( 'login-throttled' )->text() ); break; case self::USER_BLOCKED: - $this->mainLoginForm( wfMsgExt( 'login-userblocked', - array( 'parsemag', 'escape' ), $this->mName ) ); + $this->mainLoginForm( $this->msg( 'login-userblocked', + $this->mUsername )->escaped() ); + break; + case self::ABORTED: + $this->mainLoginForm( $this->msg( $this->mAbortLoginErrorMsg )->text() ); break; default: - throw new MWException( "Unhandled case value" ); + throw new MWException( 'Unhandled case value' ); } } function resetLoginForm( $error ) { - global $wgOut; - $wgOut->addHTML( Xml::element('p', array( 'class' => 'error' ), $error ) ); - $reset = new SpecialResetpass(); + $this->getOutput()->addHTML( Xml::element('p', array( 'class' => 'error' ), $error ) ); + $reset = new SpecialChangePassword(); + $reset->setContext( $this ); $reset->execute( null ); } - /** - * @private - */ - function mailPassword() { - global $wgUser, $wgOut, $wgAuth; - - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return false; - } - - if( !$wgAuth->allowPasswordChange() ) { - $this->mainLoginForm( wfMsg( 'resetpass_forbidden' ) ); - return; - } - - # Check against blocked IPs so blocked users can't flood admins - # with password resets - if( $wgUser->isBlocked() ) { - $this->mainLoginForm( wfMsg( 'blocked-mailpassword' ) ); - return; - } - - # Check for hooks - $error = null; - if ( ! wfRunHooks( 'UserLoginMailPassword', array( $this->mName, &$error ) ) ) { - $this->mainLoginForm( $error ); - return; - } - - # If the user doesn't have a login token yet, set one. - if ( !self::getLoginToken() ) { - self::setLoginToken(); - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); - return; - } - - # If the user didn't pass a login token, tell them we need one - if ( !$this->mToken ) { - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); - return; - } - - # Check against the rate limiter - if( $wgUser->pingLimiter( 'mailpassword' ) ) { - $wgOut->rateLimited(); - return; - } - - if ( $this->mName == '' ) { - $this->mainLoginForm( wfMsg( 'noname' ) ); - return; - } - $u = User::newFromName( $this->mName ); - if( !$u instanceof User ) { - $this->mainLoginForm( wfMsg( 'noname' ) ); - return; - } - if ( 0 == $u->getID() ) { - $this->mainLoginForm( wfMsgWikiHtml( 'nosuchuser', htmlspecialchars( $u->getName() ) ) ); - return; - } - - # Validate the login token - if ( $this->mToken !== self::getLoginToken() ) { - $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); - return; - } - - # Check against password throttle - if ( $u->isPasswordReminderThrottled() ) { - global $wgPasswordReminderResendTime; - # Round the time in hours to 3 d.p., in case someone is specifying - # minutes or seconds. - $this->mainLoginForm( wfMsgExt( 'throttled-mailpassword', array( 'parsemag' ), - round( $wgPasswordReminderResendTime, 3 ) ) ); - return; - } - - $result = $this->mailPasswordInternal( $u, true, 'passwordremindertitle', 'passwordremindertext' ); - if( WikiError::isError( $result ) ) { - $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) ); - } else { - $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ), 'success' ); - self::clearLoginToken(); - } - } - - /** * @param $u User object * @param $throttle Boolean * @param $emailTitle String: message name of email title * @param $emailText String: message name of email text - * @return Mixed: true on success, WikiError on failure - * @private + * @return Status object */ function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext' ) { - global $wgServer, $wgScript, $wgUser, $wgNewPasswordExpiry; + global $wgServer, $wgScript, $wgNewPasswordExpiry; if ( $u->getEmail() == '' ) { - return new WikiError( wfMsg( 'noemail', $u->getName() ) ); + return Status::newFatal( 'noemail', $u->getName() ); } - $ip = wfGetIP(); + $ip = $this->getRequest()->getIP(); if( !$ip ) { - return new WikiError( wfMsg( 'badipaddress' ) ); + return Status::newFatal( 'badipaddress' ); } - - wfRunHooks( 'User::mailPasswordInternal', array(&$wgUser, &$ip, &$u) ); + + $currentUser = $this->getUser(); + wfRunHooks( 'User::mailPasswordInternal', array( &$currentUser, &$ip, &$u ) ); $np = $u->randomPassword(); $u->setNewpassword( $np, $throttle ); $u->saveSettings(); $userLanguage = $u->getOption( 'language' ); - $m = wfMsgExt( $emailText, array( 'parsemag', 'language' => $userLanguage ), $ip, $u->getName(), $np, - $wgServer . $wgScript, round( $wgNewPasswordExpiry / 86400 ) ); - $result = $u->sendMail( wfMsgExt( $emailTitle, array( 'parsemag', 'language' => $userLanguage ) ), $m ); + $m = $this->msg( $emailText, $ip, $u->getName(), $np, $wgServer . $wgScript, + round( $wgNewPasswordExpiry / 86400 ) )->inLanguage( $userLanguage )->text(); + $result = $u->sendMail( $this->msg( $emailTitle )->inLanguage( $userLanguage )->text(), $m ); return $result; } @@ -820,11 +859,10 @@ class LoginForm { * @private */ function successfulLogin() { - global $wgUser, $wgOut; - # Run any hooks; display injected HTML if any, else redirect + $currentUser = $this->getUser(); $injected_html = ''; - wfRunHooks('UserLoginComplete', array(&$wgUser, &$injected_html)); + wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) ); if( $injected_html !== '' ) { $this->displaySuccessfulLogin( 'loginsuccess', $injected_html ); @@ -833,7 +871,12 @@ class LoginForm { if ( !$titleObj instanceof Title ) { $titleObj = Title::newMainPage(); } - $wgOut->redirect( $titleObj->getFullURL( $this->mReturnToQuery ) ); + $redirectUrl = $titleObj->getFullURL( $this->mReturnToQuery ); + global $wgSecureLogin; + if( $wgSecureLogin && !$this->mStickHTTPS ) { + $redirectUrl = preg_replace( '/^https:/', 'http:', $redirectUrl ); + } + $this->getOutput()->redirect( $redirectUrl ); } } @@ -844,54 +887,50 @@ class LoginForm { * @private */ function successfulCreation() { - global $wgUser, $wgOut; - # Run any hooks; display injected HTML + $currentUser = $this->getUser(); $injected_html = ''; - wfRunHooks('UserLoginComplete', array(&$wgUser, &$injected_html)); + $welcome_creation_msg = 'welcomecreation'; + + wfRunHooks( 'UserLoginComplete', array( &$currentUser, &$injected_html ) ); - $this->displaySuccessfulLogin( 'welcomecreation', $injected_html ); + /** + * Let any extensions change what message is shown. + * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforeWelcomeCreation + * @since 1.18 + */ + wfRunHooks( 'BeforeWelcomeCreation', array( &$welcome_creation_msg, &$injected_html ) ); + + $this->displaySuccessfulLogin( $welcome_creation_msg, $injected_html ); } /** * Display a "login successful" page. */ private function displaySuccessfulLogin( $msgname, $injected_html ) { - global $wgOut, $wgUser; + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'loginsuccesstitle' ) ); + if( $msgname ){ + $out->addWikiMsg( $msgname, wfEscapeWikiText( $this->getUser()->getName() ) ); + } - $wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) ); - $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->setArticleRelated( false ); - $wgOut->addWikiMsg( $msgname, $wgUser->getName() ); - $wgOut->addHTML( $injected_html ); + $out->addHTML( $injected_html ); if ( !empty( $this->mReturnTo ) ) { - $wgOut->returnToMain( null, $this->mReturnTo, $this->mReturnToQuery ); + $out->returnToMain( null, $this->mReturnTo, $this->mReturnToQuery ); } else { - $wgOut->returnToMain( null ); + $out->returnToMain( null ); } } - /** */ - function userNotPrivilegedMessage($errors) { - global $wgOut; - - $wgOut->setPageTitle( wfMsg( 'permissionserrors' ) ); - $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->setArticleRelated( false ); - - $wgOut->addWikitext( $wgOut->formatPermissionsErrorMessage( $errors, 'createaccount' ) ); - // Stuff that might want to be added at the end. For example, instruc- - // tions if blocked. - $wgOut->addWikiMsg( 'cantcreateaccount-nonblock-text' ); - - $wgOut->returnToMain( false ); - } - - /** */ - function userBlockedMessage() { - global $wgOut, $wgUser; - + /** + * Output a message that informs the user that they cannot create an account because + * there is a block on them or their IP which prevents account creation. Note that + * User::isBlockedFromCreateAccount(), which gets this block, ignores the 'hardblock' + * setting on blocks (bug 13611). + * @param $block Block the block causing this error + */ + function userBlockedMessage( Block $block ) { # Let's be nice about this, it's likely that this feature will be used # for blocking large numbers of innocent people, e.g. range blocks on # schools. Don't blame it on the user. There's a small chance that it @@ -900,57 +939,59 @@ class LoginForm { # evade it, but we'll leave that to their guilty conscience to figure # out. - $wgOut->setPageTitle( wfMsg( 'cantcreateaccounttitle' ) ); - $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->setArticleRelated( false ); - - $ip = wfGetIP(); - $blocker = User::whoIs( $wgUser->mBlock->mBy ); - $block_reason = $wgUser->mBlock->mReason; + $out = $this->getOutput(); + $out->setPageTitle( $this->msg( 'cantcreateaccounttitle' ) ); + $block_reason = $block->mReason; if ( strval( $block_reason ) === '' ) { - $block_reason = wfMsg( 'blockednoreason' ); + $block_reason = $this->msg( 'blockednoreason' )->text(); } - $wgOut->addWikiMsg( 'cantcreateaccount-text', $ip, $block_reason, $blocker ); - $wgOut->returnToMain( false ); + + $out->addWikiMsg( + 'cantcreateaccount-text', + $block->getTarget(), + $block_reason, + $block->getByName() + ); + + $out->returnToMain( false ); } /** * @private */ function mainLoginForm( $msg, $msgtype = 'error' ) { - global $wgUser, $wgOut, $wgHiddenPrefs, $wgEnableEmail; - global $wgCookiePrefix, $wgLoginLanguageSelector; + global $wgEnableEmail, $wgEnableUserEmail; + global $wgHiddenPrefs, $wgLoginLanguageSelector; global $wgAuth, $wgEmailConfirmToEdit, $wgCookieExpiration; - - $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); - + global $wgSecureLogin, $wgPasswordResetRoutes; + + $titleObj = $this->getTitle(); + $user = $this->getUser(); + if ( $this->mType == 'signup' ) { - // Block signup here if in readonly. Keeps user from - // going through the process (filling out data, etc) + // Block signup here if in readonly. Keeps user from + // going through the process (filling out data, etc) // and being informed later. - if ( wfReadOnly() ) { - $wgOut->readOnlyPage(); - return; - } elseif ( $wgUser->isBlockedFromCreateAccount() ) { - $this->userBlockedMessage(); - return; - } elseif ( count( $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $wgUser, true ) )>0 ) { - $wgOut->showPermissionsErrorPage( $permErrors, 'createaccount' ); + $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $user, true ); + if ( count( $permErrors ) ) { + throw new PermissionsError( 'createaccount', $permErrors ); + } elseif ( $user->isBlockedFromCreateAccount() ) { + $this->userBlockedMessage( $user->isBlockedFromCreateAccount() ); return; + } elseif ( wfReadOnly() ) { + throw new ReadOnlyError; } } - if ( $this->mName == '' ) { - if ( $wgUser->isLoggedIn() ) { - $this->mName = $wgUser->getName(); + if ( $this->mUsername == '' ) { + if ( $user->isLoggedIn() ) { + $this->mUsername = $user->getName(); } else { - $this->mName = isset( $_COOKIE[$wgCookiePrefix.'UserName'] ) ? $_COOKIE[$wgCookiePrefix.'UserName'] : null; + $this->mUsername = $this->getRequest()->getCookie( 'UserName' ); } } - $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); - if ( $this->mType == 'signup' ) { $template = new UsercreateTemplate(); $q = 'action=submitlogin&type=signup'; @@ -965,45 +1006,56 @@ class LoginForm { if ( !empty( $this->mReturnTo ) ) { $returnto = '&returnto=' . wfUrlencode( $this->mReturnTo ); - if ( !empty( $this->mReturnToQuery ) ) + if ( !empty( $this->mReturnToQuery ) ) { $returnto .= '&returntoquery=' . wfUrlencode( $this->mReturnToQuery ); + } $q .= $returnto; $linkq .= $returnto; } - # Pass any language selection on to the mode switch link - if( $wgLoginLanguageSelector && $this->mLanguage ) - $linkq .= '&uselang=' . $this->mLanguage; - - $link = ''; - $link .= wfMsgHtml( $linkmsg . 'link' ); # Calling either 'gotaccountlink' or 'nologinlink' - $link .= ''; - # Don't show a "create account" link if the user can't - if( $this->showCreateOrLoginLink( $wgUser ) ) - $template->set( 'link', preg_replace('/(^

|<\/p>$)/', '', wfMsgWikiHtml( $linkmsg, $link ) ) ); - else + if( $this->showCreateOrLoginLink( $user ) ) { + # Pass any language selection on to the mode switch link + if( $wgLoginLanguageSelector && $this->mLanguage ) { + $linkq .= '&uselang=' . $this->mLanguage; + } + $link = Html::element( 'a', array( 'href' => $titleObj->getLocalURL( $linkq ) ), + $this->msg( $linkmsg . 'link' )->text() ); # Calling either 'gotaccountlink' or 'nologinlink' + + $template->set( 'link', $this->msg( $linkmsg )->rawParams( $link )->parse() ); + } else { $template->set( 'link', '' ); + } + + $resetLink = $this->mType == 'signup' + ? null + : is_array( $wgPasswordResetRoutes ) && in_array( true, array_values( $wgPasswordResetRoutes ) ); $template->set( 'header', '' ); - $template->set( 'name', $this->mName ); + $template->set( 'name', $this->mUsername ); $template->set( 'password', $this->mPassword ); $template->set( 'retype', $this->mRetype ); $template->set( 'email', $this->mEmail ); $template->set( 'realname', $this->mRealName ); $template->set( 'domain', $this->mDomain ); + $template->set( 'reason', $this->mReason ); - $template->set( 'action', $titleObj->getLocalUrl( $q ) ); + $template->set( 'action', $titleObj->getLocalURL( $q ) ); $template->set( 'message', $msg ); $template->set( 'messagetype', $msgtype ); - $template->set( 'createemail', $wgEnableEmail && $wgUser->isLoggedIn() ); + $template->set( 'createemail', $wgEnableEmail && $user->isLoggedIn() ); $template->set( 'userealname', !in_array( 'realname', $wgHiddenPrefs ) ); $template->set( 'useemail', $wgEnableEmail ); $template->set( 'emailrequired', $wgEmailConfirmToEdit ); + $template->set( 'emailothers', $wgEnableUserEmail ); $template->set( 'canreset', $wgAuth->allowPasswordChange() ); + $template->set( 'resetlink', $resetLink ); $template->set( 'canremember', ( $wgCookieExpiration > 0 ) ); - $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember ); + $template->set( 'usereason', $user->isLoggedIn() ); + $template->set( 'remember', $user->getOption( 'rememberpassword' ) || $this->mRemember ); + $template->set( 'cansecurelogin', ( $wgSecureLogin === true ) ); + $template->set( 'stickHTTPS', $this->mStickHTTPS ); if ( $this->mType == 'signup' ) { if ( !self::getCreateaccountToken() ) { @@ -1016,12 +1068,29 @@ class LoginForm { } $template->set( 'token', self::getLoginToken() ); } - + # Prepare language selection links as needed if( $wgLoginLanguageSelector ) { $template->set( 'languages', $this->makeLanguageSelector() ); - if( $this->mLanguage ) + if( $this->mLanguage ) { $template->set( 'uselang', $this->mLanguage ); + } + } + + // Use loginend-https for HTTPS requests if it's not blank, loginend otherwise + // Ditto for signupend + $usingHTTPS = WebRequest::detectProtocol() == 'https'; + $loginendHTTPS = $this->msg( 'loginend-https' ); + $signupendHTTPS = $this->msg( 'signupend-https' ); + if ( $usingHTTPS && !$loginendHTTPS->isBlank() ) { + $template->set( 'loginend', $loginendHTTPS->parse() ); + } else { + $template->set( 'loginend', $this->msg( 'loginend' )->parse() ); + } + if ( $usingHTTPS && !$signupendHTTPS->isBlank() ) { + $template->set( 'signupend', $signupendHTTPS->parse() ); + } else { + $template->set( 'signupend', $this->msg( 'signupend' )->parse() ); } // Give authentication and captcha plugins a chance to modify the form @@ -1032,29 +1101,25 @@ class LoginForm { wfRunHooks( 'UserLoginForm', array( &$template ) ); } - //Changes the title depending on permissions for creating account - if ( $wgUser->isAllowed( 'createaccount' ) ) { - $wgOut->setPageTitle( wfMsg( 'userlogin' ) ); - } else { - $wgOut->setPageTitle( wfMsg( 'userloginnocreate' ) ); - } - - $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->setArticleRelated( false ); - $wgOut->disallowUserJs(); // just in case... - $wgOut->addTemplate( $template ); + $out = $this->getOutput(); + $out->disallowUserJs(); // just in case... + $out->addTemplate( $template ); } /** * @private + * + * @param $user User + * + * @return Boolean */ function showCreateOrLoginLink( &$user ) { if( $this->mType == 'signup' ) { - return( true ); + return true; } elseif( $user->isAllowed( 'createaccount' ) ) { - return( true ); + return true; } else { - return( false ); + return false; } } @@ -1068,10 +1133,10 @@ class LoginForm { * @private */ function hasSessionCookie() { - global $wgDisableCookieCheck, $wgRequest; - return $wgDisableCookieCheck ? true : $wgRequest->checkSessionCookie(); + global $wgDisableCookieCheck; + return $wgDisableCookieCheck ? true : $this->getRequest()->checkSessionCookie(); } - + /** * Get the login token from the current session */ @@ -1079,7 +1144,7 @@ class LoginForm { global $wgRequest; return $wgRequest->getSessionData( 'wsLoginToken' ); } - + /** * Randomly generate a new login token and attach it to the current session */ @@ -1089,7 +1154,7 @@ class LoginForm { // because the latter reuses $_SESSION['wsEditToken'] $wgRequest->setSessionData( 'wsLoginToken', User::generateToken() ); } - + /** * Remove any login token attached to the current session */ @@ -1105,7 +1170,7 @@ class LoginForm { global $wgRequest; return $wgRequest->getSessionData( 'wsCreateaccountToken' ); } - + /** * Randomly generate a new createaccount token and attach it to the current session */ @@ -1113,7 +1178,7 @@ class LoginForm { global $wgRequest; $wgRequest->setSessionData( 'wsCreateaccountToken', User::generateToken() ); } - + /** * Remove any createaccount token attached to the current session */ @@ -1126,14 +1191,14 @@ class LoginForm { * @private */ function cookieRedirectCheck( $type ) { - global $wgOut; - $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); $query = array( 'wpCookieCheck' => $type ); - if ( $this->mReturnTo ) $query['returnto'] = $this->mReturnTo; + if ( $this->mReturnTo ) { + $query['returnto'] = $this->mReturnTo; + } $check = $titleObj->getFullURL( $query ); - return $wgOut->redirect( $check ); + return $this->getOutput()->redirect( $check ); } /** @@ -1142,12 +1207,12 @@ class LoginForm { function onCookieRedirectCheck( $type ) { if ( !$this->hasSessionCookie() ) { if ( $type == 'new' ) { - return $this->mainLoginForm( wfMsgExt( 'nocookiesnew', array( 'parseinline' ) ) ); - } else if ( $type == 'login' ) { - return $this->mainLoginForm( wfMsgExt( 'nocookieslogin', array( 'parseinline' ) ) ); + return $this->mainLoginForm( $this->msg( 'nocookiesnew' )->parse() ); + } elseif ( $type == 'login' ) { + return $this->mainLoginForm( $this->msg( 'nocookieslogin' )->parse() ); } else { # shouldn't happen - return $this->mainLoginForm( wfMsg( 'error' ) ); + return $this->mainLoginForm( $this->msg( 'error' )->text() ); } } else { return $this->successfulLogin(); @@ -1158,7 +1223,7 @@ class LoginForm { * @private */ function throttleHit( $limit ) { - $this->mainLoginForm( wfMsgExt( 'acct_creation_throttle_hit', array( 'parseinline' ), $limit ) ); + $this->mainLoginForm( $this->msg( 'acct_creation_throttle_hit' )->numParams( $limit )->parse() ); } /** @@ -1168,20 +1233,19 @@ class LoginForm { * @return string */ function makeLanguageSelector() { - global $wgLang; - - $msg = wfMsgForContent( 'loginlanguagelinks' ); - if( $msg != '' && !wfEmptyMsg( 'loginlanguagelinks', $msg ) ) { - $langs = explode( "\n", $msg ); + $msg = $this->msg( 'loginlanguagelinks' )->inContentLanguage(); + if( !$msg->isBlank() ) { + $langs = explode( "\n", $msg->text() ); $links = array(); foreach( $langs as $lang ) { $lang = trim( $lang, '* ' ); $parts = explode( '|', $lang ); - if (count($parts) >= 2) { - $links[] = $this->makeLanguageSelectorLink( $parts[0], $parts[1] ); + if ( count( $parts ) >= 2 ) { + $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) ); } } - return count( $links ) > 0 ? wfMsgHtml( 'loginlanguagelabel', $wgLang->pipeList( $links ) ) : ''; + return count( $links ) > 0 ? $this->msg( 'loginlanguagelabel' )->rawParams( + $this->getLanguage()->pipeList( $links ) )->escaped() : ''; } else { return ''; } @@ -1195,16 +1259,15 @@ class LoginForm { * @param $lang Language code */ function makeLanguageSelectorLink( $text, $lang ) { - global $wgUser; - $self = SpecialPage::getTitleFor( 'Userlogin' ); $attr = array( 'uselang' => $lang ); - if( $this->mType == 'signup' ) + if( $this->mType == 'signup' ) { $attr['type'] = 'signup'; - if( $this->mReturnTo ) + } + if( $this->mReturnTo ) { $attr['returnto'] = $this->mReturnTo; - $skin = $wgUser->getSkin(); - return $skin->linkKnown( - $self, + } + return Linker::linkKnown( + $this->getTitle(), htmlspecialchars( $text ), array(), $attr