X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/d7967d5e4460e08b6b258307afbca0596b18a3dd:/includes/SpecialUserlogin.php..refs/tags/mediawiki-1.14.0:/includes/specials/SpecialUserlogin.php diff --git a/includes/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php similarity index 58% rename from includes/SpecialUserlogin.php rename to includes/specials/SpecialUserlogin.php index f358c1fd..6a4da7a4 100644 --- a/includes/SpecialUserlogin.php +++ b/includes/specials/SpecialUserlogin.php @@ -1,25 +1,25 @@ execute(); } /** * implements Special:Login - * @addtogroup SpecialPage + * @ingroup SpecialPage */ class LoginForm { @@ -32,20 +32,22 @@ class LoginForm { const EMPTY_PASS = 6; const RESET_PASS = 7; const ABORTED = 8; + const CREATE_BLOCKED = 9; + const THROTTLED = 10; var $mName, $mPassword, $mRetype, $mReturnTo, $mCookieCheck, $mPosted; var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword; - var $mLoginattempt, $mRemember, $mEmail, $mDomain, $mLanguage; + var $mLoginattempt, $mRemember, $mEmail, $mDomain, $mLanguage, $mSkipCookieCheck; /** * Constructor * @param WebRequest $request A WebRequest object passed by reference */ - function LoginForm( &$request ) { + function LoginForm( &$request, $par = '' ) { global $wgLang, $wgAllowRealName, $wgEnableEmail; global $wgAuth; - $this->mType = $request->getText( 'type' ); + $this->mType = ( $par == 'signup' ) ? $par : $request->getText( 'type' ); # Check for [[Special:Userlogin/signup]] $this->mName = $request->getText( 'wpName' ); $this->mPassword = $request->getText( 'wpPassword' ); $this->mRetype = $request->getText( 'wpRetype' ); @@ -62,6 +64,7 @@ class LoginForm { $this->mAction = $request->getVal( 'action' ); $this->mRemember = $request->getCheck( 'wpRemember' ); $this->mLanguage = $request->getText( 'uselang' ); + $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' ); if( $wgEnableEmail ) { $this->mEmail = $request->getText( 'wpEmail' ); @@ -123,18 +126,19 @@ class LoginForm { // Wipe the initial password and mail a temporary one $u->setPassword( null ); $u->saveSettings(); - $result = $this->mailPasswordInternal( $u, false ); + $result = $this->mailPasswordInternal( $u, false, 'createaccount-title', 'createaccount-text' ); - wfRunHooks( 'AddNewAccount', array( $u ) ); + wfRunHooks( 'AddNewAccount', array( $u, true ) ); + $u->addNewUserLogEntry(); $wgOut->setPageTitle( wfMsg( 'accmailtitle' ) ); - $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->setRobotPolicy( 'noindex,nofollow' ); $wgOut->setArticleRelated( false ); if( WikiError::isError( $result ) ) { $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) ); } else { - $wgOut->addWikiText( wfMsg( 'accmailtext', $u->getName(), $u->getEmail() ) ); + $wgOut->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() ); $wgOut->returnToMain( false ); } $u = 0; @@ -158,26 +162,30 @@ class LoginForm { if( $wgLoginLanguageSelector && $this->mLanguage ) $u->setOption( 'language', $this->mLanguage ); - # Save user settings and send out an email authentication message if needed - $u->saveSettings(); + # Send out an email authentication message if needed if( $wgEmailAuthentication && User::isValidEmailAddr( $u->getEmail() ) ) { global $wgOut; $error = $u->sendConfirmationMail(); if( WikiError::isError( $error ) ) { - $wgOut->addWikiText( wfMsg( 'confirmemail_sendfailed', $error->getMessage() ) ); + $wgOut->addWikiMsg( 'confirmemail_sendfailed', $error->getMessage() ); } else { - $wgOut->addWikiText( wfMsg( 'confirmemail_oncreate' ) ); + $wgOut->addWikiMsg( 'confirmemail_oncreate' ); } } - # 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 + # Save settings (including confirmation token) + $u->saveSettings(); + + # 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() ) { $wgUser = $u; $wgUser->setCookies(); wfRunHooks( 'AddNewAccount', array( $wgUser ) ); + $wgUser->addNewUserLogEntry(); if( $this->hasSessionCookie() ) { - return $this->successfulLogin( wfMsg( 'welcomecreation', $wgUser->getName() ), false ); + return $this->successfulCreation(); } else { return $this->cookieRedirectCheck( 'new' ); } @@ -188,9 +196,10 @@ class LoginForm { $wgOut->setPageTitle( wfMsgHtml( 'accountcreated' ) ); $wgOut->setArticleRelated( false ); $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->addHtml( wfMsgWikiHtml( 'accountcreatedtext', $u->getName() ) ); - $wgOut->returnToMain( $self->getPrefixedText() ); + $wgOut->addHTML( wfMsgWikiHtml( 'accountcreatedtext', $u->getName() ) ); + $wgOut->returnToMain( false, $self ); wfRunHooks( 'AddNewAccount', array( $u ) ); + $u->addNewUserLogEntry(); return true; } } @@ -203,6 +212,7 @@ class LoginForm { global $wgEnableSorbs, $wgProxyWhitelist; global $wgMemc, $wgAccountCreationThrottle; global $wgAuth, $wgMinimalPasswordLength; + global $wgEmailConfirmToEdit; // If the user passes an invalid domain, something is fishy if( !$wgAuth->validDomain( $this->mDomain ) ) { @@ -210,12 +220,11 @@ class LoginForm { return false; } - // If we are not allowing users to login locally, we should - // be checking to see if the user is actually able to - // authenticate to the authentication server before they - // create an account (otherwise, they can create a local account - // and login as any domain user). We only need to check this for - // domains that aren't local. + // If we are not allowing users to login locally, we should be checking + // to see if the user is actually able to authenticate to the authenti- + // cation server before they create an account (otherwise, they can + // 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' ) ); @@ -228,10 +237,13 @@ class LoginForm { return false; } - # Check anonymous user ($wgUser) limitations : - if (!$wgUser->isAllowedToCreateAccount()) { + # Check permissions + if ( !$wgUser->isAllowed( 'createaccount' ) ) { $this->userNotPrivilegedMessage(); return false; + } elseif ( $wgUser->isBlockedFromCreateAccount() ) { + $this->userBlockedMessage(); + return false; } $ip = wfGetIP(); @@ -260,13 +272,32 @@ class LoginForm { return false; } + # check for minimal password length if ( !$u->isValidPassword( $this->mPassword ) ) { - $this->mainLoginForm( wfMsg( 'passwordtooshort', $wgMinimalPasswordLength ) ); + if ( !$this->mCreateaccountMail ) { + $this->mainLoginForm( wfMsgExt( 'passwordtooshort', array( 'parsemag' ), $wgMinimalPasswordLength ) ); + return false; + } else { + # do not force a password for account creation by email + # set invalid password, it will be replaced later by a random generated password + $this->mPassword = null; + } + } + + # 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' ) ); return false; } - - # Set some additional data so the AbortNewAccount hook can be - # used for more than just username validation + + if( !empty( $this->mEmail ) && !User::isValidEmailAddr( $this->mEmail ) ) { + $this->mainLoginForm( wfMsg( 'invalidemailaddress' ) ); + return false; + } + + # Set some additional data so the AbortNewAccount hook can be used for + # more than just username validation $u->setEmail( $this->mEmail ); $u->setRealName( $this->mRealName ); @@ -280,14 +311,15 @@ class LoginForm { if ( $wgAccountCreationThrottle && $wgUser->isPingLimitable() ) { $key = wfMemcKey( 'acctcreate', 'ip', $ip ); - $value = $wgMemc->incr( $key ); + $value = $wgMemc->get( $key ); if ( !$value ) { - $wgMemc->set( $key, 1, 86400 ); + $wgMemc->set( $key, 0, 86400 ); } - if ( $value > $wgAccountCreationThrottle ) { + if ( $value >= $wgAccountCreationThrottle ) { $this->throttleHit( $wgAccountCreationThrottle ); return false; } + $wgMemc->incr( $key ); } if( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) { @@ -346,25 +378,48 @@ class LoginForm { if ( '' == $this->mName ) { return self::NO_NAME; } + + 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; + } + } + + // 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 + // will effectively be using stale data. + if ( $wgUser->getName() === $this->mName ) { + wfDebug( __METHOD__.": already logged in as {$this->mName}\n" ); + return self::SUCCESS; + } $u = User::newFromName( $this->mName ); if( is_null( $u ) || !User::isUsableName( $u->getName() ) ) { return self::ILLEGAL; } + + $isAutoCreated = false; if ( 0 == $u->getID() ) { - global $wgAuth; - /** - * If the external authentication plugin allows it, - * automatically create a new account for users that - * are externally defined but have not yet logged in. - */ - if ( $wgAuth->autoCreate() && $wgAuth->userExists( $u->getName() ) ) { - if ( $wgAuth->authenticate( $u->getName(), $this->mPassword ) ) { - $u = $this->initUser( $u, true ); - } else { - return self::WRONG_PLUGIN_PASS; - } + $status = $this->attemptAutoCreate( $u ); + if ( $status !== self::SUCCESS ) { + return $status; } else { - return self::NOT_EXISTS; + $isAutoCreated = true; } } else { $u->load(); @@ -375,36 +430,33 @@ class LoginForm { if( !wfRunHooks( 'AbortLogin', array( $u, $this->mPassword, &$abort ) ) ) { return $abort; } - + if (!$u->checkPassword( $this->mPassword )) { if( $u->checkTemporaryPassword( $this->mPassword ) ) { - // The e-mailed temporary password should not be used - // for actual logins; that's a very sloppy habit, - // and insecure if an attacker has a few seconds to - // click "search" on someone's open mail reader. + // The e-mailed temporary password should not be used for actu- + // al logins; that's a very sloppy habit, and insecure if an + // attacker has a few seconds to click "search" on someone's o- + // pen mail reader. // - // Allow it to be used only to reset the password - // a single time to a new value, which won't be in - // the user's e-mail archives. + // Allow it to be used only to reset the password a single time + // to a new value, which won't be in the user's e-mail ar- + // chives. // - // For backwards compatibility, we'll still recognize - // it at the login form to minimize surprises for - // people who have been logging in with a temporary - // password for some time. - // - // As a side-effect, we can authenticate the user's - // e-mail address if it's not already done, since - // the temporary password was sent via e-mail. + // For backwards compatibility, we'll still recognize it at the + // login form to minimize surprises for people who have been + // logging in with a temporary password for some time. // + // As a side-effect, we can authenticate the user's e-mail ad- + // dress if it's not already done, since the temporary password + // was sent via e-mail. if( !$u->isEmailConfirmed() ) { $u->confirmEmail(); + $u->saveSettings(); } - // At this point we just return an appropriate code - // indicating that the UI should show a password - // reset form; bot interfaces etc will probably just - // fail cleanly here. - // + // At this point we just return an appropriate code/ indicating + // that the UI should show a password reset form; bot inter- + // faces etc will probably just fail cleanly here. $retval = self::RESET_PASS; } else { $retval = '' == $this->mPassword ? self::EMPTY_PASS : self::WRONG_PASS; @@ -413,12 +465,55 @@ class LoginForm { $wgAuth->updateUser( $u ); $wgUser = $u; + // Please reset throttle for successful logins, thanks! + if($throttleCount) { + $wgMemc->delete($throttleKey); + } + + if ( $isAutoCreated ) { + // Must be run after $wgUser is set, for correct new user log + wfRunHooks( 'AuthPluginAutoCreate', array( $wgUser ) ); + } + $retval = self::SUCCESS; } wfRunHooks( 'LoginAuthenticateAudit', array( $u, $this->mPassword, $retval ) ); return $retval; } + /** + * Attempt to automatically create a user on login. Only succeeds if there + * is an external authentication method which allows it. + * @return integer Status code + */ + function attemptAutoCreate( $user ) { + global $wgAuth, $wgUser; + /** + * If the external authentication plugin allows it, automatically cre- + * ate a new account for users that are externally defined but have not + * yet logged in. + */ + if ( !$wgAuth->autoCreate() ) { + return self::NOT_EXISTS; + } + if ( !$wgAuth->userExists( $user->getName() ) ) { + 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" ); + return self::WRONG_PLUGIN_PASS; + } + if ( $wgUser->isBlockedFromCreateAccount() ) { + wfDebug( __METHOD__.": user is blocked from account creation\n" ); + return self::CREATE_BLOCKED; + } + + wfDebug( __METHOD__.": creating account\n" ); + $user = $this->initUser( $user, true ); + return self::SUCCESS; + } + function processLogin() { global $wgUser, $wgAuth; @@ -434,8 +529,19 @@ class LoginForm { } $wgUser->setCookies(); - if( $this->hasSessionCookie() ) { - return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) ); + // Reset the throttle + $key = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mName ) ); + global $wgMemc; + $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 ); + return $this->successfulLogin(); } else { return $this->cookieRedirectCheck( 'login' ); } @@ -449,7 +555,11 @@ class LoginForm { $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); break; case self::NOT_EXISTS: - $this->mainLoginForm( wfMsg( 'nosuchuser', htmlspecialchars( $this->mName ) ) ); + if( $wgUser->isAllowed( 'createaccount' ) ){ + $this->mainLoginForm( wfMsgWikiHtml( 'nosuchuser', htmlspecialchars( $this->mName ) ) ); + } else { + $this->mainLoginForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->mName ) ) ); + } break; case self::WRONG_PASS: $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); @@ -460,16 +570,22 @@ class LoginForm { case self::RESET_PASS: $this->resetLoginForm( wfMsg( 'resetpass_announce' ) ); break; + case self::CREATE_BLOCKED: + $this->userBlockedMessage(); + break; + case self::THROTTLED: + $this->mainLoginForm( wfMsg( 'login-throttled' ) ); + break; default: - wfDebugDieBacktrace( "Unhandled case value" ); + throw new MWException( "Unhandled case value" ); } } function resetLoginForm( $error ) { global $wgOut; - $wgOut->addWikiText( "
$error
" ); - $reset = new PasswordResetForm( $this->mName, $this->mPassword ); - $reset->execute(); + $wgOut->addHTML( Xml::element('p', array( 'class' => 'error' ), $error ) ); + $reset = new SpecialResetpass(); + $reset->execute( null ); } /** @@ -506,20 +622,21 @@ class LoginForm { return; } if ( 0 == $u->getID() ) { - $this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName() ) ); + $this->mainLoginForm( wfMsgWikiHtml( 'nosuchuser', htmlspecialchars( $u->getName() ) ) ); 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( wfMsg( 'throttled-mailpassword', + # 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 ); + $result = $this->mailPasswordInternal( $u, true, 'passwordremindertitle', 'passwordremindertext' ); if( WikiError::isError( $result ) ) { $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) ); } else { @@ -529,89 +646,141 @@ class LoginForm { /** + * @param object user + * @param bool throttle + * @param string message name of email title + * @param string message name of email text * @return mixed true on success, WikiError on failure * @private */ - function mailPasswordInternal( $u, $throttle = true ) { - global $wgCookiePath, $wgCookieDomain, $wgCookiePrefix, $wgCookieSecure; - global $wgServer, $wgScript; + function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext' ) { + global $wgServer, $wgScript, $wgUser; if ( '' == $u->getEmail() ) { return new WikiError( wfMsg( 'noemail', $u->getName() ) ); } + $ip = wfGetIP(); + if( !$ip ) { + return new WikiError( wfMsg( 'badipaddress' ) ); + } + + wfRunHooks( 'User::mailPasswordInternal', array(&$wgUser, &$ip, &$u) ); $np = $u->randomPassword(); $u->setNewpassword( $np, $throttle ); - - setcookie( "{$wgCookiePrefix}Token", '', time() - 3600, $wgCookiePath, $wgCookieDomain, $wgCookieSecure ); - $u->saveSettings(); - $ip = wfGetIP(); - if ( '' == $ip ) { $ip = '(Unknown)'; } - - $m = wfMsg( 'passwordremindertext', $ip, $u->getName(), $np, $wgServer . $wgScript ); + $m = wfMsg( $emailText, $ip, $u->getName(), $np, $wgServer . $wgScript ); + $result = $u->sendMail( wfMsg( $emailTitle ), $m ); - $result = $u->sendMail( wfMsg( 'passwordremindertitle' ), $m ); return $result; } /** - * @param string $msg Message that will be shown on success - * @param bool $auto Toggle auto-redirect to main page; default true + * Run any hooks registered for logins, then HTTP redirect to + * $this->mReturnTo (or Main Page if that's undefined). Formerly we had a + * nice message here, but that's really not as useful as just being sent to + * wherever you logged in from. It should be clear that the action was + * successful, given the lack of error messages plus the appearance of your + * name in the upper right. + * * @private */ - function successfulLogin( $msg, $auto = true ) { - global $wgUser; - global $wgOut; + function successfulLogin() { + global $wgUser, $wgOut; + + # Run any hooks; display injected HTML if any, else redirect + $injected_html = ''; + wfRunHooks('UserLoginComplete', array(&$wgUser, &$injected_html)); + + if( $injected_html !== '' ) { + $this->displaySuccessfulLogin( 'loginsuccess', $injected_html ); + } else { + $titleObj = Title::newFromText( $this->mReturnTo ); + if ( !$titleObj instanceof Title ) { + $titleObj = Title::newMainPage(); + } + + $wgOut->redirect( $titleObj->getFullURL() ); + } + } + + /** + * Run any hooks registered for logins, then display a message welcoming + * the user. + * + * @private + */ + function successfulCreation() { + global $wgUser, $wgOut; - # Run any hooks; ignore results + # Run any hooks; display injected HTML + $injected_html = ''; + wfRunHooks('UserLoginComplete', array(&$wgUser, &$injected_html)); - wfRunHooks('UserLoginComplete', array(&$wgUser)); + $this->displaySuccessfulLogin( 'welcomecreation', $injected_html ); + } + + /** + * Display a "login successful" page. + */ + private function displaySuccessfulLogin( $msgname, $injected_html ) { + global $wgOut, $wgUser; $wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) ); - $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->setRobotPolicy( 'noindex,nofollow' ); $wgOut->setArticleRelated( false ); - $wgOut->addWikiText( $msg ); + $wgOut->addWikiMsg( $msgname, $wgUser->getName() ); + $wgOut->addHTML( $injected_html ); + if ( !empty( $this->mReturnTo ) ) { - $wgOut->returnToMain( $auto, $this->mReturnTo ); + $wgOut->returnToMain( null, $this->mReturnTo ); } else { - $wgOut->returnToMain( $auto ); + $wgOut->returnToMain( null ); } } /** */ - function userNotPrivilegedMessage() { + function userNotPrivilegedMessage($errors) { global $wgOut; - $wgOut->setPageTitle( wfMsg( 'whitelistacctitle' ) ); - $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->setPageTitle( wfMsg( 'permissionserrors' ) ); + $wgOut->setRobotPolicy( 'noindex,nofollow' ); $wgOut->setArticleRelated( false ); - $wgOut->addWikiText( wfMsg( 'whitelistacctext' ) ); + $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; + global $wgOut, $wgUser; # 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 - # really is the user's fault, i.e. the username is blocked and they - # haven't bothered to log out before trying to create an account to + # 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 + # really is the user's fault, i.e. the username is blocked and they + # haven't bothered to log out before trying to create an account to # evade it, but we'll leave that to their guilty conscience to figure # out. $wgOut->setPageTitle( wfMsg( 'cantcreateaccounttitle' ) ); - $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->setRobotPolicy( 'noindex,nofollow' ); $wgOut->setArticleRelated( false ); $ip = wfGetIP(); - $wgOut->addWikiText( wfMsg( 'cantcreateaccounttext', $ip ) ); + $blocker = User::whoIs( $wgUser->mBlock->mBy ); + $block_reason = $wgUser->mBlock->mReason; + + if ( strval( $block_reason ) === '' ) { + $block_reason = wfMsg( 'blockednoreason' ); + } + $wgOut->addWikiMsg( 'cantcreateaccount-text', $ip, $block_reason, $blocker ); $wgOut->returnToMain( false ); } @@ -620,16 +789,24 @@ class LoginForm { */ function mainLoginForm( $msg, $msgtype = 'error' ) { global $wgUser, $wgOut, $wgAllowRealName, $wgEnableEmail; - global $wgCookiePrefix, $wgAuth, $wgLoginLanguageSelector; - global $wgAuth; - + global $wgCookiePrefix, $wgLoginLanguageSelector; + global $wgAuth, $wgEmailConfirmToEdit, $wgCookieExpiration; + + $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); + if ( $this->mType == 'signup' ) { - if ( !$wgUser->isAllowed( 'createaccount' ) ) { - $this->userNotPrivilegedMessage(); + // 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' ); + return; } } @@ -666,7 +843,7 @@ class LoginForm { $linkq .= '&uselang=' . $this->mLanguage; $link = ''; - $link .= wfMsgHtml( $linkmsg . 'link' ); + $link .= wfMsgHtml( $linkmsg . 'link' ); # Calling either 'gotaccountlink' or 'nologinlink' $link .= ''; # Don't show a "create account" link if the user can't @@ -689,7 +866,9 @@ class LoginForm { $template->set( 'createemail', $wgEnableEmail && $wgUser->isLoggedIn() ); $template->set( 'userealname', $wgAllowRealName ); $template->set( 'useemail', $wgEnableEmail ); + $template->set( 'emailrequired', $wgEmailConfirmToEdit ); $template->set( 'canreset', $wgAuth->allowPasswordChange() ); + $template->set( 'canremember', ( $wgCookieExpiration > 0 ) ); $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember ); # Prepare language selection links as needed @@ -708,7 +887,7 @@ class LoginForm { } $wgOut->setPageTitle( wfMsg( 'userlogin' ) ); - $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->setRobotPolicy( 'noindex,nofollow' ); $wgOut->setArticleRelated( false ); $wgOut->disallowUserJs(); // just in case... $wgOut->addTemplate( $template ); @@ -730,9 +909,9 @@ class LoginForm { /** * Check if a session cookie is present. * - * This will not pick up a cookie set during _this_ request, but is - * meant to ensure that the client is returning the cookie which was - * set on a previous pass through the system. + * This will not pick up a cookie set during _this_ request, but is meant + * to ensure that the client is returning the cookie which was set on a + * previous pass through the system. * * @private */ @@ -748,7 +927,9 @@ class LoginForm { global $wgOut; $titleObj = SpecialPage::getTitleFor( 'Userlogin' ); - $check = $titleObj->getFullURL( 'wpCookieCheck='.$type ); + $query = array( 'wpCookieCheck' => $type ); + if ( $this->mReturnTo ) $query['returnto'] = $this->mReturnTo; + $check = $titleObj->getFullURL( $query ); return $wgOut->redirect( $check ); } @@ -761,15 +942,15 @@ class LoginForm { if ( !$this->hasSessionCookie() ) { if ( $type == 'new' ) { - return $this->mainLoginForm( wfMsg( 'nocookiesnew' ) ); + return $this->mainLoginForm( wfMsgExt( 'nocookiesnew', array( 'parseinline' ) ) ); } else if ( $type == 'login' ) { - return $this->mainLoginForm( wfMsg( 'nocookieslogin' ) ); + return $this->mainLoginForm( wfMsgExt( 'nocookieslogin', array( 'parseinline' ) ) ); } else { # shouldn't happen return $this->mainLoginForm( wfMsg( 'error' ) ); } } else { - return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) ); + return $this->successfulLogin(); } } @@ -777,9 +958,7 @@ class LoginForm { * @private */ function throttleHit( $limit ) { - global $wgOut; - - $wgOut->addWikiText( wfMsg( 'acct_creation_throttle_hit', $limit ) ); + $this->mainLoginForm( wfMsgExt( 'acct_creation_throttle_hit', array( 'parseinline' ), $limit ) ); } /** @@ -796,7 +975,9 @@ class LoginForm { foreach( $langs as $lang ) { $lang = trim( $lang, '* ' ); $parts = explode( '|', $lang ); - $links[] = $this->makeLanguageSelectorLink( $parts[0], $parts[1] ); + if (count($parts) >= 2) { + $links[] = $this->makeLanguageSelectorLink( $parts[0], $parts[1] ); + } } return count( $links ) > 0 ? wfMsgHtml( 'loginlanguagelabel', implode( ' | ', $links ) ) : ''; } else { @@ -823,4 +1004,3 @@ class LoginForm { return $skin->makeKnownLinkObj( $self, htmlspecialchars( $text ), implode( '&', $attr ) ); } } -