MediaWiki
REL1_24
|
00001 <?php 00029 class SpecialChangePassword extends FormSpecialPage { 00030 protected $mUserName; 00031 protected $mDomain; 00032 00033 // Optional Wikitext Message to show above the password change form 00034 protected $mPreTextMessage = null; 00035 00036 // label for old password input 00037 protected $mOldPassMsg = null; 00038 00039 public function __construct() { 00040 parent::__construct( 'ChangePassword', 'editmyprivateinfo' ); 00041 $this->listed( false ); 00042 } 00043 00048 function execute( $par ) { 00049 $this->getOutput()->disallowUserJs(); 00050 00051 parent::execute( $par ); 00052 } 00053 00054 protected function checkExecutePermissions( User $user ) { 00055 parent::checkExecutePermissions( $user ); 00056 00057 if ( !$this->getRequest()->wasPosted() ) { 00058 $this->requireLogin( 'resetpass-no-info' ); 00059 } 00060 } 00061 00067 public function setChangeMessage( Message $msg ) { 00068 $this->mPreTextMessage = $msg; 00069 } 00070 00076 public function setOldPasswordMessage( $msg ) { 00077 $this->mOldPassMsg = $msg; 00078 } 00079 00080 protected function getFormFields() { 00081 $user = $this->getUser(); 00082 $request = $this->getRequest(); 00083 00084 $oldpassMsg = $this->mOldPassMsg; 00085 if ( $oldpassMsg === null ) { 00086 $oldpassMsg = $user->isLoggedIn() ? 'oldpassword' : 'resetpass-temp-password'; 00087 } 00088 00089 $fields = array( 00090 'Name' => array( 00091 'type' => 'info', 00092 'label-message' => 'username', 00093 'default' => $request->getVal( 'wpName', $user->getName() ), 00094 ), 00095 'Password' => array( 00096 'type' => 'password', 00097 'label-message' => $oldpassMsg, 00098 ), 00099 'NewPassword' => array( 00100 'type' => 'password', 00101 'label-message' => 'newpassword', 00102 ), 00103 'Retype' => array( 00104 'type' => 'password', 00105 'label-message' => 'retypenew', 00106 ), 00107 ); 00108 00109 if ( !$this->getUser()->isLoggedIn() ) { 00110 if ( !LoginForm::getLoginToken() ) { 00111 LoginForm::setLoginToken(); 00112 } 00113 $fields['LoginOnChangeToken'] = array( 00114 'type' => 'hidden', 00115 'label' => 'Change Password Token', 00116 'default' => LoginForm::getLoginToken(), 00117 ); 00118 } 00119 00120 $extraFields = array(); 00121 wfRunHooks( 'ChangePasswordForm', array( &$extraFields ) ); 00122 foreach ( $extraFields as $extra ) { 00123 list( $name, $label, $type, $default ) = $extra; 00124 $fields[$name] = array( 00125 'type' => $type, 00126 'name' => $name, 00127 'label-message' => $label, 00128 'default' => $default, 00129 ); 00130 } 00131 00132 if ( !$user->isLoggedIn() ) { 00133 $fields['Remember'] = array( 00134 'type' => 'check', 00135 'label' => $this->msg( 'remembermypassword' ) 00136 ->numParams( 00137 ceil( $this->getConfig()->get( 'CookieExpiration' ) / ( 3600 * 24 ) ) 00138 )->text(), 00139 'default' => $request->getVal( 'wpRemember' ), 00140 ); 00141 } 00142 00143 return $fields; 00144 } 00145 00146 protected function alterForm( HTMLForm $form ) { 00147 $form->setId( 'mw-resetpass-form' ); 00148 $form->setTableId( 'mw-resetpass-table' ); 00149 $form->setWrapperLegendMsg( 'resetpass_header' ); 00150 $form->setSubmitTextMsg( 00151 $this->getUser()->isLoggedIn() 00152 ? 'resetpass-submit-loggedin' 00153 : 'resetpass_submit' 00154 ); 00155 $form->addButton( 'wpCancel', $this->msg( 'resetpass-submit-cancel' )->text() ); 00156 $form->setHeaderText( $this->msg( 'resetpass_text' )->parseAsBlock() ); 00157 if ( $this->mPreTextMessage instanceof Message ) { 00158 $form->addPreText( $this->mPreTextMessage->parseAsBlock() ); 00159 } 00160 $form->addHiddenFields( 00161 $this->getRequest()->getValues( 'wpName', 'wpDomain', 'returnto', 'returntoquery' ) ); 00162 } 00163 00164 public function onSubmit( array $data ) { 00165 global $wgAuth; 00166 00167 $request = $this->getRequest(); 00168 00169 if ( $request->getCheck( 'wpLoginToken' ) ) { 00170 // This comes from Special:Userlogin when logging in with a temporary password 00171 return false; 00172 } 00173 00174 if ( !$this->getUser()->isLoggedIn() 00175 && $request->getVal( 'wpLoginOnChangeToken' ) !== LoginForm::getLoginToken() 00176 ) { 00177 // Potential CSRF (bug 62497) 00178 return false; 00179 } 00180 00181 if ( $request->getCheck( 'wpCancel' ) ) { 00182 $titleObj = Title::newFromText( $request->getVal( 'returnto' ) ); 00183 if ( !$titleObj instanceof Title ) { 00184 $titleObj = Title::newMainPage(); 00185 } 00186 $query = $request->getVal( 'returntoquery' ); 00187 $this->getOutput()->redirect( $titleObj->getFullURL( $query ) ); 00188 00189 return true; 00190 } 00191 00192 try { 00193 $this->mUserName = $request->getVal( 'wpName', $this->getUser()->getName() ); 00194 $this->mDomain = $wgAuth->getDomain(); 00195 00196 if ( !$wgAuth->allowPasswordChange() ) { 00197 throw new ErrorPageError( 'changepassword', 'resetpass_forbidden' ); 00198 } 00199 00200 $this->attemptReset( $data['Password'], $data['NewPassword'], $data['Retype'] ); 00201 00202 return true; 00203 } catch ( PasswordError $e ) { 00204 return $e->getMessage(); 00205 } 00206 } 00207 00208 public function onSuccess() { 00209 if ( $this->getUser()->isLoggedIn() ) { 00210 $this->getOutput()->wrapWikiMsg( 00211 "<div class=\"successbox\">\n$1\n</div>", 00212 'changepassword-success' 00213 ); 00214 $this->getOutput()->returnToMain(); 00215 } else { 00216 $request = $this->getRequest(); 00217 LoginForm::setLoginToken(); 00218 $token = LoginForm::getLoginToken(); 00219 $data = array( 00220 'action' => 'submitlogin', 00221 'wpName' => $this->mUserName, 00222 'wpDomain' => $this->mDomain, 00223 'wpLoginToken' => $token, 00224 'wpPassword' => $request->getVal( 'wpNewPassword' ), 00225 ) + $request->getValues( 'wpRemember', 'returnto', 'returntoquery' ); 00226 $login = new LoginForm( new DerivativeRequest( $request, $data, true ) ); 00227 $login->setContext( $this->getContext() ); 00228 $login->execute( null ); 00229 } 00230 } 00231 00238 protected function attemptReset( $oldpass, $newpass, $retype ) { 00239 $isSelf = ( $this->mUserName === $this->getUser()->getName() ); 00240 if ( $isSelf ) { 00241 $user = $this->getUser(); 00242 } else { 00243 $user = User::newFromName( $this->mUserName ); 00244 } 00245 00246 if ( !$user || $user->isAnon() ) { 00247 throw new PasswordError( $this->msg( 'nosuchusershort', $this->mUserName )->text() ); 00248 } 00249 00250 if ( $newpass !== $retype ) { 00251 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'badretype' ) ); 00252 throw new PasswordError( $this->msg( 'badretype' )->text() ); 00253 } 00254 00255 $throttleCount = LoginForm::incLoginThrottle( $this->mUserName ); 00256 if ( $throttleCount === true ) { 00257 $lang = $this->getLanguage(); 00258 $throttleInfo = $this->getConfig()->get( 'PasswordAttemptThrottle' ); 00259 throw new PasswordError( $this->msg( 'changepassword-throttled' ) 00260 ->params( $lang->formatDuration( $throttleInfo['seconds'] ) ) 00261 ->text() 00262 ); 00263 } 00264 00265 // @todo Make these separate messages, since the message is written for both cases 00266 if ( !$user->checkTemporaryPassword( $oldpass ) && !$user->checkPassword( $oldpass ) ) { 00267 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) ); 00268 throw new PasswordError( $this->msg( 'resetpass-wrong-oldpass' )->text() ); 00269 } 00270 00271 // User is resetting their password to their old password 00272 if ( $oldpass === $newpass ) { 00273 throw new PasswordError( $this->msg( 'resetpass-recycled' )->text() ); 00274 } 00275 00276 // Do AbortChangePassword after checking mOldpass, so we don't leak information 00277 // by possibly aborting a new password before verifying the old password. 00278 $abortMsg = 'resetpass-abort-generic'; 00279 if ( !wfRunHooks( 'AbortChangePassword', array( $user, $oldpass, $newpass, &$abortMsg ) ) ) { 00280 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'abortreset' ) ); 00281 throw new PasswordError( $this->msg( $abortMsg )->text() ); 00282 } 00283 00284 // Please reset throttle for successful logins, thanks! 00285 if ( $throttleCount ) { 00286 LoginForm::clearLoginThrottle( $this->mUserName ); 00287 } 00288 00289 try { 00290 $user->setPassword( $newpass ); 00291 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'success' ) ); 00292 } catch ( PasswordError $e ) { 00293 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) ); 00294 throw new PasswordError( $e->getMessage() ); 00295 } 00296 00297 if ( $isSelf ) { 00298 // This is needed to keep the user connected since 00299 // changing the password also modifies the user's token. 00300 $remember = $this->getRequest()->getCookie( 'Token' ) !== null; 00301 $user->setCookies( null, null, $remember ); 00302 } 00303 $user->resetPasswordExpiration(); 00304 $user->saveSettings(); 00305 } 00306 00307 public function requiresUnblock() { 00308 return false; 00309 } 00310 00311 protected function getGroupName() { 00312 return 'users'; 00313 } 00314 }