r82283 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r82282‎ | r82283 | r82284 >
Date:19:49, 16 February 2011
Author:happy-melon
Status:reverted
Tags:
Comment:
Create a user.groups module in ResourceLoader, which bundles a CSS and JS page for each usergroup the user is a member of (MediaWiki:Sysop.js, MediaWiki:Autoconfirmed.css, etc). Groups '*' and 'user' are not included.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/HTMLForm.php (modified) (history)
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/includes/Skin.php (modified) (history)
  • /trunk/phase3/includes/User.php (modified) (history)
  • /trunk/phase3/includes/resourceloader/ResourceLoaderUserGroupsModule.php (added) (history)
  • /trunk/phase3/includes/specials/SpecialResetpass.php (modified) (history)
  • /trunk/phase3/resources/Resources.php (modified) (history)

Diff [purge]

Index: trunk/phase3/RELEASE-NOTES
@@ -72,6 +72,8 @@
7373 (maintenance/fixDoubleRedirects.php)
7474 * (bug 23315) New body classes to allow easier styling of special pages
7575 * (bug 27159) Make email confirmation code expiration time configurable
 76+* CSS/JS for each user group is imported from MediaWiki:Sysop.js,
 77+ MediaWiki:Autoconfirmed.css, etc.
7678
7779 === Bug fixes in 1.18 ===
7880 * (bug 23119) WikiError class and subclasses are now marked as deprecated
Index: trunk/phase3/resources/Resources.php
@@ -8,6 +8,7 @@
99 'startup' => array( 'class' => 'ResourceLoaderStartUpModule' ),
1010 'user' => array( 'class' => 'ResourceLoaderUserModule' ),
1111 'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ),
 12+ 'user.groups' => array( 'class' => 'ResourceLoaderUserGroupsModule' ),
1213
1314 /* Skins */
1415
Index: trunk/phase3/includes/resourceloader/ResourceLoaderUserGroupsModule.php
@@ -0,0 +1,61 @@
 2+<?php
 3+/**
 4+ * This program is free software; you can redistribute it and/or modify
 5+ * it under the terms of the GNU General Public License as published by
 6+ * the Free Software Foundation; either version 2 of the License, or
 7+ * (at your option) any later version.
 8+ *
 9+ * This program is distributed in the hope that it will be useful,
 10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 12+ * GNU General Public License for more details.
 13+ *
 14+ * You should have received a copy of the GNU General Public License along
 15+ * with this program; if not, write to the Free Software Foundation, Inc.,
 16+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 17+ * http://www.gnu.org/copyleft/gpl.html
 18+ *
 19+ * @file
 20+ * @author Trevor Parscal
 21+ * @author Roan Kattouw
 22+ */
 23+
 24+/**
 25+ * Module for user customizations
 26+ */
 27+class ResourceLoaderUserGroupsModule extends ResourceLoaderWikiModule {
 28+
 29+ /* Protected Methods */
 30+ protected $origin = self::ORIGIN_USER_SITEWIDE;
 31+
 32+ protected function getPages( ResourceLoaderContext $context ) {
 33+ if ( $context->getUser() ) {
 34+ $user = User::newFromName( $context->getUser() );
 35+ if( $user instanceof User ){
 36+ $pages = array();
 37+ foreach( $user->getEffectiveGroups() as $group ){
 38+ if( in_array( $group, array( '*', 'user' ) ) ){
 39+ continue;
 40+ }
 41+ $g = ucfirst( $group );
 42+ $pages["MediaWiki:$g.js"] = array( 'type' => 'script' );
 43+ $pages["MediaWiki:$g.css"] = array( 'type' => 'style' );
 44+ }
 45+ return $pages;
 46+ }
 47+ }
 48+ return array();
 49+ }
 50+
 51+ /* Methods */
 52+
 53+ public function getGroup() {
 54+ return 'user';
 55+ }
 56+
 57+ public function getFlip( $context ) {
 58+ global $wgContLang;
 59+
 60+ return $wgContLang->getDir() !== $context->getDirection();
 61+ }
 62+}
Property changes on: trunk/phase3/includes/resourceloader/ResourceLoaderUserGroupsModule.php
___________________________________________________________________
Added: svn:eol-style
163 + native
Index: trunk/phase3/includes/AutoLoader.php
@@ -152,6 +152,7 @@
153153 'LinksUpdate' => 'includes/LinksUpdate.php',
154154 'LocalisationCache' => 'includes/LocalisationCache.php',
155155 'LocalisationCache_BulkLoad' => 'includes/LocalisationCache.php',
 156+ 'Login' => 'includes/Login.php',
156157 'LogPage' => 'includes/LogPage.php',
157158 'LogPager' => 'includes/LogEventsList.php',
158159 'LogEventsList' => 'includes/LogEventsList.php',
@@ -211,6 +212,7 @@
212213 'ResourceLoaderFileModule' => 'includes/resourceloader/ResourceLoaderFileModule.php',
213214 'ResourceLoaderSiteModule' => 'includes/resourceloader/ResourceLoaderSiteModule.php',
214215 'ResourceLoaderUserModule' => 'includes/resourceloader/ResourceLoaderUserModule.php',
 216+ 'ResourceLoaderUserGroupsModule' => 'includes/resourceloader/ResourceLoaderUserGroupsModule.php',
