MediaWiki  master
BlockUtils.php
Go to the documentation of this file.
1 <?php
2 
22 namespace MediaWiki\Block;
23 
27 use Status;
28 use User;
29 use Wikimedia\IPUtils;
30 
44 class BlockUtils {
46  private $options;
47 
49  private $userFactory;
50 
54  public const CONSTRUCTOR_OPTIONS = [
55  'BlockCIDRLimit',
56  ];
57 
62  public function __construct(
65  ) {
66  $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
67  $this->options = $options;
68  $this->userFactory = $userFactory;
69  }
70 
83  public function parseBlockTarget( $target ) : array {
84  // We may have been through this before
85  if ( $target instanceof UserIdentity ) {
86  $userObj = $this->userFactory->newFromUserIdentity( $target );
87  if ( IPUtils::isValid( $target->getName() ) ) {
88  return [ $userObj, AbstractBlock::TYPE_IP ];
89  } else {
90  return [ $userObj, AbstractBlock::TYPE_USER ];
91  }
92  } elseif ( $target === null ) {
93  return [ null, null ];
94  }
95 
96  $target = trim( $target );
97 
98  if ( IPUtils::isValid( $target ) ) {
99  // We can still create a User if it's an IP address, but we need to turn
100  // off validation checking (which would exclude IP addresses)
101  return [
102  $this->userFactory->newFromName(
103  IPUtils::sanitizeIP( $target ),
104  UserFactory::RIGOR_NONE
105  ),
107  ];
108 
109  } elseif ( IPUtils::isValidRange( $target ) ) {
110  // Can't create a User from an IP range
111  return [ IPUtils::sanitizeRange( $target ), AbstractBlock::TYPE_RANGE ];
112  }
113 
114  // Consider the possibility that this is not a username at all
115  // but actually an old subpage (T31797)
116  if ( strpos( $target, '/' ) !== false ) {
117  // An old subpage, drill down to the user behind it
118  $target = explode( '/', $target )[0];
119  }
120 
121  $userObj = $this->userFactory->newFromName( $target );
122  if ( $userObj instanceof User ) {
123  // Note that since numbers are valid usernames, a $target of "12345" will be
124  // considered a User. If you want to pass a block ID, prepend a hash "#12345",
125  // since hash characters are not valid in usernames or titles generally.
126  return [ $userObj, AbstractBlock::TYPE_USER ];
127  } elseif ( preg_match( '/^#\d+$/', $target ) ) {
128  // Autoblock reference in the form "#12345"
129  return [ substr( $target, 1 ), AbstractBlock::TYPE_AUTO ];
130  } else {
131  return [ null, null ];
132  }
133  }
134 
142  public function validateTarget( $value ) : Status {
143  list( $target, $type ) = $this->parseBlockTarget( $value );
144 
145  $status = Status::newGood( $target );
146 
147  switch ( $type ) {
149  if ( $target->isAnon() ) {
150  $status->fatal(
151  'nosuchusershort',
152  wfEscapeWikiText( $target->getName() )
153  );
154  }
155  break;
156 
158  list( $ip, $range ) = explode( '/', $target, '2' );
159 
160  if ( IPUtils::isIPv4( $ip ) ) {
161  $status->merge( $this->validateIPv4Range( $range ) );
162  } elseif ( IPUtils::isIPv6( $ip ) ) {
163  $status->merge( $this->validateIPv6Range( $range ) );
164  } else {
165  // Something is FUBAR
166  $status->fatal( 'badipaddress' );
167  }
168  break;
169 
171  // All is well
172  break;
173 
174  default:
175  $status->fatal( 'badipaddress' );
176  break;
177  }
178 
179  return $status;
180  }
181 
189  private function validateIPv4Range( int $range ) : Status {
190  $status = Status::newGood();
191  $blockCIDRLimit = $this->options->get( 'BlockCIDRLimit' );
192 
193  if ( $blockCIDRLimit['IPv4'] == 32 ) {
194  // Range block effectively disabled
195  $status->fatal( 'range_block_disabled' );
196  } elseif ( $range > 32 ) {
197  // Such a range cannot exist
198  $status->fatal( 'ip_range_invalid' );
199  } elseif ( $range < $blockCIDRLimit['IPv4'] ) {
200  $status->fatal( 'ip_range_toolarge', $blockCIDRLimit['IPv4'] );
201  }
202 
203  return $status;
204  }
205 
213  private function validateIPv6Range( int $range ) : Status {
214  $status = Status::newGood();
215  $blockCIDRLimit = $this->options->get( 'BlockCIDRLimit' );
216 
217  if ( $blockCIDRLimit['IPv6'] == 128 ) {
218  // Range block effectively disabled
219  $status->fatal( 'range_block_disabled' );
220  } elseif ( $range > 128 ) {
221  // Dodgy range - such a range cannot exist
222  $status->fatal( 'ip_range_invalid' );
223  } elseif ( $range < $blockCIDRLimit['IPv6'] ) {
224  $status->fatal( 'ip_range_toolarge', $blockCIDRLimit['IPv6'] );
225  }
226 
227  return $status;
228  }
229 }
MediaWiki\Block
Definition: AbstractBlock.php:21
MediaWiki\Block\BlockUtils
Backend class for blocking utils.
Definition: BlockUtils.php:44
MediaWiki\Block\BlockUtils\$userFactory
UserFactory $userFactory
Definition: BlockUtils.php:49
MediaWiki\Block\AbstractBlock\TYPE_AUTO
const TYPE_AUTO
Definition: AbstractBlock.php:94
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:32
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:44
MediaWiki\Block\AbstractBlock\TYPE_RANGE
const TYPE_RANGE
Definition: AbstractBlock.php:93
MediaWiki\Block\BlockUtils\validateTarget
validateTarget( $value)
Validate block target.
Definition: BlockUtils.php:142
MediaWiki\Config\ServiceOptions
A class for passing options to services.
Definition: ServiceOptions.php:27
MediaWiki\Block\BlockUtils\validateIPv4Range
validateIPv4Range(int $range)
Validate an IPv4 range.
Definition: BlockUtils.php:189
MediaWiki\Block\AbstractBlock\TYPE_IP
const TYPE_IP
Definition: AbstractBlock.php:92
MediaWiki\Block\BlockUtils\$options
ServiceOptions $options
Definition: BlockUtils.php:46
MediaWiki\Block\AbstractBlock\TYPE_USER
const TYPE_USER
Definition: AbstractBlock.php:91
MediaWiki\Block\BlockUtils\validateIPv6Range
validateIPv6Range(int $range)
Validate an IPv6 range.
Definition: BlockUtils.php:213
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:82
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1504
MediaWiki\Block\BlockUtils\CONSTRUCTOR_OPTIONS
const CONSTRUCTOR_OPTIONS
Definition: BlockUtils.php:54
MediaWiki\Block\BlockUtils\__construct
__construct(ServiceOptions $options, UserFactory $userFactory)
Definition: BlockUtils.php:62
MediaWiki\Block\BlockUtils\parseBlockTarget
parseBlockTarget( $target)
From an existing block, get the target and the type of target.
Definition: BlockUtils.php:83
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:63
MediaWiki\User\UserFactory
Creates User objects.
Definition: UserFactory.php:41
MediaWiki\Config\ServiceOptions\assertRequiredOptions
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
Definition: ServiceOptions.php:66
$type
$type
Definition: testCompression.php:52