Add ip_in_ranges function

Added support for ip_in_ranges which allow multiple ranges to be
checked at the same time. If the IP is in any of the ranges, the
function returns true.

Bug: T305017
Change-Id: Ic75c87ecd4cacf47ce2ff1b04173405230ff81d0
This commit is contained in:
fossifer 2022-05-08 09:14:40 +08:00
parent d24c993c71
commit b1739a588f
6 changed files with 57 additions and 0 deletions

View file

@ -337,6 +337,7 @@
"abusefilter-edit-builder-funcs-rmwhitespace": "Remove whitespace (rmwhitespace)",
"abusefilter-edit-builder-funcs-rmspecials": "Remove special characters (rmspecials)",
"abusefilter-edit-builder-funcs-ip_in_range": "Is IP in range? (ip_in_range)",
"abusefilter-edit-builder-funcs-ip_in_ranges": "Is IP in any of the ranges? (ip_in_ranges)",
"abusefilter-edit-builder-funcs-contains-any": "Search string for multiple substrings in OR mode. (contains_any)",
"abusefilter-edit-builder-funcs-contains-all": "Search string for multiple substrings in AND mode. (contains_all)",
"abusefilter-edit-builder-funcs-equals-to-any": "Check if a given argument is equal (===) to any of the following arguments (equals_to_any)",

View file

@ -379,6 +379,7 @@
"abusefilter-edit-builder-funcs-rmwhitespace": "{{doc-important|Do not translate \"rmwhitespace\"}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
"abusefilter-edit-builder-funcs-rmspecials": "{{doc-important|Do not translate \"'''rmspecials'''\".}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
"abusefilter-edit-builder-funcs-ip_in_range": "{{doc-important|Do not translate \"'''ip_in_range'''\".}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
"abusefilter-edit-builder-funcs-ip_in_ranges": "{{doc-important|Do not translate \"'''ip_in_ranges'''\".}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
"abusefilter-edit-builder-funcs-contains-any": "{{doc-important|Do not translate \"'''contains_any'''\".}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
"abusefilter-edit-builder-funcs-contains-all": "{{doc-important|Do not translate \"'''contains_all'''\".}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
"abusefilter-edit-builder-funcs-equals-to-any": "{{doc-important|Do not translate <code><nowiki>===</nowiki></code> and <code><nowiki>equals_to_any</nowiki></code> (but feel free to change brackets to reflect bracket rules of your language).}} Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",

View file

