From: Florian Date: Tue, 25 Aug 2015 18:05:35 +0000 (+0200) Subject: Enable IP ranges in HTMLUserTextField X-Git-Tag: 1.31.0-rc.0~1907^2 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=b73c0c4d3fc90d61694216126f65a4420b6bfcc4 Enable IP ranges in HTMLUserTextField Like an existing user and a single IP, allow to use an IP range, too. Bug: T107039 Change-Id: I9137f71f6119c68d787f508a3f57b476404315d8 --- diff --git a/includes/htmlform/fields/HTMLUserTextField.php b/includes/htmlform/fields/HTMLUserTextField.php index 12c09c1d7e..e1939705ab 100644 --- a/includes/htmlform/fields/HTMLUserTextField.php +++ b/includes/htmlform/fields/HTMLUserTextField.php @@ -10,15 +10,25 @@ use MediaWiki\Widget\UserInputWidget; * * Optional parameters: * 'exists' - Whether to validate that the user already exists + * 'ipallowed' - Whether an IP adress is interpreted as "valid" + * 'iprange' - Whether an IP adress range is interpreted as "valid" + * 'iprangelimits' - Specifies the valid IP ranges for IPv4 and IPv6 in an array. + * defaults to IPv4 => 16; IPv6 => 32. * * @since 1.26 */ class HTMLUserTextField extends HTMLTextField { public function __construct( $params ) { - $params += [ - 'exists' => false, - 'ipallowed' => false, - ]; + $params = wfArrayPlus2d( $params, [ + 'exists' => false, + 'ipallowed' => false, + 'iprange' => false, + 'iprangelimits' => [ + 'IPv4' => '16', + 'IPv6' => '32', + ], + ] + ); parent::__construct( $params ); } @@ -26,19 +36,63 @@ class HTMLUserTextField extends HTMLTextField { public function validate( $value, $alldata ) { // check, if a user exists with the given username $user = User::newFromName( $value, false ); + $rangeError = null; if ( !$user ) { return $this->msg( 'htmlform-user-not-valid', $value ); } elseif ( + // check, if the user exists, if requested ( $this->mParams['exists'] && $user->getId() === 0 ) && - !( $this->mParams['ipallowed'] && User::isIP( $value ) ) + // check, if the username is a valid IP address, otherweise save the error message + !( $this->mParams['ipallowed'] && IP::isValid( $value ) ) && + // check, if the username is a valid IP range, otherwise save the error message + !( $this->mParams['iprange'] && ( $rangeError = $this->isValidIPRange( $value ) ) === true ) ) { + if ( is_string( $rangeError ) ) { + return $rangeError; + } return $this->msg( 'htmlform-user-not-exists', $user->getName() ); } return parent::validate( $value, $alldata ); } + protected function isValidIPRange( $value ) { + $cidrIPRanges = $this->mParams['iprangelimits']; + + if ( !IP::isValidBlock( $value ) ) { + return false; + } + + list( $ip, $range ) = explode( '/', $value, 2 ); + + if ( + ( IP::isIPv4( $ip ) && $cidrIPRanges['IPv4'] == 32 ) || + ( IP::isIPv6( $ip ) && $cidrIPRanges['IPv6'] == 128 ) + ) { + // Range block effectively disabled + return $this->msg( 'ip_range_toolow' )->parse(); + } + + if ( + ( IP::isIPv4( $ip ) && $range > 32 ) || + ( IP::isIPv6( $ip ) && $range > 128 ) + ) { + // Dodgy range + return $this->msg( 'ip_range_invalid' )->parse(); + } + + if ( IP::isIPv4( $ip ) && $range < $cidrIPRanges['IPv4'] ) { + return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv4'] )->parse(); + } + + if ( IP::isIPv6( $ip ) && $range < $cidrIPRanges['IPv6'] ) { + return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv6'] )->parse(); + } + + return true; + } + protected function getInputWidget( $params ) { return new UserInputWidget( $params ); } diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 5fccdace81..875da04e32 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -2596,6 +2596,8 @@ "ipb_blocked_as_range": "Error: The IP address $1 is not blocked directly and cannot be unblocked.\nIt is, however, blocked as part of the range $2, which can be unblocked.", "ip_range_invalid": "Invalid IP address range.", "ip_range_toolarge": "Range blocks larger than /$1 are not allowed.", + "ip_range_exceeded": "The IP range exceeds its maximum range. Allowed range: /$1.", + "ip_range_toolow": "IP ranges are effectively not allowed.", "proxyblocker": "Proxy blocker", "proxyblockreason": "Your IP address has been blocked because it is an open proxy.\nPlease contact your Internet service provider or technical support of your organization and inform them of this serious security problem.", "sorbs": "DNSBL", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index fc4319fbac..4ff05befab 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -2788,6 +2788,8 @@ "ipb_blocked_as_range": "Used when unblock of a single IP fails. Parameters:\n* $1 - IP address\n* $2 - IP address range", "ip_range_invalid": "Used as error message in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Range block disabled}}\n* {{msg-mw|Ip range invalid}}\n* {{msg-mw|Ip range toolarge}}", "ip_range_toolarge": "Used as error message in [[Special:Block]]. Parameters:\n* $1 - a number from 0 to 32 for IPv4 (from 0 to 128 for IPv6); a part of CIDR (Classless Inter-Domain Routing) notation.\nSee also:\n* {{msg-mw|Range block disabled}}\n* {{msg-mw|Ip range invalid}}\n* {{msg-mw|Ip range toolarge}}", + "ip_range_exceeded": "Used as error message in HTMLUserTextField when an IP range exceeds its maximum amount. See {{mw-msg|ip_range_toolarge}} for parameter.", + "ip_range_toolow": "Used as error message in HTMLUserTextField, if effectively no IP ranges are interpreted as valid (IPv4 CIDR range /32 or IPv6 /128).", "proxyblocker": "Used in [[Special:BlockMe]].\n\nSee also:\n* {{msg-mw|proxyblocker-disabled}}\n* {{msg-mw|proxyblockreason}}\n* {{msg-mw|proxyblocksuccess}}", "proxyblockreason": "Used as explanation of the reason in [[Special:BlockMe]].\n\nSee also:\n* {{msg-mw|proxyblocker-disabled}}\n* {{msg-mw|proxyblocker}}\n* {{msg-mw|proxyblocksuccess}}", "sorbs": "{{optional}}",