From dd5af7eb1015c103efeb32c8730118b0d17705ef Mon Sep 17 00:00:00 2001 From: Klaxon Date: Tue, 28 Aug 2018 14:48:19 +1000 Subject: [PATCH 1/5] add parse IPv4 list --- src/core/lib/IP.mjs | 51 ++++++++++++++++++++++++++-- src/core/operations/ParseIPRange.mjs | 7 ++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/core/lib/IP.mjs b/src/core/lib/IP.mjs index 8a8301a6..472759fa 100644 --- a/src/core/lib/IP.mjs +++ b/src/core/lib/IP.mjs @@ -109,8 +109,8 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) { * @returns {string} */ export function ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) { - const ip1 = strToIpv4(range[1]), - ip2 = strToIpv4(range[2]); + const ip1 = strToIpv4(range[0].split("-")[0].trim()), + ip2 = strToIpv4(range[0].split("-")[1].trim()); let output = ""; @@ -188,6 +188,42 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) { return output; } +/** + * Parses a list of IPv4 addresses separated by a new line (\n) and displays information + * about it. + * + * @param {RegExp} list + * @param {boolean} includeNetworkInfo + * @param {boolean} enumerateAddresses + * @param {boolean} allowLargeList + * @returns {string} + */ +export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList) { + + var ipv4List = match[0].split("\n"); + ipv4List = ipv4List.filter(Boolean); + + var ipv4CidrList = ipv4List.filter( function(a) { return a.includes("/")}); + for (let i = 0; i < ipv4CidrList.length; i++) { + let network = strToIpv4(ipv4CidrList[i].split("/")[0]); + let cidrRange = parseInt(ipv4CidrList[i].split("/")[1]); + if (cidrRange < 0 || cidrRange > 31) { + return "IPv4 CIDR must be less than 32"; + } + let mask = ~(0xFFFFFFFF >>> cidrRange), + cidrIp1 = network & mask, + cidrIp2 = cidrIp1 | ~mask; + ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]),1); + ipv4List.push(ipv4ToStr(cidrIp1), ipv4ToStr(cidrIp2)); + } + + ipv4List = ipv4List.sort(ipv4Compare); + let ip1 = ipv4List[0]; + let ip2 = ipv4List[ipv4List.length - 1]; + let range = [ip1 + " - " + ip2] + return ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList); +} + /** * Converts an IPv4 address from string format to numerical format. * @@ -391,6 +427,17 @@ export function genIpv6Mask(cidr) { return mask; } +/** + * Comparison operation for sorting of IPv4 addresses. + * + * @param {string} a + * @param {string} b + * @returns {number} + */ +export function ipv4Compare(a, b) { + return strToIpv4(a) - strToIpv4(b); +} + const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges."; /** diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs index 3704751f..93aff3ce 100644 --- a/src/core/operations/ParseIPRange.mjs +++ b/src/core/operations/ParseIPRange.mjs @@ -6,7 +6,7 @@ import Operation from "../Operation"; import OperationError from "../errors/OperationError"; -import {ipv4CidrRange, ipv4HyphenatedRange, ipv6CidrRange, ipv6HyphenatedRange} from "../lib/IP"; +import {ipv4CidrRange, ipv4HyphenatedRange, ipv4ListedRange, ipv6CidrRange, ipv6HyphenatedRange} from "../lib/IP"; /** * Parse IP range operation @@ -21,7 +21,7 @@ class ParseIPRange extends Operation { this.name = "Parse IP range"; this.module = "JSBN"; - this.description = "Given a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated."; + this.description = "Given a CIDR range (e.g. 10.0.0.0/24), hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), or a list of IPs, (this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated"; this.infoURL = "https://wikipedia.org/wiki/Subnetwork"; this.inputType = "string"; this.outputType = "string"; @@ -59,6 +59,7 @@ class ParseIPRange extends Operation { // Check what type of input we are looking at const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/, ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/, + ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))*$/, ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i, ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i; let match; @@ -67,6 +68,8 @@ class ParseIPRange extends Operation { return ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); } else if ((match = ipv4RangeRegex.exec(input))) { return ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + } else if ((match = ipv4ListRegex.exec(input))) { + return ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); } else if ((match = ipv6CidrRegex.exec(input))) { return ipv6CidrRange(match, includeNetworkInfo); } else if ((match = ipv6RangeRegex.exec(input))) { From ce494339ef6540a55360b224ce7a5120967712f6 Mon Sep 17 00:00:00 2001 From: Klaxon Date: Tue, 28 Aug 2018 15:35:54 +1000 Subject: [PATCH 2/5] add parse IPv6 list --- src/core/lib/IP.mjs | 69 +++++++++++++++++++++++++++- src/core/operations/ParseIPRange.mjs | 9 ++-- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/core/lib/IP.mjs b/src/core/lib/IP.mjs index 472759fa..bd1baa68 100644 --- a/src/core/lib/IP.mjs +++ b/src/core/lib/IP.mjs @@ -162,8 +162,8 @@ Total addresses in range: ${(((ip2 - ip1) >>> 0) + 1)} * @returns {string} */ export function ipv6HyphenatedRange(range, includeNetworkInfo) { - const ip1 = strToIpv6(range[1]), - ip2 = strToIpv6(range[14]), + const ip1 = strToIpv6(range[0].split("-")[0].trim()), + ip2 = strToIpv6(range[0].split("-")[1].trim()), total = new Array(128).fill(); let output = "", @@ -224,6 +224,51 @@ export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, a return ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList); } +/** + * Parses a list of IPv6 addresses separated by a new line (\n) and displays information + * about it. + * + * @param {RegExp} list + * @param {boolean} includeNetworkInfo + * @returns {string} + */ +export function ipv6ListedRange(match, includeNetworkInfo) { + + var ipv6List = match[0].split("\n"); + ipv6List = ipv6List.filter(function(str) {return str.trim();}); + for (let i =0; i < ipv6List.length; i++){ + ipv6List[i] = ipv6List[i].trim(); + } + var ipv6CidrList = ipv6List.filter( function(a) { return a.includes("/")}); + + for (let i = 0; i < ipv6CidrList.length; i++) { + + let network = strToIpv6(ipv6CidrList[i].split("/")[0]); + let cidrRange = parseInt(ipv6CidrList[i].split("/")[1]); + + if (cidrRange < 0 || cidrRange > 127) { + return "IPv6 CIDR must be less than 128"; + } + + let cidrIp1 = new Array(8), + cidrIp2 = new Array(8); + + let mask = genIpv6Mask(cidrRange); + + for (let j = 0; j < 8; j++) { + cidrIp1[j] = network[j] & mask[j]; + cidrIp2[j] = cidrIp1[j] | (~mask[j] & 0x0000FFFF); + } + ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]),1); + ipv6List.push(ipv6ToStr(cidrIp1), ipv6ToStr(cidrIp2)); + } + ipv6List = ipv6List.sort(ipv6Compare); + let ip1 = ipv6List[0]; + let ip2 = ipv6List[ipv6List.length - 1]; + let range = [ip1 + " - " + ip2] + return ipv6HyphenatedRange(range, includeNetworkInfo); +} + /** * Converts an IPv4 address from string format to numerical format. * @@ -438,6 +483,26 @@ export function ipv4Compare(a, b) { return strToIpv4(a) - strToIpv4(b); } +/** + * Comparison operation for sorting of IPv6 addresses. + * + * @param {string} a + * @param {string} b + * @returns {number} + */ +export function ipv6Compare(a, b) { + + let a_ = strToIpv6(a), + b_ = strToIpv6(b); + + for (let i = 0; i < a_.length; i++){ + if (a_[i] != b_[i]){ + return a_[i] - b_[i]; + } + } + return 0; +} + const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges."; /** diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs index 93aff3ce..3a3bb1e6 100644 --- a/src/core/operations/ParseIPRange.mjs +++ b/src/core/operations/ParseIPRange.mjs @@ -6,7 +6,7 @@ import Operation from "../Operation"; import OperationError from "../errors/OperationError"; -import {ipv4CidrRange, ipv4HyphenatedRange, ipv4ListedRange, ipv6CidrRange, ipv6HyphenatedRange} from "../lib/IP"; +import {ipv4CidrRange, ipv4HyphenatedRange, ipv4ListedRange, ipv6CidrRange, ipv6HyphenatedRange, ipv6ListedRange} from "../lib/IP"; /** * Parse IP range operation @@ -21,7 +21,7 @@ class ParseIPRange extends Operation { this.name = "Parse IP range"; this.module = "JSBN"; - this.description = "Given a CIDR range (e.g. 10.0.0.0/24), hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), or a list of IPs, (this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated"; + this.description = "Given a CIDR range (e.g. 10.0.0.0/24), hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), or a list of IPs and CIDR ranges (new line separated), (this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated"; this.infoURL = "https://wikipedia.org/wiki/Subnetwork"; this.inputType = "string"; this.outputType = "string"; @@ -61,7 +61,8 @@ class ParseIPRange extends Operation { ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/, ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))*$/, ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i, - ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i; + ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i, + ipv6ListRegex = /^((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))*$/ig; let match; if ((match = ipv4CidrRegex.exec(input))) { @@ -74,6 +75,8 @@ class ParseIPRange extends Operation { return ipv6CidrRange(match, includeNetworkInfo); } else if ((match = ipv6RangeRegex.exec(input))) { return ipv6HyphenatedRange(match, includeNetworkInfo); + } else if ((match = ipv6ListRegex.exec(input))) { + return ipv6ListedRange(match, includeNetworkInfo); } else { throw new OperationError("Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported."); } From 135b17186efa39b90429246d47f47e3ff42da6a6 Mon Sep 17 00:00:00 2001 From: Klaxon Date: Tue, 28 Aug 2018 16:42:24 +1000 Subject: [PATCH 3/5] update description --- src/core/operations/ParseIPRange.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs index 3a3bb1e6..5304d814 100644 --- a/src/core/operations/ParseIPRange.mjs +++ b/src/core/operations/ParseIPRange.mjs @@ -21,7 +21,7 @@ class ParseIPRange extends Operation { this.name = "Parse IP range"; this.module = "JSBN"; - this.description = "Given a CIDR range (e.g. 10.0.0.0/24), hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), or a list of IPs and CIDR ranges (new line separated), (this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated"; + this.description = "Given a CIDR range (e.g. 10.0.0.0/24), hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), or a list of IPs and/or CIDR ranges (separated by a new line), this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated"; this.infoURL = "https://wikipedia.org/wiki/Subnetwork"; this.inputType = "string"; this.outputType = "string"; From 86145dbf67a253a36f2b6d778cfc0bab4c561b70 Mon Sep 17 00:00:00 2001 From: Klaxon Date: Tue, 28 Aug 2018 20:14:40 +1000 Subject: [PATCH 4/5] add tests --- src/core/operations/ParseIPRange.mjs | 1 + test/index.mjs | 2 +- test/tests/operations/ParseIPRange.mjs | 132 +++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 test/tests/operations/ParseIPRange.mjs diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs index 5304d814..7a15c29f 100644 --- a/src/core/operations/ParseIPRange.mjs +++ b/src/core/operations/ParseIPRange.mjs @@ -1,5 +1,6 @@ /** * @author n1474335 [n1474335@gmail.com] + * @author Klaxon [klaxon@veyr.com] * @copyright Crown Copyright 2016 * @license Apache-2.0 */ diff --git a/test/index.mjs b/test/index.mjs index 8cf69732..3099daa6 100644 --- a/test/index.mjs +++ b/test/index.mjs @@ -64,6 +64,7 @@ import "./tests/operations/SetUnion"; import "./tests/operations/SymmetricDifference"; import "./tests/operations/TranslateDateTimeFormat"; import "./tests/operations/Magic"; +import "./tests/operations/ParseIPRange"; let allTestsPassing = true; const testStatusCounts = { @@ -142,4 +143,3 @@ TestRegister.runTests() process.exit(allTestsPassing ? 0 : 1); }); - diff --git a/test/tests/operations/ParseIPRange.mjs b/test/tests/operations/ParseIPRange.mjs new file mode 100644 index 00000000..41ca5a43 --- /dev/null +++ b/test/tests/operations/ParseIPRange.mjs @@ -0,0 +1,132 @@ +/** + * MS tests. + * + * @author Klaxon [klaxon@veyr.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +import TestRegister from "../../TestRegister"; + +TestRegister.addTests([ + { + name: "Parse IPv4 CIDR", + input: "10.0.0.0/30", + expectedOutput: "Network: 10.0.0.0\nCIDR: 30\nMask: 255.255.255.252\nRange: 10.0.0.0 - 10.0.0.3\nTotal addresses in range: 4\n\n10.0.0.0\n10.0.0.1\n10.0.0.2\n10.0.0.3", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "Parse IPv4 hyphenated", + input: "10.0.0.0 - 10.0.0.3", + expectedOutput: "Minimum subnet required to hold this range:\n\tNetwork: 10.0.0.0\n\tCIDR: 30\n\tMask: 255.255.255.252\n\tSubnet range: 10.0.0.0 - 10.0.0.3\n\tTotal addresses in subnet: 4\n\nRange: 10.0.0.0 - 10.0.0.3\nTotal addresses in range: 4\n\n10.0.0.0\n10.0.0.1\n10.0.0.2\n10.0.0.3", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "Parse IPv4 list", + input: "10.0.0.8\n10.0.0.5/30\n10.0.0.1\n10.0.0.3", + expectedOutput: "Minimum subnet required to hold this range:\n\tNetwork: 10.0.0.0\n\tCIDR: 28\n\tMask: 255.255.255.240\n\tSubnet range: 10.0.0.0 - 10.0.0.15\n\tTotal addresses in subnet: 16\n\nRange: 10.0.0.1 - 10.0.0.8\nTotal addresses in range: 8\n\n10.0.0.1\n10.0.0.2\n10.0.0.3\n10.0.0.4\n10.0.0.5\n10.0.0.6\n10.0.0.7\n10.0.0.8", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "Parse IPv6 CIDR - full", + input: "2404:6800:4001:0000:0000:0000:0000:0000/48", + expectedOutput: "Network: 2404:6800:4001:0000:0000:0000:0000:0000\nShorthand: 2404:6800:4001::\nCIDR: 48\nMask: ffff:ffff:ffff:0000:0000:0000:0000:0000\nRange: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "Parse IPv6 CIDR - collapsed", + input: "2404:6800:4001::/48", + expectedOutput: "Network: 2404:6800:4001:0000:0000:0000:0000:0000\nShorthand: 2404:6800:4001::\nCIDR: 48\nMask: ffff:ffff:ffff:0000:0000:0000:0000:0000\nRange: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "Parse IPv6 hyphenated", + input: "2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff", + expectedOutput: "Range: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nShorthand range: 2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "Parse IPv6 list", + input: "2404:6800:4001:ffff:ffff:ffff:ffff:ffff\n2404:6800:4001::ffff\n2404:6800:4001:ffff:ffff::1111\n2404:6800:4001::/64", + expectedOutput: "Range: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nShorthand range: 2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "IPv4 subnet out of range error", + input: "10.1.1.1/34", + expectedOutput: "IPv4 CIDR must be less than 32", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "invalid IPv4 address error", + input: "444.1.1.1/30", + expectedOutput: "Block out of range.", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "IPv6 subnet out of range error", + input: "2404:6800:4001::/129", + expectedOutput: "IPv6 CIDR must be less than 128", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, + { + name: "invalid IPv6 address error", + input: "2404:6800:4001:/12", + expectedOutput: "Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.", + recipeConfig: [ + { + "op": "Parse IP range", + "args": [true,true,false] + }, + ], + }, +]); From 28206602649a0dd09561b91e622c6a77517bf2e4 Mon Sep 17 00:00:00 2001 From: Klaxon Date: Tue, 28 Aug 2018 20:15:59 +1000 Subject: [PATCH 5/5] fix regex issues and ESlint errors and warnings fix comment fix ESlint errors and warnings fix regex add author --- src/core/lib/IP.mjs | 53 +++++++++++++++----------- src/core/operations/ParseIPRange.mjs | 4 +- test/tests/operations/ParseIPRange.mjs | 24 ++++++------ 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/core/lib/IP.mjs b/src/core/lib/IP.mjs index bd1baa68..cfefbd11 100644 --- a/src/core/lib/IP.mjs +++ b/src/core/lib/IP.mjs @@ -3,6 +3,7 @@ * * @author picapi * @author n1474335 [n1474335@gmail.com] + * @author Klaxon [klaxon@veyr.com] * @copyright Crown Copyright 2016 * @license Apache-2.0 */ @@ -110,7 +111,7 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) { */ export function ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) { const ip1 = strToIpv4(range[0].split("-")[0].trim()), - ip2 = strToIpv4(range[0].split("-")[1].trim()); + ip2 = strToIpv4(range[0].split("-")[1].trim()); let output = ""; @@ -200,27 +201,29 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) { */ export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList) { - var ipv4List = match[0].split("\n"); + let ipv4List = match[0].split("\n"); ipv4List = ipv4List.filter(Boolean); - var ipv4CidrList = ipv4List.filter( function(a) { return a.includes("/")}); + const ipv4CidrList = ipv4List.filter(function(a) { + return a.includes("/"); + }); for (let i = 0; i < ipv4CidrList.length; i++) { - let network = strToIpv4(ipv4CidrList[i].split("/")[0]); - let cidrRange = parseInt(ipv4CidrList[i].split("/")[1]); + const network = strToIpv4(ipv4CidrList[i].split("/")[0]); + const cidrRange = parseInt(ipv4CidrList[i].split("/")[1], 10); if (cidrRange < 0 || cidrRange > 31) { return "IPv4 CIDR must be less than 32"; } - let mask = ~(0xFFFFFFFF >>> cidrRange), + const mask = ~(0xFFFFFFFF >>> cidrRange), cidrIp1 = network & mask, cidrIp2 = cidrIp1 | ~mask; - ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]),1); + ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1); ipv4List.push(ipv4ToStr(cidrIp1), ipv4ToStr(cidrIp2)); } ipv4List = ipv4List.sort(ipv4Compare); - let ip1 = ipv4List[0]; - let ip2 = ipv4List[ipv4List.length - 1]; - let range = [ip1 + " - " + ip2] + const ip1 = ipv4List[0]; + const ip2 = ipv4List[ipv4List.length - 1]; + const range = [ip1 + " - " + ip2]; return ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList); } @@ -234,38 +237,42 @@ export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, a */ export function ipv6ListedRange(match, includeNetworkInfo) { - var ipv6List = match[0].split("\n"); - ipv6List = ipv6List.filter(function(str) {return str.trim();}); + let ipv6List = match[0].split("\n"); + ipv6List = ipv6List.filter(function(str) { + return str.trim(); + }); for (let i =0; i < ipv6List.length; i++){ ipv6List[i] = ipv6List[i].trim(); } - var ipv6CidrList = ipv6List.filter( function(a) { return a.includes("/")}); + const ipv6CidrList = ipv6List.filter(function(a) { + return a.includes("/"); + }); for (let i = 0; i < ipv6CidrList.length; i++) { - let network = strToIpv6(ipv6CidrList[i].split("/")[0]); - let cidrRange = parseInt(ipv6CidrList[i].split("/")[1]); + const network = strToIpv6(ipv6CidrList[i].split("/")[0]); + const cidrRange = parseInt(ipv6CidrList[i].split("/")[1], 10); if (cidrRange < 0 || cidrRange > 127) { return "IPv6 CIDR must be less than 128"; } - let cidrIp1 = new Array(8), + const cidrIp1 = new Array(8), cidrIp2 = new Array(8); - let mask = genIpv6Mask(cidrRange); + const mask = genIpv6Mask(cidrRange); for (let j = 0; j < 8; j++) { cidrIp1[j] = network[j] & mask[j]; cidrIp2[j] = cidrIp1[j] | (~mask[j] & 0x0000FFFF); } - ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]),1); + ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]), 1); ipv6List.push(ipv6ToStr(cidrIp1), ipv6ToStr(cidrIp2)); } ipv6List = ipv6List.sort(ipv6Compare); - let ip1 = ipv6List[0]; - let ip2 = ipv6List[ipv6List.length - 1]; - let range = [ip1 + " - " + ip2] + const ip1 = ipv6List[0]; + const ip2 = ipv6List[ipv6List.length - 1]; + const range = [ip1 + " - " + ip2]; return ipv6HyphenatedRange(range, includeNetworkInfo); } @@ -492,11 +499,11 @@ export function ipv4Compare(a, b) { */ export function ipv6Compare(a, b) { - let a_ = strToIpv6(a), + const a_ = strToIpv6(a), b_ = strToIpv6(b); for (let i = 0; i < a_.length; i++){ - if (a_[i] != b_[i]){ + if (a_[i] !== b_[i]){ return a_[i] - b_[i]; } } diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs index 7a15c29f..84d4dd63 100644 --- a/src/core/operations/ParseIPRange.mjs +++ b/src/core/operations/ParseIPRange.mjs @@ -60,10 +60,10 @@ class ParseIPRange extends Operation { // Check what type of input we are looking at const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/, ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/, - ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))*$/, + ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))+\s*$/, ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i, ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i, - ipv6ListRegex = /^((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))*$/ig; + ipv6ListRegex = /^\s*((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))+\s*$/i; let match; if ((match = ipv4CidrRegex.exec(input))) { diff --git a/test/tests/operations/ParseIPRange.mjs b/test/tests/operations/ParseIPRange.mjs index 41ca5a43..1b81cbc0 100644 --- a/test/tests/operations/ParseIPRange.mjs +++ b/test/tests/operations/ParseIPRange.mjs @@ -1,5 +1,5 @@ /** - * MS tests. + * Parse IP Range tests. * * @author Klaxon [klaxon@veyr.com] * @copyright Crown Copyright 2017 @@ -15,7 +15,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -26,7 +26,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -37,7 +37,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -48,7 +48,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -59,7 +59,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -70,7 +70,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -81,7 +81,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -92,7 +92,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -103,7 +103,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -114,7 +114,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], }, @@ -125,7 +125,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse IP range", - "args": [true,true,false] + "args": [true, true, false] }, ], },