@ -62,6 +62,7 @@ class KeywordsManager {
'rmwhitespace(text)' => 'rmwhitespace',
'rmspecials(text)' => 'rmspecials',
'ip_in_range(ip, range)' => 'ip_in_range',
'ip_in_ranges(ip, range1, range2, ...)' => 'ip_in_ranges',
'contains_any(haystack,needle1,needle2,...)' => 'contains-any',
'contains_all(haystack,needle1,needle2,...)' => 'contains-all',
'equals_to_any(haystack,needle1,needle2,...)' => 'equals-to-any',

View file

@ -52,6 +52,7 @@ class FilterEvaluator {
'rcount' => 'funcRCount',
'get_matches' => 'funcGetMatches',
'ip_in_range' => 'funcIPInRange',
'ip_in_ranges' => 'funcIPInRanges',
'contains_any' => 'funcContainsAny',
'contains_all' => 'funcContainsAll',
'equals_to_any' => 'funcEqualsToAny',
@ -89,6 +90,7 @@ class FilterEvaluator {
'rcount' => [ 1, 2 ],
'get_matches' => [ 2, 2 ],
'ip_in_range' => [ 2, 2 ],
'ip_in_ranges' => [ 3, INF ],
'contains_any' => [ 2, INF ],
'contains_all' => [ 2, INF ],
'equals_to_any' => [ 2, INF ],
@ -1011,6 +1013,34 @@ class FilterEvaluator {
return new AFPData( AFPData::DBOOL, $result );
}
/**
* @param array $args
* @param int $position
* @return AFPData
* @throws UserVisibleException
*/
protected function funcIPInRanges( $args, int $position ) {
$ip = array_shift( $args )->toString();
foreach ( $args as $range ) {
$range = $range->toString();
if ( !IPUtils::isValidRange( $range ) && !IPUtils::isIPAddress( $range ) ) {
throw new UserVisibleException(
'invalidiprange',
$position,
[ $range ]
);
}
if ( IPUtils::isInRange( $ip, $range ) ) {
return new AFPData( AFPData::DBOOL, true );
}
}
return new AFPData( AFPData::DBOOL, false );
}
/**
* @param array $args
* @return AFPData

View file

@ -0,0 +1,21 @@
ip_in_ranges( '12.34.56.78', '12.34.56.0/24', '12.34.0.0/16' ) === true &
ip_in_ranges( '12.34.56.78', '65.43.0.0/16', '12.34.56.78/32' ) === true &
ip_in_ranges( '12.34.56.78', '12.0.0.0/8', '13.0.0.0/8' ) === true &
ip_in_ranges( '12.34.56.78', '12.34.56.78', '2001:db8::/16' ) === true &
ip_in_ranges( '12.34.56.78', '12.1.2.255/8', '::' ) === true &
ip_in_ranges( '1.1.1.1', '1.1.1.1/32', '2.2.2.2/32' ) === true &
ip_in_ranges( '1.1.1.1', '1.1.1.1', '1.1.1.1', '1.1.1.1/32' ) === true &
ip_in_ranges( '1.1.1.1', '0.0.0.0/0', '0.0.0.0/1', '0.0.0.0/2', '0.0.0.0/3' ) === true &
ip_in_ranges( '1.1.1.1', '::', '::/0', '::/1' ) === false &
ip_in_ranges( '123.123.123.123', '123.123.123.123', '123.123.123.123' ) === true &
ip_in_ranges( '123.123.123.123', '123.0.0.0-123.122.0.0', '123.124.0.0-124.122.0.0' ) === false &
ip_in_ranges( '123.123.123.123', '125.0.0.0 - 127.0.0.0', '123.0.0.0-124.0.0.0' ) === true &
ip_in_ranges( '123.123.123.123', '123.0.0.0-127.0.0.0', '123.123.0.0 - 124.0.0.0' ) === true &
ip_in_ranges( '123.123.123.123', '127.0.0.0-123.0.0.0', '120.0.0.0-123.0.0.0' ) === false &
ip_in_ranges( '123.123.123.123', '127.0.0.0-123.0.0.0', '123.0.0.0-127.0.0.0' ) === true &
ip_in_ranges( '11.11.11.11', '11.11.11.1', '1.11.11.11', '11.1.11.11', '11.11.1.11' ) === false &
ip_in_ranges( '1.1.1.1', '::-ffff::', '0.0.0.0-255.255.255.255' ) === true &
ip_in_ranges( '2001:db8:85a3::8a2e:0370:7334', '::-ffff::', '0.0.0.0-255.255.255.255' ) === true &
ip_in_ranges( '2001:db8:85a3::8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7334/113', '2001:db8:85a3::8a2e:370:0000-2001:db8:85a3::8a2e:370:8888' ) === true &
ip_in_ranges( '1.1.1.1', '::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', '0.0.0.0' ) === false &
ip_in_ranges( '2001:db8:85a3::8a2e:370:0000', '0.0.0.0-255.255.255.255', '::' ) === false

View file

@ -575,6 +575,7 @@ class ParserTest extends ParserTestCase {
public function invalidIPRange() {
return [
[ "ip_in_range('0.0.0.0', 'lol')", 'funcIPInRange' ],
[ "ip_in_ranges('0.0.0.0', ':', '0.0.0.256')", 'funcIPInRanges' ],
];
}
@ -679,6 +680,7 @@ class ParserTest extends ParserTestCase {
public function threeParamsFuncs() {
return [
[ 'str_replace' ],
[ 'ip_in_ranges' ],
];
}
@ -1132,6 +1134,7 @@ class ParserTest extends ParserTestCase {
[ 'added_lines contains string(3/0)', 'dividebyzero' ],
[ 'norm(new_text) irlike ")"', 'regexfailure' ],
[ 'ip_in_range( user_name, "foobar" )', 'invalidiprange' ],
[ 'ip_in_ranges( user_name, "foo", "bar" )', 'invalidiprange' ],
];
}