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 | * Implements Special:Unblock |
||
4 | * |
||
5 | * This program is free software; you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU General Public License as published by |
||
7 | * the Free Software Foundation; either version 2 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * |
||
10 | * This program is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | * GNU General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU General Public License along |
||
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
18 | * http://www.gnu.org/copyleft/gpl.html |
||
19 | * |
||
20 | * @file |
||
21 | * @ingroup SpecialPage |
||
22 | */ |
||
23 | |||
24 | /** |
||
25 | * A special page for unblocking users |
||
26 | * |
||
27 | * @ingroup SpecialPage |
||
28 | */ |
||
29 | class SpecialUnblock extends SpecialPage { |
||
30 | |||
31 | protected $target; |
||
32 | protected $type; |
||
33 | protected $block; |
||
34 | |||
35 | public function __construct() { |
||
36 | parent::__construct( 'Unblock', 'block' ); |
||
37 | } |
||
38 | |||
39 | public function doesWrites() { |
||
40 | return true; |
||
41 | } |
||
42 | |||
43 | public function execute( $par ) { |
||
44 | $this->checkPermissions(); |
||
45 | $this->checkReadOnly(); |
||
46 | |||
47 | list( $this->target, $this->type ) = SpecialBlock::getTargetAndType( $par, $this->getRequest() ); |
||
48 | $this->block = Block::newFromTarget( $this->target ); |
||
49 | if ( $this->target instanceof User ) { |
||
50 | # Set the 'relevant user' in the skin, so it displays links like Contributions, |
||
51 | # User logs, UserRights, etc. |
||
52 | $this->getSkin()->setRelevantUser( $this->target ); |
||
53 | } |
||
54 | |||
55 | $this->setHeaders(); |
||
56 | $this->outputHeader(); |
||
57 | |||
58 | $out = $this->getOutput(); |
||
59 | $out->setPageTitle( $this->msg( 'unblockip' ) ); |
||
60 | $out->addModules( [ 'mediawiki.special', 'mediawiki.userSuggest' ] ); |
||
61 | |||
62 | $form = new HTMLForm( $this->getFields(), $this->getContext() ); |
||
63 | $form->setWrapperLegendMsg( 'unblockip' ); |
||
64 | $form->setSubmitCallback( [ __CLASS__, 'processUIUnblock' ] ); |
||
65 | $form->setSubmitTextMsg( 'ipusubmit' ); |
||
66 | $form->addPreText( $this->msg( 'unblockiptext' )->parseAsBlock() ); |
||
67 | |||
68 | if ( $form->show() ) { |
||
69 | switch ( $this->type ) { |
||
70 | case Block::TYPE_IP: |
||
71 | $out->addWikiMsg( 'unblocked-ip', wfEscapeWikiText( $this->target ) ); |
||
72 | break; |
||
73 | case Block::TYPE_USER: |
||
74 | $out->addWikiMsg( 'unblocked', wfEscapeWikiText( $this->target ) ); |
||
75 | break; |
||
76 | case Block::TYPE_RANGE: |
||
77 | $out->addWikiMsg( 'unblocked-range', wfEscapeWikiText( $this->target ) ); |
||
78 | break; |
||
79 | case Block::TYPE_ID: |
||
80 | case Block::TYPE_AUTO: |
||
81 | $out->addWikiMsg( 'unblocked-id', wfEscapeWikiText( $this->target ) ); |
||
82 | break; |
||
83 | } |
||
84 | } |
||
85 | } |
||
86 | |||
87 | protected function getFields() { |
||
88 | $fields = [ |
||
89 | 'Target' => [ |
||
90 | 'type' => 'text', |
||
91 | 'label-message' => 'ipaddressorusername', |
||
92 | 'autofocus' => true, |
||
93 | 'size' => '45', |
||
94 | 'required' => true, |
||
95 | 'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest |
||
96 | ], |
||
97 | 'Name' => [ |
||
98 | 'type' => 'info', |
||
99 | 'label-message' => 'ipaddressorusername', |
||
100 | ], |
||
101 | 'Reason' => [ |
||
102 | 'type' => 'text', |
||
103 | 'label-message' => 'ipbreason', |
||
104 | ] |
||
105 | ]; |
||
106 | |||
107 | if ( $this->block instanceof Block ) { |
||
108 | list( $target, $type ) = $this->block->getTargetAndType(); |
||
109 | |||
110 | # Autoblocks are logged as "autoblock #123 because the IP was recently used by |
||
111 | # User:Foo, and we've just got any block, auto or not, that applies to a target |
||
112 | # the user has specified. Someone could be fishing to connect IPs to autoblocks, |
||
113 | # so don't show any distinction between unblocked IPs and autoblocked IPs |
||
114 | if ( $type == Block::TYPE_AUTO && $this->type == Block::TYPE_IP ) { |
||
115 | $fields['Target']['default'] = $this->target; |
||
116 | unset( $fields['Name'] ); |
||
117 | } else { |
||
118 | $fields['Target']['default'] = $target; |
||
119 | $fields['Target']['type'] = 'hidden'; |
||
120 | switch ( $type ) { |
||
121 | case Block::TYPE_IP: |
||
122 | $fields['Name']['default'] = Linker::linkKnown( |
||
123 | SpecialPage::getTitleFor( 'Contributions', $target->getName() ), |
||
124 | $target->getName() |
||
125 | ); |
||
126 | $fields['Name']['raw'] = true; |
||
127 | break; |
||
128 | case Block::TYPE_USER: |
||
129 | $fields['Name']['default'] = Linker::link( |
||
130 | $target->getUserPage(), |
||
131 | $target->getName() |
||
132 | ); |
||
133 | $fields['Name']['raw'] = true; |
||
134 | break; |
||
135 | |||
136 | case Block::TYPE_RANGE: |
||
137 | $fields['Name']['default'] = $target; |
||
138 | break; |
||
139 | |||
140 | case Block::TYPE_AUTO: |
||
141 | $fields['Name']['default'] = $this->block->getRedactedName(); |
||
142 | $fields['Name']['raw'] = true; |
||
143 | # Don't expose the real target of the autoblock |
||
144 | $fields['Target']['default'] = "#{$this->target}"; |
||
145 | break; |
||
146 | } |
||
147 | // target is hidden, so the reason is the first element |
||
148 | $fields['Target']['autofocus'] = false; |
||
149 | $fields['Reason']['autofocus'] = true; |
||
150 | } |
||
151 | } else { |
||
152 | $fields['Target']['default'] = $this->target; |
||
153 | unset( $fields['Name'] ); |
||
154 | } |
||
155 | |||
156 | return $fields; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Submit callback for an HTMLForm object |
||
161 | * @param array $data |
||
162 | * @param HTMLForm $form |
||
163 | * @return array|bool Array(message key, parameters) |
||
164 | */ |
||
165 | public static function processUIUnblock( array $data, HTMLForm $form ) { |
||
166 | return self::processUnblock( $data, $form->getContext() ); |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * Process the form |
||
171 | * |
||
172 | * Change tags can be provided via $data['Tags'], but the calling function |
||
173 | * must check if the tags can be added by the user prior to this function. |
||
174 | * |
||
175 | * @param array $data |
||
176 | * @param IContextSource $context |
||
177 | * @throws ErrorPageError |
||
178 | * @return array|bool Array(message key, parameters) on failure, True on success |
||
179 | */ |
||
180 | public static function processUnblock( array $data, IContextSource $context ) { |
||
181 | $performer = $context->getUser(); |
||
182 | $target = $data['Target']; |
||
183 | $block = Block::newFromTarget( $data['Target'] ); |
||
184 | |||
185 | if ( !$block instanceof Block ) { |
||
186 | return [ [ 'ipb_cant_unblock', $target ] ]; |
||
187 | } |
||
188 | |||
189 | # bug 15810: blocked admins should have limited access here. This |
||
190 | # won't allow sysops to remove autoblocks on themselves, but they |
||
191 | # should have ipblock-exempt anyway |
||
192 | $status = SpecialBlock::checkUnblockSelf( $target, $performer ); |
||
193 | if ( $status !== true ) { |
||
194 | throw new ErrorPageError( 'badaccess', $status ); |
||
0 ignored issues
–
show
|
|||
195 | } |
||
196 | |||
197 | # If the specified IP is a single address, and the block is a range block, don't |
||
198 | # unblock the whole range. |
||
199 | list( $target, $type ) = SpecialBlock::getTargetAndType( $target ); |
||
200 | if ( $block->getType() == Block::TYPE_RANGE && $type == Block::TYPE_IP ) { |
||
201 | $range = $block->getTarget(); |
||
202 | |||
203 | return [ [ 'ipb_blocked_as_range', $target, $range ] ]; |
||
204 | } |
||
205 | |||
206 | # If the name was hidden and the blocking user cannot hide |
||
207 | # names, then don't allow any block removals... |
||
208 | if ( !$performer->isAllowed( 'hideuser' ) && $block->mHideName ) { |
||
209 | return [ 'unblock-hideuser' ]; |
||
210 | } |
||
211 | |||
212 | # Delete block |
||
213 | if ( !$block->delete() ) { |
||
214 | return [ 'ipb_cant_unblock', htmlspecialchars( $block->getTarget() ) ]; |
||
215 | } |
||
216 | |||
217 | # Unset _deleted fields as needed |
||
218 | if ( $block->mHideName ) { |
||
219 | # Something is deeply FUBAR if this is not a User object, but who knows? |
||
220 | $id = $block->getTarget() instanceof User |
||
221 | ? $block->getTarget()->getId() |
||
222 | : User::idFromName( $block->getTarget() ); |
||
223 | |||
224 | RevisionDeleteUser::unsuppressUserName( $block->getTarget(), $id ); |
||
225 | } |
||
226 | |||
227 | # Redact the name (IP address) for autoblocks |
||
228 | if ( $block->getType() == Block::TYPE_AUTO ) { |
||
229 | $page = Title::makeTitle( NS_USER, '#' . $block->getId() ); |
||
230 | } else { |
||
231 | $page = $block->getTarget() instanceof User |
||
232 | ? $block->getTarget()->getUserPage() |
||
233 | : Title::makeTitle( NS_USER, $block->getTarget() ); |
||
234 | } |
||
235 | |||
236 | # Make log entry |
||
237 | $logEntry = new ManualLogEntry( 'block', 'unblock' ); |
||
238 | $logEntry->setTarget( $page ); |
||
239 | $logEntry->setComment( $data['Reason'] ); |
||
240 | $logEntry->setPerformer( $performer ); |
||
241 | if ( isset( $data['Tags'] ) ) { |
||
242 | $logEntry->setTags( $data['Tags'] ); |
||
243 | } |
||
244 | $logId = $logEntry->insert(); |
||
245 | $logEntry->publish( $logId ); |
||
246 | |||
247 | return true; |
||
248 | } |
||
249 | |||
250 | /** |
||
251 | * Return an array of subpages beginning with $search that this special page will accept. |
||
252 | * |
||
253 | * @param string $search Prefix to search for |
||
254 | * @param int $limit Maximum number of results to return (usually 10) |
||
255 | * @param int $offset Number of results to skip (usually 0) |
||
256 | * @return string[] Matching subpages |
||
257 | */ |
||
258 | View Code Duplication | public function prefixSearchSubpages( $search, $limit, $offset ) { |
|
259 | $user = User::newFromName( $search ); |
||
260 | if ( !$user ) { |
||
261 | // No prefix suggestion for invalid user |
||
262 | return []; |
||
263 | } |
||
264 | // Autocomplete subpage as user list - public to allow caching |
||
265 | return UserNamePrefixSearch::search( 'public', $search, $limit, $offset ); |
||
266 | } |
||
267 | |||
268 | protected function getGroupName() { |
||
269 | return 'users'; |
||
270 | } |
||
271 | } |
||
272 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.