This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Copyright © 2004 Brion Vibber, lcrocker, Tim Starling, |
||
4 | * Domas Mituzas, Antoine Musso, Jens Frank, Zhengzhu, |
||
5 | * 2006 Rob Church <[email protected]> |
||
6 | * |
||
7 | * This program is free software; you can redistribute it and/or modify |
||
8 | * it under the terms of the GNU General Public License as published by |
||
9 | * the Free Software Foundation; either version 2 of the License, or |
||
10 | * (at your option) any later version. |
||
11 | * |
||
12 | * This program is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
15 | * GNU General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU General Public License along |
||
18 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
20 | * http://www.gnu.org/copyleft/gpl.html |
||
21 | * |
||
22 | * @file |
||
23 | * @ingroup Pager |
||
24 | */ |
||
25 | |||
26 | /** |
||
27 | * This class is used to get a list of user. The ones with specials |
||
28 | * rights (sysop, bureaucrat, developer) will have them displayed |
||
29 | * next to their names. |
||
30 | * |
||
31 | * @ingroup Pager |
||
32 | */ |
||
33 | class UsersPager extends AlphabeticPager { |
||
34 | |||
35 | /** |
||
36 | * @var array A array with user ids as key and a array of groups as value |
||
37 | */ |
||
38 | protected $userGroupCache; |
||
39 | |||
40 | /** |
||
41 | * @param IContextSource $context |
||
42 | * @param array $par (Default null) |
||
43 | * @param bool $including Whether this page is being transcluded in |
||
44 | * another page |
||
45 | */ |
||
46 | function __construct( IContextSource $context = null, $par = null, $including = null ) { |
||
47 | if ( $context ) { |
||
48 | $this->setContext( $context ); |
||
49 | } |
||
50 | |||
51 | $request = $this->getRequest(); |
||
52 | $par = ( $par !== null ) ? $par : ''; |
||
53 | $parms = explode( '/', $par ); |
||
54 | $symsForAll = [ '*', 'user' ]; |
||
55 | |||
56 | if ( $parms[0] != '' && |
||
57 | ( in_array( $par, User::getAllGroups() ) || in_array( $par, $symsForAll ) ) |
||
58 | ) { |
||
59 | $this->requestedGroup = $par; |
||
0 ignored issues
–
show
|
|||
60 | $un = $request->getText( 'username' ); |
||
61 | } elseif ( count( $parms ) == 2 ) { |
||
62 | $this->requestedGroup = $parms[0]; |
||
63 | $un = $parms[1]; |
||
64 | } else { |
||
65 | $this->requestedGroup = $request->getVal( 'group' ); |
||
66 | $un = ( $par != '' ) ? $par : $request->getText( 'username' ); |
||
67 | } |
||
68 | |||
69 | if ( in_array( $this->requestedGroup, $symsForAll ) ) { |
||
70 | $this->requestedGroup = ''; |
||
71 | } |
||
72 | $this->editsOnly = $request->getBool( 'editsOnly' ); |
||
0 ignored issues
–
show
The property
editsOnly does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
73 | $this->creationSort = $request->getBool( 'creationSort' ); |
||
0 ignored issues
–
show
The property
creationSort does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
74 | $this->including = $including; |
||
0 ignored issues
–
show
The property
including does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
75 | $this->mDefaultDirection = $request->getBool( 'desc' ) |
||
76 | ? IndexPager::DIR_DESCENDING |
||
77 | : IndexPager::DIR_ASCENDING; |
||
78 | |||
79 | $this->requestedUser = ''; |
||
0 ignored issues
–
show
The property
requestedUser does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
80 | |||
81 | View Code Duplication | if ( $un != '' ) { |
|
82 | $username = Title::makeTitleSafe( NS_USER, $un ); |
||
83 | |||
84 | if ( !is_null( $username ) ) { |
||
85 | $this->requestedUser = $username->getText(); |
||
86 | } |
||
87 | } |
||
88 | |||
89 | parent::__construct(); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * @return string |
||
94 | */ |
||
95 | function getIndexField() { |
||
96 | return $this->creationSort ? 'user_id' : 'user_name'; |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * @return array |
||
101 | */ |
||
102 | function getQueryInfo() { |
||
103 | $dbr = wfGetDB( DB_REPLICA ); |
||
104 | $conds = []; |
||
105 | |||
106 | // Don't show hidden names |
||
107 | if ( !$this->getUser()->isAllowed( 'hideuser' ) ) { |
||
108 | $conds[] = 'ipb_deleted IS NULL OR ipb_deleted = 0'; |
||
109 | } |
||
110 | |||
111 | $options = []; |
||
112 | |||
113 | if ( $this->requestedGroup != '' ) { |
||
114 | $conds['ug_group'] = $this->requestedGroup; |
||
115 | } |
||
116 | |||
117 | if ( $this->requestedUser != '' ) { |
||
118 | # Sorted either by account creation or name |
||
119 | if ( $this->creationSort ) { |
||
120 | $conds[] = 'user_id >= ' . intval( User::idFromName( $this->requestedUser ) ); |
||
121 | } else { |
||
122 | $conds[] = 'user_name >= ' . $dbr->addQuotes( $this->requestedUser ); |
||
123 | } |
||
124 | } |
||
125 | |||
126 | if ( $this->editsOnly ) { |
||
127 | $conds[] = 'user_editcount > 0'; |
||
128 | } |
||
129 | |||
130 | $options['GROUP BY'] = $this->creationSort ? 'user_id' : 'user_name'; |
||
131 | |||
132 | $query = [ |
||
133 | 'tables' => [ 'user', 'user_groups', 'ipblocks' ], |
||
134 | 'fields' => [ |
||
135 | 'user_name' => $this->creationSort ? 'MAX(user_name)' : 'user_name', |
||
136 | 'user_id' => $this->creationSort ? 'user_id' : 'MAX(user_id)', |
||
137 | 'edits' => 'MAX(user_editcount)', |
||
138 | 'creation' => 'MIN(user_registration)', |
||
139 | 'ipb_deleted' => 'MAX(ipb_deleted)' // block/hide status |
||
140 | ], |
||
141 | 'options' => $options, |
||
142 | 'join_conds' => [ |
||
143 | 'user_groups' => [ 'LEFT JOIN', 'user_id=ug_user' ], |
||
144 | 'ipblocks' => [ |
||
145 | 'LEFT JOIN', [ |
||
146 | 'user_id=ipb_user', |
||
147 | 'ipb_auto' => 0 |
||
148 | ] |
||
149 | ], |
||
150 | ], |
||
151 | 'conds' => $conds |
||
152 | ]; |
||
153 | |||
154 | Hooks::run( 'SpecialListusersQueryInfo', [ $this, &$query ] ); |
||
155 | |||
156 | return $query; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * @param stdClass $row |
||
161 | * @return string |
||
162 | */ |
||
163 | function formatRow( $row ) { |
||
164 | if ( $row->user_id == 0 ) { # Bug 16487 |
||
165 | return ''; |
||
166 | } |
||
167 | |||
168 | $userName = $row->user_name; |
||
169 | |||
170 | $ulinks = Linker::userLink( $row->user_id, $userName ); |
||
171 | $ulinks .= Linker::userToolLinksRedContribs( |
||
172 | $row->user_id, |
||
173 | $userName, |
||
174 | (int)$row->edits |
||
175 | ); |
||
176 | |||
177 | $lang = $this->getLanguage(); |
||
178 | |||
179 | $groups = ''; |
||
180 | $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache ); |
||
181 | |||
182 | if ( !$this->including && count( $groups_list ) > 0 ) { |
||
183 | $list = []; |
||
184 | foreach ( $groups_list as $group ) { |
||
185 | $list[] = self::buildGroupLink( $group, $userName ); |
||
186 | } |
||
187 | $groups = $lang->commaList( $list ); |
||
188 | } |
||
189 | |||
190 | $item = $lang->specialList( $ulinks, $groups ); |
||
191 | |||
192 | if ( $row->ipb_deleted ) { |
||
193 | $item = "<span class=\"deleted\">$item</span>"; |
||
194 | } |
||
195 | |||
196 | $edits = ''; |
||
197 | if ( !$this->including && $this->getConfig()->get( 'Edititis' ) ) { |
||
198 | $count = $this->msg( 'usereditcount' )->numParams( $row->edits )->escaped(); |
||
199 | $edits = $this->msg( 'word-separator' )->escaped() . $this->msg( 'brackets', $count )->escaped(); |
||
200 | } |
||
201 | |||
202 | $created = ''; |
||
203 | # Some rows may be null |
||
204 | if ( !$this->including && $row->creation ) { |
||
205 | $user = $this->getUser(); |
||
206 | $d = $lang->userDate( $row->creation, $user ); |
||
207 | $t = $lang->userTime( $row->creation, $user ); |
||
208 | $created = $this->msg( 'usercreated', $d, $t, $row->user_name )->escaped(); |
||
209 | $created = ' ' . $this->msg( 'parentheses' )->rawParams( $created )->escaped(); |
||
210 | } |
||
211 | $blocked = !is_null( $row->ipb_deleted ) ? |
||
212 | ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() : |
||
213 | ''; |
||
214 | |||
215 | Hooks::run( 'SpecialListusersFormatRow', [ &$item, $row ] ); |
||
216 | |||
217 | return Html::rawElement( 'li', [], "{$item}{$edits}{$created}{$blocked}" ); |
||
218 | } |
||
219 | |||
220 | function doBatchLookups() { |
||
221 | $batch = new LinkBatch(); |
||
222 | $userIds = []; |
||
223 | # Give some pointers to make user links |
||
224 | foreach ( $this->mResult as $row ) { |
||
225 | $batch->add( NS_USER, $row->user_name ); |
||
226 | $batch->add( NS_USER_TALK, $row->user_name ); |
||
227 | $userIds[] = $row->user_id; |
||
228 | } |
||
229 | |||
230 | // Lookup groups for all the users |
||
231 | $dbr = wfGetDB( DB_REPLICA ); |
||
232 | $groupRes = $dbr->select( |
||
233 | 'user_groups', |
||
234 | [ 'ug_user', 'ug_group' ], |
||
235 | [ 'ug_user' => $userIds ], |
||
236 | __METHOD__ |
||
237 | ); |
||
238 | $cache = []; |
||
239 | $groups = []; |
||
240 | foreach ( $groupRes as $row ) { |
||
241 | $cache[intval( $row->ug_user )][] = $row->ug_group; |
||
242 | $groups[$row->ug_group] = true; |
||
243 | } |
||
244 | |||
245 | // Give extensions a chance to add things like global user group data |
||
246 | // into the cache array to ensure proper output later on |
||
247 | Hooks::run( 'UsersPagerDoBatchLookups', [ $dbr, $userIds, &$cache, &$groups ] ); |
||
248 | |||
249 | $this->userGroupCache = $cache; |
||
250 | |||
251 | // Add page of groups to link batch |
||
252 | foreach ( $groups as $group => $unused ) { |
||
253 | $groupPage = User::getGroupPage( $group ); |
||
254 | if ( $groupPage ) { |
||
255 | $batch->addObj( $groupPage ); |
||
256 | } |
||
257 | } |
||
258 | |||
259 | $batch->execute(); |
||
260 | $this->mResult->rewind(); |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * @return string |
||
265 | */ |
||
266 | function getPageHeader() { |
||
267 | list( $self ) = explode( '/', $this->getTitle()->getPrefixedDBkey() ); |
||
268 | |||
269 | $this->getOutput()->addModules( 'mediawiki.userSuggest' ); |
||
270 | |||
271 | # Form tag |
||
272 | $out = Xml::openElement( |
||
273 | 'form', |
||
274 | [ 'method' => 'get', 'action' => wfScript(), 'id' => 'mw-listusers-form' ] |
||
275 | ) . |
||
276 | Xml::fieldset( $this->msg( 'listusers' )->text() ) . |
||
277 | Html::hidden( 'title', $self ); |
||
278 | |||
279 | # Username field (with autocompletion support) |
||
280 | $out .= Xml::label( $this->msg( 'listusersfrom' )->text(), 'offset' ) . ' ' . |
||
281 | Html::input( |
||
282 | 'username', |
||
283 | $this->requestedUser, |
||
284 | 'text', |
||
285 | [ |
||
286 | 'class' => 'mw-autocomplete-user', |
||
287 | 'id' => 'offset', |
||
288 | 'size' => 20, |
||
289 | 'autofocus' => $this->requestedUser === '' |
||
290 | ] |
||
291 | ) . ' '; |
||
292 | |||
293 | # Group drop-down list |
||
294 | $sel = new XmlSelect( 'group', 'group', $this->requestedGroup ); |
||
295 | $sel->addOption( $this->msg( 'group-all' )->text(), '' ); |
||
296 | foreach ( $this->getAllGroups() as $group => $groupText ) { |
||
297 | $sel->addOption( $groupText, $group ); |
||
298 | } |
||
299 | |||
300 | $out .= Xml::label( $this->msg( 'group' )->text(), 'group' ) . ' '; |
||
301 | $out .= $sel->getHTML() . '<br />'; |
||
302 | $out .= Xml::checkLabel( |
||
303 | $this->msg( 'listusers-editsonly' )->text(), |
||
304 | 'editsOnly', |
||
305 | 'editsOnly', |
||
306 | $this->editsOnly |
||
307 | ); |
||
308 | $out .= ' '; |
||
309 | $out .= Xml::checkLabel( |
||
310 | $this->msg( 'listusers-creationsort' )->text(), |
||
311 | 'creationSort', |
||
312 | 'creationSort', |
||
313 | $this->creationSort |
||
314 | ); |
||
315 | $out .= ' '; |
||
316 | $out .= Xml::checkLabel( |
||
317 | $this->msg( 'listusers-desc' )->text(), |
||
318 | 'desc', |
||
319 | 'desc', |
||
320 | $this->mDefaultDirection |
||
321 | ); |
||
322 | $out .= '<br />'; |
||
323 | |||
324 | Hooks::run( 'SpecialListusersHeaderForm', [ $this, &$out ] ); |
||
325 | |||
326 | # Submit button and form bottom |
||
327 | $out .= Html::hidden( 'limit', $this->mLimit ); |
||
328 | $out .= Xml::submitButton( $this->msg( 'listusers-submit' )->text() ); |
||
329 | Hooks::run( 'SpecialListusersHeader', [ $this, &$out ] ); |
||
330 | $out .= Xml::closeElement( 'fieldset' ) . |
||
331 | Xml::closeElement( 'form' ); |
||
332 | |||
333 | return $out; |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * Get a list of all explicit groups |
||
338 | * @return array |
||
339 | */ |
||
340 | function getAllGroups() { |
||
341 | $result = []; |
||
342 | foreach ( User::getAllGroups() as $group ) { |
||
343 | $result[$group] = User::getGroupName( $group ); |
||
344 | } |
||
345 | asort( $result ); |
||
346 | |||
347 | return $result; |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * Preserve group and username offset parameters when paging |
||
352 | * @return array |
||
353 | */ |
||
354 | function getDefaultQuery() { |
||
355 | $query = parent::getDefaultQuery(); |
||
356 | if ( $this->requestedGroup != '' ) { |
||
357 | $query['group'] = $this->requestedGroup; |
||
358 | } |
||
359 | if ( $this->requestedUser != '' ) { |
||
360 | $query['username'] = $this->requestedUser; |
||
361 | } |
||
362 | Hooks::run( 'SpecialListusersDefaultQuery', [ $this, &$query ] ); |
||
363 | |||
364 | return $query; |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Get a list of groups the specified user belongs to |
||
369 | * |
||
370 | * @param int $uid User id |
||
371 | * @param array|null $cache |
||
372 | * @return array |
||
373 | */ |
||
374 | protected static function getGroups( $uid, $cache = null ) { |
||
375 | if ( $cache === null ) { |
||
376 | $user = User::newFromId( $uid ); |
||
377 | $effectiveGroups = $user->getEffectiveGroups(); |
||
378 | } else { |
||
379 | $effectiveGroups = isset( $cache[$uid] ) ? $cache[$uid] : []; |
||
380 | } |
||
381 | $groups = array_diff( $effectiveGroups, User::getImplicitGroups() ); |
||
382 | |||
383 | return $groups; |
||
384 | } |
||
385 | |||
386 | /** |
||
387 | * Format a link to a group description page |
||
388 | * |
||
389 | * @param string $group Group name |
||
390 | * @param string $username Username |
||
391 | * @return string |
||
392 | */ |
||
393 | protected static function buildGroupLink( $group, $username ) { |
||
394 | return User::makeGroupLinkHTML( |
||
395 | $group, |
||
396 | User::getGroupMember( $group, $username ) |
||
397 | ); |
||
398 | } |
||
399 | |||
400 | } |
||
401 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: