const WRONG_TOKEN = 13;
var $mUsername, $mPassword, $mRetype, $mReturnTo, $mCookieCheck, $mPosted;
- var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
+ var $mAction, $mCreateaccount, $mCreateaccountMail;
var $mLoginattempt, $mRemember, $mEmail, $mDomain, $mLanguage;
var $mSkipCookieCheck, $mReturnToQuery, $mToken, $mStickHTTPS;
var $mType, $mReason, $mRealName;
$this->mCreateaccount = $request->getCheck( 'wpCreateaccount' );
$this->mCreateaccountMail = $request->getCheck( 'wpCreateaccountMail' )
&& $wgEnableEmail;
- $this->mMailmypassword = $request->getCheck( 'wpMailmypassword' )
- && $wgEnableEmail;
$this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
$this->mAction = $request->getVal( 'action' );
$this->mRemember = $request->getCheck( 'wpRemember' );
return $this->addNewAccount();
} elseif ( $this->mCreateaccountMail ) {
return $this->addNewAccountMailPassword();
- } elseif ( $this->mMailmypassword ) {
- return $this->mailPassword();
} elseif ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
return $this->processLogin();
}
global $wgOut;
if ( $this->mEmail == '' ) {
- $this->mainLoginForm( wfMsgExt( 'noemail', array( 'parsemag', 'escape' ), $this->mUsername ) );
+ $this->mainLoginForm( wfMsgExt( 'noemailcreate', array( 'parsemag', 'escape' ) ) );
return;
}
}
# Send out an email authentication message if needed
- if( $wgEmailAuthentication && User::isValidEmailAddr( $u->getEmail() ) ) {
+ if( $wgEmailAuthentication && Sanitizer::validateEmail( $u->getEmail() ) ) {
$status = $u->sendConfirmationMail();
if( $status->isGood() ) {
$wgOut->addWikiMsg( 'confirmemail_oncreate' );
if( $wgUser->isAnon() ) {
$wgUser = $u;
$wgUser->setCookies();
+ // This should set it for OutputPage and the Skin
+ // which is needed or the personal links will be
+ // wrong.
+ RequestContext::getMain()->setUser( $u );
wfRunHooks( 'AddNewAccount', array( $wgUser, false ) );
$wgUser->addNewUserLogEntry();
if( $this->hasSessionCookie() ) {
* @private
*/
function addNewAccountInternal() {
- global $wgUser, $wgOut;
+ global $wgUser, $wgOut, $wgRequest;
global $wgMemc, $wgAccountCreationThrottle;
global $wgAuth, $wgMinimalPasswordLength;
global $wgEmailConfirmToEdit;
$wgOut->permissionRequired( 'createaccount' );
return false;
} elseif ( $wgUser->isBlockedFromCreateAccount() ) {
- $this->userBlockedMessage();
+ $this->userBlockedMessage( $wgUser->isBlockedFromCreateAccount() );
return false;
}
- $ip = wfGetIP();
+ $ip = $wgRequest->getIP();
if ( $wgUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) {
$this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $ip ) . ')' );
return false;
return false;
}
- if( !empty( $this->mEmail ) && !User::isValidEmailAddr( $this->mEmail ) ) {
+ if( !empty( $this->mEmail ) && !Sanitizer::validateEmail( $this->mEmail ) ) {
$this->mainLoginForm( wfMsg( 'invalidemailaddress' ) );
return false;
}
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 && $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;
+ }
+ $wgMemc->incr( $key );
}
- $wgMemc->incr( $key );
}
if( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) {
* creation.
*/
public function authenticateUserData() {
- global $wgUser, $wgAuth, $wgMemc;
+ global $wgUser, $wgAuth;
if ( $this->mUsername == '' ) {
return self::NO_NAME;
return self::NEED_TOKEN;
}
- global $wgPasswordAttemptThrottle;
-
- $throttleCount = 0;
- if ( is_array( $wgPasswordAttemptThrottle ) ) {
- $throttleKey = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mUsername ) );
- $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 self::THROTTLED;
- }
+ $throttleCount = self::incLoginThrottle( $this->mUsername );
+ if ( $throttleCount === true ) {
+ return self::THROTTLED;
}
// Validate the login token
$wgUser = $u;
// Please reset throttle for successful logins, thanks!
- if( $throttleCount ) {
- $wgMemc->delete( $throttleKey );
+ if ( $throttleCount ) {
+ self::clearLoginThrottle( $this->mUsername );
}
if ( $isAutoCreated ) {
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.
}
}
+ $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;
+ global $wgUser, $wgRequest, $wgLang;
switch ( $this->authenticateUserData() ) {
case self::SUCCESS:
self::clearLoginToken();
// Reset the throttle
- $key = wfMemcKey( 'password-throttle', wfGetIP(), md5( $this->mUsername ) );
+ $key = wfMemcKey( 'password-throttle', $wgRequest->getIP(), md5( $this->mUsername ) );
global $wgMemc;
$wgMemc->delete( $key );
/* 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();
break;
case self::NOT_EXISTS:
if( $wgUser->isAllowed( 'createaccount' ) ) {
- $this->mainLoginForm( wfMsgExt( 'nosuchuser', 'parseinline', $this->mUsername ) );
+ $this->mainLoginForm( wfMsgExt( 'nosuchuser', 'parseinline',
+ wfEscapeWikiText( $this->mUsername ) ) );
} else {
- $this->mainLoginForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->mUsername ) ) );
+ $this->mainLoginForm( wfMsg( 'nosuchusershort',
+ wfEscapeWikiText( $this->mUsername ) ) );
}
break;
case self::WRONG_PASS:
$this->resetLoginForm( wfMsg( 'resetpass_announce' ) );
break;
case self::CREATE_BLOCKED:
- $this->userBlockedMessage();
+ $this->userBlockedMessage( $wgUser->mBlock );
break;
case self::THROTTLED:
$this->mainLoginForm( wfMsg( 'login-throttled' ) );
function resetLoginForm( $error ) {
global $wgOut;
$wgOut->addHTML( Xml::element('p', array( 'class' => 'error' ), $error ) );
- $reset = new SpecialResetpass();
+ $reset = new SpecialChangePassword();
$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->mUsername, &$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->mUsername == '' ) {
- $this->mainLoginForm( wfMsg( 'noname' ) );
- return;
- }
- $u = User::newFromName( $this->mUsername );
- if( !$u instanceof User ) {
- $this->mainLoginForm( wfMsg( 'noname' ) );
- return;
- }
- if ( 0 == $u->getID() ) {
- $this->mainLoginForm( wfMsgExt( 'nosuchuser', 'parseinline', $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( $result->isGood() ) {
- $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ), 'success' );
- self::clearLoginToken();
- } else {
- $this->mainLoginForm( $result->getWikiText( 'mailerror' ) );
- }
- }
-
-
/**
* @param $u User object
* @param $throttle Boolean
* @param $emailTitle String: message name of email title
* @param $emailText String: message name of email text
* @return Status object
- * @private
*/
function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext' ) {
- global $wgServer, $wgScript, $wgUser, $wgNewPasswordExpiry;
+ global $wgServer, $wgScript, $wgUser, $wgNewPasswordExpiry, $wgRequest;
if ( $u->getEmail() == '' ) {
return Status::newFatal( 'noemail', $u->getName() );
}
- $ip = wfGetIP();
+ $ip = $wgRequest->getIP();
if( !$ip ) {
return Status::newFatal( 'badipaddress' );
}
global $wgUser;
# Run any hooks; display injected HTML
$injected_html = '';
+ $welcome_creation_msg = 'welcomecreation';
+
wfRunHooks( 'UserLoginComplete', array( &$wgUser, &$injected_html ) );
- $this->displaySuccessfulLogin( 'welcomecreation', $injected_html );
+ //let any extensions change what message is shown
+ wfRunHooks( 'BeforeWelcomeCreation', array( &$welcome_creation_msg, &$injected_html ) );
+
+ $this->displaySuccessfulLogin( $welcome_creation_msg, $injected_html );
}
/**
global $wgOut, $wgUser;
$wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) );
- $wgOut->addWikiMsg( $msgname, $wgUser->getName() );
+ if( $msgname ){
+ $wgOut->addWikiMsg( $msgname, wfEscapeWikiText( $wgUser->getName() ) );
+ }
+
$wgOut->addHTML( $injected_html );
if ( !empty( $this->mReturnTo ) ) {
}
}
- /** */
- 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 ) {
+ global $wgOut;
# 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
$wgOut->setPageTitle( wfMsg( 'cantcreateaccounttitle' ) );
- $ip = wfGetIP();
- $blocker = User::whoIs( $wgUser->mBlock->mBy );
- $block_reason = $wgUser->mBlock->mReason;
-
+ $block_reason = $block->mReason;
if ( strval( $block_reason ) === '' ) {
$block_reason = wfMsg( 'blockednoreason' );
}
- $wgOut->addWikiMsg( 'cantcreateaccount-text', $ip, $block_reason, $blocker );
+
+ $wgOut->addWikiMsg(
+ 'cantcreateaccount-text',
+ $block->getTarget(),
+ $block_reason,
+ $block->getBlocker()->getName()
+ );
+
$wgOut->returnToMain( false );
}
global $wgEnableEmail, $wgEnableUserEmail;
global $wgRequest, $wgLoginLanguageSelector;
global $wgAuth, $wgEmailConfirmToEdit, $wgCookieExpiration;
- global $wgSecureLogin;
+ global $wgSecureLogin, $wgPasswordResetRoutes;
$titleObj = SpecialPage::getTitleFor( 'Userlogin' );
$wgOut->readOnlyPage();
return;
} elseif ( $wgUser->isBlockedFromCreateAccount() ) {
- $this->userBlockedMessage();
+ $this->userBlockedMessage( $wgUser->isBlockedFromCreateAccount() );
return;
} elseif ( count( $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $wgUser, true ) )>0 ) {
$wgOut->showPermissionsErrorPage( $permErrors, 'createaccount' );
}
if ( $this->mType == 'signup' ) {
- global $wgLivePasswordStrengthChecks;
- if ( $wgLivePasswordStrengthChecks ) {
- $wgOut->addPasswordSecurity( 'wpPassword2', 'wpRetype' );
- }
$template = new UsercreateTemplate();
$q = 'action=submitlogin&type=signup';
$linkq = 'type=login';
$template->set( 'link', '' );
}
+ $resetLink = $this->mType == 'signup'
+ ? null
+ : is_array( $wgPasswordResetRoutes ) && in_array( true, array_values( $wgPasswordResetRoutes ) );
+
$template->set( 'header', '' );
$template->set( 'name', $this->mUsername );
$template->set( 'password', $this->mPassword );
$template->set( 'emailrequired', $wgEmailConfirmToEdit );
$template->set( 'emailothers', $wgEnableUserEmail );
$template->set( 'canreset', $wgAuth->allowPasswordChange() );
+ $template->set( 'resetlink', $resetLink );
$template->set( 'canremember', ( $wgCookieExpiration > 0 ) );
$template->set( 'usereason', $wgUser->isLoggedIn() );
$template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) || $this->mRemember );
$lang = trim( $lang, '* ' );
$parts = explode( '|', $lang );
if ( count( $parts ) >= 2 ) {
- $links[] = $this->makeLanguageSelectorLink( $parts[0], $parts[1] );
+ $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
}
}
return count( $links ) > 0 ? wfMsgHtml( 'loginlanguagelabel', $wgLang->pipeList( $links ) ) : '';
* @param $lang Language code
*/
function makeLanguageSelectorLink( $text, $lang ) {
- global $wgUser;
$self = SpecialPage::getTitleFor( 'Userlogin' );
$attr = array( 'uselang' => $lang );
if( $this->mType == 'signup' ) {
if( $this->mReturnTo ) {
$attr['returnto'] = $this->mReturnTo;
}
- $skin = $wgUser->getSkin();
- return $skin->linkKnown(
+ return Linker::linkKnown(
$self,
htmlspecialchars( $text ),
array(),