215217 'ResourceLoaderUserOptionsModule' => 'includes/resourceloader/ResourceLoaderUserOptionsModule.php',
216218 'ResourceLoaderStartUpModule' => 'includes/resourceloader/ResourceLoaderStartUpModule.php',
217219 'ReverseChronologicalPager' => 'includes/Pager.php',
@@ -579,6 +581,7 @@
580582 'AncientPagesPage' => 'includes/specials/SpecialAncientpages.php',
581583 'BrokenRedirectsPage' => 'includes/specials/SpecialBrokenRedirects.php',
582584 'ContribsPager' => 'includes/specials/SpecialContributions.php',
 585+ 'SpecialCreateAccount' => 'includes/specials/SpecialCreateAccount.php',
583586 'DBLockForm' => 'includes/specials/SpecialLockdb.php',
584587 'DBUnlockForm' => 'includes/specials/SpecialUnlockdb.php',
585588 'DeadendPagesPage' => 'includes/specials/SpecialDeadendpages.php',
@@ -678,6 +681,7 @@
679682 'UnwatchedpagesPage' => 'includes/specials/SpecialUnwatchedpages.php',
680683 'UploadForm' => 'includes/specials/SpecialUpload.php',
681684 'UploadSourceField' => 'includes/specials/SpecialUpload.php',
 685+ 'SpecialUserlogin' => 'includes/specials/SpecialUserlogin.php',
