MediaWiki
REL1_21
|
00001 <?php 00029 class SpecialChangePassword extends UnlistedSpecialPage { 00030 00031 protected $mUserName, $mOldpass, $mNewpass, $mRetype, $mDomain; 00032 00033 public function __construct() { 00034 parent::__construct( 'ChangePassword' ); 00035 } 00036 00040 function execute( $par ) { 00041 global $wgAuth; 00042 00043 $this->setHeaders(); 00044 $this->outputHeader(); 00045 $this->getOutput()->disallowUserJs(); 00046 00047 $request = $this->getRequest(); 00048 $this->mUserName = trim( $request->getVal( 'wpName' ) ); 00049 $this->mOldpass = $request->getVal( 'wpPassword' ); 00050 $this->mNewpass = $request->getVal( 'wpNewPassword' ); 00051 $this->mRetype = $request->getVal( 'wpRetype' ); 00052 $this->mDomain = $request->getVal( 'wpDomain' ); 00053 00054 $user = $this->getUser(); 00055 00056 if ( !$user->isLoggedIn() && !LoginForm::getLoginToken() ) { 00057 LoginForm::setLoginToken(); 00058 } 00059 00060 if( !$request->wasPosted() && !$user->isLoggedIn() ) { 00061 $this->error( $this->msg( 'resetpass-no-info' )->text() ); 00062 return; 00063 } 00064 00065 if( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) { 00066 $this->doReturnTo(); 00067 return; 00068 } 00069 00070 $this->checkReadOnly(); 00071 00072 if( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'token' ) ) ) { 00073 try { 00074 $this->mDomain = $wgAuth->getDomain(); 00075 if( !$wgAuth->allowPasswordChange() ) { 00076 $this->error( $this->msg( 'resetpass_forbidden' )->text() ); 00077 return; 00078 } 00079 00080 if ( !$user->isLoggedIn() 00081 && $request->getVal( 'wpLoginOnChangeToken' ) !== LoginForm::getLoginToken() 00082 ) { 00083 // Potential CSRF (bug 62497) 00084 $this->error( $this->msg( 'sessionfailure' )->text() ); 00085 return false; 00086 } 00087 00088 $this->attemptReset( $this->mNewpass, $this->mRetype ); 00089 00090 if( $user->isLoggedIn() ) { 00091 $this->doReturnTo(); 00092 } else { 00093 LoginForm::setLoginToken(); 00094 $token = LoginForm::getLoginToken(); 00095 $data = array( 00096 'action' => 'submitlogin', 00097 'wpName' => $this->mUserName, 00098 'wpDomain' => $this->mDomain, 00099 'wpLoginToken' => $token, 00100 'wpPassword' => $request->getVal( 'wpNewPassword' ), 00101 ) + $request->getValues( 'wpRemember', 'returnto', 'returntoquery' ); 00102 $login = new LoginForm( new FauxRequest( $data, true ) ); 00103 $login->setContext( $this->getContext() ); 00104 $login->execute( null ); 00105 } 00106 return; 00107 } catch( PasswordError $e ) { 00108 $this->error( $e->getMessage() ); 00109 } 00110 } 00111 $this->showForm(); 00112 } 00113 00114 function doReturnTo() { 00115 $request = $this->getRequest(); 00116 $titleObj = Title::newFromText( $request->getVal( 'returnto' ) ); 00117 if ( !$titleObj instanceof Title ) { 00118 $titleObj = Title::newMainPage(); 00119 } 00120 $query = $request->getVal( 'returntoquery' ); 00121 $this->getOutput()->redirect( $titleObj->getFullURL( $query ) ); 00122 } 00123 00127 function error( $msg ) { 00128 $this->getOutput()->addHTML( Xml::element( 'p', array( 'class' => 'error' ), $msg ) ); 00129 } 00130 00131 function showForm() { 00132 global $wgCookieExpiration; 00133 00134 $user = $this->getUser(); 00135 if ( !$this->mUserName ) { 00136 $this->mUserName = $user->getName(); 00137 } 00138 $rememberMe = ''; 00139 if ( !$user->isLoggedIn() ) { 00140 $rememberMe = '<tr>' . 00141 '<td></td>' . 00142 '<td class="mw-input">' . 00143 Xml::checkLabel( 00144 $this->msg( 'remembermypassword' )->numParams( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) )->text(), 00145 'wpRemember', 'wpRemember', 00146 $this->getRequest()->getCheck( 'wpRemember' ) ) . 00147 '</td>' . 00148 '</tr>'; 00149 $submitMsg = 'resetpass_submit'; 00150 $oldpassMsg = 'resetpass-temp-password'; 00151 } else { 00152 $oldpassMsg = 'oldpassword'; 00153 $submitMsg = 'resetpass-submit-loggedin'; 00154 } 00155 $extraFields = array(); 00156 wfRunHooks( 'ChangePasswordForm', array( &$extraFields ) ); 00157 $prettyFields = array( 00158 array( 'wpName', 'username', 'text', $this->mUserName ), 00159 array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass ), 00160 array( 'wpNewPassword', 'newpassword', 'password', null ), 00161 array( 'wpRetype', 'retypenew', 'password', null ), 00162 ); 00163 $prettyFields = array_merge( $prettyFields, $extraFields ); 00164 $hiddenFields = array( 00165 'token' => $user->getEditToken(), 00166 'wpName' => $this->mUserName, 00167 'wpDomain' => $this->mDomain, 00168 ) + $this->getRequest()->getValues( 'returnto', 'returntoquery' ); 00169 if ( !$user->isLoggedIn() ) { 00170 $hiddenFields['wpLoginOnChangeToken'] = LoginForm::getLoginToken(); 00171 } 00172 $hiddenFieldsStr = ''; 00173 foreach( $hiddenFields as $fieldname => $fieldvalue ) { 00174 $hiddenFieldsStr .= Html::hidden( $fieldname, $fieldvalue ) . "\n"; 00175 } 00176 $this->getOutput()->addHTML( 00177 Xml::fieldset( $this->msg( 'resetpass_header' )->text() ) . 00178 Xml::openElement( 'form', 00179 array( 00180 'method' => 'post', 00181 'action' => $this->getTitle()->getLocalUrl(), 00182 'id' => 'mw-resetpass-form' ) ) . "\n" . 00183 $hiddenFieldsStr . 00184 $this->msg( 'resetpass_text' )->parseAsBlock() . "\n" . 00185 Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) . "\n" . 00186 $this->pretty( $prettyFields ) . "\n" . 00187 $rememberMe . 00188 "<tr>\n" . 00189 "<td></td>\n" . 00190 '<td class="mw-input">' . 00191 Xml::submitButton( $this->msg( $submitMsg )->text() ) . 00192 Xml::submitButton( $this->msg( 'resetpass-submit-cancel' )->text(), array( 'name' => 'wpCancel' ) ) . 00193 "</td>\n" . 00194 "</tr>\n" . 00195 Xml::closeElement( 'table' ) . 00196 Xml::closeElement( 'form' ) . 00197 Xml::closeElement( 'fieldset' ) . "\n" 00198 ); 00199 } 00200 00205 function pretty( $fields ) { 00206 $out = ''; 00207 foreach ( $fields as $list ) { 00208 list( $name, $label, $type, $value ) = $list; 00209 if( $type == 'text' ) { 00210 $field = htmlspecialchars( $value ); 00211 } else { 00212 $attribs = array( 'id' => $name ); 00213 if ( $name == 'wpNewPassword' || $name == 'wpRetype' ) { 00214 $attribs = array_merge( $attribs, 00215 User::passwordChangeInputAttribs() ); 00216 } 00217 if ( $name == 'wpPassword' ) { 00218 $attribs[] = 'autofocus'; 00219 } 00220 $field = Html::input( $name, $value, $type, $attribs ); 00221 } 00222 $out .= "<tr>\n"; 00223 $out .= "\t<td class='mw-label'>"; 00224 if ( $type != 'text' ) 00225 $out .= Xml::label( $this->msg( $label )->text(), $name ); 00226 else 00227 $out .= $this->msg( $label )->escaped(); 00228 $out .= "</td>\n"; 00229 $out .= "\t<td class='mw-input'>"; 00230 $out .= $field; 00231 $out .= "</td>\n"; 00232 $out .= "</tr>"; 00233 } 00234 return $out; 00235 } 00236 00240 protected function attemptReset( $newpass, $retype ) { 00241 $isSelf = ( $this->mUserName === $this->getUser()->getName() ); 00242 if ( $isSelf ) { 00243 $user = $this->getUser(); 00244 } else { 00245 $user = User::newFromName( $this->mUserName ); 00246 } 00247 00248 if( !$user || $user->isAnon() ) { 00249 throw new PasswordError( $this->msg( 'nosuchusershort', $this->mUserName )->text() ); 00250 } 00251 00252 if( $newpass !== $retype ) { 00253 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'badretype' ) ); 00254 throw new PasswordError( $this->msg( 'badretype' )->text() ); 00255 } 00256 00257 $throttleCount = LoginForm::incLoginThrottle( $this->mUserName ); 00258 if ( $throttleCount === true ) { 00259 throw new PasswordError( $this->msg( 'login-throttled' )->text() ); 00260 } 00261 00262 $abortMsg = 'resetpass-abort-generic'; 00263 if ( !wfRunHooks( 'AbortChangePassword', array( $user, $this->mOldpass, $newpass, &$abortMsg ) ) ) { 00264 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'abortreset' ) ); 00265 throw new PasswordError( $this->msg( $abortMsg )->text() ); 00266 } 00267 00268 if( !$user->checkTemporaryPassword( $this->mOldpass ) && !$user->checkPassword( $this->mOldpass ) ) { 00269 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) ); 00270 throw new PasswordError( $this->msg( 'resetpass-wrong-oldpass' )->text() ); 00271 } 00272 00273 // Please reset throttle for successful logins, thanks! 00274 if ( $throttleCount ) { 00275 LoginForm::clearLoginThrottle( $this->mUserName ); 00276 } 00277 00278 try { 00279 $user->setPassword( $this->mNewpass ); 00280 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'success' ) ); 00281 $this->mNewpass = $this->mOldpass = $this->mRetype = ''; 00282 } catch( PasswordError $e ) { 00283 wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) ); 00284 throw new PasswordError( $e->getMessage() ); 00285 } 00286 00287 if ( $isSelf ) { 00288 // This is needed to keep the user connected since 00289 // changing the password also modifies the user's token. 00290 $user->setCookies(); 00291 } 00292 00293 $user->saveSettings(); 00294 } 00295 00296 protected function getGroupName() { 00297 return 'users'; 00298 } 00299 }