Index: trunk/extensions/CentralAuth/SpecialGlobalGroupMembership.php |
— | — | @@ -1,111 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Equivalent of Special:Userrights for global groups. |
5 | | - * |
6 | | - * @ingroup Extensions |
7 | | - */ |
8 | | - |
9 | | -class SpecialGlobalGroupMembership extends UserrightsPage { |
10 | | - var $mGlobalUser; |
11 | | - |
12 | | - function __construct() { |
13 | | - SpecialPage::__construct( 'GlobalGroupMembership' ); |
14 | | - |
15 | | - global $wgUser; |
16 | | - $this->mGlobalUser = CentralAuthUser::getInstance( $wgUser ); |
17 | | - } |
18 | | - |
19 | | - function getSuccessURL() { |
20 | | - $knownWikis = $this->mGlobalUser->listAttached(); |
21 | | - $title = $this->getTitle( $this->mTarget ); |
22 | | - return $title->getFullURL( 'wpKnownWiki=' . urlencode( $knownWikis[0] ) ); |
23 | | - } |
24 | | - |
25 | | - /** |
26 | | - * Output a form to allow searching for a user |
27 | | - */ |
28 | | - function switchForm() { |
29 | | - global $wgOut, $wgScript, $wgRequest; |
30 | | - |
31 | | - $knownwiki = $wgRequest->getVal( 'wpKnownWiki' ); |
32 | | - $knownwiki = $knownwiki ? $knownwiki : wfWikiId(); |
33 | | - |
34 | | - // Generate wiki selector |
35 | | - $selector = new XmlSelect( 'wpKnownWiki', 'wpKnownWiki', $knownwiki ); |
36 | | - |
37 | | - foreach ( CentralAuthUser::getWikiList() as $wiki ) { |
38 | | - $selector->addOption( $wiki ); |
39 | | - } |
40 | | - |
41 | | - $wgOut->addModuleStyles( 'mediawiki.special' ); |
42 | | - $wgOut->addHTML( |
43 | | - Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'name' => 'uluser', 'id' => 'mw-userrights-form1' ) ) . |
44 | | - Html::hidden( 'title', $this->getTitle() ) . |
45 | | - Xml::openElement( 'fieldset' ) . |
46 | | - Xml::element( 'legend', array(), wfMsg( 'userrights-lookup-user' ) ) . |
47 | | - Xml::inputLabel( wfMsg( 'userrights-user-editname' ), 'user', 'username', 30, $this->mTarget ) . ' <br />' . |
48 | | - Xml::label( wfMsg( 'centralauth-globalgrouppermissions-knownwiki' ), 'wpKnownWiki' ) . ' ' . |
49 | | - $selector->getHTML() . '<br />' . |
50 | | - Xml::submitButton( wfMsg( 'editusergroup' ) ) . |
51 | | - Xml::closeElement( 'fieldset' ) . |
52 | | - Xml::closeElement( 'form' ) . "\n" |
53 | | - ); |
54 | | - } |
55 | | - |
56 | | - function changeableGroups() { |
57 | | - # # Should be a global user |
58 | | - if ( !$this->mGlobalUser->exists() || !$this->mGlobalUser->isAttached() ) { |
59 | | - return array(); |
60 | | - } |
61 | | - |
62 | | - $allGroups = CentralAuthUser::availableGlobalGroups(); |
63 | | - |
64 | | - # # Permission MUST be gained from global rights. |
65 | | - if ( $this->mGlobalUser->hasGlobalPermission( 'globalgroupmembership' ) ) { |
66 | | - # specify addself and removeself as empty arrays -- bug 16098 |
67 | | - return array( 'add' => $allGroups, 'remove' => $allGroups, 'add-self' => array(), 'remove-self' => array() ); |
68 | | - } else { |
69 | | - return array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); |
70 | | - } |
71 | | - } |
72 | | - |
73 | | - function fetchUser( $username ) { |
74 | | - global $wgRequest; |
75 | | - |
76 | | - $knownwiki = $wgRequest->getVal( 'wpKnownWiki' ); |
77 | | - |
78 | | - $user = CentralAuthGroupMembershipProxy::newFromName( $username ); |
79 | | - |
80 | | - if ( !$user ) { |
81 | | - return Status::newFatal( 'nosuchusershort', $username ); |
82 | | - } elseif ( !$wgRequest->getCheck( 'saveusergroups' ) && !$user->attachedOn( $knownwiki ) ) { |
83 | | - return Status::newFatal( 'centralauth-globalgroupmembership-badknownwiki', |
84 | | - $username, $knownwiki ); |
85 | | - } |
86 | | - |
87 | | - return Status::newGood( $user ); |
88 | | - } |
89 | | - |
90 | | - protected static function getAllGroups() { |
91 | | - return CentralAuthUser::availableGlobalGroups(); |
92 | | - } |
93 | | - |
94 | | - protected function showLogFragment( $user, $output ) { |
95 | | - $pageTitle = Title::makeTitleSafe( NS_USER, $user->getName() ); |
96 | | - $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'gblrights' ) . "\n" ) ); |
97 | | - LogEventsList::showLogExtract( $output, 'gblrights', $pageTitle->getPrefixedText() ); |
98 | | - } |
99 | | - |
100 | | - function addLogEntry( $user, $oldGroups, $newGroups, $reason ) { |
101 | | - $log = new LogPage( 'gblrights' ); |
102 | | - |
103 | | - $log->addEntry( 'usergroups', |
104 | | - $user->getUserPage(), |
105 | | - $reason, |
106 | | - array( |
107 | | - $this->makeGroupNameList( $oldGroups ), |
108 | | - $this->makeGroupNameList( $newGroups ) |
109 | | - ) |
110 | | - ); |
111 | | - } |
112 | | -} |
Index: trunk/extensions/CentralAuth/SpecialAutoLogin.php |
— | — | @@ -1,86 +0,0 @@ |
2 | | -<?php |
3 | | -if ( !defined( 'MEDIAWIKI' ) ) { |
4 | | - die( 'CentralAuth' ); |
5 | | -} |
6 | | - |
7 | | -/** |
8 | | - * Unlisted Special page to set requisite cookies for being logged into this wiki. |
9 | | - * |
10 | | - * @ingroup Extensions |
11 | | - */ |
12 | | -class SpecialAutoLogin extends UnlistedSpecialPage { |
13 | | - function __construct() { |
14 | | - parent::__construct( 'AutoLogin' ); |
15 | | - } |
16 | | - |
17 | | - function execute( $par ) { |
18 | | - global $wgRequest, $wgOut, $wgMemc; |
19 | | - |
20 | | - $tempToken = $wgRequest->getVal( 'token' ); |
21 | | - $logout = $wgRequest->getBool( 'logout' ); |
22 | | - |
23 | | - # Don't cache error messages |
24 | | - $wgOut->enableClientCache( false ); |
25 | | - |
26 | | - if ( strlen( $tempToken ) == 0 ) { |
27 | | - $this->setHeaders(); |
28 | | - $wgOut->addWikiMsg( 'centralauth-autologin-desc' ); |
29 | | - return; |
30 | | - } |
31 | | - |
32 | | - $key = CentralAuthUser::memcKey( 'login-token', $tempToken ); |
33 | | - $data = $wgMemc->get( $key ); |
34 | | - $wgMemc->delete( $key ); |
35 | | - |
36 | | - if ( !$data ) { |
37 | | - $msg = 'Token is invalid or has expired'; |
38 | | - wfDebug( __METHOD__ . ": $msg\n" ); |
39 | | - $this->setHeaders(); |
40 | | - $wgOut->addWikiText( $msg ); |
41 | | - return; |
42 | | - } |
43 | | - |
44 | | - $userName = $data['userName']; |
45 | | - $token = $data['token']; |
46 | | - $remember = $data['remember']; |
47 | | - |
48 | | - if ( $data['wiki'] != wfWikiID() ) { |
49 | | - $msg = 'Bad token (wrong wiki)'; |
50 | | - wfDebug( __METHOD__ . ": $msg\n" ); |
51 | | - $this->setHeaders(); |
52 | | - $wgOut->addWikiText( $msg ); |
53 | | - return; |
54 | | - } |
55 | | - |
56 | | - $centralUser = new CentralAuthUser( $userName ); |
57 | | - $loginResult = $centralUser->authenticateWithToken( $token ); |
58 | | - |
59 | | - if ( $loginResult != 'ok' ) { |
60 | | - $msg = "Bad token: $loginResult"; |
61 | | - wfDebug( __METHOD__ . ": $msg\n" ); |
62 | | - $this->setHeaders(); |
63 | | - $wgOut->addWikiText( $msg ); |
64 | | - return; |
65 | | - } |
66 | | - |
67 | | - // Auth OK. |
68 | | - if ( $logout ) { |
69 | | - $centralUser->deleteGlobalCookies(); |
70 | | - } else { |
71 | | - $centralUser->setGlobalCookies( $remember ); |
72 | | - } |
73 | | - |
74 | | - $wgOut->disable(); |
75 | | - |
76 | | - wfResetOutputBuffers(); |
77 | | - header( 'Cache-Control: no-cache' ); |
78 | | - header( 'Content-Type: image/png' ); |
79 | | - |
80 | | - global $wgCentralAuthLoginIcon; |
81 | | - if ( $wgCentralAuthLoginIcon ) { |
82 | | - readfile( $wgCentralAuthLoginIcon ); |
83 | | - } else { |
84 | | - readfile( dirname( __FILE__ ) . '/1x1.png' ); |
85 | | - } |
86 | | - } |
87 | | -} |
Index: trunk/extensions/CentralAuth/SpecialWikiSets.php |
— | — | @@ -1,293 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Special page to allow to edit "wikisets" which are used to restrict |
5 | | - * specific global group permissions to certain wikis. |
6 | | - * |
7 | | - * @file |
8 | | - * @ingroup Extensions |
9 | | - */ |
10 | | - |
11 | | -if ( !defined( 'MEDIAWIKI' ) ) { |
12 | | - echo "CentralAuth extension\n"; |
13 | | - exit( 1 ); |
14 | | -} |
15 | | - |
16 | | - |
17 | | -class SpecialWikiSets extends SpecialPage { |
18 | | - var $mCanEdit; |
19 | | - |
20 | | - function __construct() { |
21 | | - parent::__construct( 'WikiSets' ); |
22 | | - } |
23 | | - |
24 | | - function getDescription() { |
25 | | - return wfMsg( 'centralauth-editset' ); |
26 | | - } |
27 | | - |
28 | | - function execute( $subpage ) { |
29 | | - global $wgRequest, $wgOut, $wgUser; |
30 | | - |
31 | | - $this->mCanEdit = $wgUser->isAllowed( 'globalgrouppermissions' ); |
32 | | - |
33 | | - $this->setHeaders(); |
34 | | - |
35 | | - if ( strpos( $subpage, 'delete/' ) === 0 && $this->mCanEdit ) { |
36 | | - $subpage = substr( $subpage, 7 ); // Remove delete/ part |
37 | | - if ( is_numeric( $subpage ) ) { |
38 | | - if ( $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) |
39 | | - $this->doDelete( $subpage ); |
40 | | - else |
41 | | - $this->buildDeleteView( $subpage ); |
42 | | - } else { |
43 | | - $this->buildMainView(); |
44 | | - } |
45 | | - } else { |
46 | | - if ( $subpage ) { |
47 | | - $set = is_numeric( $subpage ) ? WikiSet::newFromId( $subpage ) : WikiSet::newFromName( $subpage ); |
48 | | - if ( $set ) { |
49 | | - $subpage = $set->getID(); |
50 | | - } else { |
51 | | - $wgOut->setPageTitle( wfMsg( 'error' ) ); |
52 | | - $error = wfMsgExt( 'centralauth-editset-notfound', array( 'escapenoentities' ), $subpage ); |
53 | | - $this->buildMainView( "<strong class='error'>{$error}</strong>" ); |
54 | | - return; |
55 | | - } |
56 | | - } |
57 | | - |
58 | | - if ( ( $subpage || $subpage === '0' ) && $this->mCanEdit && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
59 | | - $this->doSubmit( $subpage ); |
60 | | - } else if ( ( $subpage || $subpage === '0' ) && is_numeric( $subpage ) ) { |
61 | | - $this->buildSetView( $subpage ); |
62 | | - } else { |
63 | | - $this->buildMainView(); |
64 | | - } |
65 | | - } |
66 | | - } |
67 | | - |
68 | | - function buildMainView( $msg = '' ) { |
69 | | - global $wgOut, $wgUser; |
70 | | - $sk = $wgUser->getSkin(); |
71 | | - |
72 | | - $msgPostfix = $this->mCanEdit ? 'rw' : 'ro'; |
73 | | - $legend = wfMsg( "centralauth-editset-legend-{$msgPostfix}" ); |
74 | | - $wgOut->addHTML( "<fieldset><legend>{$legend}</legend>" ); |
75 | | - if ( $msg ) |
76 | | - $wgOut->addHTML( $msg ); |
77 | | - $wgOut->addWikiMsg( "centralauth-editset-intro-{$msgPostfix}" ); |
78 | | - $wgOut->addHTML( '<ul>' ); |
79 | | - |
80 | | - $sets = WikiSet::getAllWikiSets(); |
81 | | - foreach ( $sets as $set ) { |
82 | | - $text = wfMsgExt( "centralauth-editset-item-{$msgPostfix}", array( 'parseinline' ), $set->getName(), $set->getID() ); |
83 | | - $wgOut->addHTML( "<li>{$text}</li>" ); |
84 | | - } |
85 | | - |
86 | | - if ( $this->mCanEdit ) { |
87 | | - $target = SpecialPage::getTitleFor( 'WikiSets', '0' ); |
88 | | - $newlink = $sk->makeLinkObj( $target, wfMsgHtml( 'centralauth-editset-new' ) ); |
89 | | - $wgOut->addHTML( "<li>{$newlink}</li>" ); |
90 | | - } |
91 | | - |
92 | | - $wgOut->addHTML( '</ul></fieldset>' ); |
93 | | - } |
94 | | - |
95 | | - function buildSetView( $subpage, $error = false, $name = null, $type = null, $wikis = null, $reason = null ) { |
96 | | - global $wgOut, $wgUser; |
97 | | - |
98 | | - $wgOut->setSubtitle( wfMsgExt( 'centralauth-editset-subtitle', 'parseinline' ) ); |
99 | | - |
100 | | - $set = $subpage ? WikiSet::newFromID( $subpage ) : null; |
101 | | - if ( !$name ) $name = $set ? $set->getName() : ''; |
102 | | - if ( !$type ) $type = $set ? $set->getType() : WikiSet::OPTIN; |
103 | | - if ( !$wikis ) $wikis = implode( "\n", $set ? $set->getWikisRaw() : array() ); |
104 | | - else $wikis = implode( "\n", $wikis ); |
105 | | - $url = SpecialPage::getTitleFor( 'WikiSets', $subpage )->getLocalUrl(); |
106 | | - if ( $this->mCanEdit ) { |
107 | | - $legend = wfMsgHtml( 'centralauth-editset-legend-' . ( $set ? 'edit' : 'new' ), $name ); |
108 | | - } else { |
109 | | - $legend = wfMsgHtml( 'centralauth-editset-legend-view', $name ); |
110 | | - } |
111 | | - |
112 | | - $wgOut->addHTML( "<fieldset><legend>{$legend}</legend>" ); |
113 | | - |
114 | | - if ( $set ) { |
115 | | - $groups = $set->getRestrictedGroups(); |
116 | | - if ( $groups ) { |
117 | | - $usage = "<ul>\n"; |
118 | | - foreach ( $groups as $group ) |
119 | | - $usage .= "<li>" . wfMsgExt( 'centralauth-editset-grouplink', 'parseinline', $group ) . "</li>\n"; |
120 | | - $usage .= "</ul>"; |
121 | | - } else { |
122 | | - $usage = wfMsgExt( 'centralauth-editset-nouse', 'parse' ); |
123 | | - } |
124 | | - } else { |
125 | | - $usage = ''; |
126 | | - } |
127 | | - |
128 | | - if ( $this->mCanEdit ) { |
129 | | - if ( $error ) { |
130 | | - $wgOut->addHTML( "<strong class='error'>{$error}</strong>" ); |
131 | | - } |
132 | | - $wgOut->addHTML( "<form action='{$url}' method='post'>" ); |
133 | | - |
134 | | - $form = array(); |
135 | | - $form['centralauth-editset-name'] = Xml::input( 'wpName', false, $name ); |
136 | | - if ( $usage ) { |
137 | | - $form['centralauth-editset-usage'] = $usage; |
138 | | - } |
139 | | - $form['centralauth-editset-type'] = $this->buildTypeSelector( 'wpType', $type ); |
140 | | - $form['centralauth-editset-wikis'] = Xml::textarea( 'wpWikis', $wikis ); |
141 | | - $form['centralauth-editset-reason'] = Xml::input( 'wpReason', false, $reason ); |
142 | | - |
143 | | - $wgOut->addHTML( Xml::buildForm( $form, 'centralauth-editset-submit' ) ); |
144 | | - |
145 | | - $edittoken = Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
146 | | - $wgOut->addHTML( "<p>{$edittoken}</p></form></fieldset>" ); |
147 | | - } else { |
148 | | - $form = array(); |
149 | | - $form['centralauth-editset-name'] = htmlspecialchars( $name ); |
150 | | - $form['centralauth-editset-usage'] = $usage; |
151 | | - $form['centralauth-editset-type'] = wfMsg( "centralauth-editset-{$type}" ); |
152 | | - $form['centralauth-editset-wikis'] = $this->buildWikiList( $set->getWikisRaw() ); |
153 | | - |
154 | | - $wgOut->addHTML( Xml::buildForm( $form ) ); |
155 | | - } |
156 | | - } |
157 | | - |
158 | | - function buildTypeSelector( $name, $value ) { |
159 | | - $select = new XmlSelect( $name, 'set-type', $value ); |
160 | | - foreach ( array( WikiSet::OPTIN, WikiSet::OPTOUT ) as $type ) { |
161 | | - $select->addOption( wfMsg( "centralauth-editset-{$type}" ), $type ); |
162 | | - } |
163 | | - return $select->getHTML(); |
164 | | - } |
165 | | - |
166 | | - function buildWikiList( $list ) { |
167 | | - sort( $list ); |
168 | | - $html = '<ul>'; |
169 | | - foreach ( $list as $wiki ) { |
170 | | - $escWiki = htmlspecialchars( $wiki ); |
171 | | - $html .= "<li>{$escWiki}</li>"; |
172 | | - } |
173 | | - $html .= '</ul>'; |
174 | | - return $html; |
175 | | - } |
176 | | - |
177 | | - function buildDeleteView( $subpage ) { |
178 | | - global $wgOut, $wgUser; |
179 | | - $wgOut->setSubtitle( wfMsgExt( 'centralauth-editset-subtitle', 'parseinline' ) ); |
180 | | - |
181 | | - $set = WikiSet::newFromID( $subpage ); |
182 | | - if ( !$set ) { |
183 | | - $this->buildMainView( '<strong class="error">' . wfMsgHtml( 'centralauth-editset-notfound', $subpage ) . '</strong>' ); |
184 | | - return; |
185 | | - } |
186 | | - |
187 | | - $legend = wfMsgHtml( 'centralauth-editset-legend-delete', $set->getName() ); |
188 | | - $form = array( 'centralauth-editset-reason' => Xml::input( 'wpReason' ) ); |
189 | | - $url = htmlspecialchars( SpecialPage::getTitleFor( 'WikiSets', "delete/{$subpage}" )->getLocalUrl() ); |
190 | | - $edittoken = Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
191 | | - |
192 | | - $wgOut->addHTML( "<fieldset><legend>{$legend}</legend><form action='{$url}' method='post'>" ); |
193 | | - $wgOut->addHTML( Xml::buildForm( $form, 'centralauth-editset-submit-delete' ) ); |
194 | | - $wgOut->addHTML( "<p>{$edittoken}</p></form></fieldset>" ); |
195 | | - } |
196 | | - |
197 | | - function doSubmit( $id ) { |
198 | | - global $wgRequest, $wgContLang; |
199 | | - |
200 | | - $name = $wgContLang->ucfirst( $wgRequest->getVal( 'wpName' ) ); |
201 | | - $type = $wgRequest->getVal( 'wpType' ); |
202 | | - $wikis = array_unique( preg_split( '/(\s+|\s*\W\s*)/', $wgRequest->getVal( 'wpWikis' ), -1, PREG_SPLIT_NO_EMPTY ) ); |
203 | | - $reason = $wgRequest->getVal( 'wpReason' ); |
204 | | - $set = WikiSet::newFromId( $id ); |
205 | | - |
206 | | - if ( !Title::newFromText( $name ) ) { |
207 | | - $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-badname' ), $name, $type, $wikis, $reason ); |
208 | | - return; |
209 | | - } |
210 | | - if ( ( !$id || $set->getName() != $name ) && WikiSet::newFromName( $name ) ) { |
211 | | - $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-setexists' ), $name, $type, $wikis, $reason ); |
212 | | - return; |
213 | | - } |
214 | | - if ( !in_array( $type, array( WikiSet::OPTIN, WikiSet::OPTOUT ) ) ) { |
215 | | - $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-badtype' ), $name, $type, $wikis, $reason ); |
216 | | - return; |
217 | | - } |
218 | | - if ( !$wikis ) { |
219 | | - $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-nowikis' ), $name, $type, $wikis, $reason ); |
220 | | - return; |
221 | | - } |
222 | | - $badwikis = array(); |
223 | | - $allwikis = CentralAuthUser::getWikiList(); |
224 | | - foreach ( $wikis as $wiki ) { |
225 | | - if ( !in_array( $wiki, $allwikis ) ) { |
226 | | - $badwikis[] = $wiki; |
227 | | - } |
228 | | - } |
229 | | - if ( $badwikis ) { |
230 | | - $this->buildSetView( $id, wfMsgExt( 'centralauth-editset-badwikis', array( 'escapenoentities', 'parsemag' ), |
231 | | - implode( ', ', $badwikis ), count( $badwikis ) ), $name, $type, $wikis, $reason ); |
232 | | - return; |
233 | | - } |
234 | | - |
235 | | - if ( $set ) { |
236 | | - $oldname = $set->getName(); |
237 | | - $oldtype = $set->getType(); |
238 | | - $oldwikis = $set->getWikisRaw(); |
239 | | - } else { |
240 | | - $set = new WikiSet(); |
241 | | - $oldname = $oldtype = null; $oldwikis = array(); |
242 | | - } |
243 | | - $set->setName( $name ); |
244 | | - $set->setType( $type ); |
245 | | - $set->setWikisRaw( $wikis ); |
246 | | - $set->commit(); |
247 | | - |
248 | | - // Now logging |
249 | | - $log = new LogPage( 'gblrights' ); |
250 | | - $title = SpecialPage::getTitleFor( 'WikiSets', $set->getID() ); |
251 | | - if ( !$oldname ) { |
252 | | - // New set |
253 | | - $log->addEntry( 'newset', $title, $reason, array( $name, $type, implode( ', ', $wikis ) ) ); |
254 | | - } else { |
255 | | - if ( $oldname != $name ) { |
256 | | - $log->addEntry( 'setrename', $title, $reason, array( $name, $oldname ) ); |
257 | | - } |
258 | | - if ( $oldtype != $type ) { |
259 | | - $log->addEntry( 'setnewtype', $title, $reason, array( $name, $oldtype, $type ) ); |
260 | | - } |
261 | | - $added = implode( ', ', array_diff( $wikis, $oldwikis ) ); |
262 | | - $removed = implode( ', ', array_diff( $oldwikis, $wikis ) ); |
263 | | - if ( $added || $removed ) { |
264 | | - $log->addEntry( 'setchange', $title, $reason, array( $name, $added, $removed ) ); |
265 | | - } |
266 | | - } |
267 | | - |
268 | | - global $wgUser, $wgOut; |
269 | | - $sk = $wgUser->getSkin(); |
270 | | - $returnLink = $sk->makeKnownLinkObj( $this->getTitle(), wfMsg( 'centralauth-editset-return' ) ); |
271 | | - |
272 | | - $wgOut->addHTML( '<strong class="success">' . wfMsgHtml( 'centralauth-editset-success' ) . '</strong> <p>' . $returnLink . '</p>' ); |
273 | | - } |
274 | | - |
275 | | - function doDelete( $set ) { |
276 | | - global $wgRequest; |
277 | | - |
278 | | - $set = WikiSet::newFromID( $set ); |
279 | | - if ( !$set ) { |
280 | | - $this->buildMainView( '<strong class="error">' . wfMsgHtml( 'centralauth-editset-notfound', $subpage ) . '</strong>' ); |
281 | | - return; |
282 | | - } |
283 | | - |
284 | | - $reason = $wgRequest->getVal( 'wpReason' ); |
285 | | - $name = $set->getName(); |
286 | | - $set->delete(); |
287 | | - |
288 | | - $title = SpecialPage::getTitleFor( 'WikiSets', $set->getID() ); |
289 | | - $log = new LogPage( 'gblrights' ); |
290 | | - $log->addEntry( 'deleteset', $title, $reason, array( $name ) ); |
291 | | - |
292 | | - $this->buildMainView( '<strong class="success">' . wfMsg( 'centralauth-editset-success-delete' ) . '</strong>' ); |
293 | | - } |
294 | | -} |
Index: trunk/extensions/CentralAuth/SpecialGlobalGroupPermissions.php |
— | — | @@ -1,370 +0,0 @@ |
2 | | -<?php |
3 | | -# This file is part of MediaWiki. |
4 | | - |
5 | | -# MediaWiki is free software: you can redistribute it and/or modify |
6 | | -# it under the terms of version 2 of the GNU General Public License |
7 | | -# as published by the Free Software Foundation. |
8 | | - |
9 | | -# MediaWiki 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 | | -/** |
15 | | - * Special page to allow managing global groups |
16 | | - * Prototype for a similar system in core. |
17 | | - * |
18 | | - * @file |
19 | | - * @ingroup Extensions |
20 | | - */ |
21 | | - |
22 | | -if ( !defined( 'MEDIAWIKI' ) ) { |
23 | | - echo "CentralAuth extension\n"; |
24 | | - exit( 1 ); |
25 | | -} |
26 | | - |
27 | | -class SpecialGlobalGroupPermissions extends SpecialPage { |
28 | | - function __construct() { |
29 | | - parent::__construct( 'GlobalGroupPermissions' ); |
30 | | - } |
31 | | - |
32 | | - function userCanEdit( $user ) { |
33 | | - $globalUser = CentralAuthUser::getInstance( $user ); |
34 | | - |
35 | | - # # Should be a global user |
36 | | - if ( !$globalUser->exists() || !$globalUser->isAttached() ) { |
37 | | - return false; |
38 | | - } |
39 | | - |
40 | | - # # Permission MUST be gained from global rights. |
41 | | - return $globalUser->hasGlobalPermission( 'globalgrouppermissions' ); |
42 | | - } |
43 | | - |
44 | | - function execute( $subpage ) { |
45 | | - global $wgRequest, $wgOut, $wgUser; |
46 | | - |
47 | | - if ( !$this->userCanExecute( $wgUser ) ) { |
48 | | - $this->displayRestrictionError(); |
49 | | - return; |
50 | | - } |
51 | | - |
52 | | - $wgOut->setPageTitle( wfMsg( 'globalgrouppermissions' ) ); |
53 | | - $wgOut->setRobotPolicy( "noindex,nofollow" ); |
54 | | - $wgOut->setArticleRelated( false ); |
55 | | - $wgOut->enableClientCache( false ); |
56 | | - |
57 | | - if ( $subpage == '' ) { |
58 | | - $subpage = $wgRequest->getVal( 'wpGroup' ); |
59 | | - } |
60 | | - |
61 | | - if ( $subpage != '' && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
62 | | - $this->doSubmit( $subpage ); |
63 | | - } else if ( $subpage != '' ) { |
64 | | - $this->buildGroupView( $subpage ); |
65 | | - } else { |
66 | | - $this->buildMainView(); |
67 | | - } |
68 | | - } |
69 | | - |
70 | | - function buildMainView() { |
71 | | - global $wgOut, $wgUser, $wgScript; |
72 | | - |
73 | | - $groups = CentralAuthUser::availableGlobalGroups(); |
74 | | - |
75 | | - // Existing groups |
76 | | - $html = Xml::fieldset( wfMsg( 'centralauth-existinggroup-legend' ) ); |
77 | | - |
78 | | - $wgOut->addHTML( $html ); |
79 | | - |
80 | | - if ( count( $groups ) ) { |
81 | | - $wgOut->addWikiMsg( 'centralauth-globalgroupperms-grouplist' ); |
82 | | - $wgOut->addHTML( '<ul>' ); |
83 | | - |
84 | | - foreach ( $groups as $group ) { |
85 | | - $text = wfMsgExt( 'centralauth-globalgroupperms-grouplistitem', array( 'parseinline' ), User::getGroupName( $group ), $group, '<span class="centralauth-globalgroupperms-groupname">' . $group . '</span>' ); |
86 | | - |
87 | | - $wgOut->addHTML( "<li> $text </li>" ); |
88 | | - } |
89 | | - } else { |
90 | | - $wgOut->addWikiMsg( 'centralauth-globalgroupperms-nogroups' ); |
91 | | - } |
92 | | - |
93 | | - $wgOut->addHTML( Xml::closeElement( 'ul' ) . Xml::closeElement( 'fieldset' ) ); |
94 | | - |
95 | | - if ( $this->userCanEdit( $wgUser ) ) { |
96 | | - // "Create a group" prompt |
97 | | - $html = Xml::fieldset( wfMsg( 'centralauth-newgroup-legend' ) ); |
98 | | - $html .= wfMsgExt( 'centralauth-newgroup-intro', array( 'parse' ) ); |
99 | | - $html .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $wgScript, 'name' => 'centralauth-globalgroups-newgroup' ) ); |
100 | | - $html .= Html::hidden( 'title', SpecialPage::getTitleFor( 'GlobalGroupPermissions' )->getPrefixedText() ); |
101 | | - |
102 | | - $fields = array( 'centralauth-globalgroupperms-newgroupname' => Xml::input( 'wpGroup' ) ); |
103 | | - |
104 | | - $html .= Xml::buildForm( $fields, 'centralauth-globalgroupperms-creategroup-submit' ); |
105 | | - $html .= Xml::closeElement( 'form' ); |
106 | | - $html .= Xml::closeElement( 'fieldset' ); |
107 | | - |
108 | | - $wgOut->addHTML( $html ); |
109 | | - } |
110 | | - } |
111 | | - |
112 | | - function buildGroupView( $group ) { |
113 | | - global $wgOut, $wgUser; |
114 | | - |
115 | | - $editable = $this->userCanEdit( $wgUser ); |
116 | | - |
117 | | - $wgOut->setSubtitle( wfMsg( 'centralauth-editgroup-subtitle', $group ) ); |
118 | | - |
119 | | - $html = Xml::fieldset( wfMsg( 'centralauth-editgroup-fieldset', $group ) ); |
120 | | - |
121 | | - if ( $editable ) { |
122 | | - $html .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => SpecialPage::getTitleFor( 'GlobalGroupPermissions', $group )->getLocalUrl(), 'name' => 'centralauth-globalgroups-newgroup' ) ); |
123 | | - $html .= Html::hidden( 'wpGroup', $group ); |
124 | | - $html .= Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
125 | | - } |
126 | | - |
127 | | - $fields = array(); |
128 | | - |
129 | | - $fields['centralauth-editgroup-name'] = $group; |
130 | | - $fields['centralauth-editgroup-display'] = wfMsgExt( 'centralauth-editgroup-display-edit', array( 'parseinline' ), $group, User::getGroupName( $group ) ); |
131 | | - $fields['centralauth-editgroup-member'] = wfMsgExt( 'centralauth-editgroup-member-edit', array( 'parseinline' ), $group, User::getGroupMember( $group ) ); |
132 | | - $fields['centralauth-editgroup-members'] = wfMsgExt( 'centralauth-editgroup-members-link', array( 'parseinline' ), $group, User::getGroupMember( $group ) ); |
133 | | - $fields['centralauth-editgroup-restrictions'] = $this->buildWikiSetSelector( $group ); |
134 | | - $fields['centralauth-editgroup-perms'] = $this->buildCheckboxes( $group ); |
135 | | - |
136 | | - if ( $editable ) { |
137 | | - $fields['centralauth-editgroup-reason'] = Xml::input( 'wpReason', 60 ); |
138 | | - } |
139 | | - |
140 | | - $html .= Xml::buildForm( $fields, $editable ? 'centralauth-editgroup-submit' : null ); |
141 | | - |
142 | | - if ( $editable ) |
143 | | - $html .= Xml::closeElement( 'form' ); |
144 | | - |
145 | | - $html .= Xml::closeElement( 'fieldset' ); |
146 | | - |
147 | | - $wgOut->addHTML( $html ); |
148 | | - |
149 | | - $this->showLogFragment( $group, $wgOut ); |
150 | | - } |
151 | | - |
152 | | - function buildWikiSetSelector( $group ) { |
153 | | - $sets = WikiSet::getAllWikiSets(); |
154 | | - $default = WikiSet::getWikiSetForGroup( $group ); |
155 | | - |
156 | | - global $wgUser; |
157 | | - if ( !$this->userCanEdit( $wgUser ) ) |
158 | | - return htmlspecialchars( $default ); |
159 | | - |
160 | | - $select = new XmlSelect( 'set', 'wikiset', $default ); |
161 | | - $select->addOption( wfMsg( 'centralauth-editgroup-noset' ), '0' ); |
162 | | - foreach ( $sets as $set ) { |
163 | | - $select->addOption( $set->getName(), $set->getID() ); |
164 | | - } |
165 | | - |
166 | | - $editlink = wfMsgExt( "centralauth-editgroup-editsets", array( "parseinline" ) ); |
167 | | - return $select->getHTML() . " {$editlink}"; |
168 | | - } |
169 | | - |
170 | | - function buildCheckboxes( $group ) { |
171 | | - global $wgUser, $wgOut; |
172 | | - |
173 | | - $editable = $this->userCanEdit( $wgUser ); |
174 | | - |
175 | | - $rights = User::getAllRights(); |
176 | | - $assignedRights = $this->getAssignedRights( $group ); |
177 | | - |
178 | | - sort( $rights ); |
179 | | - |
180 | | - $checkboxes = array(); |
181 | | - $attribs = array(); |
182 | | - |
183 | | - if ( !$editable ) |
184 | | - $attribs['disabled'] = 'disabled'; |
185 | | - |
186 | | - foreach ( $rights as $right ) { |
187 | | - # Build a checkbox. |
188 | | - $checked = in_array( $right, $assignedRights ); |
189 | | - |
190 | | - $desc = $wgOut->parseInline( User::getRightDescription( $right ) ) . ' ' . |
191 | | - Xml::element( 'tt', null, wfMsg( 'parentheses', $right ) ); |
192 | | - |
193 | | - $checkbox = Xml::check( "wpRightAssigned-$right", $checked, $attribs ); |
194 | | - $label = Xml::tags( 'label', array( 'for' => "wpRightAssigned-$right" ), |
195 | | - $desc ); |
196 | | - |
197 | | - $checkboxes[] = "<li>$checkbox $label</li>"; |
198 | | - } |
199 | | - |
200 | | - $count = count( $checkboxes ); |
201 | | - |
202 | | - $firstCol = round( $count / 2 ); |
203 | | - |
204 | | - $checkboxes1 = array_slice( $checkboxes, 0, $firstCol ); |
205 | | - $checkboxes2 = array_slice( $checkboxes, $firstCol ); |
206 | | - |
207 | | - $html = '<table><tbody><tr><td><ul>'; |
208 | | - |
209 | | - foreach ( $checkboxes1 as $cb ) { |
210 | | - $html .= $cb; |
211 | | - } |
212 | | - |
213 | | - $html .= '</ul></td><td><ul>'; |
214 | | - |
215 | | - foreach ( $checkboxes2 as $cb ) { |
216 | | - $html .= $cb; |
217 | | - } |
218 | | - |
219 | | - $html .= '</ul></td></tr></tbody></table>'; |
220 | | - |
221 | | - return $html; |
222 | | - } |
223 | | - |
224 | | - function getAssignedRights( $group ) { |
225 | | - return CentralAuthUser::globalGroupPermissions( $group ); |
226 | | - } |
227 | | - |
228 | | - function doSubmit( $group ) { |
229 | | - global $wgRequest, $wgOut, $wgUser; |
230 | | - |
231 | | - // Paranoia -- the edit token shouldn't match anyway |
232 | | - if ( !$this->userCanEdit( $wgUser ) ) |
233 | | - return; |
234 | | - |
235 | | - $newRights = array(); |
236 | | - $addRights = array(); |
237 | | - $removeRights = array(); |
238 | | - $oldRights = $this->getAssignedRights( $group ); |
239 | | - $allRights = User::getAllRights(); |
240 | | - |
241 | | - $reason = $wgRequest->getVal( 'wpReason', '' ); |
242 | | - |
243 | | - foreach ( $allRights as $right ) { |
244 | | - $alreadyAssigned = in_array( $right, $oldRights ); |
245 | | - |
246 | | - if ( $wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
247 | | - $newRights[] = $right; |
248 | | - } |
249 | | - |
250 | | - if ( !$alreadyAssigned && $wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
251 | | - $addRights[] = $right; |
252 | | - } else if ( $alreadyAssigned && !$wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
253 | | - $removeRights[] = $right; |
254 | | - } # Otherwise, do nothing. |
255 | | - } |
256 | | - |
257 | | - // Assign the rights. |
258 | | - if ( count( $addRights ) > 0 ) |
259 | | - $this->grantRightsToGroup( $group, $addRights ); |
260 | | - if ( count( $removeRights ) > 0 ) |
261 | | - $this->revokeRightsFromGroup( $group, $removeRights ); |
262 | | - |
263 | | - // Log it |
264 | | - if ( !( count( $addRights ) == 0 && count( $removeRights ) == 0 ) ) |
265 | | - $this->addLogEntry( $group, $addRights, $removeRights, $reason ); |
266 | | - |
267 | | - // Change set |
268 | | - $current = WikiSet::getWikiSetForGroup( $group ); |
269 | | - $new = $wgRequest->getVal( 'set' ); |
270 | | - if ( $current != $new ) { |
271 | | - $this->setRestrictions( $group, $new ); |
272 | | - $this->addLogEntry2( $group, $current, $new, $reason ); |
273 | | - } |
274 | | - |
275 | | - $this->invalidateRightsCache( $group ); |
276 | | - |
277 | | - // Display success |
278 | | - $wgOut->setSubTitle( wfMsg( 'centralauth-editgroup-success' ) ); |
279 | | - $wgOut->addWikiMsg( 'centralauth-editgroup-success-text', $group ); |
280 | | - } |
281 | | - |
282 | | - function revokeRightsFromGroup( $group, $rights ) { |
283 | | - $dbw = CentralAuthUser::getCentralDB(); |
284 | | - |
285 | | - # Delete from the DB |
286 | | - $dbw->delete( 'global_group_permissions', array( 'ggp_group' => $group, 'ggp_permission' => $rights ), __METHOD__ ); |
287 | | - } |
288 | | - |
289 | | - function grantRightsToGroup( $group, $rights ) { |
290 | | - $dbw = CentralAuthUser::getCentralDB(); |
291 | | - |
292 | | - if ( !is_array( $rights ) ) { |
293 | | - $rights = array( $rights ); |
294 | | - } |
295 | | - |
296 | | - $insertRows = array(); |
297 | | - foreach ( $rights as $right ) { |
298 | | - $insertRows[] = array( 'ggp_group' => $group, 'ggp_permission' => $right ); |
299 | | - } |
300 | | - |
301 | | - # Replace into the DB |
302 | | - $dbw->replace( 'global_group_permissions', array( 'ggp_group', 'ggp_permission' ), $insertRows, __METHOD__ ); |
303 | | - } |
304 | | - |
305 | | - protected function showLogFragment( $group, $output ) { |
306 | | - $title = SpecialPage::getTitleFor( 'GlobalUsers', $group ); |
307 | | - $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'gblrights' ) . "\n" ) ); |
308 | | - LogEventsList::showLogExtract( $output, 'gblrights', $title->getPrefixedText() ); |
309 | | - } |
310 | | - |
311 | | - function addLogEntry( $group, $addRights, $removeRights, $reason ) { |
312 | | - $log = new LogPage( 'gblrights' ); |
313 | | - |
314 | | - $log->addEntry( 'groupprms2', |
315 | | - SpecialPage::getTitleFor( 'GlobalUsers', $group ), |
316 | | - $reason, |
317 | | - array( |
318 | | - $this->makeRightsList( $addRights ), |
319 | | - $this->makeRightsList( $removeRights ) |
320 | | - ) |
321 | | - ); |
322 | | - } |
323 | | - |
324 | | - function makeRightsList( $ids ) { |
325 | | - return (bool)count( $ids ) ? implode( ', ', $ids ) : wfMsgForContent( 'rightsnone' ); |
326 | | - } |
327 | | - |
328 | | - function setRestrictions( $group, $set ) { |
329 | | - $dbw = CentralAuthUser::getCentralDB(); |
330 | | - if ( $set == 0 ) { |
331 | | - $dbw->delete( 'global_group_restrictions', array( 'ggr_group' => $group ), __METHOD__ ); |
332 | | - } else { |
333 | | - $dbw->replace( 'global_group_restrictions', array( 'ggr_group' ), |
334 | | - array( 'ggr_group' => $group, 'ggr_set' => $set, ), __METHOD__ ); |
335 | | - } |
336 | | - return (bool)$dbw->affectedRows(); |
337 | | - } |
338 | | - |
339 | | - function addLogEntry2( $group, $old, $new, $reason ) { |
340 | | - $log = new LogPage( 'gblrights' ); |
341 | | - |
342 | | - $log->addEntry( 'groupprms3', |
343 | | - SpecialPage::getTitleFor( 'GlobalUsers', $group ), |
344 | | - $reason, |
345 | | - array( |
346 | | - $this->getWikiSetName( $old ), |
347 | | - $this->getWikiSetName( $new ), |
348 | | - ) |
349 | | - ); |
350 | | - } |
351 | | - |
352 | | - function getWikiSetName( $id ) { |
353 | | - if ( $id ) |
354 | | - return WikiSet::newFromID( $id )->getName(); |
355 | | - else |
356 | | - return wfMsgForContent( 'centralauth-editgroup-noset' ); |
357 | | - } |
358 | | - |
359 | | - function invalidateRightsCache( $group ) { |
360 | | - // Figure out all the users in this group. |
361 | | - $dbr = CentralAuthUser::getCentralDB(); |
362 | | - |
363 | | - $res = $dbr->select( array( 'global_user_groups', 'globaluser' ), 'gu_name', array( 'gug_group' => $group, 'gu_id=gug_user' ), __METHOD__ ); |
364 | | - |
365 | | - // Invalidate their rights cache. |
366 | | - foreach ( $res as $row ) { |
367 | | - $cu = new CentralAuthUser( $row->gu_name ); |
368 | | - $cu->quickInvalidateCache(); |
369 | | - } |
370 | | - } |
371 | | -} |
Index: trunk/extensions/CentralAuth/SpecialCentralAuth.php |
— | — | @@ -1,633 +0,0 @@ |
2 | | -<?php |
3 | | -class SpecialCentralAuth extends SpecialPage { |
4 | | - var $mUserName, $mCanUnmerge, $mCanLock, $mCanOversight, $mCanEdit; |
5 | | - var $mGlobalUser, $mAttachedLocalAccounts, $mUnattachedLocalAccounts; |
6 | | - |
7 | | - function __construct() { |
8 | | - parent::__construct( 'CentralAuth' ); |
9 | | - } |
10 | | - |
11 | | - function execute( $subpage ) { |
12 | | - global $wgOut; |
13 | | - global $wgExtensionAssetsPath, $wgCentralAuthStyleVersion; |
14 | | - global $wgUser, $wgRequest, $wgContLang; |
15 | | - $this->setHeaders(); |
16 | | - |
17 | | - $this->mCanUnmerge = $wgUser->isAllowed( 'centralauth-unmerge' ); |
18 | | - $this->mCanLock = $wgUser->isAllowed( 'centralauth-lock' ); |
19 | | - $this->mCanOversight = $wgUser->isAllowed( 'centralauth-oversight' ); |
20 | | - $this->mCanEdit = $this->mCanUnmerge || $this->mCanLock || $this->mCanOversight; |
21 | | - |
22 | | - $wgOut->addExtensionStyle( "{$wgExtensionAssetsPath}/CentralAuth/centralauth.css?" . |
23 | | - $wgCentralAuthStyleVersion ); |
24 | | - $wgOut->addScriptFile( "{$wgExtensionAssetsPath}/CentralAuth/centralauth.js?" . |
25 | | - $wgCentralAuthStyleVersion ); |
26 | | - $this->addMergeMethodDescriptions(); |
27 | | - |
28 | | - $this->mUserName = |
29 | | - trim( |
30 | | - str_replace( '_', ' ', |
31 | | - $wgRequest->getText( 'target', $subpage ) ) ); |
32 | | - |
33 | | - $this->mUserName = $wgContLang->ucfirst( $this->mUserName ); |
34 | | - |
35 | | - $this->mPosted = $wgRequest->wasPosted(); |
36 | | - $this->mMethod = $wgRequest->getVal( 'wpMethod' ); |
37 | | - $this->mWikis = (array)$wgRequest->getArray( 'wpWikis' ); |
38 | | - |
39 | | - // Possible demo states |
40 | | - |
41 | | - // success, all accounts merged |
42 | | - // successful login, some accounts merged, others left |
43 | | - // successful login, others left |
44 | | - // not account owner, others left |
45 | | - |
46 | | - // is owner / is not owner |
47 | | - // did / did not merge some accounts |
48 | | - // do / don't have more accounts to merge |
49 | | - |
50 | | - if ( $this->mUserName === '' ) { |
51 | | - # First time through |
52 | | - $wgOut->addWikiMsg( 'centralauth-admin-intro' ); |
53 | | - $this->showUsernameForm(); |
54 | | - return; |
55 | | - } |
56 | | - |
57 | | - $this->mGlobalUser = $globalUser = new CentralAuthUser( $this->mUserName ); |
58 | | - |
59 | | - if ( !$globalUser->exists() || |
60 | | - ( $globalUser->isOversighted() && !$this->mCanOversight ) ) { |
61 | | - $this->showError( 'centralauth-admin-nonexistent', $this->mUserName ); |
62 | | - $this->showUsernameForm(); |
63 | | - return; |
64 | | - } |
65 | | - |
66 | | - $continue = true; |
67 | | - if ( $this->mCanEdit && $this->mPosted ) { |
68 | | - $continue = $this->doSubmit(); |
69 | | - } |
70 | | - |
71 | | - $this->mAttachedLocalAccounts = $this->mGlobalUser->queryAttached(); |
72 | | - $this->mUnattachedLocalAccounts = $this->mGlobalUser->queryUnattached(); |
73 | | - |
74 | | - $this->showUsernameForm(); |
75 | | - if ( $continue ) { |
76 | | - $this->showInfo(); |
77 | | - if ( $this->mCanLock ) |
78 | | - $this->showStatusForm(); |
79 | | - if ( $this->mCanUnmerge ) |
80 | | - $this->showActionForm( 'delete' ); |
81 | | - if ( $this->mCanEdit ) |
82 | | - $this->showLogExtract(); |
83 | | - $this->showWikiLists(); |
84 | | - } |
85 | | - } |
86 | | - |
87 | | - /** Returns true if the normal form should be displayed */ |
88 | | - function doSubmit() { |
89 | | - $deleted = false; |
90 | | - $globalUser = $this->mGlobalUser; |
91 | | - global $wgUser, $wgRequest; |
92 | | - if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
93 | | - $this->showError( 'centralauth-token-mismatch' ); |
94 | | - } elseif ( $this->mMethod == 'unmerge' && $this->mCanUnmerge ) { |
95 | | - $status = $globalUser->adminUnattach( $this->mWikis ); |
96 | | - if ( !$status->isGood() ) { |
97 | | - $this->showStatusError( $status->getWikiText() ); |
98 | | - } else { |
99 | | - global $wgLang; |
100 | | - $this->showSuccess( 'centralauth-admin-unmerge-success', |
101 | | - $wgLang->formatNum( $status->successCount ), |
102 | | - /* deprecated */ $status->successCount ); |
103 | | - } |
104 | | - } elseif ( $this->mMethod == 'delete' && $this->mCanUnmerge ) { |
105 | | - $status = $globalUser->adminDelete(); |
106 | | - if ( !$status->isGood() ) { |
107 | | - $this->showStatusError( $status->getWikiText() ); |
108 | | - } else { |
109 | | - $this->showSuccess( 'centralauth-admin-delete-success', $this->mUserName ); |
110 | | - $deleted = true; |
111 | | - $this->logAction( 'delete', $this->mUserName, $wgRequest->getVal( 'reason' ) ); |
112 | | - } |
113 | | - } elseif ( $this->mMethod == 'set-status' && $this->mCanLock ) { |
114 | | - $setLocked = $wgRequest->getBool( 'wpStatusLocked' ); |
115 | | - $setHidden = $wgRequest->getVal( 'wpStatusHidden' ); |
116 | | - $isLocked = $globalUser->isLocked(); |
117 | | - $oldHiddenLevel = $globalUser->getHiddenLevel(); |
118 | | - $lockStatus = $hideStatus = null; |
119 | | - $added = array(); |
120 | | - $removed = array(); |
121 | | - |
122 | | - // Sanitizing input value... |
123 | | - $hiddenLevels = array( |
124 | | - CentralAuthUser::HIDDEN_NONE, |
125 | | - CentralAuthUser::HIDDEN_LISTS, |
126 | | - CentralAuthUser::HIDDEN_OVERSIGHT ); |
127 | | - if ( !in_array( $setHidden, $hiddenLevels ) ) |
128 | | - $setHidden = ''; |
129 | | - |
130 | | - if ( !$isLocked && $setLocked ) { |
131 | | - $lockStatus = $globalUser->adminLock(); |
132 | | - $added[] = wfMsgForContent( 'centralauth-log-status-locked' ); |
133 | | - } elseif ( $isLocked && !$setLocked ) { |
134 | | - $lockStatus = $globalUser->adminUnlock(); |
135 | | - $removed[] = wfMsgForContent( 'centralauth-log-status-locked' ); |
136 | | - } |
137 | | - |
138 | | - $reason = $wgRequest->getText( 'wpReasonList' ); |
139 | | - $reasonDetail = $wgRequest->getText( 'wpReason' ); |
140 | | - if ( $reason == 'other' ) { |
141 | | - $reason = $reasonDetail; |
142 | | - } elseif ( $reasonDetail ) { |
143 | | - $reason .= wfMsgForContent( 'colon-separator' ) . $reasonDetail; |
144 | | - } |
145 | | - |
146 | | - if ( $oldHiddenLevel != $setHidden ) { |
147 | | - $hideStatus = $globalUser->adminSetHidden( $setHidden ); |
148 | | - switch( $setHidden ) { |
149 | | - case CentralAuthUser::HIDDEN_NONE: |
150 | | - $removed[] = $oldHiddenLevel == CentralAuthUser::HIDDEN_OVERSIGHT ? |
151 | | - wfMsgForContent( 'centralauth-log-status-oversighted' ) : |
152 | | - wfMsgForContent( 'centralauth-log-status-hidden' ); |
153 | | - break; |
154 | | - case CentralAuthUser::HIDDEN_LISTS: |
155 | | - $added[] = wfMsgForContent( 'centralauth-log-status-hidden' ); |
156 | | - if ( $oldHiddenLevel == CentralAuthUser::HIDDEN_OVERSIGHT ) |
157 | | - $removed[] = wfMsgForContent( 'centralauth-log-status-oversighted' ); |
158 | | - break; |
159 | | - case CentralAuthUser::HIDDEN_OVERSIGHT: |
160 | | - $added[] = wfMsgForContent( 'centralauth-log-status-oversighted' ); |
161 | | - if ( $oldHiddenLevel == CentralAuthUser::HIDDEN_LISTS ) |
162 | | - $removed[] = wfMsgForContent( 'centralauth-log-status-hidden' ); |
163 | | - break; |
164 | | - } |
165 | | - |
166 | | - if ( $setHidden == CentralAuthUser::HIDDEN_OVERSIGHT ) |
167 | | - $globalUser->suppress( $reason ); |
168 | | - elseif ( $oldHiddenLevel == CentralAuthUser::HIDDEN_OVERSIGHT ) |
169 | | - $globalUser->unsuppress( $reason ); |
170 | | - } |
171 | | - |
172 | | - $good = |
173 | | - ( is_null( $lockStatus ) || $lockStatus->isGood() ) && |
174 | | - ( is_null( $hideStatus ) || $hideStatus->isGood() ); |
175 | | - |
176 | | - // Logging etc |
177 | | - if ( $good && ( count( $added ) || count( $removed ) ) ) { |
178 | | - $added = count( $added ) ? |
179 | | - implode( ', ', $added ) : wfMsgForContent( 'centralauth-log-status-none' ); |
180 | | - $removed = count( $removed ) ? |
181 | | - implode( ', ', $removed ) : wfMsgForContent( 'centralauth-log-status-none' ); |
182 | | - |
183 | | - $this->logAction( |
184 | | - 'setstatus', |
185 | | - $this->mUserName, |
186 | | - $reason, |
187 | | - array( $added, $removed ), |
188 | | - $setHidden == CentralAuthUser::HIDDEN_OVERSIGHT |
189 | | - ); |
190 | | - $this->showSuccess( 'centralauth-admin-setstatus-success', $this->mUserName ); |
191 | | - } elseif ( !$good ) { |
192 | | - if ( !is_null( $lockStatus ) && !$lockStatus->isGood() ) { |
193 | | - $this->showStatusError( $lockStatus->getWikiText() ); |
194 | | - } |
195 | | - if ( !is_null( $hideStatus ) && !$hideStatus->isGood() ) { |
196 | | - $this->showStatusError( $hideStatus->getWikiText() ); |
197 | | - } |
198 | | - } |
199 | | - } else { |
200 | | - $this->showError( 'centralauth-admin-bad-input' ); |
201 | | - } |
202 | | - return !$deleted; |
203 | | - } |
204 | | - |
205 | | - function showStatusError( $wikitext ) { |
206 | | - global $wgOut; |
207 | | - $wrap = Xml::tags( 'div', array( 'class' => 'error' ), $wikitext ); |
208 | | - $wgOut->addHTML( $wgOut->parse( $wrap, /*linestart*/true, /*uilang*/true ) ); |
209 | | - } |
210 | | - |
211 | | - function showError( /* varargs */ ) { |
212 | | - global $wgOut; |
213 | | - $args = func_get_args(); |
214 | | - $wgOut->wrapWikiMsg( '<div class="error">$1</div>', $args ); |
215 | | - } |
216 | | - |
217 | | - |
218 | | - function showSuccess( /* varargs */ ) { |
219 | | - global $wgOut; |
220 | | - $args = func_get_args(); |
221 | | - $wgOut->wrapWikiMsg( '<div class="success">$1</div>', $args ); |
222 | | - } |
223 | | - |
224 | | - function showUsernameForm() { |
225 | | - global $wgOut, $wgScript; |
226 | | - $lookup = $this->mCanEdit ? |
227 | | - wfMsg( 'centralauth-admin-lookup-rw' ) : |
228 | | - wfMsg( 'centralauth-admin-lookup-ro' ); |
229 | | - $wgOut->addHTML( |
230 | | - Xml::openElement( 'form', array( |
231 | | - 'method' => 'get', |
232 | | - 'action' => $wgScript ) ) . |
233 | | - '<fieldset>' . |
234 | | - Xml::element( 'legend', array(), wfMsg( 'centralauth-admin-manage' ) ) . |
235 | | - Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . |
236 | | - '<p>' . |
237 | | - Xml::inputLabel( wfMsg( 'centralauth-admin-username' ), |
238 | | - 'target', 'target', 25, $this->mUserName ) . |
239 | | - '</p>' . |
240 | | - '<p>' . |
241 | | - Xml::submitButton( $lookup ) . |
242 | | - '</p>' . |
243 | | - '</fieldset>' . |
244 | | - '</form>' |
245 | | - ); |
246 | | - } |
247 | | - |
248 | | - function prettyTimespan( $span ) { |
249 | | - global $wgLang; |
250 | | - $units = array( |
251 | | - 'seconds' => 60, |
252 | | - 'minutes' => 60, |
253 | | - 'hours' => 24, |
254 | | - 'days' => 30.417, |
255 | | - 'months' => 12, |
256 | | - 'years' => 1 ); |
257 | | - foreach ( $units as $unit => $chunk ) { |
258 | | - // Used messaged (to make sure that grep finds them): |
259 | | - // 'centralauth-seconds-ago', 'centralauth-minutes-ago', 'centralauth-hours-ago' |
260 | | - // 'centralauth-days-ago', 'centralauth-months-ago', 'centralauth-years-ago' |
261 | | - if ( $span < 2 * $chunk ) { |
262 | | - return wfMsgExt( "centralauth-$unit-ago", 'parsemag', $wgLang->formatNum( $span ) ); |
263 | | - } |
264 | | - $span = intval( $span / $chunk ); |
265 | | - } |
266 | | - return wfMsgExt( "centralauth-$unit-ago", 'parsemag', $wgLang->formatNum( $span ) ); |
267 | | - } |
268 | | - |
269 | | - function showInfo() { |
270 | | - $globalUser = $this->mGlobalUser; |
271 | | - |
272 | | - global $wgOut, $wgLang; |
273 | | - $reg = $globalUser->getRegistration(); |
274 | | - $age = $this->prettyTimespan( wfTimestamp( TS_UNIX ) - wfTimestamp( TS_UNIX, $reg ) ); |
275 | | - $attribs = array( |
276 | | - 'id' => $globalUser->getId(), |
277 | | - 'registered' => $wgLang->timeanddate( $reg ) . " ($age)", |
278 | | - 'home' => $this->determineHomeWiki(), |
279 | | - 'editcount' => $wgLang->formatNum( $this->evaluateTotalEditcount() ), |
280 | | - 'locked' => $globalUser->isLocked() ? wfMsg( 'centralauth-admin-yes' ) : wfMsg( 'centralauth-admin-no' ), |
281 | | - 'hidden' => $this->formatHiddenLevel( $globalUser->getHiddenLevel() ) ); |
282 | | - $out = '<fieldset id="mw-centralauth-info">'; |
283 | | - $out .= '<legend>' . wfMsgHtml( 'centralauth-admin-info-header' ) . '</legend>'; |
284 | | - foreach ( $attribs as $tag => $data ) { |
285 | | - $out .= '<p><strong>' . wfMsgHtml( "centralauth-admin-info-$tag" ) . '</strong> ' . |
286 | | - htmlspecialchars( $data ) . '</p>'; |
287 | | - } |
288 | | - $out .= '</fieldset>'; |
289 | | - $wgOut->addHTML( $out ); |
290 | | - } |
291 | | - |
292 | | - function showWikiLists() { |
293 | | - global $wgOut; |
294 | | - $merged = $this->mAttachedLocalAccounts; |
295 | | - $remainder = $this->mUnattachedLocalAccounts; |
296 | | - |
297 | | - $legend = $this->mCanUnmerge ? |
298 | | - wfMsgHtml( 'centralauth-admin-list-legend-rw' ) : |
299 | | - wfMsgHtml( 'centralauth-admin-list-legend-ro' ); |
300 | | - |
301 | | - $wgOut->addHTML( "<fieldset><legend>{$legend}</legend>" ); |
302 | | - $wgOut->addHTML( $this->listHeader() ); |
303 | | - $wgOut->addHTML( $this->listMerged( $merged ) ); |
304 | | - if ( $remainder ) |
305 | | - $wgOut->addHTML( $this->listRemainder( $remainder ) ); |
306 | | - $wgOut->addHTML( $this->listFooter() ); |
307 | | - $wgOut->addHTML( '</fieldset>' ); |
308 | | - } |
309 | | - |
310 | | - function listHeader() { |
311 | | - global $wgUser; |
312 | | - return |
313 | | - Xml::openElement( 'form', |
314 | | - array( |
315 | | - 'method' => 'post', |
316 | | - 'action' => |
317 | | - $this->getTitle( $this->mUserName )->getLocalUrl( 'action=submit' ), |
318 | | - 'id' => 'mw-centralauth-merged' ) ) . |
319 | | - Html::hidden( 'wpMethod', 'unmerge' ) . |
320 | | - Html::hidden( 'wpEditToken', $wgUser->editToken() ) . |
321 | | - Xml::openElement( 'table', array( 'class' => 'wikitable sortable mw-centralauth-wikislist' ) ) . "\n" . |
322 | | - '<thead><tr>' . |
323 | | - ( $this->mCanUnmerge ? '<th></th>' : '' ) . |
324 | | - '<th>' . wfMsgHtml( 'centralauth-admin-list-localwiki' ) . '</th>' . |
325 | | - '<th>' . wfMsgHtml( 'centralauth-admin-list-attached-on' ) . '</th>' . |
326 | | - '<th>' . wfMsgHtml( 'centralauth-admin-list-method' ) . '</th>' . |
327 | | - '<th>' . wfMsgHtml( 'centralauth-admin-list-blocked' ) . '</th>' . |
328 | | - '<th>' . wfMsgHtml( 'centralauth-admin-list-editcount' ) . '</th>' . |
329 | | - '</tr></thead>' . |
330 | | - '<tbody>'; |
331 | | - } |
332 | | - |
333 | | - function listFooter() { |
334 | | - $footer = ''; |
335 | | - if ( $this->mCanUnmerge ) |
336 | | - $footer .= |
337 | | - '<tr>' . |
338 | | - '<td style="border-right: none"></td>' . |
339 | | - '<td style="border-left: none" colspan="5">' . |
340 | | - Xml::submitButton( wfMsg( 'centralauth-admin-unmerge' ) ) . |
341 | | - '</td>' . |
342 | | - '</tr>'; |
343 | | - $footer .= '</tbody></table></form>'; |
344 | | - return $footer; |
345 | | - } |
346 | | - |
347 | | - function listMerged( $list ) { |
348 | | - ksort( $list ); |
349 | | - return implode( "\n", array_map( array( $this, 'listMergedWikiItem' ), $list ) ); |
350 | | - } |
351 | | - |
352 | | - function listRemainder( $list ) { |
353 | | - ksort( $list ); |
354 | | - $notMerged = wfMsgExt( 'centralauth-admin-unattached', array( 'parseinline' ) ); |
355 | | - $rows = array(); |
356 | | - foreach ( $list as $row ) { |
357 | | - $rows[] = '<tr class="unattached-row"><td>' . |
358 | | - ( $this->mCanUnmerge ? '</td><td>' : '' ) . |
359 | | - $this->foreignUserLink( $row['wiki'] ) . |
360 | | - "</td><td colspan='4'>{$notMerged}</td></tr>\n"; |
361 | | - } |
362 | | - return implode( $rows ); |
363 | | - } |
364 | | - |
365 | | - function listMergedWikiItem( $row ) { |
366 | | - global $wgLang; |
367 | | - return '<tr>' . |
368 | | - ( $this->mCanUnmerge ? '<td>' . $this->adminCheck( $row['wiki'] ) . '</td>' : '' ) . |
369 | | - '<td>' . $this->foreignUserLink( $row['wiki'] ) . '</td>' . |
370 | | - '<td>' . |
371 | | - // invisible, to make this column sortable |
372 | | - Html::element( 'span', array( 'style' => 'display: none' ), htmlspecialchars( $row['attachedTimestamp'] ) ) . |
373 | | - // visible date and time in users preference |
374 | | - htmlspecialchars( $wgLang->timeanddate( $row['attachedTimestamp'] ) ) . |
375 | | - '</td>' . |
376 | | - '<td style="text-align: center">' . $this->formatMergeMethod( $row['attachedMethod'] ) . '</td>' . |
377 | | - '<td>' . $this->formatBlockStatus( $row ) . '</td>' . |
378 | | - '<td style="text-align: right">' . $this->formatEditcount( $row ) . '</td>' . |
379 | | - '</tr>'; |
380 | | - } |
381 | | - |
382 | | - function formatMergeMethod( $method ) { |
383 | | - global $wgExtensionAssetsPath; |
384 | | - |
385 | | - $img = htmlspecialchars( "{$wgExtensionAssetsPath}/CentralAuth/icons/merged-{$method}.png" ); |
386 | | - $brief = wfMsgHtml( "centralauth-merge-method-{$method}" ); |
387 | | - return "<img src=\"{$img}\" alt=\"{$brief}\" title=\"{$brief}\"/>" . |
388 | | - "<span class=\"merge-method-help\" title=\"{$brief}\" onclick=\"showMethodHint('{$method}')\">(?)</span>"; |
389 | | - } |
390 | | - |
391 | | - function formatBlockStatus( $row ) { |
392 | | - if ( $row['blocked'] ) { |
393 | | - if ( $row['block-expiry'] == 'infinity' ) { |
394 | | - $reason = $row['block-reason']; |
395 | | - return wfMsgExt( 'centralauth-admin-blocked-indef', 'parseinline', array( $reason ) ); |
396 | | - } else { |
397 | | - global $wgLang; |
398 | | - $expiry = $wgLang->timeanddate( $row['block-expiry'] ); |
399 | | - $expiryd = $wgLang->date( $row['block-expiry'] ); |
400 | | - $expiryt = $wgLang->time( $row['block-expiry'] ); |
401 | | - $reason = $row['block-reason']; |
402 | | - |
403 | | - $text = wfMsgExt( 'centralauth-admin-blocked', 'parseinline', array( $expiry, $reason, $expiryd, $expiryt ) ); |
404 | | - } |
405 | | - } else { |
406 | | - $text = wfMsgExt( 'centralauth-admin-notblocked', 'parseinline' ); |
407 | | - } |
408 | | - |
409 | | - return $this->foreignLink( |
410 | | - $row['wiki'], |
411 | | - 'Special:Log/block', |
412 | | - $text, |
413 | | - wfMsg( 'centralauth-admin-blocklog' ), |
414 | | - 'page=User:' . urlencode( $this->mUserName ) ); |
415 | | - } |
416 | | - |
417 | | - function formatEditcount( $row ) { |
418 | | - global $wgLang; |
419 | | - return $this->foreignLink( |
420 | | - $row['wiki'], |
421 | | - 'Special:Contributions/' . $this->mUserName, |
422 | | - $wgLang->formatNum( intval( $row['editCount'] ) ), |
423 | | - 'contributions' ); |
424 | | - } |
425 | | - |
426 | | - function formatHiddenLevel( $level ) { |
427 | | - switch( $level ) { |
428 | | - case CentralAuthUser::HIDDEN_NONE: |
429 | | - return wfMsg( 'centralauth-admin-no' ); |
430 | | - case CentralAuthUser::HIDDEN_LISTS: |
431 | | - return wfMsg( 'centralauth-admin-hidden-list' ); |
432 | | - case CentralAuthUser::HIDDEN_OVERSIGHT: |
433 | | - return wfMsg( 'centralauth-admin-hidden-oversight' ); |
434 | | - } |
435 | | - } |
436 | | - |
437 | | - function tableRow( $element, $cols ) { |
438 | | - return "<tr><$element>" . |
439 | | - implode( "</$element><$element>", $cols ) . |
440 | | - "</$element></tr>"; |
441 | | - } |
442 | | - |
443 | | - function foreignLink( $wikiID, $title, $text, $hint = '', $params = '' ) { |
444 | | - if ( $wikiID instanceof WikiReference ) { |
445 | | - $wiki = $wikiID; |
446 | | - } else { |
447 | | - $wiki = WikiMap::getWiki( $wikiID ); |
448 | | - if ( !$wiki ) { |
449 | | - throw new MWException( "Invalid wiki: $wikiID" ); |
450 | | - } |
451 | | - } |
452 | | - |
453 | | - $url = $wiki->getUrl( $title ); |
454 | | - if ( $params ) |
455 | | - $url .= '?' . $params; |
456 | | - return Xml::element( 'a', |
457 | | - array( |
458 | | - 'href' => $url, |
459 | | - 'title' => $hint, |
460 | | - ), |
461 | | - $text ); |
462 | | - } |
463 | | - |
464 | | - function foreignUserLink( $wikiID ) { |
465 | | - $wiki = WikiMap::getWiki( $wikiID ); |
466 | | - if ( !$wiki ) { |
467 | | - throw new MWException( "Invalid wiki: $wikiID" ); |
468 | | - } |
469 | | - |
470 | | - $wikiname = $wiki->getDisplayName(); |
471 | | - return $this->foreignLink( |
472 | | - $wiki, |
473 | | - 'User:' . $this->mUserName, |
474 | | - $wikiname, |
475 | | - wfMsg( 'centralauth-foreign-link', $this->mUserName, $wikiname ) ); |
476 | | - |
477 | | - } |
478 | | - |
479 | | - function adminCheck( $wikiID ) { |
480 | | - return |
481 | | - Xml::check( 'wpWikis[]', false, array( 'value' => $wikiID ) ); |
482 | | - } |
483 | | - |
484 | | - function showActionForm( $action ) { |
485 | | - global $wgOut, $wgUser; |
486 | | - $wgOut->addHTML( |
487 | | - Xml::fieldset( wfMsg( "centralauth-admin-{$action}-title" ) ) . |
488 | | - Xml::openElement( 'form', array( |
489 | | - 'method' => 'POST', |
490 | | - 'action' => $this->getTitle()->getFullUrl( 'target=' . urlencode( $this->mUserName ) ), |
491 | | - 'id' => "mw-centralauth-$action" ) ) . |
492 | | - Html::hidden( 'wpMethod', $action ) . |
493 | | - Html::hidden( 'wpEditToken', $wgUser->editToken() ) . |
494 | | - wfMsgExt( "centralauth-admin-{$action}-description", 'parse' ) . |
495 | | - Xml::buildForm( |
496 | | - array( 'centralauth-admin-reason' => Xml::input( 'reason', |
497 | | - false, false, array( 'id' => "{$action}-reason" ) ) ), |
498 | | - "centralauth-admin-{$action}-button" |
499 | | - ) . |
500 | | - '</form></fieldset>' ); |
501 | | - } |
502 | | - |
503 | | - function showStatusForm() { |
504 | | - // Allows locking, hiding, locking and hiding. |
505 | | - global $wgUser, $wgOut; |
506 | | - $form = ''; |
507 | | - $form .= Xml::fieldset( wfMsg( 'centralauth-admin-status' ) ); |
508 | | - $form .= Html::hidden( 'wpMethod', 'set-status' ); |
509 | | - $form .= Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
510 | | - $form .= wfMsgExt( 'centralauth-admin-status-intro', 'parse' ); |
511 | | - |
512 | | - // Radio buttons |
513 | | - $radioLocked = |
514 | | - Xml::radioLabel( |
515 | | - wfMsgExt( 'centralauth-admin-status-locked-no', array( 'parseinline' ) ), |
516 | | - 'wpStatusLocked', |
517 | | - '0', |
518 | | - 'mw-centralauth-status-locked-no', |
519 | | - !$this->mGlobalUser->isLocked() ) . |
520 | | - '<br />' . |
521 | | - Xml::radioLabel( |
522 | | - wfMsgExt( 'centralauth-admin-status-locked-yes', array( 'parseinline' ) ), |
523 | | - 'wpStatusLocked', |
524 | | - '1', |
525 | | - 'mw-centralauth-status-locked-yes', |
526 | | - $this->mGlobalUser->isLocked() ); |
527 | | - $radioHidden = |
528 | | - Xml::radioLabel( |
529 | | - wfMsgExt( 'centralauth-admin-status-hidden-no', array( 'parseinline' ) ), |
530 | | - 'wpStatusHidden', |
531 | | - CentralAuthUser::HIDDEN_NONE, |
532 | | - 'mw-centralauth-status-hidden-no', |
533 | | - $this->mGlobalUser->getHiddenLevel() == CentralAuthUser::HIDDEN_NONE ) . |
534 | | - '<br />' . |
535 | | - Xml::radioLabel( |
536 | | - wfMsgExt( 'centralauth-admin-status-hidden-list', array( 'parseinline' ) ), |
537 | | - 'wpStatusHidden', |
538 | | - CentralAuthUser::HIDDEN_LISTS, |
539 | | - 'mw-centralauth-status-hidden-list', |
540 | | - $this->mGlobalUser->getHiddenLevel() == CentralAuthUser::HIDDEN_LISTS ) . |
541 | | - '<br />'; |
542 | | - if ( $this->mCanOversight ) { |
543 | | - $radioHidden .= Xml::radioLabel( |
544 | | - wfMsgExt( 'centralauth-admin-status-hidden-oversight', array( 'parseinline' ) ), |
545 | | - 'wpStatusHidden', |
546 | | - CentralAuthUser::HIDDEN_OVERSIGHT, |
547 | | - 'mw-centralauth-status-hidden-oversight', |
548 | | - $this->mGlobalUser->getHiddenLevel() == CentralAuthUser::HIDDEN_OVERSIGHT |
549 | | - ); |
550 | | - } |
551 | | - |
552 | | - // Reason |
553 | | - $reasonList = Xml::listDropDown( |
554 | | - 'wpReasonList', |
555 | | - wfMsgForContent( 'centralauth-admin-status-reasons' ), |
556 | | - wfMsgForContent( 'ipbreasonotherlist' ) |
557 | | - ); |
558 | | - $reasonField = Xml::input( 'wpReason', 45, false ); |
559 | | - |
560 | | - $form .= Xml::buildForm( |
561 | | - array( |
562 | | - 'centralauth-admin-status-locked' => $radioLocked, |
563 | | - 'centralauth-admin-status-hidden' => $radioHidden, |
564 | | - 'centralauth-admin-reason' => $reasonList, |
565 | | - 'centralauth-admin-reason-other' => $reasonField ), |
566 | | - 'centralauth-admin-status-submit' |
567 | | - ); |
568 | | - |
569 | | - $form .= '</fieldset>'; |
570 | | - $form = Xml::tags( |
571 | | - 'form', |
572 | | - array( |
573 | | - 'method' => 'POST', |
574 | | - 'action' => $this->getTitle()->getFullURL( |
575 | | - array( 'target' => $this->mUserName ) |
576 | | - ), |
577 | | - ), |
578 | | - $form |
579 | | - ); |
580 | | - $wgOut->addHTML( $form ); |
581 | | - } |
582 | | - |
583 | | - function showLogExtract() { |
584 | | - global $wgOut; |
585 | | - $user = $this->mGlobalUser->getName(); |
586 | | - $text = ''; |
587 | | - $numRows = LogEventsList::showLogExtract( |
588 | | - $text, |
589 | | - array( 'globalauth', 'suppress' ), |
590 | | - Title::newFromText( "User:{$user}@global" )->getPrefixedText(), |
591 | | - '', |
592 | | - array( 'showIfEmpty' => true ) ); |
593 | | - if ( $numRows ) { |
594 | | - $wgOut->addHTML( Xml::fieldset( wfMsg( 'centralauth-admin-logsnippet' ), $text ) ); |
595 | | - } |
596 | | - } |
597 | | - |
598 | | - function determineHomeWiki() { |
599 | | - foreach ( $this->mAttachedLocalAccounts as $wiki => $acc ) { |
600 | | - if ( $acc['attachedMethod'] == 'primary' || $acc['attachedMethod'] == 'new' ) { |
601 | | - return $wiki; |
602 | | - } |
603 | | - } |
604 | | - |
605 | | - // Home account can be renamed or unmerged |
606 | | - return wfMsgHtml( 'centralauth-admin-nohome' ); |
607 | | - } |
608 | | - |
609 | | - function evaluateTotalEditcount() { |
610 | | - $total = 0; |
611 | | - foreach ( $this->mAttachedLocalAccounts as $acc ) { |
612 | | - $total += $acc['editCount']; |
613 | | - } |
614 | | - return $total; |
615 | | - } |
616 | | - |
617 | | - function addMergeMethodDescriptions() { |
618 | | - global $wgOut, $wgLang; |
619 | | - $js = "wgMergeMethodDescriptions = {\n"; |
620 | | - foreach ( array( 'primary', 'new', 'empty', 'password', 'mail', 'admin', 'login' ) as $method ) { |
621 | | - $short = Xml::encodeJsVar( $wgLang->ucfirst( wfMsgHtml( "centralauth-merge-method-{$method}" ) ) ); |
622 | | - $desc = Xml::encodeJsVar( wfMsgWikiHtml( "centralauth-merge-method-{$method}-desc" ) ); |
623 | | - $js .= "\t'{$method}' : { 'short' : {$short}, 'desc' : {$desc} },\n"; |
624 | | - } |
625 | | - $js .= "}"; |
626 | | - $wgOut->addInlineScript( $js ); |
627 | | - } |
628 | | - |
629 | | - function logAction( $action, $target, $reason = '', $params = array(), $suppressLog = false ) { |
630 | | - $logType = $suppressLog ? 'suppress' : 'globalauth'; // Not centralauth because of some weird length limitiations |
631 | | - $log = new LogPage( $logType ); |
632 | | - $log->addEntry( $action, Title::newFromText( "User:{$target}@global" ), $reason, $params ); |
633 | | - } |
634 | | -} |
Index: trunk/extensions/CentralAuth/SpecialMergeAccount.php |
— | — | @@ -1,518 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -class SpecialMergeAccount extends SpecialPage { |
5 | | - function __construct() { |
6 | | - parent::__construct( 'MergeAccount', 'centralauth-merge' ); |
7 | | - } |
8 | | - |
9 | | - function execute( $subpage ) { |
10 | | - global $wgOut, $wgUser; |
11 | | - $this->setHeaders(); |
12 | | - |
13 | | - if ( !$this->userCanExecute( $wgUser ) ) { |
14 | | - $wgOut->addWikiMsg( 'centralauth-merge-denied' ); |
15 | | - $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
16 | | - return; |
17 | | - } |
18 | | - |
19 | | - if ( !$wgUser->isLoggedIn() ) { |
20 | | - $wgOut->addWikiMsg( 'centralauth-merge-notlogged' ); |
21 | | - $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
22 | | - |
23 | | - return; |
24 | | - } |
25 | | - |
26 | | - if ( wfReadOnly() ) { |
27 | | - $wgOut->setPagetitle( wfMsg( 'readonly' ) ); |
28 | | - $wgOut->addWikiMsg( 'readonlytext', wfReadOnlyReason() ); |
29 | | - return; |
30 | | - } |
31 | | - |
32 | | - global $wgUser, $wgRequest; |
33 | | - $this->mUserName = $wgUser->getName(); |
34 | | - |
35 | | - $this->mAttemptMerge = $wgRequest->wasPosted(); |
36 | | - |
37 | | - $this->mMergeAction = $wgRequest->getVal( 'wpMergeAction' ); |
38 | | - $this->mPassword = $wgRequest->getVal( 'wpPassword' ); |
39 | | - $this->mWikiIDs = $wgRequest->getArray( 'wpWikis' ); |
40 | | - $this->mSessionToken = $wgRequest->getVal( 'wpMergeSessionToken' ); |
41 | | - $this->mSessionKey = pack( "H*", $wgRequest->getVal( 'wpMergeSessionKey' ) ); |
42 | | - |
43 | | - // Possible demo states |
44 | | - |
45 | | - // success, all accounts merged |
46 | | - // successful login, some accounts merged, others left |
47 | | - // successful login, others left |
48 | | - // not account owner, others left |
49 | | - |
50 | | - // is owner / is not owner |
51 | | - // did / did not merge some accounts |
52 | | - // do / don't have more accounts to merge |
53 | | - |
54 | | - if ( $this->mAttemptMerge ) { |
55 | | - switch( $this->mMergeAction ) { |
56 | | - case "dryrun": |
57 | | - return $this->doDryRunMerge(); |
58 | | - case "initial": |
59 | | - return $this->doInitialMerge(); |
60 | | - case "cleanup": |
61 | | - return $this->doCleanupMerge(); |
62 | | - case "attach": |
63 | | - return $this->doAttachMerge(); |
64 | | - case "remove": |
65 | | - return $this->doUnattach(); |
66 | | - default: |
67 | | - return $this->invalidAction(); |
68 | | - } |
69 | | - } |
70 | | - |
71 | | - $globalUser = new CentralAuthUser( $this->mUserName ); |
72 | | - if ( $globalUser->exists() ) { |
73 | | - if ( $globalUser->isAttached() ) { |
74 | | - $this->showCleanupForm(); |
75 | | - } else { |
76 | | - $this->showAttachForm(); |
77 | | - } |
78 | | - } else { |
79 | | - $this->showWelcomeForm(); |
80 | | - } |
81 | | - } |
82 | | - |
83 | | - /** |
84 | | - * To pass potentially multiple passwords from one form submission |
85 | | - * to another while previewing the merge behavior, we can store them |
86 | | - * in the server-side session information. |
87 | | - * |
88 | | - * We'd rather not have plaintext passwords floating about on disk |
89 | | - * or memcached, so the session store is obfuscated with simple XOR |
90 | | - * encryption. The key is passed in the form instead of the session |
91 | | - * data, so they won't be found floating in the same place. |
92 | | - */ |
93 | | - private function initSession() { |
94 | | - global $wgUser; |
95 | | - $this->mSessionToken = $wgUser->generateToken(); |
96 | | - |
97 | | - // Generate a random binary string |
98 | | - $key = ''; |
99 | | - for ( $i = 0; $i < 128; $i++ ) { |
100 | | - $key .= chr( mt_rand( 0, 255 ) ); |
101 | | - } |
102 | | - $this->mSessionKey = $key; |
103 | | - } |
104 | | - |
105 | | - private function getWorkingPasswords() { |
106 | | - wfSuppressWarnings(); |
107 | | - $passwords = unserialize( |
108 | | - gzinflate( |
109 | | - $this->xorString( |
110 | | - $_SESSION['wsCentralAuthMigration'][$this->mSessionToken], |
111 | | - $this->mSessionKey ) ) ); |
112 | | - wfRestoreWarnings(); |
113 | | - if ( is_array( $passwords ) ) { |
114 | | - return $passwords; |
115 | | - } |
116 | | - return array(); |
117 | | - } |
118 | | - |
119 | | - private function addWorkingPassword( $password ) { |
120 | | - $passwords = $this->getWorkingPasswords(); |
121 | | - if ( !in_array( $password, $passwords ) ) { |
122 | | - $passwords[] = $password; |
123 | | - } |
124 | | - |
125 | | - // Lightly obfuscate the passwords while we're storing them, |
126 | | - // just to make us feel better about them floating around. |
127 | | - $_SESSION['wsCentralAuthMigration'][$this->mSessionToken] = |
128 | | - $this->xorString( |
129 | | - gzdeflate( |
130 | | - serialize( |
131 | | - $passwords ) ), |
132 | | - $this->mSessionKey ); |
133 | | - } |
134 | | - |
135 | | - private function clearWorkingPasswords() { |
136 | | - unset( $_SESSION['wsCentralAuthMigration'][$this->mSessionToken] ); |
137 | | - } |
138 | | - |
139 | | - function xorString( $text, $key ) { |
140 | | - if ( $key != '' ) { |
141 | | - for ( $i = 0; $i < strlen( $text ); $i++ ) { |
142 | | - $text[$i] = chr( 0xff & ( ord( $text[$i] ) ^ ord( $key[$i % strlen( $key )] ) ) ); |
143 | | - } |
144 | | - } |
145 | | - return $text; |
146 | | - } |
147 | | - |
148 | | - function doDryRunMerge() { |
149 | | - global $wgUser, $wgRequest, $wgOut, $wgCentralAuthDryRun; |
150 | | - $globalUser = new CentralAuthUser( $wgUser->getName() ); |
151 | | - |
152 | | - if ( $globalUser->exists() ) { |
153 | | - throw new MWException( "Already exists -- race condition" ); |
154 | | - } |
155 | | - |
156 | | - if ( $wgCentralAuthDryRun ) { |
157 | | - $wgOut->addWikiMsg( 'centralauth-notice-dryrun' ); |
158 | | - } |
159 | | - |
160 | | - $password = $wgRequest->getVal( 'wpPassword' ); |
161 | | - $this->addWorkingPassword( $password ); |
162 | | - $passwords = $this->getWorkingPasswords(); |
163 | | - |
164 | | - $home = false; |
165 | | - $attached = array(); |
166 | | - $unattached = array(); |
167 | | - $methods = array(); |
168 | | - $status = $globalUser->migrationDryRun( $passwords, $home, $attached, $unattached, $methods ); |
169 | | - |
170 | | - if ( $status->isGood() ) { |
171 | | - // This is the global account or matched it |
172 | | - if ( count( $unattached ) == 0 ) { |
173 | | - // Everything matched -- very convenient! |
174 | | - $wgOut->addWikiMsg( 'centralauth-merge-dryrun-complete' ); |
175 | | - } else { |
176 | | - $wgOut->addWikiMsg( 'centralauth-merge-dryrun-incomplete' ); |
177 | | - } |
178 | | - |
179 | | - if ( count( $unattached ) > 0 ) { |
180 | | - $wgOut->addHTML( $this->step2PasswordForm( $unattached ) ); |
181 | | - $wgOut->addWikiMsg( 'centralauth-merge-dryrun-or' ); |
182 | | - } |
183 | | - |
184 | | - $subAttached = array_diff( $attached, array( $home ) ); |
185 | | - $wgOut->addHTML( $this->step3ActionForm( $home, $subAttached, $methods ) ); |
186 | | - } else { |
187 | | - // Show error message from status |
188 | | - $wgOut->addHTML( '<div class="errorbox" style="float:none;">' ); |
189 | | - $wgOut->addWikiText( $status->getWikiText() ); |
190 | | - $wgOut->addHTML( '</div>' ); |
191 | | - |
192 | | - // Show wiki list if required |
193 | | - if ( $status->hasMessage( 'centralauth-blocked-text' ) |
194 | | - || $status->hasMessage( 'centralauth-merge-home-password' ) ) |
195 | | - { |
196 | | - $out = '<h2>' . wfMsgHtml( 'centralauth-list-home-title' ) . '</h2>'; |
197 | | - $out .= wfMsgExt( 'centralauth-list-home-dryrun', 'parse' ); |
198 | | - $out .= $this->listAttached( array( $home ), array( $home => 'primary' ) ); |
199 | | - $wgOut->addHTML( $out ); |
200 | | - } |
201 | | - |
202 | | - // Show password box |
203 | | - $wgOut->addHTML( $this->step1PasswordForm() ); |
204 | | - } |
205 | | - } |
206 | | - |
207 | | - function doInitialMerge() { |
208 | | - global $wgUser, $wgCentralAuthDryRun; |
209 | | - $globalUser = new CentralAuthUser( $wgUser->getName() ); |
210 | | - |
211 | | - if ( $wgCentralAuthDryRun ) { |
212 | | - return $this->dryRunError(); |
213 | | - } |
214 | | - |
215 | | - if ( $globalUser->exists() ) { |
216 | | - throw new MWException( "Already exists -- race condition" ); |
217 | | - } |
218 | | - |
219 | | - $passwords = $this->getWorkingPasswords(); |
220 | | - if ( empty( $passwords ) ) { |
221 | | - throw new MWException( "Submission error -- invalid input" ); |
222 | | - } |
223 | | - |
224 | | - $globalUser->storeAndMigrate( $passwords ); |
225 | | - $this->clearWorkingPasswords(); |
226 | | - |
227 | | - $this->showCleanupForm(); |
228 | | - } |
229 | | - |
230 | | - function doCleanupMerge() { |
231 | | - global $wgUser, $wgRequest, $wgOut, $wgCentralAuthDryRun; |
232 | | - $globalUser = new CentralAuthUser( $wgUser->getName() ); |
233 | | - |
234 | | - if ( !$globalUser->exists() ) { |
235 | | - throw new MWException( "User doesn't exist -- race condition?" ); |
236 | | - } |
237 | | - |
238 | | - if ( !$globalUser->isAttached() ) { |
239 | | - throw new MWException( "Can't cleanup merge if not already attached." ); |
240 | | - } |
241 | | - |
242 | | - if ( $wgCentralAuthDryRun ) { |
243 | | - return $this->dryRunError(); |
244 | | - } |
245 | | - $password = $wgRequest->getText( 'wpPassword' ); |
246 | | - |
247 | | - $attached = array(); |
248 | | - $unattached = array(); |
249 | | - $ok = $globalUser->attemptPasswordMigration( $password, $attached, $unattached ); |
250 | | - $this->clearWorkingPasswords(); |
251 | | - |
252 | | - if ( !$ok ) { |
253 | | - if ( empty( $attached ) ) { |
254 | | - $wgOut->addWikiMsg( 'centralauth-finish-noconfirms' ); |
255 | | - } else { |
256 | | - $wgOut->addWikiMsg( 'centralauth-finish-incomplete' ); |
257 | | - } |
258 | | - } |
259 | | - $this->showCleanupForm(); |
260 | | - } |
261 | | - |
262 | | - function doAttachMerge() { |
263 | | - global $wgUser, $wgRequest, $wgOut, $wgCentralAuthDryRun; |
264 | | - $globalUser = new CentralAuthUser( $wgUser->getName() ); |
265 | | - |
266 | | - if ( !$globalUser->exists() ) { |
267 | | - throw new MWException( "User doesn't exist -- race condition?" ); |
268 | | - } |
269 | | - |
270 | | - if ( $globalUser->isAttached() ) { |
271 | | - throw new MWException( "Already attached -- race condition?" ); |
272 | | - } |
273 | | - |
274 | | - if ( $wgCentralAuthDryRun ) { |
275 | | - return $this->dryRunError(); |
276 | | - } |
277 | | - $password = $wgRequest->getText( 'wpPassword' ); |
278 | | - if ( $globalUser->authenticate( $password ) == 'ok' ) { |
279 | | - $globalUser->attach( wfWikiID(), 'password' ); |
280 | | - $wgOut->addWikiMsg( 'centralauth-attach-success' ); |
281 | | - $this->showCleanupForm(); |
282 | | - } else { |
283 | | - $wgOut->addHTML( |
284 | | - '<div class="errorbox">' . |
285 | | - wfMsg( 'wrongpassword' ) . |
286 | | - '</div>' . |
287 | | - $this->attachActionForm() ); |
288 | | - } |
289 | | - } |
290 | | - |
291 | | - private function showWelcomeForm() { |
292 | | - global $wgOut, $wgCentralAuthDryRun; |
293 | | - |
294 | | - if ( $wgCentralAuthDryRun ) { |
295 | | - $wgOut->addWikiMsg( 'centralauth-notice-dryrun' ); |
296 | | - } |
297 | | - |
298 | | - $wgOut->addWikiMsg( 'centralauth-merge-welcome' ); |
299 | | - $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
300 | | - |
301 | | - $this->initSession(); |
302 | | - $wgOut->addHTML( |
303 | | - $this->passwordForm( |
304 | | - 'dryrun', |
305 | | - wfMsg( 'centralauth-merge-step1-title' ), |
306 | | - wfMsg( 'centralauth-merge-step1-detail' ), |
307 | | - wfMsg( 'centralauth-merge-step1-submit' ) ) |
308 | | - ); |
309 | | - } |
310 | | - |
311 | | - function showCleanupForm() { |
312 | | - global $wgUser; |
313 | | - $globalUser = new CentralAuthUser( $wgUser->getName() ); |
314 | | - |
315 | | - $merged = $globalUser->listAttached(); |
316 | | - $remainder = $globalUser->listUnattached(); |
317 | | - $this->showStatus( $merged, $remainder ); |
318 | | - } |
319 | | - |
320 | | - function showAttachForm() { |
321 | | - global $wgOut, $wgUser; |
322 | | - $globalUser = new CentralAuthUser( $wgUser->getName() ); |
323 | | - $merged = $globalUser->listAttached(); |
324 | | - $wgOut->addWikiMsg( 'centralauth-attach-list-attached', $this->mUserName ); |
325 | | - $wgOut->addHTML( $this->listAttached( $merged ) ); |
326 | | - $wgOut->addHTML( $this->attachActionForm() ); |
327 | | - } |
328 | | - |
329 | | - function showStatus( $merged, $remainder ) { |
330 | | - global $wgOut; |
331 | | - |
332 | | - if ( count( $remainder ) > 0 ) { |
333 | | - $wgOut->setPageTitle( wfMsg( 'centralauth-incomplete' ) ); |
334 | | - $wgOut->addWikiMsg( 'centralauth-incomplete-text' ); |
335 | | - } else { |
336 | | - $wgOut->setPageTitle( wfMsg( 'centralauth-complete' ) ); |
337 | | - $wgOut->addWikiMsg( 'centralauth-complete-text' ); |
338 | | - } |
339 | | - $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
340 | | - |
341 | | - if ( $merged ) { |
342 | | - $wgOut->addHTML( '<hr />' ); |
343 | | - $wgOut->addWikiMsg( 'centralauth-list-attached', |
344 | | - $this->mUserName ); |
345 | | - $wgOut->addHTML( $this->listAttached( $merged ) ); |
346 | | - } |
347 | | - |
348 | | - if ( $remainder ) { |
349 | | - $wgOut->addHTML( '<hr />' ); |
350 | | - $wgOut->addWikiMsg( 'centralauth-list-unattached', |
351 | | - $this->mUserName ); |
352 | | - $wgOut->addHTML( $this->listUnattached( $remainder ) ); |
353 | | - |
354 | | - // Try the password form! |
355 | | - $wgOut->addHTML( $this->passwordForm( |
356 | | - 'cleanup', |
357 | | - wfMsg( 'centralauth-finish-title' ), |
358 | | - wfMsgExt( 'centralauth-finish-text', array( 'parse' ) ), |
359 | | - wfMsg( 'centralauth-finish-login' ) ) ); |
360 | | - } |
361 | | - } |
362 | | - |
363 | | - function listAttached( $wikiList, $methods = array() ) { |
364 | | - return $this->listWikis( $wikiList, $methods ); |
365 | | - } |
366 | | - |
367 | | - function listUnattached( $wikiList ) { |
368 | | - return $this->listWikis( $wikiList ); |
369 | | - } |
370 | | - |
371 | | - function listWikis( $list, $methods = array() ) { |
372 | | - asort( $list ); |
373 | | - return $this->formatList( $list, $methods, array( $this, 'listWikiItem' ) ); |
374 | | - } |
375 | | - |
376 | | - function formatList( $items, $methods, $callback ) { |
377 | | - if ( !$items ) { |
378 | | - return ''; |
379 | | - } else { |
380 | | - $itemMethods = array(); |
381 | | - foreach ( $items as $item ) { |
382 | | - $itemMethods[] = isset( $methods[$item] ) ? $methods[$item] : ''; |
383 | | - } |
384 | | - return "<ul>\n<li>" . |
385 | | - implode( "</li>\n<li>", |
386 | | - array_map( $callback, $items, $itemMethods ) ) . |
387 | | - "</li>\n</ul>\n"; |
388 | | - } |
389 | | - } |
390 | | - |
391 | | - function listWikiItem( $wikiID, $method ) { |
392 | | - return |
393 | | - $this->foreignUserLink( $wikiID ) . ( $method ? ' (' . wfMsgHtml( "centralauth-merge-method-$method" ) . ')' : '' ); |
394 | | - } |
395 | | - |
396 | | - function foreignUserLink( $wikiID ) { |
397 | | - $wiki = WikiMap::getWiki( $wikiID ); |
398 | | - if ( !$wiki ) { |
399 | | - throw new MWException( "no wiki for $wikiID" ); |
400 | | - } |
401 | | - |
402 | | - $hostname = $wiki->getDisplayName(); |
403 | | - $userPageName = 'User:' . $this->mUserName; |
404 | | - $url = $wiki->getUrl( $userPageName ); |
405 | | - return Xml::element( 'a', |
406 | | - array( |
407 | | - 'href' => $url, |
408 | | - 'title' => wfMsg( 'centralauth-foreign-link', |
409 | | - $this->mUserName, |
410 | | - $hostname ), |
411 | | - ), |
412 | | - $hostname ); |
413 | | - } |
414 | | - |
415 | | - private function actionForm( $action, $title, $text ) { |
416 | | - global $wgUser; |
417 | | - return |
418 | | - '<div id="userloginForm">' . |
419 | | - Xml::openElement( 'form', |
420 | | - array( |
421 | | - 'method' => 'post', |
422 | | - 'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) ) . |
423 | | - Xml::element( 'h2', array(), $title ) . |
424 | | - Html::hidden( 'wpEditToken', $wgUser->editToken() ) . |
425 | | - Html::hidden( 'wpMergeAction', $action ) . |
426 | | - Html::hidden( 'wpMergeSessionToken', $this->mSessionToken ) . |
427 | | - Html::hidden( 'wpMergeSessionKey', bin2hex( $this->mSessionKey ) ) . |
428 | | - |
429 | | - $text . |
430 | | - |
431 | | - Xml::closeElement( 'form' ) . |
432 | | - |
433 | | - '<br clear="all" />' . |
434 | | - |
435 | | - '</div>'; |
436 | | - } |
437 | | - |
438 | | - private function passwordForm( $action, $title, $text, $submit ) { |
439 | | - return $this->actionForm( |
440 | | - $action, |
441 | | - $title, |
442 | | - $text . |
443 | | - '<table>' . |
444 | | - '<tr>' . |
445 | | - '<td>' . |
446 | | - Xml::label( |
447 | | - wfMsg( 'centralauth-finish-password' ), |
448 | | - 'wpPassword1' ) . |
449 | | - '</td>' . |
450 | | - '<td>' . |
451 | | - Xml::input( |
452 | | - 'wpPassword', 20, '', |
453 | | - array( |
454 | | - 'type' => 'password', |
455 | | - 'id' => 'wpPassword1' ) ) . |
456 | | - '</td>' . |
457 | | - '</tr>' . |
458 | | - '<tr>' . |
459 | | - '<td></td>' . |
460 | | - '<td>' . |
461 | | - Xml::submitButton( $submit, |
462 | | - array( 'name' => 'wpLogin' ) ) . |
463 | | - '</td>' . |
464 | | - '</tr>' . |
465 | | - '</table>' ); |
466 | | - } |
467 | | - |
468 | | - private function step1PasswordForm() { |
469 | | - return $this->passwordForm( |
470 | | - 'dryrun', |
471 | | - wfMsg( 'centralauth-merge-step1-title' ), |
472 | | - wfMsg( 'centralauth-merge-step1-detail' ), |
473 | | - wfMsg( 'centralauth-merge-step1-submit' ) ); |
474 | | - } |
475 | | - |
476 | | - private function step2PasswordForm( $unattached ) { |
477 | | - global $wgUser; |
478 | | - return $this->passwordForm( |
479 | | - 'dryrun', |
480 | | - wfMsg( 'centralauth-merge-step2-title' ), |
481 | | - wfMsgExt( 'centralauth-merge-step2-detail', 'parse', $wgUser->getName() ) . |
482 | | - $this->listUnattached( $unattached ), |
483 | | - wfMsg( 'centralauth-merge-step2-submit' ) ); |
484 | | - } |
485 | | - |
486 | | - private function step3ActionForm( $home, $attached, $methods ) { |
487 | | - global $wgUser; |
488 | | - return $this->actionForm( |
489 | | - 'initial', |
490 | | - wfMsg( 'centralauth-merge-step3-title' ), |
491 | | - wfMsgExt( 'centralauth-merge-step3-detail', 'parse', $wgUser->getName() ) . |
492 | | - '<h3>' . wfMsgHtml( 'centralauth-list-home-title' ) . '</h3>' . |
493 | | - wfMsgExt( 'centralauth-list-home-dryrun', 'parse' ) . |
494 | | - $this->listAttached( array( $home ), $methods ) . |
495 | | - ( count( $attached ) |
496 | | - ? ( '<h3>' . wfMsgHtml( 'centralauth-list-attached-title' ) . '</h3>' . |
497 | | - wfMsgExt( 'centralauth-list-attached-dryrun', 'parse', $wgUser->getName() ) ) |
498 | | - : '' ) . |
499 | | - $this->listAttached( $attached, $methods ) . |
500 | | - '<p>' . |
501 | | - Xml::submitButton( wfMsg( 'centralauth-merge-step3-submit' ), |
502 | | - array( 'name' => 'wpLogin' ) ) . |
503 | | - '</p>' |
504 | | - ); |
505 | | - } |
506 | | - |
507 | | - private function attachActionForm() { |
508 | | - return $this->passwordForm( |
509 | | - 'attach', |
510 | | - wfMsg( 'centralauth-attach-title' ), |
511 | | - wfMsg( 'centralauth-attach-text' ), |
512 | | - wfMsg( 'centralauth-attach-submit' ) ); |
513 | | - } |
514 | | - |
515 | | - private function dryRunError() { |
516 | | - global $wgOut; |
517 | | - $wgOut->addWikiMsg( 'centralauth-disabled-dryrun' ); |
518 | | - } |
519 | | -} |
Index: trunk/extensions/CentralAuth/SpecialGlobalUsers.php |
— | — | @@ -1,155 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -class SpecialGlobalUsers extends SpecialPage { |
5 | | - function __construct() { |
6 | | - parent::__construct( 'GlobalUsers' ); |
7 | | - } |
8 | | - |
9 | | - function execute( $par ) { |
10 | | - global $wgOut, $wgRequest, $wgContLang; |
11 | | - $this->setHeaders(); |
12 | | - |
13 | | - $pg = new GlobalUsersPager(); |
14 | | - |
15 | | - if ( $par ) { |
16 | | - $pg->setGroup( $par ); |
17 | | - } |
18 | | - $rqGroup = $wgRequest->getVal( 'group' ); |
19 | | - if ( $rqGroup ) { |
20 | | - $pg->setGroup( $rqGroup ); |
21 | | - } |
22 | | - $rqUsername = $wgContLang->ucfirst( $wgRequest->getVal( 'username' ) ); |
23 | | - if ( $rqUsername ) { |
24 | | - $pg->setUsername( $rqUsername ); |
25 | | - } |
26 | | - |
27 | | - $wgOut->addHTML( $pg->getPageHeader() ); |
28 | | - $wgOut->addHTML( $pg->getNavigationBar() ); |
29 | | - $wgOut->addHTML( '<ul>' . $pg->getBody() . '</ul>' ); |
30 | | - $wgOut->addHTML( $pg->getNavigationBar() ); |
31 | | - } |
32 | | -} |
33 | | - |
34 | | -class GlobalUsersPager extends UsersPager { |
35 | | - protected $requestedGroup = false, $requestedUser; |
36 | | - |
37 | | - function __construct() { |
38 | | - parent::__construct(); |
39 | | - $this->mDb = CentralAuthUser::getCentralSlaveDB(); |
40 | | - } |
41 | | - |
42 | | - function setGroup( $group = '' ) { |
43 | | - if ( !$group ) { |
44 | | - $this->requestedGroup = false; |
45 | | - return; |
46 | | - } |
47 | | - $groups = array_keys( $this->getAllGroups() ); |
48 | | - $this->requestedGroup = $group; |
49 | | - } |
50 | | - |
51 | | - function setUsername( $username = '' ) { |
52 | | - if ( !$username ) { |
53 | | - $this->requestedUser = false; |
54 | | - return; |
55 | | - } |
56 | | - $this->requestedUser = $username; |
57 | | - } |
58 | | - |
59 | | - function getIndexField() { |
60 | | - return 'gu_name'; |
61 | | - } |
62 | | - |
63 | | - function getDefaultQuery() { |
64 | | - $query = parent::getDefaultQuery(); |
65 | | - if ( !isset( $query['group'] ) && $this->requestedGroup ) { |
66 | | - $query['group'] = $this->requestedGroup; |
67 | | - } |
68 | | - return $this->mDefaultQuery = $query; |
69 | | - |
70 | | - } |
71 | | - |
72 | | - function getQueryInfo() { |
73 | | - $localwiki = wfWikiID(); |
74 | | - $conds = array( 'gu_hidden' => CentralAuthUser::HIDDEN_NONE ); |
75 | | - |
76 | | - if ( $this->requestedGroup ) { |
77 | | - $conds['gug_group'] = $this->requestedGroup; |
78 | | - } |
79 | | - |
80 | | - if ( $this->requestedUser ) { |
81 | | - $conds[] = 'gu_name >= ' . $this->mDb->addQuotes( $this->requestedUser ); |
82 | | - } |
83 | | - |
84 | | - return array( |
85 | | - 'tables' => " (globaluser LEFT JOIN localuser ON gu_name = lu_name AND lu_wiki = '{$localwiki}') LEFT JOIN global_user_groups ON gu_id = gug_user ", |
86 | | - 'fields' => array( 'gu_id', 'gu_name', 'gu_locked', 'lu_attached_method', 'COUNT(gug_group) AS gug_numgroups', 'MAX(gug_group) AS gug_singlegroup' ), |
87 | | - 'conds' => $conds, |
88 | | - 'options' => array( 'GROUP BY' => 'gu_name' ), |
89 | | - ); |
90 | | - } |
91 | | - |
92 | | - /** |
93 | | - * Formats a row |
94 | | - * @param object $row The row to be formatted for output |
95 | | - * @return string HTML li element with username and info about this user |
96 | | - */ |
97 | | - function formatRow( $row ) { |
98 | | - global $wgLang; |
99 | | - $user = htmlspecialchars( $row->gu_name ); |
100 | | - $info = array(); |
101 | | - if ( $row->gu_locked ) { |
102 | | - $info[] = wfMsg( 'centralauth-listusers-locked' ); |
103 | | - } |
104 | | - if ( $row->lu_attached_method ) { |
105 | | - $info[] = wfMsg( 'centralauth-listusers-attached', $row->gu_name ); |
106 | | - } else { |
107 | | - $info[] = wfMsg( 'centralauth-listusers-nolocal' ); |
108 | | - } |
109 | | - $groups = $this->getUserGroups( $row ); |
110 | | - |
111 | | - if ( $groups ) { |
112 | | - $info[] = $groups; |
113 | | - } |
114 | | - $info = $wgLang->commaList( $info ); |
115 | | - return Html::rawElement( 'li', array(), wfMsgExt( 'centralauth-listusers-item', array('parseinline'), $user, $info ) ); |
116 | | - } |
117 | | - |
118 | | - function getBody() { |
119 | | - if ( !$this->mQueryDone ) { |
120 | | - $this->doQuery(); |
121 | | - } |
122 | | - $batch = new LinkBatch; |
123 | | - |
124 | | - $this->mResult->rewind(); |
125 | | - |
126 | | - foreach ( $this->mResult as $row ) { |
127 | | - $batch->addObj( Title::makeTitleSafe( NS_USER, $row->gu_name ) ); |
128 | | - } |
129 | | - $batch->execute(); |
130 | | - $this->mResult->rewind(); |
131 | | - return AlphabeticPager::getBody(); |
132 | | - } |
133 | | - |
134 | | - protected function getUserGroups( $row ) { |
135 | | - if ( !$row->gug_numgroups ) { |
136 | | - return false; |
137 | | - } |
138 | | - if ( $row->gug_numgroups == 1 ) { |
139 | | - return User::makeGroupLinkWiki( $row->gug_singlegroup, User::getGroupMember( $row->gug_singlegroup ) ); |
140 | | - } |
141 | | - $result = $this->mDb->select( 'global_user_groups', 'gug_group', array( 'gug_user' => $row->gu_id ), __METHOD__ ); |
142 | | - $rights = array(); |
143 | | - foreach ( $result as $row2 ) { |
144 | | - $rights[] = User::makeGroupLinkWiki( $row2->gug_group, User::getGroupMember( $row2->gug_group ) ); |
145 | | - } |
146 | | - return implode( ', ', $rights ); |
147 | | - } |
148 | | - |
149 | | - public function getAllGroups() { |
150 | | - $result = array(); |
151 | | - foreach ( CentralAuthUser::availableGlobalGroups() as $group ) { |
152 | | - $result[$group] = User::getGroupName( $group ); |
153 | | - } |
154 | | - return $result; |
155 | | - } |
156 | | -} |
Index: trunk/extensions/CentralAuth/CentralAuth.php |
— | — | @@ -145,21 +145,21 @@ |
146 | 146 | * Initialization of the autoloaders, and special extension pages. |
147 | 147 | */ |
148 | 148 | $caBase = dirname( __FILE__ ); |
149 | | -$wgAutoloadClasses['SpecialCentralAuth'] = "$caBase/SpecialCentralAuth.php"; |
150 | | -$wgAutoloadClasses['SpecialMergeAccount'] = "$caBase/SpecialMergeAccount.php"; |
151 | | -$wgAutoloadClasses['SpecialGlobalUsers'] = "$caBase/SpecialGlobalUsers.php"; |
| 149 | +$wgAutoloadClasses['SpecialCentralAuth'] = "$caBase/specials/SpecialCentralAuth.php"; |
| 150 | +$wgAutoloadClasses['SpecialMergeAccount'] = "$caBase/specials/SpecialMergeAccount.php"; |
| 151 | +$wgAutoloadClasses['SpecialGlobalUsers'] = "$caBase/specials/SpecialGlobalUsers.php"; |
152 | 152 | $wgAutoloadClasses['CentralAuthUser'] = "$caBase/CentralAuthUser.php"; |
153 | 153 | $wgAutoloadClasses['CentralAuthPlugin'] = "$caBase/CentralAuthPlugin.php"; |
154 | 154 | $wgAutoloadClasses['CentralAuthHooks'] = "$caBase/CentralAuthHooks.php"; |
155 | 155 | $wgAutoloadClasses['CentralAuthSuppressUserJob'] = "$caBase/SuppressUserJob.php"; |
156 | 156 | $wgAutoloadClasses['WikiSet'] = "$caBase/WikiSet.php"; |
157 | | -$wgAutoloadClasses['SpecialAutoLogin'] = "$caBase/SpecialAutoLogin.php"; |
| 157 | +$wgAutoloadClasses['SpecialAutoLogin'] = "$caBase/specials/SpecialAutoLogin.php"; |
158 | 158 | $wgAutoloadClasses['CentralAuthUserArray'] = "$caBase/CentralAuthUserArray.php"; |
159 | 159 | $wgAutoloadClasses['CentralAuthUserArrayFromResult'] = "$caBase/CentralAuthUserArray.php"; |
160 | | -$wgAutoloadClasses['SpecialGlobalGroupMembership'] = "$caBase/SpecialGlobalGroupMembership.php"; |
| 160 | +$wgAutoloadClasses['SpecialGlobalGroupMembership'] = "$caBase/specials/SpecialGlobalGroupMembership.php"; |
161 | 161 | $wgAutoloadClasses['CentralAuthGroupMembershipProxy'] = "$caBase/CentralAuthGroupMembershipProxy.php"; |
162 | | -$wgAutoloadClasses['SpecialGlobalGroupPermissions'] = "$caBase/SpecialGlobalGroupPermissions.php"; |
163 | | -$wgAutoloadClasses['SpecialWikiSets'] = "$caBase/SpecialWikiSets.php"; |
| 162 | +$wgAutoloadClasses['SpecialGlobalGroupPermissions'] = "$caBase/specials/SpecialGlobalGroupPermissions.php"; |
| 163 | +$wgAutoloadClasses['SpecialWikiSets'] = "$caBase/specials/SpecialWikiSets.php"; |
164 | 164 | $wgAutoloadClasses['ApiQueryGlobalUserInfo'] = "$caBase/ApiQueryGlobalUserInfo.php"; |
165 | 165 | |
166 | 166 | $wgExtensionMessagesFiles['SpecialCentralAuth'] = "$caBase/CentralAuth.i18n.php"; |
Index: trunk/extensions/CentralAuth/specials/SpecialGlobalGroupMembership.php |
— | — | @@ -0,0 +1,111 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Equivalent of Special:Userrights for global groups. |
| 5 | + * |
| 6 | + * @ingroup Extensions |
| 7 | + */ |
| 8 | + |
| 9 | +class SpecialGlobalGroupMembership extends UserrightsPage { |
| 10 | + var $mGlobalUser; |
| 11 | + |
| 12 | + function __construct() { |
| 13 | + SpecialPage::__construct( 'GlobalGroupMembership' ); |
| 14 | + |
| 15 | + global $wgUser; |
| 16 | + $this->mGlobalUser = CentralAuthUser::getInstance( $wgUser ); |
| 17 | + } |
| 18 | + |
| 19 | + function getSuccessURL() { |
| 20 | + $knownWikis = $this->mGlobalUser->listAttached(); |
| 21 | + $title = $this->getTitle( $this->mTarget ); |
| 22 | + return $title->getFullURL( 'wpKnownWiki=' . urlencode( $knownWikis[0] ) ); |
| 23 | + } |
| 24 | + |
| 25 | + /** |
| 26 | + * Output a form to allow searching for a user |
| 27 | + */ |
| 28 | + function switchForm() { |
| 29 | + global $wgOut, $wgScript, $wgRequest; |
| 30 | + |
| 31 | + $knownwiki = $wgRequest->getVal( 'wpKnownWiki' ); |
| 32 | + $knownwiki = $knownwiki ? $knownwiki : wfWikiId(); |
| 33 | + |
| 34 | + // Generate wiki selector |
| 35 | + $selector = new XmlSelect( 'wpKnownWiki', 'wpKnownWiki', $knownwiki ); |
| 36 | + |
| 37 | + foreach ( CentralAuthUser::getWikiList() as $wiki ) { |
| 38 | + $selector->addOption( $wiki ); |
| 39 | + } |
| 40 | + |
| 41 | + $wgOut->addModuleStyles( 'mediawiki.special' ); |
| 42 | + $wgOut->addHTML( |
| 43 | + Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'name' => 'uluser', 'id' => 'mw-userrights-form1' ) ) . |
| 44 | + Html::hidden( 'title', $this->getTitle() ) . |
| 45 | + Xml::openElement( 'fieldset' ) . |
| 46 | + Xml::element( 'legend', array(), wfMsg( 'userrights-lookup-user' ) ) . |
| 47 | + Xml::inputLabel( wfMsg( 'userrights-user-editname' ), 'user', 'username', 30, $this->mTarget ) . ' <br />' . |
| 48 | + Xml::label( wfMsg( 'centralauth-globalgrouppermissions-knownwiki' ), 'wpKnownWiki' ) . ' ' . |
| 49 | + $selector->getHTML() . '<br />' . |
| 50 | + Xml::submitButton( wfMsg( 'editusergroup' ) ) . |
| 51 | + Xml::closeElement( 'fieldset' ) . |
| 52 | + Xml::closeElement( 'form' ) . "\n" |
| 53 | + ); |
| 54 | + } |
| 55 | + |
| 56 | + function changeableGroups() { |
| 57 | + # # Should be a global user |
| 58 | + if ( !$this->mGlobalUser->exists() || !$this->mGlobalUser->isAttached() ) { |
| 59 | + return array(); |
| 60 | + } |
| 61 | + |
| 62 | + $allGroups = CentralAuthUser::availableGlobalGroups(); |
| 63 | + |
| 64 | + # # Permission MUST be gained from global rights. |
| 65 | + if ( $this->mGlobalUser->hasGlobalPermission( 'globalgroupmembership' ) ) { |
| 66 | + # specify addself and removeself as empty arrays -- bug 16098 |
| 67 | + return array( 'add' => $allGroups, 'remove' => $allGroups, 'add-self' => array(), 'remove-self' => array() ); |
| 68 | + } else { |
| 69 | + return array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + function fetchUser( $username ) { |
| 74 | + global $wgRequest; |
| 75 | + |
| 76 | + $knownwiki = $wgRequest->getVal( 'wpKnownWiki' ); |
| 77 | + |
| 78 | + $user = CentralAuthGroupMembershipProxy::newFromName( $username ); |
| 79 | + |
| 80 | + if ( !$user ) { |
| 81 | + return Status::newFatal( 'nosuchusershort', $username ); |
| 82 | + } elseif ( !$wgRequest->getCheck( 'saveusergroups' ) && !$user->attachedOn( $knownwiki ) ) { |
| 83 | + return Status::newFatal( 'centralauth-globalgroupmembership-badknownwiki', |
| 84 | + $username, $knownwiki ); |
| 85 | + } |
| 86 | + |
| 87 | + return Status::newGood( $user ); |
| 88 | + } |
| 89 | + |
| 90 | + protected static function getAllGroups() { |
| 91 | + return CentralAuthUser::availableGlobalGroups(); |
| 92 | + } |
| 93 | + |
| 94 | + protected function showLogFragment( $user, $output ) { |
| 95 | + $pageTitle = Title::makeTitleSafe( NS_USER, $user->getName() ); |
| 96 | + $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'gblrights' ) . "\n" ) ); |
| 97 | + LogEventsList::showLogExtract( $output, 'gblrights', $pageTitle->getPrefixedText() ); |
| 98 | + } |
| 99 | + |
| 100 | + function addLogEntry( $user, $oldGroups, $newGroups, $reason ) { |
| 101 | + $log = new LogPage( 'gblrights' ); |
| 102 | + |
| 103 | + $log->addEntry( 'usergroups', |
| 104 | + $user->getUserPage(), |
| 105 | + $reason, |
| 106 | + array( |
| 107 | + $this->makeGroupNameList( $oldGroups ), |
| 108 | + $this->makeGroupNameList( $newGroups ) |
| 109 | + ) |
| 110 | + ); |
| 111 | + } |
| 112 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialGlobalGroupMembership.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 113 | + native |
Index: trunk/extensions/CentralAuth/specials/SpecialGlobalGroupPermissions.php |
— | — | @@ -0,0 +1,370 @@ |
| 2 | +<?php |
| 3 | +# This file is part of MediaWiki. |
| 4 | + |
| 5 | +# MediaWiki is free software: you can redistribute it and/or modify |
| 6 | +# it under the terms of version 2 of the GNU General Public License |
| 7 | +# as published by the Free Software Foundation. |
| 8 | + |
| 9 | +# MediaWiki 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 | +/** |
| 15 | + * Special page to allow managing global groups |
| 16 | + * Prototype for a similar system in core. |
| 17 | + * |
| 18 | + * @file |
| 19 | + * @ingroup Extensions |
| 20 | + */ |
| 21 | + |
| 22 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 23 | + echo "CentralAuth extension\n"; |
| 24 | + exit( 1 ); |
| 25 | +} |
| 26 | + |
| 27 | +class SpecialGlobalGroupPermissions extends SpecialPage { |
| 28 | + function __construct() { |
| 29 | + parent::__construct( 'GlobalGroupPermissions' ); |
| 30 | + } |
| 31 | + |
| 32 | + function userCanEdit( $user ) { |
| 33 | + $globalUser = CentralAuthUser::getInstance( $user ); |
| 34 | + |
| 35 | + # # Should be a global user |
| 36 | + if ( !$globalUser->exists() || !$globalUser->isAttached() ) { |
| 37 | + return false; |
| 38 | + } |
| 39 | + |
| 40 | + # # Permission MUST be gained from global rights. |
| 41 | + return $globalUser->hasGlobalPermission( 'globalgrouppermissions' ); |
| 42 | + } |
| 43 | + |
| 44 | + function execute( $subpage ) { |
| 45 | + global $wgRequest, $wgOut, $wgUser; |
| 46 | + |
| 47 | + if ( !$this->userCanExecute( $wgUser ) ) { |
| 48 | + $this->displayRestrictionError(); |
| 49 | + return; |
| 50 | + } |
| 51 | + |
| 52 | + $wgOut->setPageTitle( wfMsg( 'globalgrouppermissions' ) ); |
| 53 | + $wgOut->setRobotPolicy( "noindex,nofollow" ); |
| 54 | + $wgOut->setArticleRelated( false ); |
| 55 | + $wgOut->enableClientCache( false ); |
| 56 | + |
| 57 | + if ( $subpage == '' ) { |
| 58 | + $subpage = $wgRequest->getVal( 'wpGroup' ); |
| 59 | + } |
| 60 | + |
| 61 | + if ( $subpage != '' && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
| 62 | + $this->doSubmit( $subpage ); |
| 63 | + } else if ( $subpage != '' ) { |
| 64 | + $this->buildGroupView( $subpage ); |
| 65 | + } else { |
| 66 | + $this->buildMainView(); |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + function buildMainView() { |
| 71 | + global $wgOut, $wgUser, $wgScript; |
| 72 | + |
| 73 | + $groups = CentralAuthUser::availableGlobalGroups(); |
| 74 | + |
| 75 | + // Existing groups |
| 76 | + $html = Xml::fieldset( wfMsg( 'centralauth-existinggroup-legend' ) ); |
| 77 | + |
| 78 | + $wgOut->addHTML( $html ); |
| 79 | + |
| 80 | + if ( count( $groups ) ) { |
| 81 | + $wgOut->addWikiMsg( 'centralauth-globalgroupperms-grouplist' ); |
| 82 | + $wgOut->addHTML( '<ul>' ); |
| 83 | + |
| 84 | + foreach ( $groups as $group ) { |
| 85 | + $text = wfMsgExt( 'centralauth-globalgroupperms-grouplistitem', array( 'parseinline' ), User::getGroupName( $group ), $group, '<span class="centralauth-globalgroupperms-groupname">' . $group . '</span>' ); |
| 86 | + |
| 87 | + $wgOut->addHTML( "<li> $text </li>" ); |
| 88 | + } |
| 89 | + } else { |
| 90 | + $wgOut->addWikiMsg( 'centralauth-globalgroupperms-nogroups' ); |
| 91 | + } |
| 92 | + |
| 93 | + $wgOut->addHTML( Xml::closeElement( 'ul' ) . Xml::closeElement( 'fieldset' ) ); |
| 94 | + |
| 95 | + if ( $this->userCanEdit( $wgUser ) ) { |
| 96 | + // "Create a group" prompt |
| 97 | + $html = Xml::fieldset( wfMsg( 'centralauth-newgroup-legend' ) ); |
| 98 | + $html .= wfMsgExt( 'centralauth-newgroup-intro', array( 'parse' ) ); |
| 99 | + $html .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $wgScript, 'name' => 'centralauth-globalgroups-newgroup' ) ); |
| 100 | + $html .= Html::hidden( 'title', SpecialPage::getTitleFor( 'GlobalGroupPermissions' )->getPrefixedText() ); |
| 101 | + |
| 102 | + $fields = array( 'centralauth-globalgroupperms-newgroupname' => Xml::input( 'wpGroup' ) ); |
| 103 | + |
| 104 | + $html .= Xml::buildForm( $fields, 'centralauth-globalgroupperms-creategroup-submit' ); |
| 105 | + $html .= Xml::closeElement( 'form' ); |
| 106 | + $html .= Xml::closeElement( 'fieldset' ); |
| 107 | + |
| 108 | + $wgOut->addHTML( $html ); |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + function buildGroupView( $group ) { |
| 113 | + global $wgOut, $wgUser; |
| 114 | + |
| 115 | + $editable = $this->userCanEdit( $wgUser ); |
| 116 | + |
| 117 | + $wgOut->setSubtitle( wfMsg( 'centralauth-editgroup-subtitle', $group ) ); |
| 118 | + |
| 119 | + $html = Xml::fieldset( wfMsg( 'centralauth-editgroup-fieldset', $group ) ); |
| 120 | + |
| 121 | + if ( $editable ) { |
| 122 | + $html .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => SpecialPage::getTitleFor( 'GlobalGroupPermissions', $group )->getLocalUrl(), 'name' => 'centralauth-globalgroups-newgroup' ) ); |
| 123 | + $html .= Html::hidden( 'wpGroup', $group ); |
| 124 | + $html .= Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
| 125 | + } |
| 126 | + |
| 127 | + $fields = array(); |
| 128 | + |
| 129 | + $fields['centralauth-editgroup-name'] = $group; |
| 130 | + $fields['centralauth-editgroup-display'] = wfMsgExt( 'centralauth-editgroup-display-edit', array( 'parseinline' ), $group, User::getGroupName( $group ) ); |
| 131 | + $fields['centralauth-editgroup-member'] = wfMsgExt( 'centralauth-editgroup-member-edit', array( 'parseinline' ), $group, User::getGroupMember( $group ) ); |
| 132 | + $fields['centralauth-editgroup-members'] = wfMsgExt( 'centralauth-editgroup-members-link', array( 'parseinline' ), $group, User::getGroupMember( $group ) ); |
| 133 | + $fields['centralauth-editgroup-restrictions'] = $this->buildWikiSetSelector( $group ); |
| 134 | + $fields['centralauth-editgroup-perms'] = $this->buildCheckboxes( $group ); |
| 135 | + |
| 136 | + if ( $editable ) { |
| 137 | + $fields['centralauth-editgroup-reason'] = Xml::input( 'wpReason', 60 ); |
| 138 | + } |
| 139 | + |
| 140 | + $html .= Xml::buildForm( $fields, $editable ? 'centralauth-editgroup-submit' : null ); |
| 141 | + |
| 142 | + if ( $editable ) |
| 143 | + $html .= Xml::closeElement( 'form' ); |
| 144 | + |
| 145 | + $html .= Xml::closeElement( 'fieldset' ); |
| 146 | + |
| 147 | + $wgOut->addHTML( $html ); |
| 148 | + |
| 149 | + $this->showLogFragment( $group, $wgOut ); |
| 150 | + } |
| 151 | + |
| 152 | + function buildWikiSetSelector( $group ) { |
| 153 | + $sets = WikiSet::getAllWikiSets(); |
| 154 | + $default = WikiSet::getWikiSetForGroup( $group ); |
| 155 | + |
| 156 | + global $wgUser; |
| 157 | + if ( !$this->userCanEdit( $wgUser ) ) |
| 158 | + return htmlspecialchars( $default ); |
| 159 | + |
| 160 | + $select = new XmlSelect( 'set', 'wikiset', $default ); |
| 161 | + $select->addOption( wfMsg( 'centralauth-editgroup-noset' ), '0' ); |
| 162 | + foreach ( $sets as $set ) { |
| 163 | + $select->addOption( $set->getName(), $set->getID() ); |
| 164 | + } |
| 165 | + |
| 166 | + $editlink = wfMsgExt( "centralauth-editgroup-editsets", array( "parseinline" ) ); |
| 167 | + return $select->getHTML() . " {$editlink}"; |
| 168 | + } |
| 169 | + |
| 170 | + function buildCheckboxes( $group ) { |
| 171 | + global $wgUser, $wgOut; |
| 172 | + |
| 173 | + $editable = $this->userCanEdit( $wgUser ); |
| 174 | + |
| 175 | + $rights = User::getAllRights(); |
| 176 | + $assignedRights = $this->getAssignedRights( $group ); |
| 177 | + |
| 178 | + sort( $rights ); |
| 179 | + |
| 180 | + $checkboxes = array(); |
| 181 | + $attribs = array(); |
| 182 | + |
| 183 | + if ( !$editable ) |
| 184 | + $attribs['disabled'] = 'disabled'; |
| 185 | + |
| 186 | + foreach ( $rights as $right ) { |
| 187 | + # Build a checkbox. |
| 188 | + $checked = in_array( $right, $assignedRights ); |
| 189 | + |
| 190 | + $desc = $wgOut->parseInline( User::getRightDescription( $right ) ) . ' ' . |
| 191 | + Xml::element( 'tt', null, wfMsg( 'parentheses', $right ) ); |
| 192 | + |
| 193 | + $checkbox = Xml::check( "wpRightAssigned-$right", $checked, $attribs ); |
| 194 | + $label = Xml::tags( 'label', array( 'for' => "wpRightAssigned-$right" ), |
| 195 | + $desc ); |
| 196 | + |
| 197 | + $checkboxes[] = "<li>$checkbox $label</li>"; |
| 198 | + } |
| 199 | + |
| 200 | + $count = count( $checkboxes ); |
| 201 | + |
| 202 | + $firstCol = round( $count / 2 ); |
| 203 | + |
| 204 | + $checkboxes1 = array_slice( $checkboxes, 0, $firstCol ); |
| 205 | + $checkboxes2 = array_slice( $checkboxes, $firstCol ); |
| 206 | + |
| 207 | + $html = '<table><tbody><tr><td><ul>'; |
| 208 | + |
| 209 | + foreach ( $checkboxes1 as $cb ) { |
| 210 | + $html .= $cb; |
| 211 | + } |
| 212 | + |
| 213 | + $html .= '</ul></td><td><ul>'; |
| 214 | + |
| 215 | + foreach ( $checkboxes2 as $cb ) { |
| 216 | + $html .= $cb; |
| 217 | + } |
| 218 | + |
| 219 | + $html .= '</ul></td></tr></tbody></table>'; |
| 220 | + |
| 221 | + return $html; |
| 222 | + } |
| 223 | + |
| 224 | + function getAssignedRights( $group ) { |
| 225 | + return CentralAuthUser::globalGroupPermissions( $group ); |
| 226 | + } |
| 227 | + |
| 228 | + function doSubmit( $group ) { |
| 229 | + global $wgRequest, $wgOut, $wgUser; |
| 230 | + |
| 231 | + // Paranoia -- the edit token shouldn't match anyway |
| 232 | + if ( !$this->userCanEdit( $wgUser ) ) |
| 233 | + return; |
| 234 | + |
| 235 | + $newRights = array(); |
| 236 | + $addRights = array(); |
| 237 | + $removeRights = array(); |
| 238 | + $oldRights = $this->getAssignedRights( $group ); |
| 239 | + $allRights = User::getAllRights(); |
| 240 | + |
| 241 | + $reason = $wgRequest->getVal( 'wpReason', '' ); |
| 242 | + |
| 243 | + foreach ( $allRights as $right ) { |
| 244 | + $alreadyAssigned = in_array( $right, $oldRights ); |
| 245 | + |
| 246 | + if ( $wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
| 247 | + $newRights[] = $right; |
| 248 | + } |
| 249 | + |
| 250 | + if ( !$alreadyAssigned && $wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
| 251 | + $addRights[] = $right; |
| 252 | + } else if ( $alreadyAssigned && !$wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
| 253 | + $removeRights[] = $right; |
| 254 | + } # Otherwise, do nothing. |
| 255 | + } |
| 256 | + |
| 257 | + // Assign the rights. |
| 258 | + if ( count( $addRights ) > 0 ) |
| 259 | + $this->grantRightsToGroup( $group, $addRights ); |
| 260 | + if ( count( $removeRights ) > 0 ) |
| 261 | + $this->revokeRightsFromGroup( $group, $removeRights ); |
| 262 | + |
| 263 | + // Log it |
| 264 | + if ( !( count( $addRights ) == 0 && count( $removeRights ) == 0 ) ) |
| 265 | + $this->addLogEntry( $group, $addRights, $removeRights, $reason ); |
| 266 | + |
| 267 | + // Change set |
| 268 | + $current = WikiSet::getWikiSetForGroup( $group ); |
| 269 | + $new = $wgRequest->getVal( 'set' ); |
| 270 | + if ( $current != $new ) { |
| 271 | + $this->setRestrictions( $group, $new ); |
| 272 | + $this->addLogEntry2( $group, $current, $new, $reason ); |
| 273 | + } |
| 274 | + |
| 275 | + $this->invalidateRightsCache( $group ); |
| 276 | + |
| 277 | + // Display success |
| 278 | + $wgOut->setSubTitle( wfMsg( 'centralauth-editgroup-success' ) ); |
| 279 | + $wgOut->addWikiMsg( 'centralauth-editgroup-success-text', $group ); |
| 280 | + } |
| 281 | + |
| 282 | + function revokeRightsFromGroup( $group, $rights ) { |
| 283 | + $dbw = CentralAuthUser::getCentralDB(); |
| 284 | + |
| 285 | + # Delete from the DB |
| 286 | + $dbw->delete( 'global_group_permissions', array( 'ggp_group' => $group, 'ggp_permission' => $rights ), __METHOD__ ); |
| 287 | + } |
| 288 | + |
| 289 | + function grantRightsToGroup( $group, $rights ) { |
| 290 | + $dbw = CentralAuthUser::getCentralDB(); |
| 291 | + |
| 292 | + if ( !is_array( $rights ) ) { |
| 293 | + $rights = array( $rights ); |
| 294 | + } |
| 295 | + |
| 296 | + $insertRows = array(); |
| 297 | + foreach ( $rights as $right ) { |
| 298 | + $insertRows[] = array( 'ggp_group' => $group, 'ggp_permission' => $right ); |
| 299 | + } |
| 300 | + |
| 301 | + # Replace into the DB |
| 302 | + $dbw->replace( 'global_group_permissions', array( 'ggp_group', 'ggp_permission' ), $insertRows, __METHOD__ ); |
| 303 | + } |
| 304 | + |
| 305 | + protected function showLogFragment( $group, $output ) { |
| 306 | + $title = SpecialPage::getTitleFor( 'GlobalUsers', $group ); |
| 307 | + $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'gblrights' ) . "\n" ) ); |
| 308 | + LogEventsList::showLogExtract( $output, 'gblrights', $title->getPrefixedText() ); |
| 309 | + } |
| 310 | + |
| 311 | + function addLogEntry( $group, $addRights, $removeRights, $reason ) { |
| 312 | + $log = new LogPage( 'gblrights' ); |
| 313 | + |
| 314 | + $log->addEntry( 'groupprms2', |
| 315 | + SpecialPage::getTitleFor( 'GlobalUsers', $group ), |
| 316 | + $reason, |
| 317 | + array( |
| 318 | + $this->makeRightsList( $addRights ), |
| 319 | + $this->makeRightsList( $removeRights ) |
| 320 | + ) |
| 321 | + ); |
| 322 | + } |
| 323 | + |
| 324 | + function makeRightsList( $ids ) { |
| 325 | + return (bool)count( $ids ) ? implode( ', ', $ids ) : wfMsgForContent( 'rightsnone' ); |
| 326 | + } |
| 327 | + |
| 328 | + function setRestrictions( $group, $set ) { |
| 329 | + $dbw = CentralAuthUser::getCentralDB(); |
| 330 | + if ( $set == 0 ) { |
| 331 | + $dbw->delete( 'global_group_restrictions', array( 'ggr_group' => $group ), __METHOD__ ); |
| 332 | + } else { |
| 333 | + $dbw->replace( 'global_group_restrictions', array( 'ggr_group' ), |
| 334 | + array( 'ggr_group' => $group, 'ggr_set' => $set, ), __METHOD__ ); |
| 335 | + } |
| 336 | + return (bool)$dbw->affectedRows(); |
| 337 | + } |
| 338 | + |
| 339 | + function addLogEntry2( $group, $old, $new, $reason ) { |
| 340 | + $log = new LogPage( 'gblrights' ); |
| 341 | + |
| 342 | + $log->addEntry( 'groupprms3', |
| 343 | + SpecialPage::getTitleFor( 'GlobalUsers', $group ), |
| 344 | + $reason, |
| 345 | + array( |
| 346 | + $this->getWikiSetName( $old ), |
| 347 | + $this->getWikiSetName( $new ), |
| 348 | + ) |
| 349 | + ); |
| 350 | + } |
| 351 | + |
| 352 | + function getWikiSetName( $id ) { |
| 353 | + if ( $id ) |
| 354 | + return WikiSet::newFromID( $id )->getName(); |
| 355 | + else |
| 356 | + return wfMsgForContent( 'centralauth-editgroup-noset' ); |
| 357 | + } |
| 358 | + |
| 359 | + function invalidateRightsCache( $group ) { |
| 360 | + // Figure out all the users in this group. |
| 361 | + $dbr = CentralAuthUser::getCentralDB(); |
| 362 | + |
| 363 | + $res = $dbr->select( array( 'global_user_groups', 'globaluser' ), 'gu_name', array( 'gug_group' => $group, 'gu_id=gug_user' ), __METHOD__ ); |
| 364 | + |
| 365 | + // Invalidate their rights cache. |
| 366 | + foreach ( $res as $row ) { |
| 367 | + $cu = new CentralAuthUser( $row->gu_name ); |
| 368 | + $cu->quickInvalidateCache(); |
| 369 | + } |
| 370 | + } |
| 371 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialGlobalGroupPermissions.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 372 | + native |
Index: trunk/extensions/CentralAuth/specials/SpecialCentralAuth.php |
— | — | @@ -0,0 +1,633 @@ |
| 2 | +<?php |
| 3 | +class SpecialCentralAuth extends SpecialPage { |
| 4 | + var $mUserName, $mCanUnmerge, $mCanLock, $mCanOversight, $mCanEdit; |
| 5 | + var $mGlobalUser, $mAttachedLocalAccounts, $mUnattachedLocalAccounts; |
| 6 | + |
| 7 | + function __construct() { |
| 8 | + parent::__construct( 'CentralAuth' ); |
| 9 | + } |
| 10 | + |
| 11 | + function execute( $subpage ) { |
| 12 | + global $wgOut; |
| 13 | + global $wgExtensionAssetsPath, $wgCentralAuthStyleVersion; |
| 14 | + global $wgUser, $wgRequest, $wgContLang; |
| 15 | + $this->setHeaders(); |
| 16 | + |
| 17 | + $this->mCanUnmerge = $wgUser->isAllowed( 'centralauth-unmerge' ); |
| 18 | + $this->mCanLock = $wgUser->isAllowed( 'centralauth-lock' ); |
| 19 | + $this->mCanOversight = $wgUser->isAllowed( 'centralauth-oversight' ); |
| 20 | + $this->mCanEdit = $this->mCanUnmerge || $this->mCanLock || $this->mCanOversight; |
| 21 | + |
| 22 | + $wgOut->addExtensionStyle( "{$wgExtensionAssetsPath}/CentralAuth/centralauth.css?" . |
| 23 | + $wgCentralAuthStyleVersion ); |
| 24 | + $wgOut->addScriptFile( "{$wgExtensionAssetsPath}/CentralAuth/centralauth.js?" . |
| 25 | + $wgCentralAuthStyleVersion ); |
| 26 | + $this->addMergeMethodDescriptions(); |
| 27 | + |
| 28 | + $this->mUserName = |
| 29 | + trim( |
| 30 | + str_replace( '_', ' ', |
| 31 | + $wgRequest->getText( 'target', $subpage ) ) ); |
| 32 | + |
| 33 | + $this->mUserName = $wgContLang->ucfirst( $this->mUserName ); |
| 34 | + |
| 35 | + $this->mPosted = $wgRequest->wasPosted(); |
| 36 | + $this->mMethod = $wgRequest->getVal( 'wpMethod' ); |
| 37 | + $this->mWikis = (array)$wgRequest->getArray( 'wpWikis' ); |
| 38 | + |
| 39 | + // Possible demo states |
| 40 | + |
| 41 | + // success, all accounts merged |
| 42 | + // successful login, some accounts merged, others left |
| 43 | + // successful login, others left |
| 44 | + // not account owner, others left |
| 45 | + |
| 46 | + // is owner / is not owner |
| 47 | + // did / did not merge some accounts |
| 48 | + // do / don't have more accounts to merge |
| 49 | + |
| 50 | + if ( $this->mUserName === '' ) { |
| 51 | + # First time through |
| 52 | + $wgOut->addWikiMsg( 'centralauth-admin-intro' ); |
| 53 | + $this->showUsernameForm(); |
| 54 | + return; |
| 55 | + } |
| 56 | + |
| 57 | + $this->mGlobalUser = $globalUser = new CentralAuthUser( $this->mUserName ); |
| 58 | + |
| 59 | + if ( !$globalUser->exists() || |
| 60 | + ( $globalUser->isOversighted() && !$this->mCanOversight ) ) { |
| 61 | + $this->showError( 'centralauth-admin-nonexistent', $this->mUserName ); |
| 62 | + $this->showUsernameForm(); |
| 63 | + return; |
| 64 | + } |
| 65 | + |
| 66 | + $continue = true; |
| 67 | + if ( $this->mCanEdit && $this->mPosted ) { |
| 68 | + $continue = $this->doSubmit(); |
| 69 | + } |
| 70 | + |
| 71 | + $this->mAttachedLocalAccounts = $this->mGlobalUser->queryAttached(); |
| 72 | + $this->mUnattachedLocalAccounts = $this->mGlobalUser->queryUnattached(); |
| 73 | + |
| 74 | + $this->showUsernameForm(); |
| 75 | + if ( $continue ) { |
| 76 | + $this->showInfo(); |
| 77 | + if ( $this->mCanLock ) |
| 78 | + $this->showStatusForm(); |
| 79 | + if ( $this->mCanUnmerge ) |
| 80 | + $this->showActionForm( 'delete' ); |
| 81 | + if ( $this->mCanEdit ) |
| 82 | + $this->showLogExtract(); |
| 83 | + $this->showWikiLists(); |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + /** Returns true if the normal form should be displayed */ |
| 88 | + function doSubmit() { |
| 89 | + $deleted = false; |
| 90 | + $globalUser = $this->mGlobalUser; |
| 91 | + global $wgUser, $wgRequest; |
| 92 | + if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
| 93 | + $this->showError( 'centralauth-token-mismatch' ); |
| 94 | + } elseif ( $this->mMethod == 'unmerge' && $this->mCanUnmerge ) { |
| 95 | + $status = $globalUser->adminUnattach( $this->mWikis ); |
| 96 | + if ( !$status->isGood() ) { |
| 97 | + $this->showStatusError( $status->getWikiText() ); |
| 98 | + } else { |
| 99 | + global $wgLang; |
| 100 | + $this->showSuccess( 'centralauth-admin-unmerge-success', |
| 101 | + $wgLang->formatNum( $status->successCount ), |
| 102 | + /* deprecated */ $status->successCount ); |
| 103 | + } |
| 104 | + } elseif ( $this->mMethod == 'delete' && $this->mCanUnmerge ) { |
| 105 | + $status = $globalUser->adminDelete(); |
| 106 | + if ( !$status->isGood() ) { |
| 107 | + $this->showStatusError( $status->getWikiText() ); |
| 108 | + } else { |
| 109 | + $this->showSuccess( 'centralauth-admin-delete-success', $this->mUserName ); |
| 110 | + $deleted = true; |
| 111 | + $this->logAction( 'delete', $this->mUserName, $wgRequest->getVal( 'reason' ) ); |
| 112 | + } |
| 113 | + } elseif ( $this->mMethod == 'set-status' && $this->mCanLock ) { |
| 114 | + $setLocked = $wgRequest->getBool( 'wpStatusLocked' ); |
| 115 | + $setHidden = $wgRequest->getVal( 'wpStatusHidden' ); |
| 116 | + $isLocked = $globalUser->isLocked(); |
| 117 | + $oldHiddenLevel = $globalUser->getHiddenLevel(); |
| 118 | + $lockStatus = $hideStatus = null; |
| 119 | + $added = array(); |
| 120 | + $removed = array(); |
| 121 | + |
| 122 | + // Sanitizing input value... |
| 123 | + $hiddenLevels = array( |
| 124 | + CentralAuthUser::HIDDEN_NONE, |
| 125 | + CentralAuthUser::HIDDEN_LISTS, |
| 126 | + CentralAuthUser::HIDDEN_OVERSIGHT ); |
| 127 | + if ( !in_array( $setHidden, $hiddenLevels ) ) |
| 128 | + $setHidden = ''; |
| 129 | + |
| 130 | + if ( !$isLocked && $setLocked ) { |
| 131 | + $lockStatus = $globalUser->adminLock(); |
| 132 | + $added[] = wfMsgForContent( 'centralauth-log-status-locked' ); |
| 133 | + } elseif ( $isLocked && !$setLocked ) { |
| 134 | + $lockStatus = $globalUser->adminUnlock(); |
| 135 | + $removed[] = wfMsgForContent( 'centralauth-log-status-locked' ); |
| 136 | + } |
| 137 | + |
| 138 | + $reason = $wgRequest->getText( 'wpReasonList' ); |
| 139 | + $reasonDetail = $wgRequest->getText( 'wpReason' ); |
| 140 | + if ( $reason == 'other' ) { |
| 141 | + $reason = $reasonDetail; |
| 142 | + } elseif ( $reasonDetail ) { |
| 143 | + $reason .= wfMsgForContent( 'colon-separator' ) . $reasonDetail; |
| 144 | + } |
| 145 | + |
| 146 | + if ( $oldHiddenLevel != $setHidden ) { |
| 147 | + $hideStatus = $globalUser->adminSetHidden( $setHidden ); |
| 148 | + switch( $setHidden ) { |
| 149 | + case CentralAuthUser::HIDDEN_NONE: |
| 150 | + $removed[] = $oldHiddenLevel == CentralAuthUser::HIDDEN_OVERSIGHT ? |
| 151 | + wfMsgForContent( 'centralauth-log-status-oversighted' ) : |
| 152 | + wfMsgForContent( 'centralauth-log-status-hidden' ); |
| 153 | + break; |
| 154 | + case CentralAuthUser::HIDDEN_LISTS: |
| 155 | + $added[] = wfMsgForContent( 'centralauth-log-status-hidden' ); |
| 156 | + if ( $oldHiddenLevel == CentralAuthUser::HIDDEN_OVERSIGHT ) |
| 157 | + $removed[] = wfMsgForContent( 'centralauth-log-status-oversighted' ); |
| 158 | + break; |
| 159 | + case CentralAuthUser::HIDDEN_OVERSIGHT: |
| 160 | + $added[] = wfMsgForContent( 'centralauth-log-status-oversighted' ); |
| 161 | + if ( $oldHiddenLevel == CentralAuthUser::HIDDEN_LISTS ) |
| 162 | + $removed[] = wfMsgForContent( 'centralauth-log-status-hidden' ); |
| 163 | + break; |
| 164 | + } |
| 165 | + |
| 166 | + if ( $setHidden == CentralAuthUser::HIDDEN_OVERSIGHT ) |
| 167 | + $globalUser->suppress( $reason ); |
| 168 | + elseif ( $oldHiddenLevel == CentralAuthUser::HIDDEN_OVERSIGHT ) |
| 169 | + $globalUser->unsuppress( $reason ); |
| 170 | + } |
| 171 | + |
| 172 | + $good = |
| 173 | + ( is_null( $lockStatus ) || $lockStatus->isGood() ) && |
| 174 | + ( is_null( $hideStatus ) || $hideStatus->isGood() ); |
| 175 | + |
| 176 | + // Logging etc |
| 177 | + if ( $good && ( count( $added ) || count( $removed ) ) ) { |
| 178 | + $added = count( $added ) ? |
| 179 | + implode( ', ', $added ) : wfMsgForContent( 'centralauth-log-status-none' ); |
| 180 | + $removed = count( $removed ) ? |
| 181 | + implode( ', ', $removed ) : wfMsgForContent( 'centralauth-log-status-none' ); |
| 182 | + |
| 183 | + $this->logAction( |
| 184 | + 'setstatus', |
| 185 | + $this->mUserName, |
| 186 | + $reason, |
| 187 | + array( $added, $removed ), |
| 188 | + $setHidden == CentralAuthUser::HIDDEN_OVERSIGHT |
| 189 | + ); |
| 190 | + $this->showSuccess( 'centralauth-admin-setstatus-success', $this->mUserName ); |
| 191 | + } elseif ( !$good ) { |
| 192 | + if ( !is_null( $lockStatus ) && !$lockStatus->isGood() ) { |
| 193 | + $this->showStatusError( $lockStatus->getWikiText() ); |
| 194 | + } |
| 195 | + if ( !is_null( $hideStatus ) && !$hideStatus->isGood() ) { |
| 196 | + $this->showStatusError( $hideStatus->getWikiText() ); |
| 197 | + } |
| 198 | + } |
| 199 | + } else { |
| 200 | + $this->showError( 'centralauth-admin-bad-input' ); |
| 201 | + } |
| 202 | + return !$deleted; |
| 203 | + } |
| 204 | + |
| 205 | + function showStatusError( $wikitext ) { |
| 206 | + global $wgOut; |
| 207 | + $wrap = Xml::tags( 'div', array( 'class' => 'error' ), $wikitext ); |
| 208 | + $wgOut->addHTML( $wgOut->parse( $wrap, /*linestart*/true, /*uilang*/true ) ); |
| 209 | + } |
| 210 | + |
| 211 | + function showError( /* varargs */ ) { |
| 212 | + global $wgOut; |
| 213 | + $args = func_get_args(); |
| 214 | + $wgOut->wrapWikiMsg( '<div class="error">$1</div>', $args ); |
| 215 | + } |
| 216 | + |
| 217 | + |
| 218 | + function showSuccess( /* varargs */ ) { |
| 219 | + global $wgOut; |
| 220 | + $args = func_get_args(); |
| 221 | + $wgOut->wrapWikiMsg( '<div class="success">$1</div>', $args ); |
| 222 | + } |
| 223 | + |
| 224 | + function showUsernameForm() { |
| 225 | + global $wgOut, $wgScript; |
| 226 | + $lookup = $this->mCanEdit ? |
| 227 | + wfMsg( 'centralauth-admin-lookup-rw' ) : |
| 228 | + wfMsg( 'centralauth-admin-lookup-ro' ); |
| 229 | + $wgOut->addHTML( |
| 230 | + Xml::openElement( 'form', array( |
| 231 | + 'method' => 'get', |
| 232 | + 'action' => $wgScript ) ) . |
| 233 | + '<fieldset>' . |
| 234 | + Xml::element( 'legend', array(), wfMsg( 'centralauth-admin-manage' ) ) . |
| 235 | + Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . |
| 236 | + '<p>' . |
| 237 | + Xml::inputLabel( wfMsg( 'centralauth-admin-username' ), |
| 238 | + 'target', 'target', 25, $this->mUserName ) . |
| 239 | + '</p>' . |
| 240 | + '<p>' . |
| 241 | + Xml::submitButton( $lookup ) . |
| 242 | + '</p>' . |
| 243 | + '</fieldset>' . |
| 244 | + '</form>' |
| 245 | + ); |
| 246 | + } |
| 247 | + |
| 248 | + function prettyTimespan( $span ) { |
| 249 | + global $wgLang; |
| 250 | + $units = array( |
| 251 | + 'seconds' => 60, |
| 252 | + 'minutes' => 60, |
| 253 | + 'hours' => 24, |
| 254 | + 'days' => 30.417, |
| 255 | + 'months' => 12, |
| 256 | + 'years' => 1 ); |
| 257 | + foreach ( $units as $unit => $chunk ) { |
| 258 | + // Used messaged (to make sure that grep finds them): |
| 259 | + // 'centralauth-seconds-ago', 'centralauth-minutes-ago', 'centralauth-hours-ago' |
| 260 | + // 'centralauth-days-ago', 'centralauth-months-ago', 'centralauth-years-ago' |
| 261 | + if ( $span < 2 * $chunk ) { |
| 262 | + return wfMsgExt( "centralauth-$unit-ago", 'parsemag', $wgLang->formatNum( $span ) ); |
| 263 | + } |
| 264 | + $span = intval( $span / $chunk ); |
| 265 | + } |
| 266 | + return wfMsgExt( "centralauth-$unit-ago", 'parsemag', $wgLang->formatNum( $span ) ); |
| 267 | + } |
| 268 | + |
| 269 | + function showInfo() { |
| 270 | + $globalUser = $this->mGlobalUser; |
| 271 | + |
| 272 | + global $wgOut, $wgLang; |
| 273 | + $reg = $globalUser->getRegistration(); |
| 274 | + $age = $this->prettyTimespan( wfTimestamp( TS_UNIX ) - wfTimestamp( TS_UNIX, $reg ) ); |
| 275 | + $attribs = array( |
| 276 | + 'id' => $globalUser->getId(), |
| 277 | + 'registered' => $wgLang->timeanddate( $reg ) . " ($age)", |
| 278 | + 'home' => $this->determineHomeWiki(), |
| 279 | + 'editcount' => $wgLang->formatNum( $this->evaluateTotalEditcount() ), |
| 280 | + 'locked' => $globalUser->isLocked() ? wfMsg( 'centralauth-admin-yes' ) : wfMsg( 'centralauth-admin-no' ), |
| 281 | + 'hidden' => $this->formatHiddenLevel( $globalUser->getHiddenLevel() ) ); |
| 282 | + $out = '<fieldset id="mw-centralauth-info">'; |
| 283 | + $out .= '<legend>' . wfMsgHtml( 'centralauth-admin-info-header' ) . '</legend>'; |
| 284 | + foreach ( $attribs as $tag => $data ) { |
| 285 | + $out .= '<p><strong>' . wfMsgHtml( "centralauth-admin-info-$tag" ) . '</strong> ' . |
| 286 | + htmlspecialchars( $data ) . '</p>'; |
| 287 | + } |
| 288 | + $out .= '</fieldset>'; |
| 289 | + $wgOut->addHTML( $out ); |
| 290 | + } |
| 291 | + |
| 292 | + function showWikiLists() { |
| 293 | + global $wgOut; |
| 294 | + $merged = $this->mAttachedLocalAccounts; |
| 295 | + $remainder = $this->mUnattachedLocalAccounts; |
| 296 | + |
| 297 | + $legend = $this->mCanUnmerge ? |
| 298 | + wfMsgHtml( 'centralauth-admin-list-legend-rw' ) : |
| 299 | + wfMsgHtml( 'centralauth-admin-list-legend-ro' ); |
| 300 | + |
| 301 | + $wgOut->addHTML( "<fieldset><legend>{$legend}</legend>" ); |
| 302 | + $wgOut->addHTML( $this->listHeader() ); |
| 303 | + $wgOut->addHTML( $this->listMerged( $merged ) ); |
| 304 | + if ( $remainder ) |
| 305 | + $wgOut->addHTML( $this->listRemainder( $remainder ) ); |
| 306 | + $wgOut->addHTML( $this->listFooter() ); |
| 307 | + $wgOut->addHTML( '</fieldset>' ); |
| 308 | + } |
| 309 | + |
| 310 | + function listHeader() { |
| 311 | + global $wgUser; |
| 312 | + return |
| 313 | + Xml::openElement( 'form', |
| 314 | + array( |
| 315 | + 'method' => 'post', |
| 316 | + 'action' => |
| 317 | + $this->getTitle( $this->mUserName )->getLocalUrl( 'action=submit' ), |
| 318 | + 'id' => 'mw-centralauth-merged' ) ) . |
| 319 | + Html::hidden( 'wpMethod', 'unmerge' ) . |
| 320 | + Html::hidden( 'wpEditToken', $wgUser->editToken() ) . |
| 321 | + Xml::openElement( 'table', array( 'class' => 'wikitable sortable mw-centralauth-wikislist' ) ) . "\n" . |
| 322 | + '<thead><tr>' . |
| 323 | + ( $this->mCanUnmerge ? '<th></th>' : '' ) . |
| 324 | + '<th>' . wfMsgHtml( 'centralauth-admin-list-localwiki' ) . '</th>' . |
| 325 | + '<th>' . wfMsgHtml( 'centralauth-admin-list-attached-on' ) . '</th>' . |
| 326 | + '<th>' . wfMsgHtml( 'centralauth-admin-list-method' ) . '</th>' . |
| 327 | + '<th>' . wfMsgHtml( 'centralauth-admin-list-blocked' ) . '</th>' . |
| 328 | + '<th>' . wfMsgHtml( 'centralauth-admin-list-editcount' ) . '</th>' . |
| 329 | + '</tr></thead>' . |
| 330 | + '<tbody>'; |
| 331 | + } |
| 332 | + |
| 333 | + function listFooter() { |
| 334 | + $footer = ''; |
| 335 | + if ( $this->mCanUnmerge ) |
| 336 | + $footer .= |
| 337 | + '<tr>' . |
| 338 | + '<td style="border-right: none"></td>' . |
| 339 | + '<td style="border-left: none" colspan="5">' . |
| 340 | + Xml::submitButton( wfMsg( 'centralauth-admin-unmerge' ) ) . |
| 341 | + '</td>' . |
| 342 | + '</tr>'; |
| 343 | + $footer .= '</tbody></table></form>'; |
| 344 | + return $footer; |
| 345 | + } |
| 346 | + |
| 347 | + function listMerged( $list ) { |
| 348 | + ksort( $list ); |
| 349 | + return implode( "\n", array_map( array( $this, 'listMergedWikiItem' ), $list ) ); |
| 350 | + } |
| 351 | + |
| 352 | + function listRemainder( $list ) { |
| 353 | + ksort( $list ); |
| 354 | + $notMerged = wfMsgExt( 'centralauth-admin-unattached', array( 'parseinline' ) ); |
| 355 | + $rows = array(); |
| 356 | + foreach ( $list as $row ) { |
| 357 | + $rows[] = '<tr class="unattached-row"><td>' . |
| 358 | + ( $this->mCanUnmerge ? '</td><td>' : '' ) . |
| 359 | + $this->foreignUserLink( $row['wiki'] ) . |
| 360 | + "</td><td colspan='4'>{$notMerged}</td></tr>\n"; |
| 361 | + } |
| 362 | + return implode( $rows ); |
| 363 | + } |
| 364 | + |
| 365 | + function listMergedWikiItem( $row ) { |
| 366 | + global $wgLang; |
| 367 | + return '<tr>' . |
| 368 | + ( $this->mCanUnmerge ? '<td>' . $this->adminCheck( $row['wiki'] ) . '</td>' : '' ) . |
| 369 | + '<td>' . $this->foreignUserLink( $row['wiki'] ) . '</td>' . |
| 370 | + '<td>' . |
| 371 | + // invisible, to make this column sortable |
| 372 | + Html::element( 'span', array( 'style' => 'display: none' ), htmlspecialchars( $row['attachedTimestamp'] ) ) . |
| 373 | + // visible date and time in users preference |
| 374 | + htmlspecialchars( $wgLang->timeanddate( $row['attachedTimestamp'] ) ) . |
| 375 | + '</td>' . |
| 376 | + '<td style="text-align: center">' . $this->formatMergeMethod( $row['attachedMethod'] ) . '</td>' . |
| 377 | + '<td>' . $this->formatBlockStatus( $row ) . '</td>' . |
| 378 | + '<td style="text-align: right">' . $this->formatEditcount( $row ) . '</td>' . |
| 379 | + '</tr>'; |
| 380 | + } |
| 381 | + |
| 382 | + function formatMergeMethod( $method ) { |
| 383 | + global $wgExtensionAssetsPath; |
| 384 | + |
| 385 | + $img = htmlspecialchars( "{$wgExtensionAssetsPath}/CentralAuth/icons/merged-{$method}.png" ); |
| 386 | + $brief = wfMsgHtml( "centralauth-merge-method-{$method}" ); |
| 387 | + return "<img src=\"{$img}\" alt=\"{$brief}\" title=\"{$brief}\"/>" . |
| 388 | + "<span class=\"merge-method-help\" title=\"{$brief}\" onclick=\"showMethodHint('{$method}')\">(?)</span>"; |
| 389 | + } |
| 390 | + |
| 391 | + function formatBlockStatus( $row ) { |
| 392 | + if ( $row['blocked'] ) { |
| 393 | + if ( $row['block-expiry'] == 'infinity' ) { |
| 394 | + $reason = $row['block-reason']; |
| 395 | + return wfMsgExt( 'centralauth-admin-blocked-indef', 'parseinline', array( $reason ) ); |
| 396 | + } else { |
| 397 | + global $wgLang; |
| 398 | + $expiry = $wgLang->timeanddate( $row['block-expiry'] ); |
| 399 | + $expiryd = $wgLang->date( $row['block-expiry'] ); |
| 400 | + $expiryt = $wgLang->time( $row['block-expiry'] ); |
| 401 | + $reason = $row['block-reason']; |
| 402 | + |
| 403 | + $text = wfMsgExt( 'centralauth-admin-blocked', 'parseinline', array( $expiry, $reason, $expiryd, $expiryt ) ); |
| 404 | + } |
| 405 | + } else { |
| 406 | + $text = wfMsgExt( 'centralauth-admin-notblocked', 'parseinline' ); |
| 407 | + } |
| 408 | + |
| 409 | + return $this->foreignLink( |
| 410 | + $row['wiki'], |
| 411 | + 'Special:Log/block', |
| 412 | + $text, |
| 413 | + wfMsg( 'centralauth-admin-blocklog' ), |
| 414 | + 'page=User:' . urlencode( $this->mUserName ) ); |
| 415 | + } |
| 416 | + |
| 417 | + function formatEditcount( $row ) { |
| 418 | + global $wgLang; |
| 419 | + return $this->foreignLink( |
| 420 | + $row['wiki'], |
| 421 | + 'Special:Contributions/' . $this->mUserName, |
| 422 | + $wgLang->formatNum( intval( $row['editCount'] ) ), |
| 423 | + 'contributions' ); |
| 424 | + } |
| 425 | + |
| 426 | + function formatHiddenLevel( $level ) { |
| 427 | + switch( $level ) { |
| 428 | + case CentralAuthUser::HIDDEN_NONE: |
| 429 | + return wfMsg( 'centralauth-admin-no' ); |
| 430 | + case CentralAuthUser::HIDDEN_LISTS: |
| 431 | + return wfMsg( 'centralauth-admin-hidden-list' ); |
| 432 | + case CentralAuthUser::HIDDEN_OVERSIGHT: |
| 433 | + return wfMsg( 'centralauth-admin-hidden-oversight' ); |
| 434 | + } |
| 435 | + } |
| 436 | + |
| 437 | + function tableRow( $element, $cols ) { |
| 438 | + return "<tr><$element>" . |
| 439 | + implode( "</$element><$element>", $cols ) . |
| 440 | + "</$element></tr>"; |
| 441 | + } |
| 442 | + |
| 443 | + function foreignLink( $wikiID, $title, $text, $hint = '', $params = '' ) { |
| 444 | + if ( $wikiID instanceof WikiReference ) { |
| 445 | + $wiki = $wikiID; |
| 446 | + } else { |
| 447 | + $wiki = WikiMap::getWiki( $wikiID ); |
| 448 | + if ( !$wiki ) { |
| 449 | + throw new MWException( "Invalid wiki: $wikiID" ); |
| 450 | + } |
| 451 | + } |
| 452 | + |
| 453 | + $url = $wiki->getUrl( $title ); |
| 454 | + if ( $params ) |
| 455 | + $url .= '?' . $params; |
| 456 | + return Xml::element( 'a', |
| 457 | + array( |
| 458 | + 'href' => $url, |
| 459 | + 'title' => $hint, |
| 460 | + ), |
| 461 | + $text ); |
| 462 | + } |
| 463 | + |
| 464 | + function foreignUserLink( $wikiID ) { |
| 465 | + $wiki = WikiMap::getWiki( $wikiID ); |
| 466 | + if ( !$wiki ) { |
| 467 | + throw new MWException( "Invalid wiki: $wikiID" ); |
| 468 | + } |
| 469 | + |
| 470 | + $wikiname = $wiki->getDisplayName(); |
| 471 | + return $this->foreignLink( |
| 472 | + $wiki, |
| 473 | + 'User:' . $this->mUserName, |
| 474 | + $wikiname, |
| 475 | + wfMsg( 'centralauth-foreign-link', $this->mUserName, $wikiname ) ); |
| 476 | + |
| 477 | + } |
| 478 | + |
| 479 | + function adminCheck( $wikiID ) { |
| 480 | + return |
| 481 | + Xml::check( 'wpWikis[]', false, array( 'value' => $wikiID ) ); |
| 482 | + } |
| 483 | + |
| 484 | + function showActionForm( $action ) { |
| 485 | + global $wgOut, $wgUser; |
| 486 | + $wgOut->addHTML( |
| 487 | + Xml::fieldset( wfMsg( "centralauth-admin-{$action}-title" ) ) . |
| 488 | + Xml::openElement( 'form', array( |
| 489 | + 'method' => 'POST', |
| 490 | + 'action' => $this->getTitle()->getFullUrl( 'target=' . urlencode( $this->mUserName ) ), |
| 491 | + 'id' => "mw-centralauth-$action" ) ) . |
| 492 | + Html::hidden( 'wpMethod', $action ) . |
| 493 | + Html::hidden( 'wpEditToken', $wgUser->editToken() ) . |
| 494 | + wfMsgExt( "centralauth-admin-{$action}-description", 'parse' ) . |
| 495 | + Xml::buildForm( |
| 496 | + array( 'centralauth-admin-reason' => Xml::input( 'reason', |
| 497 | + false, false, array( 'id' => "{$action}-reason" ) ) ), |
| 498 | + "centralauth-admin-{$action}-button" |
| 499 | + ) . |
| 500 | + '</form></fieldset>' ); |
| 501 | + } |
| 502 | + |
| 503 | + function showStatusForm() { |
| 504 | + // Allows locking, hiding, locking and hiding. |
| 505 | + global $wgUser, $wgOut; |
| 506 | + $form = ''; |
| 507 | + $form .= Xml::fieldset( wfMsg( 'centralauth-admin-status' ) ); |
| 508 | + $form .= Html::hidden( 'wpMethod', 'set-status' ); |
| 509 | + $form .= Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
| 510 | + $form .= wfMsgExt( 'centralauth-admin-status-intro', 'parse' ); |
| 511 | + |
| 512 | + // Radio buttons |
| 513 | + $radioLocked = |
| 514 | + Xml::radioLabel( |
| 515 | + wfMsgExt( 'centralauth-admin-status-locked-no', array( 'parseinline' ) ), |
| 516 | + 'wpStatusLocked', |
| 517 | + '0', |
| 518 | + 'mw-centralauth-status-locked-no', |
| 519 | + !$this->mGlobalUser->isLocked() ) . |
| 520 | + '<br />' . |
| 521 | + Xml::radioLabel( |
| 522 | + wfMsgExt( 'centralauth-admin-status-locked-yes', array( 'parseinline' ) ), |
| 523 | + 'wpStatusLocked', |
| 524 | + '1', |
| 525 | + 'mw-centralauth-status-locked-yes', |
| 526 | + $this->mGlobalUser->isLocked() ); |
| 527 | + $radioHidden = |
| 528 | + Xml::radioLabel( |
| 529 | + wfMsgExt( 'centralauth-admin-status-hidden-no', array( 'parseinline' ) ), |
| 530 | + 'wpStatusHidden', |
| 531 | + CentralAuthUser::HIDDEN_NONE, |
| 532 | + 'mw-centralauth-status-hidden-no', |
| 533 | + $this->mGlobalUser->getHiddenLevel() == CentralAuthUser::HIDDEN_NONE ) . |
| 534 | + '<br />' . |
| 535 | + Xml::radioLabel( |
| 536 | + wfMsgExt( 'centralauth-admin-status-hidden-list', array( 'parseinline' ) ), |
| 537 | + 'wpStatusHidden', |
| 538 | + CentralAuthUser::HIDDEN_LISTS, |
| 539 | + 'mw-centralauth-status-hidden-list', |
| 540 | + $this->mGlobalUser->getHiddenLevel() == CentralAuthUser::HIDDEN_LISTS ) . |
| 541 | + '<br />'; |
| 542 | + if ( $this->mCanOversight ) { |
| 543 | + $radioHidden .= Xml::radioLabel( |
| 544 | + wfMsgExt( 'centralauth-admin-status-hidden-oversight', array( 'parseinline' ) ), |
| 545 | + 'wpStatusHidden', |
| 546 | + CentralAuthUser::HIDDEN_OVERSIGHT, |
| 547 | + 'mw-centralauth-status-hidden-oversight', |
| 548 | + $this->mGlobalUser->getHiddenLevel() == CentralAuthUser::HIDDEN_OVERSIGHT |
| 549 | + ); |
| 550 | + } |
| 551 | + |
| 552 | + // Reason |
| 553 | + $reasonList = Xml::listDropDown( |
| 554 | + 'wpReasonList', |
| 555 | + wfMsgForContent( 'centralauth-admin-status-reasons' ), |
| 556 | + wfMsgForContent( 'ipbreasonotherlist' ) |
| 557 | + ); |
| 558 | + $reasonField = Xml::input( 'wpReason', 45, false ); |
| 559 | + |
| 560 | + $form .= Xml::buildForm( |
| 561 | + array( |
| 562 | + 'centralauth-admin-status-locked' => $radioLocked, |
| 563 | + 'centralauth-admin-status-hidden' => $radioHidden, |
| 564 | + 'centralauth-admin-reason' => $reasonList, |
| 565 | + 'centralauth-admin-reason-other' => $reasonField ), |
| 566 | + 'centralauth-admin-status-submit' |
| 567 | + ); |
| 568 | + |
| 569 | + $form .= '</fieldset>'; |
| 570 | + $form = Xml::tags( |
| 571 | + 'form', |
| 572 | + array( |
| 573 | + 'method' => 'POST', |
| 574 | + 'action' => $this->getTitle()->getFullURL( |
| 575 | + array( 'target' => $this->mUserName ) |
| 576 | + ), |
| 577 | + ), |
| 578 | + $form |
| 579 | + ); |
| 580 | + $wgOut->addHTML( $form ); |
| 581 | + } |
| 582 | + |
| 583 | + function showLogExtract() { |
| 584 | + global $wgOut; |
| 585 | + $user = $this->mGlobalUser->getName(); |
| 586 | + $text = ''; |
| 587 | + $numRows = LogEventsList::showLogExtract( |
| 588 | + $text, |
| 589 | + array( 'globalauth', 'suppress' ), |
| 590 | + Title::newFromText( "User:{$user}@global" )->getPrefixedText(), |
| 591 | + '', |
| 592 | + array( 'showIfEmpty' => true ) ); |
| 593 | + if ( $numRows ) { |
| 594 | + $wgOut->addHTML( Xml::fieldset( wfMsg( 'centralauth-admin-logsnippet' ), $text ) ); |
| 595 | + } |
| 596 | + } |
| 597 | + |
| 598 | + function determineHomeWiki() { |
| 599 | + foreach ( $this->mAttachedLocalAccounts as $wiki => $acc ) { |
| 600 | + if ( $acc['attachedMethod'] == 'primary' || $acc['attachedMethod'] == 'new' ) { |
| 601 | + return $wiki; |
| 602 | + } |
| 603 | + } |
| 604 | + |
| 605 | + // Home account can be renamed or unmerged |
| 606 | + return wfMsgHtml( 'centralauth-admin-nohome' ); |
| 607 | + } |
| 608 | + |
| 609 | + function evaluateTotalEditcount() { |
| 610 | + $total = 0; |
| 611 | + foreach ( $this->mAttachedLocalAccounts as $acc ) { |
| 612 | + $total += $acc['editCount']; |
| 613 | + } |
| 614 | + return $total; |
| 615 | + } |
| 616 | + |
| 617 | + function addMergeMethodDescriptions() { |
| 618 | + global $wgOut, $wgLang; |
| 619 | + $js = "wgMergeMethodDescriptions = {\n"; |
| 620 | + foreach ( array( 'primary', 'new', 'empty', 'password', 'mail', 'admin', 'login' ) as $method ) { |
| 621 | + $short = Xml::encodeJsVar( $wgLang->ucfirst( wfMsgHtml( "centralauth-merge-method-{$method}" ) ) ); |
| 622 | + $desc = Xml::encodeJsVar( wfMsgWikiHtml( "centralauth-merge-method-{$method}-desc" ) ); |
| 623 | + $js .= "\t'{$method}' : { 'short' : {$short}, 'desc' : {$desc} },\n"; |
| 624 | + } |
| 625 | + $js .= "}"; |
| 626 | + $wgOut->addInlineScript( $js ); |
| 627 | + } |
| 628 | + |
| 629 | + function logAction( $action, $target, $reason = '', $params = array(), $suppressLog = false ) { |
| 630 | + $logType = $suppressLog ? 'suppress' : 'globalauth'; // Not centralauth because of some weird length limitiations |
| 631 | + $log = new LogPage( $logType ); |
| 632 | + $log->addEntry( $action, Title::newFromText( "User:{$target}@global" ), $reason, $params ); |
| 633 | + } |
| 634 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialCentralAuth.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 635 | + native |
Index: trunk/extensions/CentralAuth/specials/SpecialMergeAccount.php |
— | — | @@ -0,0 +1,518 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class SpecialMergeAccount extends SpecialPage { |
| 5 | + function __construct() { |
| 6 | + parent::__construct( 'MergeAccount', 'centralauth-merge' ); |
| 7 | + } |
| 8 | + |
| 9 | + function execute( $subpage ) { |
| 10 | + global $wgOut, $wgUser; |
| 11 | + $this->setHeaders(); |
| 12 | + |
| 13 | + if ( !$this->userCanExecute( $wgUser ) ) { |
| 14 | + $wgOut->addWikiMsg( 'centralauth-merge-denied' ); |
| 15 | + $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
| 16 | + return; |
| 17 | + } |
| 18 | + |
| 19 | + if ( !$wgUser->isLoggedIn() ) { |
| 20 | + $wgOut->addWikiMsg( 'centralauth-merge-notlogged' ); |
| 21 | + $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
| 22 | + |
| 23 | + return; |
| 24 | + } |
| 25 | + |
| 26 | + if ( wfReadOnly() ) { |
| 27 | + $wgOut->setPagetitle( wfMsg( 'readonly' ) ); |
| 28 | + $wgOut->addWikiMsg( 'readonlytext', wfReadOnlyReason() ); |
| 29 | + return; |
| 30 | + } |
| 31 | + |
| 32 | + global $wgUser, $wgRequest; |
| 33 | + $this->mUserName = $wgUser->getName(); |
| 34 | + |
| 35 | + $this->mAttemptMerge = $wgRequest->wasPosted(); |
| 36 | + |
| 37 | + $this->mMergeAction = $wgRequest->getVal( 'wpMergeAction' ); |
| 38 | + $this->mPassword = $wgRequest->getVal( 'wpPassword' ); |
| 39 | + $this->mWikiIDs = $wgRequest->getArray( 'wpWikis' ); |
| 40 | + $this->mSessionToken = $wgRequest->getVal( 'wpMergeSessionToken' ); |
| 41 | + $this->mSessionKey = pack( "H*", $wgRequest->getVal( 'wpMergeSessionKey' ) ); |
| 42 | + |
| 43 | + // Possible demo states |
| 44 | + |
| 45 | + // success, all accounts merged |
| 46 | + // successful login, some accounts merged, others left |
| 47 | + // successful login, others left |
| 48 | + // not account owner, others left |
| 49 | + |
| 50 | + // is owner / is not owner |
| 51 | + // did / did not merge some accounts |
| 52 | + // do / don't have more accounts to merge |
| 53 | + |
| 54 | + if ( $this->mAttemptMerge ) { |
| 55 | + switch( $this->mMergeAction ) { |
| 56 | + case "dryrun": |
| 57 | + return $this->doDryRunMerge(); |
| 58 | + case "initial": |
| 59 | + return $this->doInitialMerge(); |
| 60 | + case "cleanup": |
| 61 | + return $this->doCleanupMerge(); |
| 62 | + case "attach": |
| 63 | + return $this->doAttachMerge(); |
| 64 | + case "remove": |
| 65 | + return $this->doUnattach(); |
| 66 | + default: |
| 67 | + return $this->invalidAction(); |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + $globalUser = new CentralAuthUser( $this->mUserName ); |
| 72 | + if ( $globalUser->exists() ) { |
| 73 | + if ( $globalUser->isAttached() ) { |
| 74 | + $this->showCleanupForm(); |
| 75 | + } else { |
| 76 | + $this->showAttachForm(); |
| 77 | + } |
| 78 | + } else { |
| 79 | + $this->showWelcomeForm(); |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + /** |
| 84 | + * To pass potentially multiple passwords from one form submission |
| 85 | + * to another while previewing the merge behavior, we can store them |
| 86 | + * in the server-side session information. |
| 87 | + * |
| 88 | + * We'd rather not have plaintext passwords floating about on disk |
| 89 | + * or memcached, so the session store is obfuscated with simple XOR |
| 90 | + * encryption. The key is passed in the form instead of the session |
| 91 | + * data, so they won't be found floating in the same place. |
| 92 | + */ |
| 93 | + private function initSession() { |
| 94 | + global $wgUser; |
| 95 | + $this->mSessionToken = $wgUser->generateToken(); |
| 96 | + |
| 97 | + // Generate a random binary string |
| 98 | + $key = ''; |
| 99 | + for ( $i = 0; $i < 128; $i++ ) { |
| 100 | + $key .= chr( mt_rand( 0, 255 ) ); |
| 101 | + } |
| 102 | + $this->mSessionKey = $key; |
| 103 | + } |
| 104 | + |
| 105 | + private function getWorkingPasswords() { |
| 106 | + wfSuppressWarnings(); |
| 107 | + $passwords = unserialize( |
| 108 | + gzinflate( |
| 109 | + $this->xorString( |
| 110 | + $_SESSION['wsCentralAuthMigration'][$this->mSessionToken], |
| 111 | + $this->mSessionKey ) ) ); |
| 112 | + wfRestoreWarnings(); |
| 113 | + if ( is_array( $passwords ) ) { |
| 114 | + return $passwords; |
| 115 | + } |
| 116 | + return array(); |
| 117 | + } |
| 118 | + |
| 119 | + private function addWorkingPassword( $password ) { |
| 120 | + $passwords = $this->getWorkingPasswords(); |
| 121 | + if ( !in_array( $password, $passwords ) ) { |
| 122 | + $passwords[] = $password; |
| 123 | + } |
| 124 | + |
| 125 | + // Lightly obfuscate the passwords while we're storing them, |
| 126 | + // just to make us feel better about them floating around. |
| 127 | + $_SESSION['wsCentralAuthMigration'][$this->mSessionToken] = |
| 128 | + $this->xorString( |
| 129 | + gzdeflate( |
| 130 | + serialize( |
| 131 | + $passwords ) ), |
| 132 | + $this->mSessionKey ); |
| 133 | + } |
| 134 | + |
| 135 | + private function clearWorkingPasswords() { |
| 136 | + unset( $_SESSION['wsCentralAuthMigration'][$this->mSessionToken] ); |
| 137 | + } |
| 138 | + |
| 139 | + function xorString( $text, $key ) { |
| 140 | + if ( $key != '' ) { |
| 141 | + for ( $i = 0; $i < strlen( $text ); $i++ ) { |
| 142 | + $text[$i] = chr( 0xff & ( ord( $text[$i] ) ^ ord( $key[$i % strlen( $key )] ) ) ); |
| 143 | + } |
| 144 | + } |
| 145 | + return $text; |
| 146 | + } |
| 147 | + |
| 148 | + function doDryRunMerge() { |
| 149 | + global $wgUser, $wgRequest, $wgOut, $wgCentralAuthDryRun; |
| 150 | + $globalUser = new CentralAuthUser( $wgUser->getName() ); |
| 151 | + |
| 152 | + if ( $globalUser->exists() ) { |
| 153 | + throw new MWException( "Already exists -- race condition" ); |
| 154 | + } |
| 155 | + |
| 156 | + if ( $wgCentralAuthDryRun ) { |
| 157 | + $wgOut->addWikiMsg( 'centralauth-notice-dryrun' ); |
| 158 | + } |
| 159 | + |
| 160 | + $password = $wgRequest->getVal( 'wpPassword' ); |
| 161 | + $this->addWorkingPassword( $password ); |
| 162 | + $passwords = $this->getWorkingPasswords(); |
| 163 | + |
| 164 | + $home = false; |
| 165 | + $attached = array(); |
| 166 | + $unattached = array(); |
| 167 | + $methods = array(); |
| 168 | + $status = $globalUser->migrationDryRun( $passwords, $home, $attached, $unattached, $methods ); |
| 169 | + |
| 170 | + if ( $status->isGood() ) { |
| 171 | + // This is the global account or matched it |
| 172 | + if ( count( $unattached ) == 0 ) { |
| 173 | + // Everything matched -- very convenient! |
| 174 | + $wgOut->addWikiMsg( 'centralauth-merge-dryrun-complete' ); |
| 175 | + } else { |
| 176 | + $wgOut->addWikiMsg( 'centralauth-merge-dryrun-incomplete' ); |
| 177 | + } |
| 178 | + |
| 179 | + if ( count( $unattached ) > 0 ) { |
| 180 | + $wgOut->addHTML( $this->step2PasswordForm( $unattached ) ); |
| 181 | + $wgOut->addWikiMsg( 'centralauth-merge-dryrun-or' ); |
| 182 | + } |
| 183 | + |
| 184 | + $subAttached = array_diff( $attached, array( $home ) ); |
| 185 | + $wgOut->addHTML( $this->step3ActionForm( $home, $subAttached, $methods ) ); |
| 186 | + } else { |
| 187 | + // Show error message from status |
| 188 | + $wgOut->addHTML( '<div class="errorbox" style="float:none;">' ); |
| 189 | + $wgOut->addWikiText( $status->getWikiText() ); |
| 190 | + $wgOut->addHTML( '</div>' ); |
| 191 | + |
| 192 | + // Show wiki list if required |
| 193 | + if ( $status->hasMessage( 'centralauth-blocked-text' ) |
| 194 | + || $status->hasMessage( 'centralauth-merge-home-password' ) ) |
| 195 | + { |
| 196 | + $out = '<h2>' . wfMsgHtml( 'centralauth-list-home-title' ) . '</h2>'; |
| 197 | + $out .= wfMsgExt( 'centralauth-list-home-dryrun', 'parse' ); |
| 198 | + $out .= $this->listAttached( array( $home ), array( $home => 'primary' ) ); |
| 199 | + $wgOut->addHTML( $out ); |
| 200 | + } |
| 201 | + |
| 202 | + // Show password box |
| 203 | + $wgOut->addHTML( $this->step1PasswordForm() ); |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + function doInitialMerge() { |
| 208 | + global $wgUser, $wgCentralAuthDryRun; |
| 209 | + $globalUser = new CentralAuthUser( $wgUser->getName() ); |
| 210 | + |
| 211 | + if ( $wgCentralAuthDryRun ) { |
| 212 | + return $this->dryRunError(); |
| 213 | + } |
| 214 | + |
| 215 | + if ( $globalUser->exists() ) { |
| 216 | + throw new MWException( "Already exists -- race condition" ); |
| 217 | + } |
| 218 | + |
| 219 | + $passwords = $this->getWorkingPasswords(); |
| 220 | + if ( empty( $passwords ) ) { |
| 221 | + throw new MWException( "Submission error -- invalid input" ); |
| 222 | + } |
| 223 | + |
| 224 | + $globalUser->storeAndMigrate( $passwords ); |
| 225 | + $this->clearWorkingPasswords(); |
| 226 | + |
| 227 | + $this->showCleanupForm(); |
| 228 | + } |
| 229 | + |
| 230 | + function doCleanupMerge() { |
| 231 | + global $wgUser, $wgRequest, $wgOut, $wgCentralAuthDryRun; |
| 232 | + $globalUser = new CentralAuthUser( $wgUser->getName() ); |
| 233 | + |
| 234 | + if ( !$globalUser->exists() ) { |
| 235 | + throw new MWException( "User doesn't exist -- race condition?" ); |
| 236 | + } |
| 237 | + |
| 238 | + if ( !$globalUser->isAttached() ) { |
| 239 | + throw new MWException( "Can't cleanup merge if not already attached." ); |
| 240 | + } |
| 241 | + |
| 242 | + if ( $wgCentralAuthDryRun ) { |
| 243 | + return $this->dryRunError(); |
| 244 | + } |
| 245 | + $password = $wgRequest->getText( 'wpPassword' ); |
| 246 | + |
| 247 | + $attached = array(); |
| 248 | + $unattached = array(); |
| 249 | + $ok = $globalUser->attemptPasswordMigration( $password, $attached, $unattached ); |
| 250 | + $this->clearWorkingPasswords(); |
| 251 | + |
| 252 | + if ( !$ok ) { |
| 253 | + if ( empty( $attached ) ) { |
| 254 | + $wgOut->addWikiMsg( 'centralauth-finish-noconfirms' ); |
| 255 | + } else { |
| 256 | + $wgOut->addWikiMsg( 'centralauth-finish-incomplete' ); |
| 257 | + } |
| 258 | + } |
| 259 | + $this->showCleanupForm(); |
| 260 | + } |
| 261 | + |
| 262 | + function doAttachMerge() { |
| 263 | + global $wgUser, $wgRequest, $wgOut, $wgCentralAuthDryRun; |
| 264 | + $globalUser = new CentralAuthUser( $wgUser->getName() ); |
| 265 | + |
| 266 | + if ( !$globalUser->exists() ) { |
| 267 | + throw new MWException( "User doesn't exist -- race condition?" ); |
| 268 | + } |
| 269 | + |
| 270 | + if ( $globalUser->isAttached() ) { |
| 271 | + throw new MWException( "Already attached -- race condition?" ); |
| 272 | + } |
| 273 | + |
| 274 | + if ( $wgCentralAuthDryRun ) { |
| 275 | + return $this->dryRunError(); |
| 276 | + } |
| 277 | + $password = $wgRequest->getText( 'wpPassword' ); |
| 278 | + if ( $globalUser->authenticate( $password ) == 'ok' ) { |
| 279 | + $globalUser->attach( wfWikiID(), 'password' ); |
| 280 | + $wgOut->addWikiMsg( 'centralauth-attach-success' ); |
| 281 | + $this->showCleanupForm(); |
| 282 | + } else { |
| 283 | + $wgOut->addHTML( |
| 284 | + '<div class="errorbox">' . |
| 285 | + wfMsg( 'wrongpassword' ) . |
| 286 | + '</div>' . |
| 287 | + $this->attachActionForm() ); |
| 288 | + } |
| 289 | + } |
| 290 | + |
| 291 | + private function showWelcomeForm() { |
| 292 | + global $wgOut, $wgCentralAuthDryRun; |
| 293 | + |
| 294 | + if ( $wgCentralAuthDryRun ) { |
| 295 | + $wgOut->addWikiMsg( 'centralauth-notice-dryrun' ); |
| 296 | + } |
| 297 | + |
| 298 | + $wgOut->addWikiMsg( 'centralauth-merge-welcome' ); |
| 299 | + $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
| 300 | + |
| 301 | + $this->initSession(); |
| 302 | + $wgOut->addHTML( |
| 303 | + $this->passwordForm( |
| 304 | + 'dryrun', |
| 305 | + wfMsg( 'centralauth-merge-step1-title' ), |
| 306 | + wfMsg( 'centralauth-merge-step1-detail' ), |
| 307 | + wfMsg( 'centralauth-merge-step1-submit' ) ) |
| 308 | + ); |
| 309 | + } |
| 310 | + |
| 311 | + function showCleanupForm() { |
| 312 | + global $wgUser; |
| 313 | + $globalUser = new CentralAuthUser( $wgUser->getName() ); |
| 314 | + |
| 315 | + $merged = $globalUser->listAttached(); |
| 316 | + $remainder = $globalUser->listUnattached(); |
| 317 | + $this->showStatus( $merged, $remainder ); |
| 318 | + } |
| 319 | + |
| 320 | + function showAttachForm() { |
| 321 | + global $wgOut, $wgUser; |
| 322 | + $globalUser = new CentralAuthUser( $wgUser->getName() ); |
| 323 | + $merged = $globalUser->listAttached(); |
| 324 | + $wgOut->addWikiMsg( 'centralauth-attach-list-attached', $this->mUserName ); |
| 325 | + $wgOut->addHTML( $this->listAttached( $merged ) ); |
| 326 | + $wgOut->addHTML( $this->attachActionForm() ); |
| 327 | + } |
| 328 | + |
| 329 | + function showStatus( $merged, $remainder ) { |
| 330 | + global $wgOut; |
| 331 | + |
| 332 | + if ( count( $remainder ) > 0 ) { |
| 333 | + $wgOut->setPageTitle( wfMsg( 'centralauth-incomplete' ) ); |
| 334 | + $wgOut->addWikiMsg( 'centralauth-incomplete-text' ); |
| 335 | + } else { |
| 336 | + $wgOut->setPageTitle( wfMsg( 'centralauth-complete' ) ); |
| 337 | + $wgOut->addWikiMsg( 'centralauth-complete-text' ); |
| 338 | + } |
| 339 | + $wgOut->addWikiMsg( 'centralauth-readmore-text' ); |
| 340 | + |
| 341 | + if ( $merged ) { |
| 342 | + $wgOut->addHTML( '<hr />' ); |
| 343 | + $wgOut->addWikiMsg( 'centralauth-list-attached', |
| 344 | + $this->mUserName ); |
| 345 | + $wgOut->addHTML( $this->listAttached( $merged ) ); |
| 346 | + } |
| 347 | + |
| 348 | + if ( $remainder ) { |
| 349 | + $wgOut->addHTML( '<hr />' ); |
| 350 | + $wgOut->addWikiMsg( 'centralauth-list-unattached', |
| 351 | + $this->mUserName ); |
| 352 | + $wgOut->addHTML( $this->listUnattached( $remainder ) ); |
| 353 | + |
| 354 | + // Try the password form! |
| 355 | + $wgOut->addHTML( $this->passwordForm( |
| 356 | + 'cleanup', |
| 357 | + wfMsg( 'centralauth-finish-title' ), |
| 358 | + wfMsgExt( 'centralauth-finish-text', array( 'parse' ) ), |
| 359 | + wfMsg( 'centralauth-finish-login' ) ) ); |
| 360 | + } |
| 361 | + } |
| 362 | + |
| 363 | + function listAttached( $wikiList, $methods = array() ) { |
| 364 | + return $this->listWikis( $wikiList, $methods ); |
| 365 | + } |
| 366 | + |
| 367 | + function listUnattached( $wikiList ) { |
| 368 | + return $this->listWikis( $wikiList ); |
| 369 | + } |
| 370 | + |
| 371 | + function listWikis( $list, $methods = array() ) { |
| 372 | + asort( $list ); |
| 373 | + return $this->formatList( $list, $methods, array( $this, 'listWikiItem' ) ); |
| 374 | + } |
| 375 | + |
| 376 | + function formatList( $items, $methods, $callback ) { |
| 377 | + if ( !$items ) { |
| 378 | + return ''; |
| 379 | + } else { |
| 380 | + $itemMethods = array(); |
| 381 | + foreach ( $items as $item ) { |
| 382 | + $itemMethods[] = isset( $methods[$item] ) ? $methods[$item] : ''; |
| 383 | + } |
| 384 | + return "<ul>\n<li>" . |
| 385 | + implode( "</li>\n<li>", |
| 386 | + array_map( $callback, $items, $itemMethods ) ) . |
| 387 | + "</li>\n</ul>\n"; |
| 388 | + } |
| 389 | + } |
| 390 | + |
| 391 | + function listWikiItem( $wikiID, $method ) { |
| 392 | + return |
| 393 | + $this->foreignUserLink( $wikiID ) . ( $method ? ' (' . wfMsgHtml( "centralauth-merge-method-$method" ) . ')' : '' ); |
| 394 | + } |
| 395 | + |
| 396 | + function foreignUserLink( $wikiID ) { |
| 397 | + $wiki = WikiMap::getWiki( $wikiID ); |
| 398 | + if ( !$wiki ) { |
| 399 | + throw new MWException( "no wiki for $wikiID" ); |
| 400 | + } |
| 401 | + |
| 402 | + $hostname = $wiki->getDisplayName(); |
| 403 | + $userPageName = 'User:' . $this->mUserName; |
| 404 | + $url = $wiki->getUrl( $userPageName ); |
| 405 | + return Xml::element( 'a', |
| 406 | + array( |
| 407 | + 'href' => $url, |
| 408 | + 'title' => wfMsg( 'centralauth-foreign-link', |
| 409 | + $this->mUserName, |
| 410 | + $hostname ), |
| 411 | + ), |
| 412 | + $hostname ); |
| 413 | + } |
| 414 | + |
| 415 | + private function actionForm( $action, $title, $text ) { |
| 416 | + global $wgUser; |
| 417 | + return |
| 418 | + '<div id="userloginForm">' . |
| 419 | + Xml::openElement( 'form', |
| 420 | + array( |
| 421 | + 'method' => 'post', |
| 422 | + 'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) ) . |
| 423 | + Xml::element( 'h2', array(), $title ) . |
| 424 | + Html::hidden( 'wpEditToken', $wgUser->editToken() ) . |
| 425 | + Html::hidden( 'wpMergeAction', $action ) . |
| 426 | + Html::hidden( 'wpMergeSessionToken', $this->mSessionToken ) . |
| 427 | + Html::hidden( 'wpMergeSessionKey', bin2hex( $this->mSessionKey ) ) . |
| 428 | + |
| 429 | + $text . |
| 430 | + |
| 431 | + Xml::closeElement( 'form' ) . |
| 432 | + |
| 433 | + '<br clear="all" />' . |
| 434 | + |
| 435 | + '</div>'; |
| 436 | + } |
| 437 | + |
| 438 | + private function passwordForm( $action, $title, $text, $submit ) { |
| 439 | + return $this->actionForm( |
| 440 | + $action, |
| 441 | + $title, |
| 442 | + $text . |
| 443 | + '<table>' . |
| 444 | + '<tr>' . |
| 445 | + '<td>' . |
| 446 | + Xml::label( |
| 447 | + wfMsg( 'centralauth-finish-password' ), |
| 448 | + 'wpPassword1' ) . |
| 449 | + '</td>' . |
| 450 | + '<td>' . |
| 451 | + Xml::input( |
| 452 | + 'wpPassword', 20, '', |
| 453 | + array( |
| 454 | + 'type' => 'password', |
| 455 | + 'id' => 'wpPassword1' ) ) . |
| 456 | + '</td>' . |
| 457 | + '</tr>' . |
| 458 | + '<tr>' . |
| 459 | + '<td></td>' . |
| 460 | + '<td>' . |
| 461 | + Xml::submitButton( $submit, |
| 462 | + array( 'name' => 'wpLogin' ) ) . |
| 463 | + '</td>' . |
| 464 | + '</tr>' . |
| 465 | + '</table>' ); |
| 466 | + } |
| 467 | + |
| 468 | + private function step1PasswordForm() { |
| 469 | + return $this->passwordForm( |
| 470 | + 'dryrun', |
| 471 | + wfMsg( 'centralauth-merge-step1-title' ), |
| 472 | + wfMsg( 'centralauth-merge-step1-detail' ), |
| 473 | + wfMsg( 'centralauth-merge-step1-submit' ) ); |
| 474 | + } |
| 475 | + |
| 476 | + private function step2PasswordForm( $unattached ) { |
| 477 | + global $wgUser; |
| 478 | + return $this->passwordForm( |
| 479 | + 'dryrun', |
| 480 | + wfMsg( 'centralauth-merge-step2-title' ), |
| 481 | + wfMsgExt( 'centralauth-merge-step2-detail', 'parse', $wgUser->getName() ) . |
| 482 | + $this->listUnattached( $unattached ), |
| 483 | + wfMsg( 'centralauth-merge-step2-submit' ) ); |
| 484 | + } |
| 485 | + |
| 486 | + private function step3ActionForm( $home, $attached, $methods ) { |
| 487 | + global $wgUser; |
| 488 | + return $this->actionForm( |
| 489 | + 'initial', |
| 490 | + wfMsg( 'centralauth-merge-step3-title' ), |
| 491 | + wfMsgExt( 'centralauth-merge-step3-detail', 'parse', $wgUser->getName() ) . |
| 492 | + '<h3>' . wfMsgHtml( 'centralauth-list-home-title' ) . '</h3>' . |
| 493 | + wfMsgExt( 'centralauth-list-home-dryrun', 'parse' ) . |
| 494 | + $this->listAttached( array( $home ), $methods ) . |
| 495 | + ( count( $attached ) |
| 496 | + ? ( '<h3>' . wfMsgHtml( 'centralauth-list-attached-title' ) . '</h3>' . |
| 497 | + wfMsgExt( 'centralauth-list-attached-dryrun', 'parse', $wgUser->getName() ) ) |
| 498 | + : '' ) . |
| 499 | + $this->listAttached( $attached, $methods ) . |
| 500 | + '<p>' . |
| 501 | + Xml::submitButton( wfMsg( 'centralauth-merge-step3-submit' ), |
| 502 | + array( 'name' => 'wpLogin' ) ) . |
| 503 | + '</p>' |
| 504 | + ); |
| 505 | + } |
| 506 | + |
| 507 | + private function attachActionForm() { |
| 508 | + return $this->passwordForm( |
| 509 | + 'attach', |
| 510 | + wfMsg( 'centralauth-attach-title' ), |
| 511 | + wfMsg( 'centralauth-attach-text' ), |
| 512 | + wfMsg( 'centralauth-attach-submit' ) ); |
| 513 | + } |
| 514 | + |
| 515 | + private function dryRunError() { |
| 516 | + global $wgOut; |
| 517 | + $wgOut->addWikiMsg( 'centralauth-disabled-dryrun' ); |
| 518 | + } |
| 519 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialMergeAccount.php |
___________________________________________________________________ |
Added: svn:keywords |
1 | 520 | + LastChangedDate LastChangedRevision |
Added: svn:eol-style |
2 | 521 | + native |
Index: trunk/extensions/CentralAuth/specials/SpecialAutoLogin.php |
— | — | @@ -0,0 +1,86 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 4 | + die( 'CentralAuth' ); |
| 5 | +} |
| 6 | + |
| 7 | +/** |
| 8 | + * Unlisted Special page to set requisite cookies for being logged into this wiki. |
| 9 | + * |
| 10 | + * @ingroup Extensions |
| 11 | + */ |
| 12 | +class SpecialAutoLogin extends UnlistedSpecialPage { |
| 13 | + function __construct() { |
| 14 | + parent::__construct( 'AutoLogin' ); |
| 15 | + } |
| 16 | + |
| 17 | + function execute( $par ) { |
| 18 | + global $wgRequest, $wgOut, $wgMemc; |
| 19 | + |
| 20 | + $tempToken = $wgRequest->getVal( 'token' ); |
| 21 | + $logout = $wgRequest->getBool( 'logout' ); |
| 22 | + |
| 23 | + # Don't cache error messages |
| 24 | + $wgOut->enableClientCache( false ); |
| 25 | + |
| 26 | + if ( strlen( $tempToken ) == 0 ) { |
| 27 | + $this->setHeaders(); |
| 28 | + $wgOut->addWikiMsg( 'centralauth-autologin-desc' ); |
| 29 | + return; |
| 30 | + } |
| 31 | + |
| 32 | + $key = CentralAuthUser::memcKey( 'login-token', $tempToken ); |
| 33 | + $data = $wgMemc->get( $key ); |
| 34 | + $wgMemc->delete( $key ); |
| 35 | + |
| 36 | + if ( !$data ) { |
| 37 | + $msg = 'Token is invalid or has expired'; |
| 38 | + wfDebug( __METHOD__ . ": $msg\n" ); |
| 39 | + $this->setHeaders(); |
| 40 | + $wgOut->addWikiText( $msg ); |
| 41 | + return; |
| 42 | + } |
| 43 | + |
| 44 | + $userName = $data['userName']; |
| 45 | + $token = $data['token']; |
| 46 | + $remember = $data['remember']; |
| 47 | + |
| 48 | + if ( $data['wiki'] != wfWikiID() ) { |
| 49 | + $msg = 'Bad token (wrong wiki)'; |
| 50 | + wfDebug( __METHOD__ . ": $msg\n" ); |
| 51 | + $this->setHeaders(); |
| 52 | + $wgOut->addWikiText( $msg ); |
| 53 | + return; |
| 54 | + } |
| 55 | + |
| 56 | + $centralUser = new CentralAuthUser( $userName ); |
| 57 | + $loginResult = $centralUser->authenticateWithToken( $token ); |
| 58 | + |
| 59 | + if ( $loginResult != 'ok' ) { |
| 60 | + $msg = "Bad token: $loginResult"; |
| 61 | + wfDebug( __METHOD__ . ": $msg\n" ); |
| 62 | + $this->setHeaders(); |
| 63 | + $wgOut->addWikiText( $msg ); |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + // Auth OK. |
| 68 | + if ( $logout ) { |
| 69 | + $centralUser->deleteGlobalCookies(); |
| 70 | + } else { |
| 71 | + $centralUser->setGlobalCookies( $remember ); |
| 72 | + } |
| 73 | + |
| 74 | + $wgOut->disable(); |
| 75 | + |
| 76 | + wfResetOutputBuffers(); |
| 77 | + header( 'Cache-Control: no-cache' ); |
| 78 | + header( 'Content-Type: image/png' ); |
| 79 | + |
| 80 | + global $wgCentralAuthLoginIcon; |
| 81 | + if ( $wgCentralAuthLoginIcon ) { |
| 82 | + readfile( $wgCentralAuthLoginIcon ); |
| 83 | + } else { |
| 84 | + readfile( dirname( __FILE__ ) . '/1x1.png' ); |
| 85 | + } |
| 86 | + } |
| 87 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialAutoLogin.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 88 | + native |
Index: trunk/extensions/CentralAuth/specials/SpecialGlobalUsers.php |
— | — | @@ -0,0 +1,155 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class SpecialGlobalUsers extends SpecialPage { |
| 5 | + function __construct() { |
| 6 | + parent::__construct( 'GlobalUsers' ); |
| 7 | + } |
| 8 | + |
| 9 | + function execute( $par ) { |
| 10 | + global $wgOut, $wgRequest, $wgContLang; |
| 11 | + $this->setHeaders(); |
| 12 | + |
| 13 | + $pg = new GlobalUsersPager(); |
| 14 | + |
| 15 | + if ( $par ) { |
| 16 | + $pg->setGroup( $par ); |
| 17 | + } |
| 18 | + $rqGroup = $wgRequest->getVal( 'group' ); |
| 19 | + if ( $rqGroup ) { |
| 20 | + $pg->setGroup( $rqGroup ); |
| 21 | + } |
| 22 | + $rqUsername = $wgContLang->ucfirst( $wgRequest->getVal( 'username' ) ); |
| 23 | + if ( $rqUsername ) { |
| 24 | + $pg->setUsername( $rqUsername ); |
| 25 | + } |
| 26 | + |
| 27 | + $wgOut->addHTML( $pg->getPageHeader() ); |
| 28 | + $wgOut->addHTML( $pg->getNavigationBar() ); |
| 29 | + $wgOut->addHTML( '<ul>' . $pg->getBody() . '</ul>' ); |
| 30 | + $wgOut->addHTML( $pg->getNavigationBar() ); |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +class GlobalUsersPager extends UsersPager { |
| 35 | + protected $requestedGroup = false, $requestedUser; |
| 36 | + |
| 37 | + function __construct() { |
| 38 | + parent::__construct(); |
| 39 | + $this->mDb = CentralAuthUser::getCentralSlaveDB(); |
| 40 | + } |
| 41 | + |
| 42 | + function setGroup( $group = '' ) { |
| 43 | + if ( !$group ) { |
| 44 | + $this->requestedGroup = false; |
| 45 | + return; |
| 46 | + } |
| 47 | + $groups = array_keys( $this->getAllGroups() ); |
| 48 | + $this->requestedGroup = $group; |
| 49 | + } |
| 50 | + |
| 51 | + function setUsername( $username = '' ) { |
| 52 | + if ( !$username ) { |
| 53 | + $this->requestedUser = false; |
| 54 | + return; |
| 55 | + } |
| 56 | + $this->requestedUser = $username; |
| 57 | + } |
| 58 | + |
| 59 | + function getIndexField() { |
| 60 | + return 'gu_name'; |
| 61 | + } |
| 62 | + |
| 63 | + function getDefaultQuery() { |
| 64 | + $query = parent::getDefaultQuery(); |
| 65 | + if ( !isset( $query['group'] ) && $this->requestedGroup ) { |
| 66 | + $query['group'] = $this->requestedGroup; |
| 67 | + } |
| 68 | + return $this->mDefaultQuery = $query; |
| 69 | + |
| 70 | + } |
| 71 | + |
| 72 | + function getQueryInfo() { |
| 73 | + $localwiki = wfWikiID(); |
| 74 | + $conds = array( 'gu_hidden' => CentralAuthUser::HIDDEN_NONE ); |
| 75 | + |
| 76 | + if ( $this->requestedGroup ) { |
| 77 | + $conds['gug_group'] = $this->requestedGroup; |
| 78 | + } |
| 79 | + |
| 80 | + if ( $this->requestedUser ) { |
| 81 | + $conds[] = 'gu_name >= ' . $this->mDb->addQuotes( $this->requestedUser ); |
| 82 | + } |
| 83 | + |
| 84 | + return array( |
| 85 | + 'tables' => " (globaluser LEFT JOIN localuser ON gu_name = lu_name AND lu_wiki = '{$localwiki}') LEFT JOIN global_user_groups ON gu_id = gug_user ", |
| 86 | + 'fields' => array( 'gu_id', 'gu_name', 'gu_locked', 'lu_attached_method', 'COUNT(gug_group) AS gug_numgroups', 'MAX(gug_group) AS gug_singlegroup' ), |
| 87 | + 'conds' => $conds, |
| 88 | + 'options' => array( 'GROUP BY' => 'gu_name' ), |
| 89 | + ); |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Formats a row |
| 94 | + * @param object $row The row to be formatted for output |
| 95 | + * @return string HTML li element with username and info about this user |
| 96 | + */ |
| 97 | + function formatRow( $row ) { |
| 98 | + global $wgLang; |
| 99 | + $user = htmlspecialchars( $row->gu_name ); |
| 100 | + $info = array(); |
| 101 | + if ( $row->gu_locked ) { |
| 102 | + $info[] = wfMsg( 'centralauth-listusers-locked' ); |
| 103 | + } |
| 104 | + if ( $row->lu_attached_method ) { |
| 105 | + $info[] = wfMsg( 'centralauth-listusers-attached', $row->gu_name ); |
| 106 | + } else { |
| 107 | + $info[] = wfMsg( 'centralauth-listusers-nolocal' ); |
| 108 | + } |
| 109 | + $groups = $this->getUserGroups( $row ); |
| 110 | + |
| 111 | + if ( $groups ) { |
| 112 | + $info[] = $groups; |
| 113 | + } |
| 114 | + $info = $wgLang->commaList( $info ); |
| 115 | + return Html::rawElement( 'li', array(), wfMsgExt( 'centralauth-listusers-item', array('parseinline'), $user, $info ) ); |
| 116 | + } |
| 117 | + |
| 118 | + function getBody() { |
| 119 | + if ( !$this->mQueryDone ) { |
| 120 | + $this->doQuery(); |
| 121 | + } |
| 122 | + $batch = new LinkBatch; |
| 123 | + |
| 124 | + $this->mResult->rewind(); |
| 125 | + |
| 126 | + foreach ( $this->mResult as $row ) { |
| 127 | + $batch->addObj( Title::makeTitleSafe( NS_USER, $row->gu_name ) ); |
| 128 | + } |
| 129 | + $batch->execute(); |
| 130 | + $this->mResult->rewind(); |
| 131 | + return AlphabeticPager::getBody(); |
| 132 | + } |
| 133 | + |
| 134 | + protected function getUserGroups( $row ) { |
| 135 | + if ( !$row->gug_numgroups ) { |
| 136 | + return false; |
| 137 | + } |
| 138 | + if ( $row->gug_numgroups == 1 ) { |
| 139 | + return User::makeGroupLinkWiki( $row->gug_singlegroup, User::getGroupMember( $row->gug_singlegroup ) ); |
| 140 | + } |
| 141 | + $result = $this->mDb->select( 'global_user_groups', 'gug_group', array( 'gug_user' => $row->gu_id ), __METHOD__ ); |
| 142 | + $rights = array(); |
| 143 | + foreach ( $result as $row2 ) { |
| 144 | + $rights[] = User::makeGroupLinkWiki( $row2->gug_group, User::getGroupMember( $row2->gug_group ) ); |
| 145 | + } |
| 146 | + return implode( ', ', $rights ); |
| 147 | + } |
| 148 | + |
| 149 | + public function getAllGroups() { |
| 150 | + $result = array(); |
| 151 | + foreach ( CentralAuthUser::availableGlobalGroups() as $group ) { |
| 152 | + $result[$group] = User::getGroupName( $group ); |
| 153 | + } |
| 154 | + return $result; |
| 155 | + } |
| 156 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialGlobalUsers.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 157 | + native |
Index: trunk/extensions/CentralAuth/specials/SpecialWikiSets.php |
— | — | @@ -0,0 +1,293 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Special page to allow to edit "wikisets" which are used to restrict |
| 5 | + * specific global group permissions to certain wikis. |
| 6 | + * |
| 7 | + * @file |
| 8 | + * @ingroup Extensions |
| 9 | + */ |
| 10 | + |
| 11 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 12 | + echo "CentralAuth extension\n"; |
| 13 | + exit( 1 ); |
| 14 | +} |
| 15 | + |
| 16 | + |
| 17 | +class SpecialWikiSets extends SpecialPage { |
| 18 | + var $mCanEdit; |
| 19 | + |
| 20 | + function __construct() { |
| 21 | + parent::__construct( 'WikiSets' ); |
| 22 | + } |
| 23 | + |
| 24 | + function getDescription() { |
| 25 | + return wfMsg( 'centralauth-editset' ); |
| 26 | + } |
| 27 | + |
| 28 | + function execute( $subpage ) { |
| 29 | + global $wgRequest, $wgOut, $wgUser; |
| 30 | + |
| 31 | + $this->mCanEdit = $wgUser->isAllowed( 'globalgrouppermissions' ); |
| 32 | + |
| 33 | + $this->setHeaders(); |
| 34 | + |
| 35 | + if ( strpos( $subpage, 'delete/' ) === 0 && $this->mCanEdit ) { |
| 36 | + $subpage = substr( $subpage, 7 ); // Remove delete/ part |
| 37 | + if ( is_numeric( $subpage ) ) { |
| 38 | + if ( $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) |
| 39 | + $this->doDelete( $subpage ); |
| 40 | + else |
| 41 | + $this->buildDeleteView( $subpage ); |
| 42 | + } else { |
| 43 | + $this->buildMainView(); |
| 44 | + } |
| 45 | + } else { |
| 46 | + if ( $subpage ) { |
| 47 | + $set = is_numeric( $subpage ) ? WikiSet::newFromId( $subpage ) : WikiSet::newFromName( $subpage ); |
| 48 | + if ( $set ) { |
| 49 | + $subpage = $set->getID(); |
| 50 | + } else { |
| 51 | + $wgOut->setPageTitle( wfMsg( 'error' ) ); |
| 52 | + $error = wfMsgExt( 'centralauth-editset-notfound', array( 'escapenoentities' ), $subpage ); |
| 53 | + $this->buildMainView( "<strong class='error'>{$error}</strong>" ); |
| 54 | + return; |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + if ( ( $subpage || $subpage === '0' ) && $this->mCanEdit && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
| 59 | + $this->doSubmit( $subpage ); |
| 60 | + } else if ( ( $subpage || $subpage === '0' ) && is_numeric( $subpage ) ) { |
| 61 | + $this->buildSetView( $subpage ); |
| 62 | + } else { |
| 63 | + $this->buildMainView(); |
| 64 | + } |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + function buildMainView( $msg = '' ) { |
| 69 | + global $wgOut, $wgUser; |
| 70 | + $sk = $wgUser->getSkin(); |
| 71 | + |
| 72 | + $msgPostfix = $this->mCanEdit ? 'rw' : 'ro'; |
| 73 | + $legend = wfMsg( "centralauth-editset-legend-{$msgPostfix}" ); |
| 74 | + $wgOut->addHTML( "<fieldset><legend>{$legend}</legend>" ); |
| 75 | + if ( $msg ) |
| 76 | + $wgOut->addHTML( $msg ); |
| 77 | + $wgOut->addWikiMsg( "centralauth-editset-intro-{$msgPostfix}" ); |
| 78 | + $wgOut->addHTML( '<ul>' ); |
| 79 | + |
| 80 | + $sets = WikiSet::getAllWikiSets(); |
| 81 | + foreach ( $sets as $set ) { |
| 82 | + $text = wfMsgExt( "centralauth-editset-item-{$msgPostfix}", array( 'parseinline' ), $set->getName(), $set->getID() ); |
| 83 | + $wgOut->addHTML( "<li>{$text}</li>" ); |
| 84 | + } |
| 85 | + |
| 86 | + if ( $this->mCanEdit ) { |
| 87 | + $target = SpecialPage::getTitleFor( 'WikiSets', '0' ); |
| 88 | + $newlink = $sk->makeLinkObj( $target, wfMsgHtml( 'centralauth-editset-new' ) ); |
| 89 | + $wgOut->addHTML( "<li>{$newlink}</li>" ); |
| 90 | + } |
| 91 | + |
| 92 | + $wgOut->addHTML( '</ul></fieldset>' ); |
| 93 | + } |
| 94 | + |
| 95 | + function buildSetView( $subpage, $error = false, $name = null, $type = null, $wikis = null, $reason = null ) { |
| 96 | + global $wgOut, $wgUser; |
| 97 | + |
| 98 | + $wgOut->setSubtitle( wfMsgExt( 'centralauth-editset-subtitle', 'parseinline' ) ); |
| 99 | + |
| 100 | + $set = $subpage ? WikiSet::newFromID( $subpage ) : null; |
| 101 | + if ( !$name ) $name = $set ? $set->getName() : ''; |
| 102 | + if ( !$type ) $type = $set ? $set->getType() : WikiSet::OPTIN; |
| 103 | + if ( !$wikis ) $wikis = implode( "\n", $set ? $set->getWikisRaw() : array() ); |
| 104 | + else $wikis = implode( "\n", $wikis ); |
| 105 | + $url = SpecialPage::getTitleFor( 'WikiSets', $subpage )->getLocalUrl(); |
| 106 | + if ( $this->mCanEdit ) { |
| 107 | + $legend = wfMsgHtml( 'centralauth-editset-legend-' . ( $set ? 'edit' : 'new' ), $name ); |
| 108 | + } else { |
| 109 | + $legend = wfMsgHtml( 'centralauth-editset-legend-view', $name ); |
| 110 | + } |
| 111 | + |
| 112 | + $wgOut->addHTML( "<fieldset><legend>{$legend}</legend>" ); |
| 113 | + |
| 114 | + if ( $set ) { |
| 115 | + $groups = $set->getRestrictedGroups(); |
| 116 | + if ( $groups ) { |
| 117 | + $usage = "<ul>\n"; |
| 118 | + foreach ( $groups as $group ) |
| 119 | + $usage .= "<li>" . wfMsgExt( 'centralauth-editset-grouplink', 'parseinline', $group ) . "</li>\n"; |
| 120 | + $usage .= "</ul>"; |
| 121 | + } else { |
| 122 | + $usage = wfMsgExt( 'centralauth-editset-nouse', 'parse' ); |
| 123 | + } |
| 124 | + } else { |
| 125 | + $usage = ''; |
| 126 | + } |
| 127 | + |
| 128 | + if ( $this->mCanEdit ) { |
| 129 | + if ( $error ) { |
| 130 | + $wgOut->addHTML( "<strong class='error'>{$error}</strong>" ); |
| 131 | + } |
| 132 | + $wgOut->addHTML( "<form action='{$url}' method='post'>" ); |
| 133 | + |
| 134 | + $form = array(); |
| 135 | + $form['centralauth-editset-name'] = Xml::input( 'wpName', false, $name ); |
| 136 | + if ( $usage ) { |
| 137 | + $form['centralauth-editset-usage'] = $usage; |
| 138 | + } |
| 139 | + $form['centralauth-editset-type'] = $this->buildTypeSelector( 'wpType', $type ); |
| 140 | + $form['centralauth-editset-wikis'] = Xml::textarea( 'wpWikis', $wikis ); |
| 141 | + $form['centralauth-editset-reason'] = Xml::input( 'wpReason', false, $reason ); |
| 142 | + |
| 143 | + $wgOut->addHTML( Xml::buildForm( $form, 'centralauth-editset-submit' ) ); |
| 144 | + |
| 145 | + $edittoken = Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
| 146 | + $wgOut->addHTML( "<p>{$edittoken}</p></form></fieldset>" ); |
| 147 | + } else { |
| 148 | + $form = array(); |
| 149 | + $form['centralauth-editset-name'] = htmlspecialchars( $name ); |
| 150 | + $form['centralauth-editset-usage'] = $usage; |
| 151 | + $form['centralauth-editset-type'] = wfMsg( "centralauth-editset-{$type}" ); |
| 152 | + $form['centralauth-editset-wikis'] = $this->buildWikiList( $set->getWikisRaw() ); |
| 153 | + |
| 154 | + $wgOut->addHTML( Xml::buildForm( $form ) ); |
| 155 | + } |
| 156 | + } |
| 157 | + |
| 158 | + function buildTypeSelector( $name, $value ) { |
| 159 | + $select = new XmlSelect( $name, 'set-type', $value ); |
| 160 | + foreach ( array( WikiSet::OPTIN, WikiSet::OPTOUT ) as $type ) { |
| 161 | + $select->addOption( wfMsg( "centralauth-editset-{$type}" ), $type ); |
| 162 | + } |
| 163 | + return $select->getHTML(); |
| 164 | + } |
| 165 | + |
| 166 | + function buildWikiList( $list ) { |
| 167 | + sort( $list ); |
| 168 | + $html = '<ul>'; |
| 169 | + foreach ( $list as $wiki ) { |
| 170 | + $escWiki = htmlspecialchars( $wiki ); |
| 171 | + $html .= "<li>{$escWiki}</li>"; |
| 172 | + } |
| 173 | + $html .= '</ul>'; |
| 174 | + return $html; |
| 175 | + } |
| 176 | + |
| 177 | + function buildDeleteView( $subpage ) { |
| 178 | + global $wgOut, $wgUser; |
| 179 | + $wgOut->setSubtitle( wfMsgExt( 'centralauth-editset-subtitle', 'parseinline' ) ); |
| 180 | + |
| 181 | + $set = WikiSet::newFromID( $subpage ); |
| 182 | + if ( !$set ) { |
| 183 | + $this->buildMainView( '<strong class="error">' . wfMsgHtml( 'centralauth-editset-notfound', $subpage ) . '</strong>' ); |
| 184 | + return; |
| 185 | + } |
| 186 | + |
| 187 | + $legend = wfMsgHtml( 'centralauth-editset-legend-delete', $set->getName() ); |
| 188 | + $form = array( 'centralauth-editset-reason' => Xml::input( 'wpReason' ) ); |
| 189 | + $url = htmlspecialchars( SpecialPage::getTitleFor( 'WikiSets', "delete/{$subpage}" )->getLocalUrl() ); |
| 190 | + $edittoken = Html::hidden( 'wpEditToken', $wgUser->editToken() ); |
| 191 | + |
| 192 | + $wgOut->addHTML( "<fieldset><legend>{$legend}</legend><form action='{$url}' method='post'>" ); |
| 193 | + $wgOut->addHTML( Xml::buildForm( $form, 'centralauth-editset-submit-delete' ) ); |
| 194 | + $wgOut->addHTML( "<p>{$edittoken}</p></form></fieldset>" ); |
| 195 | + } |
| 196 | + |
| 197 | + function doSubmit( $id ) { |
| 198 | + global $wgRequest, $wgContLang; |
| 199 | + |
| 200 | + $name = $wgContLang->ucfirst( $wgRequest->getVal( 'wpName' ) ); |
| 201 | + $type = $wgRequest->getVal( 'wpType' ); |
| 202 | + $wikis = array_unique( preg_split( '/(\s+|\s*\W\s*)/', $wgRequest->getVal( 'wpWikis' ), -1, PREG_SPLIT_NO_EMPTY ) ); |
| 203 | + $reason = $wgRequest->getVal( 'wpReason' ); |
| 204 | + $set = WikiSet::newFromId( $id ); |
| 205 | + |
| 206 | + if ( !Title::newFromText( $name ) ) { |
| 207 | + $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-badname' ), $name, $type, $wikis, $reason ); |
| 208 | + return; |
| 209 | + } |
| 210 | + if ( ( !$id || $set->getName() != $name ) && WikiSet::newFromName( $name ) ) { |
| 211 | + $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-setexists' ), $name, $type, $wikis, $reason ); |
| 212 | + return; |
| 213 | + } |
| 214 | + if ( !in_array( $type, array( WikiSet::OPTIN, WikiSet::OPTOUT ) ) ) { |
| 215 | + $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-badtype' ), $name, $type, $wikis, $reason ); |
| 216 | + return; |
| 217 | + } |
| 218 | + if ( !$wikis ) { |
| 219 | + $this->buildSetView( $id, wfMsgHtml( 'centralauth-editset-nowikis' ), $name, $type, $wikis, $reason ); |
| 220 | + return; |
| 221 | + } |
| 222 | + $badwikis = array(); |
| 223 | + $allwikis = CentralAuthUser::getWikiList(); |
| 224 | + foreach ( $wikis as $wiki ) { |
| 225 | + if ( !in_array( $wiki, $allwikis ) ) { |
| 226 | + $badwikis[] = $wiki; |
| 227 | + } |
| 228 | + } |
| 229 | + if ( $badwikis ) { |
| 230 | + $this->buildSetView( $id, wfMsgExt( 'centralauth-editset-badwikis', array( 'escapenoentities', 'parsemag' ), |
| 231 | + implode( ', ', $badwikis ), count( $badwikis ) ), $name, $type, $wikis, $reason ); |
| 232 | + return; |
| 233 | + } |
| 234 | + |
| 235 | + if ( $set ) { |
| 236 | + $oldname = $set->getName(); |
| 237 | + $oldtype = $set->getType(); |
| 238 | + $oldwikis = $set->getWikisRaw(); |
| 239 | + } else { |
| 240 | + $set = new WikiSet(); |
| 241 | + $oldname = $oldtype = null; $oldwikis = array(); |
| 242 | + } |
| 243 | + $set->setName( $name ); |
| 244 | + $set->setType( $type ); |
| 245 | + $set->setWikisRaw( $wikis ); |
| 246 | + $set->commit(); |
| 247 | + |
| 248 | + // Now logging |
| 249 | + $log = new LogPage( 'gblrights' ); |
| 250 | + $title = SpecialPage::getTitleFor( 'WikiSets', $set->getID() ); |
| 251 | + if ( !$oldname ) { |
| 252 | + // New set |
| 253 | + $log->addEntry( 'newset', $title, $reason, array( $name, $type, implode( ', ', $wikis ) ) ); |
| 254 | + } else { |
| 255 | + if ( $oldname != $name ) { |
| 256 | + $log->addEntry( 'setrename', $title, $reason, array( $name, $oldname ) ); |
| 257 | + } |
| 258 | + if ( $oldtype != $type ) { |
| 259 | + $log->addEntry( 'setnewtype', $title, $reason, array( $name, $oldtype, $type ) ); |
| 260 | + } |
| 261 | + $added = implode( ', ', array_diff( $wikis, $oldwikis ) ); |
| 262 | + $removed = implode( ', ', array_diff( $oldwikis, $wikis ) ); |
| 263 | + if ( $added || $removed ) { |
| 264 | + $log->addEntry( 'setchange', $title, $reason, array( $name, $added, $removed ) ); |
| 265 | + } |
| 266 | + } |
| 267 | + |
| 268 | + global $wgUser, $wgOut; |
| 269 | + $sk = $wgUser->getSkin(); |
| 270 | + $returnLink = $sk->makeKnownLinkObj( $this->getTitle(), wfMsg( 'centralauth-editset-return' ) ); |
| 271 | + |
| 272 | + $wgOut->addHTML( '<strong class="success">' . wfMsgHtml( 'centralauth-editset-success' ) . '</strong> <p>' . $returnLink . '</p>' ); |
| 273 | + } |
| 274 | + |
| 275 | + function doDelete( $set ) { |
| 276 | + global $wgRequest; |
| 277 | + |
| 278 | + $set = WikiSet::newFromID( $set ); |
| 279 | + if ( !$set ) { |
| 280 | + $this->buildMainView( '<strong class="error">' . wfMsgHtml( 'centralauth-editset-notfound', $subpage ) . '</strong>' ); |
| 281 | + return; |
| 282 | + } |
| 283 | + |
| 284 | + $reason = $wgRequest->getVal( 'wpReason' ); |
| 285 | + $name = $set->getName(); |
| 286 | + $set->delete(); |
| 287 | + |
| 288 | + $title = SpecialPage::getTitleFor( 'WikiSets', $set->getID() ); |
| 289 | + $log = new LogPage( 'gblrights' ); |
| 290 | + $log->addEntry( 'deleteset', $title, $reason, array( $name ) ); |
| 291 | + |
| 292 | + $this->buildMainView( '<strong class="success">' . wfMsg( 'centralauth-editset-success-delete' ) . '</strong>' ); |
| 293 | + } |
| 294 | +} |
Property changes on: trunk/extensions/CentralAuth/specials/SpecialWikiSets.php |
___________________________________________________________________ |
Added: svn:mergeinfo |
1 | 295 | Merged /branches/wmf/1.17wmf1/extensions/CentralAuth/SpecialWikiSets.php:r81956 |
Added: svn:eol-style |
2 | 296 | + native |