682686 'UserrightsPage' => 'includes/specials/SpecialUserrights.php',
683687 'UsersPager' => 'includes/specials/SpecialListusers.php',
684688 'WantedCategoriesPage' => 'includes/specials/SpecialWantedcategories.php',
Index: trunk/phase3/includes/specials/SpecialResetpass.php
@@ -27,14 +27,69 @@
2828 * @ingroup SpecialPage
2929 */
3030 class SpecialResetpass extends SpecialPage {
 31+
 32+ public $mFormFields = array(
 33+ 'NameInfo' => array(
 34+ 'type' => 'info',
 35+ 'label-message' => 'yourname',
 36+ 'default' => '',
 37+ ),
 38+ 'Name' => array(
 39+ 'type' => 'hidden',
 40+ 'name' => 'wpName',
 41+ 'default' => null,
 42+ ),
 43+ 'OldPassword' => array(
 44+ 'type' => 'password',
 45+ 'label-message' => 'oldpassword',
 46+ 'size' => '20',
 47+ 'id' => 'wpPassword',
 48+ 'required' => '',
 49+ ),
 50+ 'NewPassword' => array(
 51+ 'type' => 'password',
 52+ 'label-message' => 'newpassword',
 53+ 'size' => '20',
 54+ 'id' => 'wpNewPassword',
 55+ 'required' => '',
 56+ ),
 57+ 'Retype' => array(
 58+ 'type' => 'password',
 59+ 'label-message' => 'retypenew',
 60+ 'size' => '20',
 61+ 'id' => 'wpRetype',
 62+ 'required' => '',
 63+ ),
 64+ 'Remember' => array(
 65+ 'type' => 'check',
 66+ 'id' => 'wpRemember',
 67+ ),
 68+ );
 69+
 70+ protected $mUsername;
 71+ protected $mLogin;
 72+
3173 public function __construct() {
 74+ global $wgRequest, $wgUser, $wgLang, $wgCookieExpiration;
 75+
3276 parent::__construct( 'Resetpass' );
 77+ $this->mFormFields['Retype']['validation-callback'] = array( 'SpecialCreateAccount', 'formValidateRetype' );
 78+
 79+ $this->mUsername = $wgRequest->getVal( 'wpName', $wgUser->getName() );
 80+ $this->mReturnTo = $wgRequest->getVal( 'returnto' );
 81+ $this->mReturnToQuery = $wgRequest->getVal( 'returntoquery' );
 82+
 83+ $this->mFormFields['Remember']['label'] = wfMsgExt(
 84+ 'remembermypassword',
 85+ 'parseinline',
 86+ $wgLang->formatNum( ceil( $wgCookieExpiration / 86400 ) )
 87+ );
3388 }
3489
3590 /**
3691 * Main execution point
3792 */
38 - function execute( $par ) {
 93+ public function execute( $par ) {
3994 global $wgUser, $wgAuth, $wgOut, $wgRequest;
4095
4196 if ( wfReadOnly() ) {
@@ -42,196 +97,134 @@
4398 return;
4499 }
45100
46 - $this->mUserName = $wgRequest->getVal( 'wpName' );
47 - $this->mOldpass = $wgRequest->getVal( 'wpPassword' );
48 - $this->mNewpass = $wgRequest->getVal( 'wpNewPassword' );
49 - $this->mRetype = $wgRequest->getVal( 'wpRetype' );
50 - $this->mDomain = $wgRequest->getVal( 'wpDomain' );
51 -
52101 $this->setHeaders();
53102 $this->outputHeader();
54103 $wgOut->disallowUserJs();
55104
56 - if( !$wgRequest->wasPosted() && !$wgUser->isLoggedIn() ) {
57 - $this->error( wfMsg( 'resetpass-no-info' ) );
58 - return;
 105+ if( wfReadOnly() ){
 106+ $wgOut->readOnlyPage();
 107+ return false;
59108 }
 109+ if( !$wgAuth->allowPasswordChange() ) {
 110+ $wgOut->showErrorPage( 'errorpagetitle', 'resetpass_forbidden' );
 111+ return false;
 112+ }
60113
61 - if( $wgRequest->wasPosted() && $wgRequest->getBool( 'wpCancel' ) ) {
62 - $this->doReturnTo();
63 - return;
 114+ if( !$wgRequest->wasPosted() && !$wgUser->isLoggedIn() ) {
 115+ $wgOut->showErrorPage( 'errorpagetitle', 'resetpass-no-info' );
 116+ return false;
64117 }
65118
66 - if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal( 'token' ) ) ) {
67 - try {
68 - $wgAuth->setDomain( $this->mDomain );
69 - if( !$wgAuth->allowPasswordChange() ) {
70 - $this->error( wfMsg( 'resetpass_forbidden' ) );
71 - return;
72 - }
 119+ $this->getForm()->show();
73120
74 - $this->attemptReset( $this->mNewpass, $this->mRetype );
75 - $wgOut->addWikiMsg( 'resetpass_success' );
76 - if( !$wgUser->isLoggedIn() ) {
77 - LoginForm::setLoginToken();
78 - $token = LoginForm::getLoginToken();
79 - $data = array(
80 - 'action' => 'submitlogin',
81 - 'wpName' => $this->mUserName,
82 - 'wpDomain' => $this->mDomain,
83 - 'wpLoginToken' => $token,
84 - 'wpPassword' => $this->mNewpass,
85 - 'returnto' => $wgRequest->getVal( 'returnto' ),
86 - );
87 - if( $wgRequest->getCheck( 'wpRemember' ) ) {
88 - $data['wpRemember'] = 1;
89 - }
90 - $login = new LoginForm( new FauxRequest( $data, true ) );
91 - $login->execute( null );
92 - }
93 - $this->doReturnTo();
94 - } catch( PasswordError $e ) {
95 - $this->error( $e->getMessage() );
 121+ }
 122+
 123+ public function formSubmitCallback( $data ){
 124+ $data['Password'] = $data['OldPassword'];
 125+ $this->mLogin = new Login( $data );
 126+ $result = $this->attemptReset( $data );
 127+
 128+ if( $result === true ){
 129+ # Log the user in if they're not already (ie we're
 130+ # coming from the e-mail-password-reset route
 131+ global $wgUser;
 132+ if( !$wgUser->isLoggedIn() ) {
 133+ $this->mLogin->attemptLogin( $data['NewPassword'] );
 134+ # Redirect out to the appropriate target.
 135+ SpecialUserlogin::successfulLogin(
 136+ 'resetpass_success',
 137+ $this->mReturnTo,
 138+ $this->mReturnToQuery,
 139+ $this->mLogin->mLoginResult
 140+ );
 141+ } else {
 142+ # Redirect out to the appropriate target.
 143+ SpecialUserlogin::successfulLogin(
 144+ 'resetpass_success',
 145+ $this->mReturnTo,
 146+ $this->mReturnToQuery
 147+ );
96148 }
 149+ return true;
 150+ } else {
 151+ return $result;
97152 }
98 - $this->showForm();
99153 }
100 -
101 - function doReturnTo() {
102 - global $wgRequest, $wgOut;
103 - $titleObj = Title::newFromText( $wgRequest->getVal( 'returnto' ) );
104 - if ( !$titleObj instanceof Title ) {
105 - $titleObj = Title::newMainPage();
106 - }
107 - $wgOut->redirect( $titleObj->getFullURL() );
108 - }
109154
110 - function error( $msg ) {
111 - global $wgOut;
112 - $wgOut->addHTML( Xml::element('p', array( 'class' => 'error' ), $msg ) );
113 - }
 155+ public function getForm( $reset=false ) {
 156+ global $wgOut, $wgUser, $wgRequest;
114157
115 - function showForm() {
116 - global $wgOut, $wgUser, $wgRequest, $wgLivePasswordStrengthChecks;
117 -
118 - if ( $wgLivePasswordStrengthChecks ) {
119 - $wgOut->addPasswordSecurity( 'wpNewPassword', 'wpRetype' );
120 - }
121 - $self = $this->getTitle();
122 - if ( !$this->mUserName ) {
123 - $this->mUserName = $wgUser->getName();
124 - }
125 - $rememberMe = '';
126 - if ( !$wgUser->isLoggedIn() ) {
127 - global $wgCookieExpiration, $wgLang;
128 - $rememberMe = '<tr>' .
129 - '<td></td>' .
130 - '<td class="mw-input">' .
131 - Xml::checkLabel(
132 - wfMsgExt( 'remembermypassword', 'parsemag', $wgLang->formatNum( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) ) ),
133 - 'wpRemember', 'wpRemember',
134 - $wgRequest->getCheck( 'wpRemember' ) ) .
135 - '</td>' .
136 - '</tr>';
 158+ if( $reset || $wgRequest->getCheck( 'reset' ) ){
 159+ # Request is coming from Special:UserLogin after it
 160+ # authenticated someone with a temporary password.
 161+ $this->mFormFields['OldPassword']['label-message'] = 'resetpass-temp-password';
137162 $submitMsg = 'resetpass_submit';
138 - $oldpassMsg = 'resetpass-temp-password';
 163+ $this->mFormFields['OldPassword']['default'] = $wgRequest->getText( 'wpPassword' );
 164+ #perpetuate
 165+ $this->mFormFields['reset'] = array(
 166+ 'type' => 'hidden',
 167+ 'default' => '1',
 168+ );
139169 } else {
140 - $oldpassMsg = 'oldpassword';
 170+ unset( $this->mFormFields['Remember'] );
141171 $submitMsg = 'resetpass-submit-loggedin';
142172 }
143 - $wgOut->addHTML(
144 - Xml::fieldset( wfMsg( 'resetpass_header' ) ) .
145 - Xml::openElement( 'form',
146 - array(
147 - 'method' => 'post',
148 - 'action' => $self->getLocalUrl(),
149 - 'id' => 'mw-resetpass-form' ) ) . "\n" .
150 - Html::hidden( 'token', $wgUser->editToken() ) . "\n" .
151 - Html::hidden( 'wpName', $this->mUserName ) . "\n" .
152 - Html::hidden( 'wpDomain', $this->mDomain ) . "\n" .
153 - Html::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) . "\n" .
154 - wfMsgExt( 'resetpass_text', array( 'parse' ) ) . "\n" .
155 - Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) . "\n" .
156 - $this->pretty( array(
157 - array( 'wpName', 'username', 'text', $this->mUserName, '' ),
158 - array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass, '' ),
159 - array( 'wpNewPassword', 'newpassword', 'password', null, '<div id="password-strength"></div>' ),
160 - array( 'wpRetype', 'retypenew', 'password', null, '<div id="password-retype"></div>' ),
161 - ) ) . "\n" .
162 - $rememberMe .
163 - "<tr>\n" .
164 - "<td></td>\n" .
165 - '<td class="mw-input">' .
166 - Xml::submitButton( wfMsg( $submitMsg ) ) .
167 - Xml::submitButton( wfMsg( 'resetpass-submit-cancel' ), array( 'name' => 'wpCancel' ) ) .
168 - "</td>\n" .
169 - "</tr>\n" .
170 - Xml::closeElement( 'table' ) .
171 - Xml::closeElement( 'form' ) .
172 - Xml::closeElement( 'fieldset' ) . "\n"
173 - );
174 - }
175173
176 - function pretty( $fields ) {
177 - $out = '';
178 - foreach ( $fields as $list ) {
179 - list( $name, $label, $type, $value, $extra ) = $list;
180 - if( $type == 'text' ) {
181 - $field = htmlspecialchars( $value );
182 - } else {
183 - $attribs = array( 'id' => $name );
184 - if ( $name == 'wpNewPassword' || $name == 'wpRetype' ) {
185 - $attribs = array_merge( $attribs,
186 - User::passwordChangeInputAttribs() );
187 - }
188 - if ( $name == 'wpPassword' ) {
189 - $attribs[] = 'autofocus';
190 - }
191 - $field = Html::input( $name, $value, $type, $attribs );
192 - }
193 - $out .= "<tr>\n";
194 - $out .= "\t<td class='mw-label'>";
195 - if ( $type != 'text' )
196 - $out .= Xml::label( wfMsg( $label ), $name );
197 - else
198 - $out .= wfMsgHtml( $label );
199 - $out .= "</td>\n";
200 - $out .= "\t<td class='mw-input'>$field</td>\n";
201 - $out .= "\t<td>$extra</td>\n";
202 - $out .= "</tr>";
203 - }
204 - return $out;
 174+ $this->mFormFields['Name']['default'] =
 175+ $this->mFormFields['NameInfo']['default'] = $this->mUsername;
 176+
 177+ $form = new HTMLForm( $this->mFormFields, '' );
 178+ $form->suppressReset();
 179+ $form->setSubmitText( wfMsg( $submitMsg ) );
 180+ $form->setTitle( $this->getTitle() );
 181+ $form->addHiddenField( 'returnto', $this->mReturnTo );
 182+ $form->setWrapperLegend( wfMsg( 'resetpass_header' ) );
 183+
 184+ $form->setSubmitCallback( array( $this, 'formSubmitCallback' ) );
 185+ $form->loadData();
 186+
 187+ return $form;
205188 }
206189
207190 /**
208 - * @throws PasswordError when cannot set the new password because requirements not met.
 191+ * Try to reset the user's password
209192 */
210 - protected function attemptReset( $newpass, $retype ) {
211 - $user = User::newFromName( $this->mUserName );
212 - if( !$user || $user->isAnon() ) {
213 - throw new PasswordError( 'no such user' );
 193+ protected function attemptReset( $data ) {
 194+
 195+ if( !$data['Name']
 196+ || !$data['OldPassword']
 197+ || !$data['NewPassword']
 198+ || !$data['Retype'] )
 199+ {
 200+ return false;
214201 }
215 -
216 - if( $newpass !== $retype ) {
217 - wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'badretype' ) );
218 - throw new PasswordError( wfMsg( 'badretype' ) );
 202+
 203+ $user = $this->mLogin->getUser();
 204+ if( !( $user instanceof User ) ){
 205+ return wfMsgExt( 'nosuchuser', 'parse' );
219206 }
220207
221 - if( !$user->checkTemporaryPassword($this->mOldpass) && !$user->checkPassword($this->mOldpass) ) {
222 - wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) );
223 - throw new PasswordError( wfMsg( 'resetpass-wrong-oldpass' ) );
 208+ if( $data['NewPassword'] !== $data['Retype'] ) {
 209+ wfRunHooks( 'PrefsPasswordAudit', array( $user, $data['NewPassword'], 'badretype' ) );
 210+ return wfMsgExt( 'badretype', 'parse' );
224211 }
225 -
 212+
 213+ if( !$user->checkPassword( $data['OldPassword'] ) && !$user->checkTemporaryPassword( $data['OldPassword'] ) )
 214+ {
 215+ wfRunHooks( 'PrefsPasswordAudit', array( $user, $data['NewPassword'], 'wrongpassword' ) );
 216+ return wfMsgExt( 'resetpass-wrong-oldpass', 'parse' );
 217+ }
 218+
226219 try {
227 - $user->setPassword( $this->mNewpass );
228 - wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'success' ) );
229 - $this->mNewpass = $this->mOldpass = $this->mRetypePass = '';
 220+ $user->setPassword( $data['NewPassword'] );
 221+ wfRunHooks( 'PrefsPasswordAudit', array( $user, $data['NewPassword'], 'success' ) );
230222 } catch( PasswordError $e ) {
231 - wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) );
232 - throw new PasswordError( $e->getMessage() );
 223+ wfRunHooks( 'PrefsPasswordAudit', array( $user, $data['NewPassword'], 'error' ) );
 224+ return $e->getMessage();
