Index: phase3/includes/specials/SpecialUserlogin.php
===================================================================
--- phase3/includes/specials/SpecialUserlogin.php	(revision 36761)
+++ phase3/includes/specials/SpecialUserlogin.php	(working copy)
@@ -33,6 +33,7 @@
 	const RESET_PASS = 7;
 	const ABORTED = 8;
 	const CREATE_BLOCKED = 9;
+	const THROTTLE_BLOCKED = 10;
 
 	var $mName, $mPassword, $mRetype, $mReturnTo, $mCookieCheck, $mPosted;
 	var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
@@ -99,7 +100,11 @@
 			} else if ( $this->mMailmypassword ) {
 				return $this->mailPassword();
 			} else if ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
-				return $this->processLogin();
+				if( isset( $GLOBALS[ 'wgPasswordThrottleLimit' ] ) ) {
+					return $this->processLogin( $GLOBALS[ 'wgPasswordThrottleLimit' ] );
+				} else {
+					return $this->processLogin();
+				}
 			}
 		}
 		$this->mainLoginForm( '' );
@@ -367,7 +372,7 @@
 	 *
 	 * @public
 	 */
-	function authenticateUserData() {
+	function authenticateUserData( $throttleLimit = 20 ) {
 		global $wgUser, $wgAuth;
 		if ( '' == $this->mName ) {
 			return self::NO_NAME;
@@ -405,7 +410,17 @@
 			return $abort;
 		}
 
-		if (!$u->checkPassword( $this->mPassword )) {
+		$table = 'user';
+		$vars  = 'last_failed_login';
+		$conds = array( 'user_name' => $this->mName );
+		$dbr =& wfGetDB( DB_SLAVE );
+		$failedlogindate = $dbr->select( $table, $vars, $conds );
+		if( $failedlogindate != "" && time() - $failedlogindate <= $throttleLimit && $throttleLimit != 0 ) {
+			$throttleBlocked = true;
+		} else {
+			$throttleBlocked = false;
+		}
+		if ( !$throttleBlocked && !$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,
@@ -437,8 +452,17 @@
 				//
 				$retval = self::RESET_PASS;
 			} else {
+				$table = 'user';
+				$values = array( 'last_failed_login' => time() );
+				$conds = array( 'user_name' => $this->mName );
+				$dbw =& wfGetDB( DB_MASTER );
+				$dbw->immediateBegin();
+				$dbw->update( $table, $values, $conds );
+				$dbw->immediateCommit();
 				$retval = '' == $this->mPassword ? self::EMPTY_PASS : self::WRONG_PASS;
 			}
+		} elseif( $throttleBlocked ) {
+			$retval = self::THROTTLE_BLOCKED;
 		} else {
 			$wgAuth->updateUser( $u );
 			$wgUser = $u;
@@ -487,10 +511,10 @@
 		return self::SUCCESS;
 	}
 
-	function processLogin() {
+	function processLogin( $throttleLimit = 20 ) {
 		global $wgUser, $wgAuth;
 
-		switch ($this->authenticateUserData())
+		switch( $this->authenticateUserData( $throttleLimit ) )
 		{
 			case self::SUCCESS:
 				# We've verified now, update the real record
@@ -541,6 +565,9 @@
 			case self::CREATE_BLOCKED:
 				$this->userBlockedMessage();
 				break;
+			case self::THROTTLE_BLOCKED:
+				$this->mainLoginForm( wfMsg( 'throttle-blocked' ) );
+				break;
 			default:
 				throw new MWException( "Unhandled case value" );
 		}
