Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
91.18% |
31 / 34 |
|
80.00% |
8 / 10 |
CRAP | |
0.00% |
0 / 1 |
RangeBlockTarget | |
91.18% |
31 / 34 |
|
80.00% |
8 / 10 |
19.25 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
toString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getLogPage | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSpecificity | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
validateForCreation | |
93.75% |
15 / 16 |
|
0.00% |
0 / 1 |
6.01 | |||
toHexRange | |
60.00% |
3 / 5 |
|
0.00% |
0 / 1 |
5.02 | |||
getHexRangeStart | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getHexRangeEnd | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getLegacyUnion | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Block; |
4 | |
5 | use MediaWiki\DAO\WikiAwareEntity; |
6 | use MediaWiki\Page\PageReference; |
7 | use MediaWiki\Page\PageReferenceValue; |
8 | use StatusValue; |
9 | use Wikimedia\IPUtils; |
10 | |
11 | /** |
12 | * A block target for an IP address range |
13 | * |
14 | * @since 1.44 |
15 | */ |
16 | class RangeBlockTarget extends BlockTarget implements BlockTargetWithIp { |
17 | private string $cidr; |
18 | |
19 | /** |
20 | * @var array The minimum prefix lengths indexed by protocol (IPv4 or IPv6) |
21 | */ |
22 | private array $limits; |
23 | |
24 | /** |
25 | * @param string $cidr The range specification in CIDR notation |
26 | * @param array $limits The minimum prefix lengths indexed by protocol (IPv4 or IPv6) |
27 | * @param string|false $wikiId The wiki ID |
28 | */ |
29 | public function __construct( string $cidr, array $limits, $wikiId = WikiAwareEntity::LOCAL ) { |
30 | parent::__construct( $wikiId ); |
31 | $this->cidr = $cidr; |
32 | $this->limits = $limits; |
33 | } |
34 | |
35 | public function toString(): string { |
36 | return $this->cidr; |
37 | } |
38 | |
39 | public function getType(): int { |
40 | return Block::TYPE_RANGE; |
41 | } |
42 | |
43 | public function getLogPage(): PageReference { |
44 | return new PageReferenceValue( NS_USER, $this->cidr, $this->wikiId ); |
45 | } |
46 | |
47 | public function getSpecificity() { |
48 | // This is the number of bits that are allowed to vary in the block, give |
49 | // or take some floating point errors |
50 | [ $ip, $bits ] = explode( '/', $this->cidr, 2 ); |
51 | $max = IPUtils::isIPv6( $ip ) ? 128 : 32; |
52 | $size = $max - (int)$bits; |
53 | |
54 | // Rank a range block covering a single IP equally with a single-IP block |
55 | return 2 + ( $size / $max ); |
56 | } |
57 | |
58 | public function validateForCreation(): StatusValue { |
59 | $status = StatusValue::newGood(); |
60 | [ $ip, $prefixLength ] = explode( '/', $this->cidr, 2 ); |
61 | |
62 | if ( IPUtils::isIPv4( $ip ) ) { |
63 | $minLength = $this->limits['IPv4']; |
64 | $totalLength = 32; |
65 | } elseif ( IPUtils::isIPv6( $ip ) ) { |
66 | $minLength = $this->limits['IPv6']; |
67 | $totalLength = 128; |
68 | } else { |
69 | // The factory should not have called the constructor with an invalid range |
70 | throw new \RuntimeException( 'invalid IP range' ); |
71 | } |
72 | |
73 | if ( $minLength == $totalLength ) { |
74 | // Range block effectively disabled |
75 | $status->fatal( 'range_block_disabled' ); |
76 | } elseif ( $prefixLength > $totalLength ) { |
77 | // Such a range cannot exist |
78 | $status->fatal( 'ip_range_invalid' ); |
79 | } elseif ( $prefixLength < $minLength ) { |
80 | $status->fatal( 'ip_range_toolarge', $minLength ); |
81 | } |
82 | |
83 | return $status; |
84 | } |
85 | |
86 | public function toHexRange() { |
87 | $range = IPUtils::parseRange( $this->cidr ); |
88 | if ( count( $range ) !== 2 || !is_string( $range[0] ) || !is_string( $range[1] ) ) { |
89 | throw new \RuntimeException( |
90 | 'Failed to parse range: constructor caller should have validated it' ); |
91 | } |
92 | return $range; |
93 | } |
94 | |
95 | /** |
96 | * Get the start of the range in hexadecimal form. |
97 | * |
98 | * @return string |
99 | */ |
100 | public function getHexRangeStart(): string { |
101 | return $this->toHexRange()[0]; |
102 | } |
103 | |
104 | /** |
105 | * Get the end of the range in hexadecimal form. |
106 | * |
107 | * @return string |
108 | */ |
109 | public function getHexRangeEnd(): string { |
110 | return $this->toHexRange()[1]; |
111 | } |
112 | |
113 | protected function getLegacyUnion() { |
114 | return $this->cidr; |
115 | } |
116 | |
117 | } |