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