233225 }
234 -
 226+
235227 $user->setCookies();
236228 $user->saveSettings();
 229+ return true;
237230 }
238231 }
Index: trunk/phase3/includes/Skin.php
@@ -546,7 +546,7 @@
547547 * @private
548548 */
549549 function setupUserCss( OutputPage $out ) {
550 - global $wgRequest;
 550+ global $wgRequest, $wgUser;
551551 global $wgUseSiteCss, $wgAllowUserCss, $wgAllowUserCssPrefs;
552552
553553 wfProfileIn( __METHOD__ );
@@ -560,6 +560,9 @@
561561 // Per-site custom styles
562562 if ( $wgUseSiteCss ) {
563563 $out->addModuleStyles( 'site' );
 564+ if( $wgUser->isLoggedIn() ){
 565+ $out->addModuleStyles( 'user.groups' );
 566+ }
564567 }
565568
566569 // Per-user custom styles
Index: trunk/phase3/includes/HTMLForm.php
@@ -109,6 +109,7 @@
110110 protected $mButtons = array();
111111
112112 protected $mWrapperLegend = false;
 113+ protected $mTokenAction = 'Edit';
113114
114115 /**
115116 * Build a new HTMLForm from an array of field attributes
@@ -184,7 +185,7 @@
185186 if ( !$class ) {
186187 throw new MWException( "Descriptor with no class: " . print_r( $descriptor, true ) );
187188 }
188 -
 189+
189190 $descriptor['fieldname'] = $fieldname;
190191
191192 $obj = new $class( $descriptor );
@@ -210,14 +211,15 @@
211212
212213 /**
213214 * Try submitting, with edit token check first
214 - * @return Status|boolean
 215+ * @return Status|boolean
215216 */
216217 function tryAuthorizedSubmit() {
217218 global $wgUser, $wgRequest;
218219 $editToken = $wgRequest->getVal( 'wpEditToken' );
219220
220221 $result = false;
221 - if ( $this->getMethod() != 'post' || $wgUser->matchEditToken( $editToken ) ) {
 222+ # FIXME
 223+ if ( $wgRequest->wasPosted() ){#&& $this->getMethod() != 'post' || $wgUser->matchEditToken( $editToken ) ) {
222224 $result = $this->trySubmit();
223225 }
224226 return $result;
@@ -249,6 +251,11 @@
250252 * display.
251253 */
252254 function trySubmit() {
 255+ # Check the session tokens
 256+ # FIXME
 257+ if ( false && !Token::match( null, $this->mTokenAction ) ) {
 258+ return array( 'sessionfailure' );
 259+ }
253260 # Check for validation
254261 foreach ( $this->mFlatFields as $fieldname => $field ) {
255262 if ( !empty( $field->mParams['nodata'] ) ) {
@@ -424,9 +431,14 @@
425432 global $wgUser;
426433
427434 $html = '';
428 -
429435 if( $this->getMethod() == 'post' ){
430 - $html .= Html::hidden( 'wpEditToken', $wgUser->editToken(), array( 'id' => 'wpEditToken' ) ) . "\n";
 436+ # FIXME
 437+ $token = new Token( $this->mTokenAction );
 438+ $html .= Html::hidden(
 439+ "wp{$this->mTokenAction}Token",
 440+ $token->set(),
 441+ array( 'id' => 'wpEditToken' )
 442+ ) . "\n";
431443 $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
432444 }
433445
@@ -579,6 +591,7 @@
580592 $this->mSubmitTooltip = $name;
581593 }
582594
 595+
583596 /**
584597 * Set the id for the submit button.
585598 * @param $t String. FIXME: Integrity is *not* validated
@@ -607,6 +620,15 @@
608621 function setMessagePrefix( $p ) {
609622 $this->mMessagePrefix = $p;
610623 }
 624+ /**
 625+ * If you want to protect the form from CSRF by a token other than
 626+ * the usual wsEditToken, set something here.
 627+ * @see Token::set()
 628+ * @param $a
 629+ */
 630+ function setTokenAction( $a ){
 631+ $this->mTokenAction = ucfirst( $a );
 632+ }
611633
612634 /**
613635 * Set the title for form submission
@@ -623,7 +645,7 @@
624646 function getTitle() {
625647 return $this->mTitle;
626648 }
627 -
 649+
628650 /**
629651 * Set the method used to submit the form
630652 * @param $method String
@@ -631,7 +653,7 @@
632654 public function setMethod( $method='post' ){
633655 $this->mMethod = $method;
634656 }
635 -
 657+
636658 public function getMethod(){
637659 return $this->mMethod;
638660 }
@@ -840,12 +862,12 @@
841863 if ( isset( $params['name'] ) ) {
842864 $this->mName = $params['name'];
843865 }
844 -
 866+
845867 $validName = Sanitizer::escapeId( $this->mName );
846868 if ( $this->mName != $validName && !isset( $params['nodata'] ) ) {
847869 throw new MWException( "Invalid name '{$this->mName}' passed to " . __METHOD__ );
848870 }
849 -
 871+
850872 $this->mID = "mw-input-{$this->mName}";
851873
852874 if ( isset( $params['default'] ) ) {
@@ -887,10 +909,10 @@
888910 global $wgRequest;
889911
890912 $errors = $this->validate( $value, $this->mParent->mFieldData );
891 -
 913+
892914 $cellAttributes = array();
893915 $verticalLabel = false;
894 -
 916+
895917 if ( !empty($this->mParams['vertical-label']) ) {
896918 $cellAttributes['colspan'] = 2;
897919 $verticalLabel = true;
@@ -908,9 +930,9 @@
909931 array( 'class' => 'mw-input' ) + $cellAttributes,
910932 $this->getInputHTML( $value ) . "\n$errors"
911933 );
912 -
 934+
913935 $fieldType = get_class( $this );
914 -
 936+
915937 if ($verticalLabel) {
916938 $html = Html::rawElement( 'tr',
917939 array( 'class' => 'mw-htmlform-vertical-label' ), $label );
@@ -1139,11 +1161,11 @@
11401162 if ( $p !== true ) {
11411163 return $p;
11421164 }
1143 -
 1165+
11441166 $value = trim( $value );
11451167
11461168 # http://dev.w3.org/html5/spec/common-microsyntaxes.html#real-numbers
1147 - # with the addition that a leading '+' sign is ok.
 1169+ # with the addition that a leading '+' sign is ok.
11481170 if ( !preg_match( '/^((\+|\-)?\d+(\.\d+)?(E(\+|\-)?\d+)?)?$/i', $value ) ) {
11491171 return wfMsgExt( 'htmlform-float-invalid', 'parse' );
11501172 }
@@ -1182,8 +1204,8 @@
11831205 }
11841206
11851207 # http://dev.w3.org/html5/spec/common-microsyntaxes.html#signed-integers
1186 - # with the addition that a leading '+' sign is ok. Note that leading zeros
1187 - # are fine, and will be left in the input, which is useful for things like
 1208+ # with the addition that a leading '+' sign is ok. Note that leading zeros
 1209+ # are fine, and will be left in the input, which is useful for things like
11881210 # phone numbers when you know that they are integers (the HTML5 type=tel
11891211 # input does not require its value to be numeric). If you want a tidier
11901212 # value to, eg, save in the DB, clean it up with intval().
@@ -1415,8 +1437,8 @@
14161438 } else {
14171439 $thisAttribs = array( 'id' => "{$this->mID}-$info", 'value' => $info );
14181440
1419 - $checkbox = Xml::check(
1420 - $this->mName . '[]',
 1441+ $checkbox = Xml::check(
 1442+ $this->mName . '[]',
14211443 in_array( $info, $value, true ),
14221444 $attribs + $thisAttribs );
14231445 $checkbox .= '&#160;' . Html::rawElement( 'label', array( 'for' => "{$this->mID}-$info" ), $label );
@@ -1556,7 +1578,7 @@
15571579 class HTMLHiddenField extends HTMLFormField {
15581580 public function __construct( $params ) {
15591581 parent::__construct( $params );
1560 -
 1582+
15611583 # Per HTML5 spec, hidden fields cannot be 'required'
15621584 # http://dev.w3.org/html5/spec/states-of-the-type-attribute.html#hidden-state
15631585 unset( $this->mParams['required'] );
@@ -1605,7 +1627,7 @@
16061628 protected function needsLabel() {
16071629 return false;
16081630 }
1609 -
 1631+
16101632 /**
16111633 * Button cannot be invalid
16121634 */
Index: trunk/phase3/includes/User.php
@@ -5,12 +5,6 @@
66 */
77
88 /**
9 - * Int Number of characters in user_token field.
10 - * @ingroup Constants
11 - */
12 -define( 'USER_TOKEN_LENGTH', 32 );
13 -
14 -/**
159 * Int Serialized record version.
1610 * @ingroup Constants
1711 */
@@ -41,13 +35,6 @@
4236 * of the database.
4337 */
4438 class User {
45 - /**
46 - * Global constants made accessible as class constants so that autoloader
47 - * magic can be used.
48 - */
49 - const USER_TOKEN_LENGTH = USER_TOKEN_LENGTH;
50 - const MW_USER_VERSION = MW_USER_VERSION;
51 - const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
5239
5340 /**
5441 * Array of Strings List of member variables which are saved to the
@@ -377,7 +364,7 @@
378365 /**
379366 * Create a new user object from a user row.
380367 * The row should have all fields from the user table in it.
381 - * @param $row Array A row from the user table
 368+ * @param $row array A row from the user table
382369 * @return User
383370 */
384371 static function newFromRow( $row ) {
@@ -627,6 +614,7 @@
628615 if( !wfRunHooks( 'isValidPassword', array( $password, &$result, $this ) ) )
629616 return $result;
630617
 618+
631619 if ( $result === false ) {
632620 if( strlen( $password ) < $wgMinimalPasswordLength ) {
633621 return 'passwordtooshort';
@@ -1250,6 +1238,9 @@
12511239 // Deprecated, but kept for backwards-compatibility config
12521240 return false;
12531241 }
 1242+
 1243+
 1244+
12541245 if( in_array( wfGetIP(), $wgRateLimitsExcludedIPs ) ) {
12551246 // No other good way currently to disable rate limits
12561247 // for specific IPs. :P
@@ -1786,7 +1777,7 @@
17871778 }
17881779
17891780 if( !$this->isValidPassword( $str ) ) {
1790 - global $wgMinimalPasswordLength;
 1781+ global $wgMinimalPasswordLength;
17911782 $valid = $this->getPasswordValidity( $str );
17921783 if ( is_array( $valid ) ) {
17931784 $message = array_shift( $valid );
@@ -1796,7 +1787,7 @@
17971788 $params = array( $wgMinimalPasswordLength );
17981789 }
17991790 throw new PasswordError( wfMsgExt( $message, array( 'parsemag' ), $params ) );
1800 - }
 1791+ }
18011792 }
18021793
18031794 if( !$wgAuth->setPassword( $this, $str ) ) {
@@ -2206,6 +2197,7 @@
22072198 }
22082199
22092200 /**
 2201+
22102202 * Check if user is allowed to access a feature / make an action
22112203 * @param $action String action to be checked
22122204 * @return Boolean: True if action is allowed, else false
@@ -2529,8 +2521,8 @@
25302522 'user_newpassword' => $this->mNewpassword,
25312523 'user_newpass_time' => $dbw->timestampOrNull( $this->mNewpassTime ),
25322524 'user_real_name' => $this->mRealName,
2533 - 'user_email' => $this->mEmail,
2534 - 'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
 2525+ 'user_email' => $this->mEmail,
 2526+ 'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
25352527 'user_options' => '',
25362528 'user_touched' => $dbw->timestamp( $this->mTouched ),
25372529 'user_token' => $this->mToken,
@@ -2589,7 +2581,6 @@
25902582 }
25912583 $dbw = wfGetDB( DB_MASTER );
25922584 $seqVal = $dbw->nextSequenceValue( 'user_user_id_seq' );
2593 -
25942585 $fields = array(
25952586 'user_id' => $seqVal,
25962587 'user_name' => $name,
@@ -2801,7 +2792,7 @@
28022793 // are shorter than this, doesn't mean people wont be able
28032794 // to. Certain authentication plugins do NOT want to save
28042795 // domain passwords in a mysql database, so we should
2805 - // check this (in case $wgAuth->strict() is false).
 2796+ // check this (incase $wgAuth->strict() is false).
28062797 if( !$this->isValidPassword( $password ) ) {
28072798 return false;
28082799 }
@@ -2860,7 +2851,7 @@
28612852 return EDIT_TOKEN_SUFFIX;
28622853 } else {
28632854 if( !isset( $_SESSION['wsEditToken'] ) ) {
2864 - $token = self::generateToken();
 2855+ $token = $this->generateToken();
28652856 $_SESSION['wsEditToken'] = $token;
28662857 } else {
28672858 $token = $_SESSION['wsEditToken'];
@@ -2878,7 +2869,7 @@
28792870 * @param $salt String Optional salt value
28802871 * @return String The new random token
28812872 */
2882 - public static function generateToken( $salt = '' ) {
 2873+ function generateToken( $salt = '' ) {
28832874 $token = dechex( mt_rand() ) . dechex( mt_rand() );
28842875 return md5( $token . $salt );
28852876 }
@@ -2986,7 +2977,7 @@
29872978 $now = time();
29882979 $expires = $now + $wgUserEmailConfirmationTokenExpiry;
29892980 $expiration = wfTimestamp( TS_MW, $expires );
2990 - $token = self::generateToken( $this->mId . $this->mEmail . $expires );
 2981+ $token = wfGenerateToken( $this->mId . $this->mEmail . $expires );
29912982 $hash = md5( $token );
29922983 $this->load();
29932984 $this->mEmailToken = $hash;
@@ -3140,7 +3131,7 @@
31413132 * Get the timestamp of account creation.
31423133 *
31433134 * @return String|Bool Timestamp of account creation, or false for
3144 - * non-existent/anonymous user accounts.
 3135+ * non-existent/anonymous user accounts.
31453136 */
31463137 public function getRegistration() {
31473138 return $this->getId() > 0
@@ -3152,7 +3143,7 @@
31533144 * Get the timestamp of the first edit
31543145 *
31553146 * @return String|Bool Timestamp of first edit, or false for
3156 - * non-existent/anonymous user accounts.
 3147+ * non-existent/anonymous user accounts.
31573148 */
31583149 public function getFirstEditTimestamp() {
31593150 if( $this->getId() == 0 ) {
@@ -3342,9 +3333,9 @@
33433334 *
33443335 * @param $group String: the group to check for whether it can add/remove
33453336 * @return Array array( 'add' => array( addablegroups ),
3346 - * 'remove' => array( removablegroups ),
3347 - * 'add-self' => array( addablegroups to self),
3348 - * 'remove-self' => array( removable groups from self) )
 3337+ * 'remove' => array( removablegroups ),
 3338+ * 'add-self' => array( addablegroups to self),
 3339+ * 'remove-self' => array( removable groups from self) )
33493340 */
33503341 static function changeableByGroup( $group ) {
33513342 global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
@@ -3582,31 +3573,27 @@
35833574 * @param $byEmail Boolean: account made by email?
35843575 * @param $reason String: user supplied reason
35853576 */
3586 - public function addNewUserLogEntry( $byEmail = false, $reason = '' ) {
3587 - global $wgUser, $wgContLang, $wgNewUserLog;
 3577+ public function addNewUserLogEntry( $creator, $byEmail = false ) {
 3578+ global $wgUser, $wgNewUserLog;
35883579 if( empty( $wgNewUserLog ) ) {
35893580 return true; // disabled
35903581 }
35913582
3592 - if( $this->getName() == $wgUser->getName() ) {
3593 - $action = 'create';
3594 - } else {
3595 - $action = 'create2';
3596 - if ( $byEmail ) {
3597 - if ( $reason === '' ) {
3598 - $reason = wfMsgForContent( 'newuserlog-byemail' );
3599 - } else {
3600 - $reason = $wgContLang->commaList( array(
3601 - $reason, wfMsgForContent( 'newuserlog-byemail' ) ) );
3602 - }
3603 - }
3604 - }
 3583+ $action = ( $creator == $wgUser )
 3584+ ? 'create2' # Safe to publish the creator
 3585+ : 'create'; # Creator is an IP, don't splash it all over Special:Log
 3586+
 3587+ $message = $byEmail
 3588+ ? wfMsgForContent( 'newuserlog-byemail' )
 3589+ : '';
 3590+
36053591 $log = new LogPage( 'newusers' );
36063592 $log->addEntry(
36073593 $action,
36083594 $this->getUserPage(),
3609 - $reason,
3610 - array( $this->getId() )
 3595+ $message,
 3596+ array( $this->getId() ),
 3597+ $creator
36113598 );
36123599 return true;
36133600 }
@@ -3616,12 +3603,18 @@
36173604 * Used by things like CentralAuth and perhaps other authplugins.
36183605 */
36193606 public function addNewUserLogEntryAutoCreate() {
3620 - global $wgNewUserLog, $wgLogAutocreatedAccounts;
3621 - if( !$wgNewUserLog || !$wgLogAutocreatedAccounts ) {
 3607+ global $wgNewUserLog;
 3608+ if( empty( $wgNewUserLog ) ) {
36223609 return true; // disabled
36233610 }
36243611 $log = new LogPage( 'newusers', false );
3625 - $log->addEntry( 'autocreate', $this->getUserPage(), '', array( $this->getId() ) );
 3612+ $log->addEntry(
 3613+ 'autocreate',
 3614+ $this->getUserPage(),
 3615+ '',
 3616+ array( $this->getId() ),
 3617+ $this->getId()
 3618+ );
36263619 return true;
36273620 }
36283621
Index: trunk/phase3/includes/OutputPage.php
@@ -2555,28 +2555,29 @@
25562556 // Legacy Scripts
25572557 $scripts .= "\n" . $this->mScripts;
25582558
 2559+ $userScripts = array( 'user.options' );
 2560+
25592561 // Add site JS if enabled
25602562 if ( $wgUseSiteJs ) {
25612563 $scripts .= $this->makeResourceLoaderLink( $sk, 'site', ResourceLoaderModule::TYPE_SCRIPTS );
 2564+ if( $wgUser->isLoggedIn() ){
 2565+ $userScripts[] = 'user.groups';
 2566+ }
25622567 }
25632568
2564 - // Add user JS if enabled - trying to load user.options as a bundle if possible
2565 - $userOptionsAdded = false;
 2569+ // Add user JS if enabled
25662570 if ( $wgAllowUserJs && $wgUser->isLoggedIn() ) {
25672571 $action = $wgRequest->getVal( 'action', 'view' );
25682572 if( $this->mTitle && $this->mTitle->isJsSubpage() && $sk->userCanPreview( $action ) ) {
25692573 # XXX: additional security check/prompt?
25702574 $scripts .= Html::inlineScript( "\n" . $wgRequest->getText( 'wpTextbox1' ) . "\n" ) . "\n";
25712575 } else {
2572 - $scripts .= $this->makeResourceLoaderLink(
2573 - $sk, array( 'user', 'user.options' ), ResourceLoaderModule::TYPE_SCRIPTS
2574 - );
2575 - $userOptionsAdded = true;
 2576+ # FIXME: this means that User:Me/Common.js doesn't load when previewing
 2577+ # User:Me/Vector.js, and vice versa (bug26283)
 2578+ $userScripts[] = 'user';
25762579 }
25772580 }
2578 - if ( !$userOptionsAdded ) {
2579 - $scripts .= $this->makeResourceLoaderLink( $sk, 'user.options', ResourceLoaderModule::TYPE_SCRIPTS );
2580 - }
 2581+ $scripts .= $this->makeResourceLoaderLink( $sk, $userScripts, ResourceLoaderModule::TYPE_SCRIPTS );
25812582
25822583 return $scripts;
25832584 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r82284revert r82283, loads of unrelated changeshappy-melon19:51, 16 February 2011

Status & tagging log