aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/assets/js/bundle.js
diff options
context:
space:
mode:
authorEgor Tensin <egor@tensin.name>2026-06-06 22:18:37 +0200
committerEgor Tensin <egor@tensin.name>2026-06-06 22:25:32 +0200
commit07a784f0d654fcd552069e85b314ea7c29cb5dd6 (patch)
tree9c12dec00b68aaa33dbf8429f34f9812493c965a /assets/js/bundle.js
parentbump dependencies (diff)
downloadwireguard-config-07a784f0d654fcd552069e85b314ea7c29cb5dd6.tar.gz
wireguard-config-07a784f0d654fcd552069e85b314ea7c29cb5dd6.zip
move Jekyll source files to src/
Diffstat (limited to 'assets/js/bundle.js')
-rw-r--r--assets/js/bundle.js2064
1 files changed, 0 insertions, 2064 deletions
diff --git a/assets/js/bundle.js b/assets/js/bundle.js
deleted file mode 100644
index da8f679..0000000
--- a/assets/js/bundle.js
+++ /dev/null
@@ -1,2064 +0,0 @@
-require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.AddressError = void 0;
-class AddressError extends Error {
- constructor(message, parseMessage) {
- super(message);
- this.name = 'AddressError';
- this.parseMessage = parseMessage;
- }
-}
-exports.AddressError = AddressError;
-
-},{}],2:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.isInSubnet = isInSubnet;
-exports.isCorrect = isCorrect;
-exports.prefixLengthFromMask = prefixLengthFromMask;
-exports.numberToPaddedHex = numberToPaddedHex;
-exports.stringToPaddedHex = stringToPaddedHex;
-exports.testBit = testBit;
-const address_error_1 = require("./address-error");
-function isInSubnet(address) {
- if (this.subnetMask < address.subnetMask) {
- return false;
- }
- if (this.mask(address.subnetMask) === address.mask()) {
- return true;
- }
- return false;
-}
-function isCorrect(defaultBits) {
- return function () {
- if (this.addressMinusSuffix !== this.correctForm()) {
- return false;
- }
- if (this.subnetMask === defaultBits && !this.parsedSubnet) {
- return true;
- }
- return this.parsedSubnet === String(this.subnetMask);
- };
-}
-/**
- * Returns the prefix length (number of leading 1 bits) of a contiguous
- * subnet mask. Throws `AddressError` if the mask is non-contiguous (e.g.
- * `255.0.255.0`).
- */
-function prefixLengthFromMask(value, totalBits) {
- const binary = value.toString(2).padStart(totalBits, '0');
- if (binary.length > totalBits) {
- throw new address_error_1.AddressError('Invalid subnet mask.');
- }
- const firstZero = binary.indexOf('0');
- if (firstZero === -1) {
- return totalBits;
- }
- if (binary.slice(firstZero).includes('1')) {
- throw new address_error_1.AddressError('Invalid subnet mask.');
- }
- return firstZero;
-}
-function numberToPaddedHex(number) {
- return number.toString(16).padStart(2, '0');
-}
-function stringToPaddedHex(numberString) {
- return numberToPaddedHex(parseInt(numberString, 10));
-}
-/**
- * @param binaryValue Binary representation of a value (e.g. `10`)
- * @param position Byte position, where 0 is the least significant bit
- */
-function testBit(binaryValue, position) {
- const { length } = binaryValue;
- if (position > length) {
- return false;
- }
- const positionInString = length - position;
- return binaryValue.substring(positionInString, positionInString + 1) === '1';
-}
-
-},{"./address-error":1}],3:[function(require,module,exports){
-"use strict";
-/* eslint-disable no-param-reassign */
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.Address4 = void 0;
-const common = __importStar(require("./common"));
-const constants = __importStar(require("./v4/constants"));
-const address_error_1 = require("./address-error");
-const isCorrect4 = common.isCorrect(constants.BITS);
-/**
- * Represents an IPv4 address
- * @param {string} address - An IPv4 address string
- */
-class Address4 {
- constructor(address) {
- this.groups = constants.GROUPS;
- this.parsedAddress = [];
- this.parsedSubnet = '';
- this.subnet = '/32';
- this.subnetMask = 32;
- this.v4 = true;
- /**
- * Returns true if the address is correct, false otherwise
- * @returns {Boolean}
- */
- this.isCorrect = isCorrect4;
- /**
- * Returns true if the given address is in the subnet of the current address
- * @returns {boolean}
- */
- this.isInSubnet = common.isInSubnet;
- this.address = address;
- const subnet = constants.RE_SUBNET_STRING.exec(address);
- if (subnet) {
- this.parsedSubnet = subnet[0].replace('/', '');
- this.subnetMask = parseInt(this.parsedSubnet, 10);
- this.subnet = `/${this.subnetMask}`;
- if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {
- throw new address_error_1.AddressError('Invalid subnet mask.');
- }
- address = address.replace(constants.RE_SUBNET_STRING, '');
- }
- this.addressMinusSuffix = address;
- this.parsedAddress = this.parse(address);
- }
- /**
- * Returns true if the given string is a valid IPv4 address (with optional
- * CIDR subnet), false otherwise. Host bits in the subnet portion are
- * allowed (e.g. `192.168.1.5/24` is valid); for strict network-address
- * validation compare `correctForm()` to `startAddress().correctForm()`,
- * or use `networkForm()`.
- */
- static isValid(address) {
- try {
- // eslint-disable-next-line no-new
- new Address4(address);
- return true;
- }
- catch (e) {
- return false;
- }
- }
- /**
- * Parses an IPv4 address string into its four octet groups and stores the
- * result on `this.parsedAddress`. Called automatically by the constructor;
- * you typically don't need to call it directly. Throws `AddressError` if
- * the input is not a valid IPv4 address.
- */
- parse(address) {
- const groups = address.split('.');
- if (!address.match(constants.RE_ADDRESS)) {
- throw new address_error_1.AddressError('Invalid IPv4 address.');
- }
- return groups;
- }
- /**
- * Returns the address in correct form: octets joined with `.` and any
- * leading zeros stripped (e.g. `192.168.1.1`). For IPv4 this matches the
- * canonical dotted-decimal representation.
- */
- correctForm() {
- return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');
- }
- /**
- * Construct an `Address4` from an address and a dotted-decimal subnet
- * mask given as separate strings (e.g. as returned by Node's
- * `os.networkInterfaces()`). Throws `AddressError` if the mask is
- * non-contiguous (e.g. `255.0.255.0`).
- * @example
- * var address = Address4.fromAddressAndMask('192.168.1.1', '255.255.255.0');
- * address.subnetMask; // 24
- */
- static fromAddressAndMask(address, mask) {
- const bits = common.prefixLengthFromMask(new Address4(mask).bigInt(), constants.BITS);
- return new Address4(`${address}/${bits}`);
- }
- /**
- * Construct an `Address4` from an address and a Cisco-style wildcard mask
- * given as separate strings (e.g. `0.0.0.255` for a `/24`). The wildcard
- * mask is the bitwise inverse of the subnet mask. Throws `AddressError`
- * if the mask is non-contiguous (e.g. `0.255.0.255`).
- * @example
- * var address = Address4.fromAddressAndWildcardMask('10.0.0.1', '0.0.0.255');
- * address.subnetMask; // 24
- */
- static fromAddressAndWildcardMask(address, wildcardMask) {
- const wildcard = new Address4(wildcardMask).bigInt();
- const allOnes = (BigInt(1) << BigInt(constants.BITS)) - BigInt(1);
- // eslint-disable-next-line no-bitwise
- const mask = wildcard ^ allOnes;
- const bits = common.prefixLengthFromMask(mask, constants.BITS);
- return new Address4(`${address}/${bits}`);
- }
- /**
- * Construct an `Address4` from a wildcard pattern with trailing `*`
- * octets. The number of trailing wildcards determines the prefix
- * length: each `*` represents 8 bits.
- *
- * Only trailing whole-octet wildcards are supported. Partial-octet
- * wildcards (e.g. `192.168.0.1*`) and interior wildcards (e.g.
- * `192.*.0.1`) throw `AddressError`.
- * @example
- * Address4.fromWildcard('192.168.0.*').subnet; // '/24'
- * Address4.fromWildcard('192.168.*.*').subnet; // '/16'
- * Address4.fromWildcard('*.*.*.*').subnet; // '/0'
- */
- static fromWildcard(input) {
- const groups = input.split('.');
- if (groups.length !== constants.GROUPS) {
- throw new address_error_1.AddressError('Wildcard pattern must have 4 octets');
- }
- let firstWildcard = -1;
- for (let i = 0; i < groups.length; i++) {
- if (groups[i] === '*') {
- if (firstWildcard === -1) {
- firstWildcard = i;
- }
- }
- else if (firstWildcard !== -1) {
- throw new address_error_1.AddressError('Wildcard `*` must only appear in trailing octets (e.g. `192.168.0.*`)');
- }
- }
- const trailing = firstWildcard === -1 ? 0 : groups.length - firstWildcard;
- const replaced = groups.map((g) => (g === '*' ? '0' : g));
- const subnetBits = constants.BITS - trailing * 8;
- return new Address4(`${replaced.join('.')}/${subnetBits}`);
- }
- /**
- * Converts a hex string to an IPv4 address object. Accepts 8 hex digits
- * with optional `:` separators (e.g. `'7f000001'` or `'7f:00:00:01'`).
- * Throws `AddressError` for any other length or for non-hex characters.
- * @param {string} hex - a hex string to convert
- * @returns {Address4}
- */
- static fromHex(hex) {
- const stripped = hex.replace(/:/g, '');
- if (!/^[0-9a-fA-F]{8}$/.test(stripped)) {
- throw new address_error_1.AddressError('IPv4 hex must be exactly 8 hex digits');
- }
- const groups = [];
- for (let i = 0; i < 8; i += 2) {
- groups.push(parseInt(stripped.slice(i, i + 2), 16));
- }
- return new Address4(groups.join('.'));
- }
- /**
- * Converts an integer into a IPv4 address object. The integer must be a
- * non-negative safe integer in the range `[0, 2**32 - 1]`; otherwise
- * `AddressError` is thrown.
- * @param {integer} integer - a number to convert
- * @returns {Address4}
- */
- static fromInteger(integer) {
- if (!Number.isInteger(integer) || integer < 0 || integer > 0xffffffff) {
- throw new address_error_1.AddressError('IPv4 integer must be in the range 0 to 2**32 - 1');
- }
- return Address4.fromHex(integer.toString(16).padStart(8, '0'));
- }
- /**
- * Return an address from in-addr.arpa form
- * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address
- * @returns {Adress4}
- * @example
- * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)
- * address.correctForm(); // '192.0.2.42'
- */
- static fromArpa(arpaFormAddress) {
- // remove ending ".in-addr.arpa." or just "."
- const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, '');
- const address = leader.split('.').reverse().join('.');
- return new Address4(address);
- }
- /**
- * Converts an IPv4 address object to a hex string
- * @returns {String}
- */
- toHex() {
- return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':');
- }
- /**
- * Converts an IPv4 address object to an array of bytes.
- *
- * To get a Node.js `Buffer`, wrap the result: `Buffer.from(address.toArray())`.
- * @returns {Array}
- */
- toArray() {
- return this.parsedAddress.map((part) => parseInt(part, 10));
- }
- /**
- * Converts an IPv4 address object to an IPv6 address group
- * @returns {String}
- */
- toGroup6() {
- const output = [];
- let i;
- for (i = 0; i < constants.GROUPS; i += 2) {
- output.push(`${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(this.parsedAddress[i + 1])}`);
- }
- return output.join(':');
- }
- /**
- * Returns the address as a `bigint`
- * @returns {bigint}
- */
- bigInt() {
- return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`);
- }
- /**
- * Helper function getting start address.
- * @returns {bigint}
- */
- _startAddress() {
- return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`);
- }
- /**
- * The first address in the range given by this address' subnet.
- * Often referred to as the Network Address.
- * @returns {Address4}
- */
- startAddress() {
- return Address4.fromBigInt(this._startAddress());
- }
- /**
- * The first host address in the range given by this address's subnet ie
- * the first address after the Network Address
- * @returns {Address4}
- */
- startAddressExclusive() {
- const adjust = BigInt('1');
- return Address4.fromBigInt(this._startAddress() + adjust);
- }
- /**
- * Helper function getting end address.
- * @returns {bigint}
- */
- _endAddress() {
- return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`);
- }
- /**
- * The last address in the range given by this address' subnet
- * Often referred to as the Broadcast
- * @returns {Address4}
- */
- endAddress() {
- return Address4.fromBigInt(this._endAddress());
- }
- /**
- * The last host address in the range given by this address's subnet ie
- * the last address prior to the Broadcast Address
- * @returns {Address4}
- */
- endAddressExclusive() {
- const adjust = BigInt('1');
- return Address4.fromBigInt(this._endAddress() - adjust);
- }
- /**
- * The dotted-decimal form of the subnet mask, e.g. `255.255.240.0` for
- * a `/20`. Returns an `Address4`; call `.correctForm()` for the string.
- * @returns {Address4}
- */
- subnetMaskAddress() {
- return Address4.fromBigInt(BigInt(`0b${'1'.repeat(this.subnetMask)}${'0'.repeat(constants.BITS - this.subnetMask)}`));
- }
- /**
- * The Cisco-style wildcard mask, e.g. `0.0.0.255` for a `/24`. This is
- * the bitwise inverse of `subnetMaskAddress()`. Returns an `Address4`;
- * call `.correctForm()` for the string.
- * @returns {Address4}
- */
- wildcardMask() {
- return Address4.fromBigInt(BigInt(`0b${'0'.repeat(this.subnetMask)}${'1'.repeat(constants.BITS - this.subnetMask)}`));
- }
- /**
- * The network address in CIDR string form, e.g. `192.168.1.0/24` for
- * `192.168.1.5/24`. For an address with no explicit subnet the prefix is
- * `/32`, e.g. `networkForm()` on `192.168.1.5` returns `192.168.1.5/32`.
- * @returns {string}
- */
- networkForm() {
- return `${this.startAddress().correctForm()}/${this.subnetMask}`;
- }
- /**
- * Converts a BigInt to a v4 address object. The value must be in the
- * range `[0, 2**32 - 1]`; otherwise `AddressError` is thrown.
- * @param {bigint} bigInt - a BigInt to convert
- * @returns {Address4}
- */
- static fromBigInt(bigInt) {
- if (bigInt < 0n || bigInt > 0xffffffffn) {
- throw new address_error_1.AddressError('IPv4 BigInt must be in the range 0 to 2**32 - 1');
- }
- return Address4.fromHex(bigInt.toString(16).padStart(8, '0'));
- }
- /**
- * Convert a byte array to an Address4 object.
- *
- * To convert from a Node.js `Buffer`, spread it: `Address4.fromByteArray([...buf])`.
- * @param {Array<number>} bytes - an array of 4 bytes (0-255)
- * @returns {Address4}
- */
- static fromByteArray(bytes) {
- if (bytes.length !== 4) {
- throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');
- }
- // Validate that all bytes are within valid range (0-255)
- for (let i = 0; i < bytes.length; i++) {
- if (!Number.isInteger(bytes[i]) || bytes[i] < 0 || bytes[i] > 255) {
- throw new address_error_1.AddressError('All bytes must be integers between 0 and 255');
- }
- }
- return this.fromUnsignedByteArray(bytes);
- }
- /**
- * Convert an unsigned byte array to an Address4 object
- * @param {Array<number>} bytes - an array of 4 unsigned bytes (0-255)
- * @returns {Address4}
- */
- static fromUnsignedByteArray(bytes) {
- if (bytes.length !== 4) {
- throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');
- }
- const address = bytes.join('.');
- return new Address4(address);
- }
- /**
- * Returns the first n bits of the address, defaulting to the
- * subnet mask
- * @returns {String}
- */
- mask(mask) {
- if (mask === undefined) {
- mask = this.subnetMask;
- }
- return this.getBitsBase2(0, mask);
- }
- /**
- * Returns the bits in the given range as a base-2 string
- * @returns {string}
- */
- getBitsBase2(start, end) {
- return this.binaryZeroPad().slice(start, end);
- }
- /**
- * Return the reversed ip6.arpa form of the address
- * @param {Object} options
- * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix
- * @returns {String}
- */
- reverseForm(options) {
- if (!options) {
- options = {};
- }
- const reversed = this.correctForm().split('.').reverse().join('.');
- if (options.omitSuffix) {
- return reversed;
- }
- return `${reversed}.in-addr.arpa.`;
- }
- /**
- * Returns true if the given address is a multicast address
- * @returns {boolean}
- */
- isMulticast() {
- return this.isInSubnet(MULTICAST_V4);
- }
- /**
- * Returns true if the address is in one of the [RFC 1918](https://datatracker.ietf.org/doc/html/rfc1918) private address ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`).
- * @returns {boolean}
- */
- isPrivate() {
- return PRIVATE_V4.some((subnet) => this.isInSubnet(subnet));
- }
- /**
- * Returns true if the address is in the loopback range `127.0.0.0/8` ([RFC 1122](https://datatracker.ietf.org/doc/html/rfc1122)).
- * @returns {boolean}
- */
- isLoopback() {
- return this.isInSubnet(LOOPBACK_V4);
- }
- /**
- * Returns true if the address is in the link-local range `169.254.0.0/16` ([RFC 3927](https://datatracker.ietf.org/doc/html/rfc3927)).
- * @returns {boolean}
- */
- isLinkLocal() {
- return this.isInSubnet(LINK_LOCAL_V4);
- }
- /**
- * Returns true if the address is the unspecified address `0.0.0.0`.
- * @returns {boolean}
- */
- isUnspecified() {
- return this.isInSubnet(UNSPECIFIED_V4);
- }
- /**
- * Returns true if the address is the limited broadcast address `255.255.255.255` ([RFC 919](https://datatracker.ietf.org/doc/html/rfc919)).
- * @returns {boolean}
- */
- isBroadcast() {
- return this.isInSubnet(BROADCAST_V4);
- }
- /**
- * Returns true if the address is in the carrier-grade NAT range `100.64.0.0/10` ([RFC 6598](https://datatracker.ietf.org/doc/html/rfc6598)).
- * @returns {boolean}
- */
- isCGNAT() {
- return this.isInSubnet(CGNAT_V4);
- }
- /**
- * Returns a zero-padded base-2 string representation of the address
- * @returns {string}
- */
- binaryZeroPad() {
- if (this._binaryZeroPad === undefined) {
- this._binaryZeroPad = this.bigInt().toString(2).padStart(constants.BITS, '0');
- }
- return this._binaryZeroPad;
- }
- /**
- * Groups an IPv4 address for inclusion at the end of an IPv6 address
- * @returns {String}
- */
- groupForV6() {
- const segments = this.parsedAddress;
- return this.address.replace(constants.RE_ADDRESS, `<span class="hover-group group-v4 group-6">${segments
- .slice(0, 2)
- .join('.')}</span>.<span class="hover-group group-v4 group-7">${segments
- .slice(2, 4)
- .join('.')}</span>`);
- }
-}
-exports.Address4 = Address4;
-const MULTICAST_V4 = new Address4('224.0.0.0/4');
-const PRIVATE_V4 = [
- new Address4('10.0.0.0/8'),
- new Address4('172.16.0.0/12'),
- new Address4('192.168.0.0/16'),
-];
-const LOOPBACK_V4 = new Address4('127.0.0.0/8');
-const LINK_LOCAL_V4 = new Address4('169.254.0.0/16');
-const UNSPECIFIED_V4 = new Address4('0.0.0.0/32');
-const BROADCAST_V4 = new Address4('255.255.255.255/32');
-const CGNAT_V4 = new Address4('100.64.0.0/10');
-
-},{"./address-error":1,"./common":2,"./v4/constants":5}],4:[function(require,module,exports){
-"use strict";
-/* eslint-disable prefer-destructuring */
-/* eslint-disable no-param-reassign */
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.Address6 = void 0;
-const common = __importStar(require("./common"));
-const constants4 = __importStar(require("./v4/constants"));
-const constants6 = __importStar(require("./v6/constants"));
-const helpers = __importStar(require("./v6/helpers"));
-const ipv4_1 = require("./ipv4");
-const regular_expressions_1 = require("./v6/regular-expressions");
-const address_error_1 = require("./address-error");
-const common_1 = require("./common");
-const isCorrect6 = common.isCorrect(constants6.BITS);
-function assert(condition) {
- if (!condition) {
- throw new Error('Assertion failed.');
- }
-}
-function addCommas(number) {
- const r = /(\d+)(\d{3})/;
- while (r.test(number)) {
- number = number.replace(r, '$1,$2');
- }
- return number;
-}
-function spanLeadingZeroes4(n) {
- n = n.replace(/^(0{1,})([1-9]+)$/, '<span class="parse-error">$1</span>$2');
- n = n.replace(/^(0{1,})(0)$/, '<span class="parse-error">$1</span>$2');
- return n;
-}
-/*
- * A helper function to compact an array
- */
-function compact(address, slice) {
- const s1 = [];
- const s2 = [];
- let i;
- for (i = 0; i < address.length; i++) {
- if (i < slice[0]) {
- s1.push(address[i]);
- }
- else if (i > slice[1]) {
- s2.push(address[i]);
- }
- }
- return s1.concat(['compact']).concat(s2);
-}
-function paddedHex(octet) {
- return parseInt(octet, 16).toString(16).padStart(4, '0');
-}
-function unsignByte(b) {
- // eslint-disable-next-line no-bitwise
- return b & 0xff;
-}
-/**
- * Represents an IPv6 address
- * @param {string} address - An IPv6 address string
- * @param {number} [groups=8] - How many octets to parse
- * @example
- * var address = new Address6('2001::/32');
- */
-class Address6 {
- constructor(address, optionalGroups) {
- this.addressMinusSuffix = '';
- this.parsedSubnet = '';
- this.subnet = '/128';
- this.subnetMask = 128;
- this.v4 = false;
- this.zone = '';
- // #region Attributes
- /**
- * Returns true if the given address is in the subnet of the current address
- * @returns {boolean}
- */
- this.isInSubnet = common.isInSubnet;
- /**
- * Returns true if the address is correct, false otherwise
- * @returns {boolean}
- */
- this.isCorrect = isCorrect6;
- if (optionalGroups === undefined) {
- this.groups = constants6.GROUPS;
- }
- else {
- this.groups = optionalGroups;
- }
- this.address = address;
- const subnet = constants6.RE_SUBNET_STRING.exec(address);
- if (subnet) {
- this.parsedSubnet = subnet[0].replace('/', '');
- this.subnetMask = parseInt(this.parsedSubnet, 10);
- this.subnet = `/${this.subnetMask}`;
- if (Number.isNaN(this.subnetMask) ||
- this.subnetMask < 0 ||
- this.subnetMask > constants6.BITS) {
- throw new address_error_1.AddressError('Invalid subnet mask.');
- }
- address = address.replace(constants6.RE_SUBNET_STRING, '');
- }
- else if (/\//.test(address)) {
- throw new address_error_1.AddressError('Invalid subnet mask.');
- }
- const zone = constants6.RE_ZONE_STRING.exec(address);
- if (zone) {
- this.zone = zone[0];
- address = address.replace(constants6.RE_ZONE_STRING, '');
- }
- this.addressMinusSuffix = address;
- this.parsedAddress = this.parse(this.addressMinusSuffix);
- }
- /**
- * Returns true if the given string is a valid IPv6 address (with optional
- * CIDR subnet and zone identifier), false otherwise. Host bits in the
- * subnet portion are allowed (e.g. `2001:db8::1/32` is valid); for strict
- * network-address validation compare `correctForm()` to
- * `startAddress().correctForm()`, or use `networkForm()`.
- */
- static isValid(address) {
- try {
- // eslint-disable-next-line no-new
- new Address6(address);
- return true;
- }
- catch (e) {
- return false;
- }
- }
- /**
- * Convert a BigInt to a v6 address object. The value must be in the
- * range `[0, 2**128 - 1]`; otherwise `AddressError` is thrown.
- * @param {bigint} bigInt - a BigInt to convert
- * @returns {Address6}
- * @example
- * var bigInt = BigInt('1000000000000');
- * var address = Address6.fromBigInt(bigInt);
- * address.correctForm(); // '::e8:d4a5:1000'
- */
- static fromBigInt(bigInt) {
- if (bigInt < 0n || bigInt > (1n << BigInt(constants6.BITS)) - 1n) {
- throw new address_error_1.AddressError('IPv6 BigInt must be in the range 0 to 2**128 - 1');
- }
- const hex = bigInt.toString(16).padStart(32, '0');
- const groups = [];
- for (let i = 0; i < constants6.GROUPS; i++) {
- groups.push(hex.slice(i * 4, (i + 1) * 4));
- }
- return new Address6(groups.join(':'));
- }
- /**
- * Parse a URL (with optional bracketed host and port) into an address and
- * port. Returns either `{ address, port }` on success or
- * `{ error, address: null, port: null }` if the URL could not be parsed.
- * Ports are returned as numbers (or `null` if absent or out of range).
- * @example
- * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');
- * addressAndPort.address.correctForm(); // 'ffff::'
- * addressAndPort.port; // 8080
- */
- static fromURL(url) {
- let host;
- let port = null;
- let result;
- // If we have brackets parse them and find a port
- if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) {
- result = constants6.RE_URL_WITH_PORT.exec(url);
- if (result === null) {
- return {
- error: 'failed to parse address with port',
- address: null,
- port: null,
- };
- }
- host = result[1];
- port = result[2];
- // If there's a URL extract the address
- }
- else if (url.indexOf('/') !== -1) {
- // Remove the protocol prefix
- url = url.replace(/^[a-z0-9]+:\/\//, '');
- // Parse the address
- result = constants6.RE_URL.exec(url);
- if (result === null) {
- return {
- error: 'failed to parse address from URL',
- address: null,
- port: null,
- };
- }
- host = result[1];
- // Otherwise just assign the URL to the host and let the library parse it
- }
- else {
- host = url;
- }
- // If there's a port convert it to an integer
- if (port) {
- port = parseInt(port, 10);
- // squelch out of range ports
- if (port < 0 || port > 65536) {
- port = null;
- }
- }
- else {
- // Standardize `undefined` to `null`
- port = null;
- }
- return {
- address: new Address6(host),
- port,
- };
- }
- /**
- * Construct an `Address6` from an address and a hex subnet mask given as
- * separate strings (e.g. as returned by Node's `os.networkInterfaces()`).
- * Throws `AddressError` if the mask is non-contiguous (e.g.
- * `ffff::ffff`).
- * @example
- * var address = Address6.fromAddressAndMask('fe80::1', 'ffff:ffff:ffff:ffff::');
- * address.subnetMask; // 64
- */
- static fromAddressAndMask(address, mask) {
- const bits = common.prefixLengthFromMask(new Address6(mask).bigInt(), constants6.BITS);
- return new Address6(`${address}/${bits}`);
- }
- /**
- * Construct an `Address6` from an address and a Cisco-style wildcard mask
- * given as separate strings (e.g. `::ffff:ffff:ffff:ffff` for a `/64`).
- * The wildcard mask is the bitwise inverse of the subnet mask. Throws
- * `AddressError` if the mask is non-contiguous.
- * @example
- * var address = Address6.fromAddressAndWildcardMask('fe80::1', '::ffff:ffff:ffff:ffff');
- * address.subnetMask; // 64
- */
- static fromAddressAndWildcardMask(address, wildcardMask) {
- const wildcard = new Address6(wildcardMask).bigInt();
- const allOnes = (BigInt(1) << BigInt(constants6.BITS)) - BigInt(1);
- // eslint-disable-next-line no-bitwise
- const mask = wildcard ^ allOnes;
- const bits = common.prefixLengthFromMask(mask, constants6.BITS);
- return new Address6(`${address}/${bits}`);
- }
- /**
- * Construct an `Address6` from a wildcard pattern with trailing `*`
- * groups. The number of trailing wildcards determines the prefix
- * length: each `*` represents 16 bits. `::` is expanded to zero groups
- * (not wildcards) before evaluating trailing wildcards.
- *
- * Only trailing whole-group wildcards are supported. Partial-group
- * wildcards (e.g. `2001:db8::0*`) and interior wildcards (e.g.
- * `*::1`) throw `AddressError`.
- * @example
- * Address6.fromWildcard('2001:db8:*:*:*:*:*:*').subnet; // '/32'
- * Address6.fromWildcard('2001:db8::*').subnet; // '/112'
- * Address6.fromWildcard('*:*:*:*:*:*:*:*').subnet; // '/0'
- */
- static fromWildcard(input) {
- if (input.includes('%') || input.includes('/')) {
- throw new address_error_1.AddressError('Wildcard pattern must not include a zone or CIDR suffix');
- }
- const halves = input.split('::');
- if (halves.length > 2) {
- throw new address_error_1.AddressError("Wildcard pattern cannot contain more than one '::'");
- }
- let groups;
- if (halves.length === 2) {
- const left = halves[0] === '' ? [] : halves[0].split(':');
- const right = halves[1] === '' ? [] : halves[1].split(':');
- const remaining = constants6.GROUPS - left.length - right.length;
- if (remaining < 1) {
- throw new address_error_1.AddressError("Wildcard pattern with '::' has too many groups");
- }
- groups = [...left, ...new Array(remaining).fill('0'), ...right];
- }
- else {
- groups = input.split(':');
- }
- if (groups.length !== constants6.GROUPS) {
- throw new address_error_1.AddressError('Wildcard pattern must have 8 groups');
- }
- let firstWildcard = -1;
- for (let i = 0; i < groups.length; i++) {
- if (groups[i] === '*') {
- if (firstWildcard === -1) {
- firstWildcard = i;
- }
- }
- else if (firstWildcard !== -1) {
- throw new address_error_1.AddressError('Wildcard `*` must only appear in trailing groups (e.g. `2001:db8:*:*:*:*:*:*`)');
- }
- }
- const trailing = firstWildcard === -1 ? 0 : groups.length - firstWildcard;
- const replaced = groups.map((g) => (g === '*' ? '0' : g));
- const subnetBits = constants6.BITS - trailing * 16;
- return new Address6(`${replaced.join(':')}/${subnetBits}`);
- }
- /**
- * Create an IPv6-mapped address given an IPv4 address
- * @param {string} address - An IPv4 address string
- * @returns {Address6}
- * @example
- * var address = Address6.fromAddress4('192.168.0.1');
- * address.correctForm(); // '::ffff:c0a8:1'
- * address.to4in6(); // '::ffff:192.168.0.1'
- */
- static fromAddress4(address) {
- const address4 = new ipv4_1.Address4(address);
- const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask);
- return new Address6(`::ffff:${address4.correctForm()}/${mask6}`);
- }
- /**
- * Return an address from ip6.arpa form
- * @param {string} arpaFormAddress - an 'ip6.arpa' form address
- * @returns {Adress6}
- * @example
- * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.)
- * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe'
- */
- static fromArpa(arpaFormAddress) {
- // remove ending ".ip6.arpa." or just "."
- let address = arpaFormAddress.replace(/(\.ip6\.arpa)?\.$/, '');
- const semicolonAmount = 7;
- // correct ip6.arpa form with ending removed will be 63 characters
- if (address.length !== 63) {
- throw new address_error_1.AddressError("Invalid 'ip6.arpa' form.");
- }
- const parts = address.split('.').reverse();
- for (let i = semicolonAmount; i > 0; i--) {
- const insertIndex = i * 4;
- parts.splice(insertIndex, 0, ':');
- }
- address = parts.join('');
- return new Address6(address);
- }
- /**
- * Return the Microsoft UNC transcription of the address
- * @returns {String} the Microsoft UNC transcription of the address
- */
- microsoftTranscription() {
- return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`;
- }
- /**
- * Return the first n bits of the address, defaulting to the subnet mask
- * @param {number} [mask=subnet] - the number of bits to mask
- * @returns {String} the first n bits of the address as a string
- */
- mask(mask = this.subnetMask) {
- return this.getBitsBase2(0, mask);
- }
- /**
- * Return the number of possible subnets of a given size in the address
- * @param {number} [subnetSize=128] - the subnet size
- * @returns {String}
- */
- // TODO: probably useful to have a numeric version of this too
- possibleSubnets(subnetSize = 128) {
- const availableBits = constants6.BITS - this.subnetMask;
- const subnetBits = Math.abs(subnetSize - constants6.BITS);
- const subnetPowers = availableBits - subnetBits;
- if (subnetPowers < 0) {
- return '0';
- }
- return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10));
- }
- /**
- * Helper function getting start address.
- * @returns {bigint}
- */
- _startAddress() {
- return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`);
- }
- /**
- * The first address in the range given by this address' subnet
- * Often referred to as the Network Address.
- * @returns {Address6}
- */
- startAddress() {
- return Address6.fromBigInt(this._startAddress());
- }
- /**
- * The first host address in the range given by this address's subnet ie
- * the first address after the Network Address
- * @returns {Address6}
- */
- startAddressExclusive() {
- const adjust = BigInt('1');
- return Address6.fromBigInt(this._startAddress() + adjust);
- }
- /**
- * Helper function getting end address.
- * @returns {bigint}
- */
- _endAddress() {
- return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`);
- }
- /**
- * The last address in the range given by this address' subnet
- * Often referred to as the Broadcast
- * @returns {Address6}
- */
- endAddress() {
- return Address6.fromBigInt(this._endAddress());
- }
- /**
- * The last host address in the range given by this address's subnet ie
- * the last address prior to the Broadcast Address
- * @returns {Address6}
- */
- endAddressExclusive() {
- const adjust = BigInt('1');
- return Address6.fromBigInt(this._endAddress() - adjust);
- }
- /**
- * The hex form of the subnet mask, e.g. `ffff:ffff:ffff:ffff::` for a
- * `/64`. Returns an `Address6`; call `.correctForm()` for the string.
- * @returns {Address6}
- */
- subnetMaskAddress() {
- return Address6.fromBigInt(BigInt(`0b${'1'.repeat(this.subnetMask)}${'0'.repeat(constants6.BITS - this.subnetMask)}`));
- }
- /**
- * The Cisco-style wildcard mask, e.g. `::ffff:ffff:ffff:ffff` for a
- * `/64`. This is the bitwise inverse of `subnetMaskAddress()`. Returns
- * an `Address6`; call `.correctForm()` for the string.
- * @returns {Address6}
- */
- wildcardMask() {
- return Address6.fromBigInt(BigInt(`0b${'0'.repeat(this.subnetMask)}${'1'.repeat(constants6.BITS - this.subnetMask)}`));
- }
- /**
- * The network address in CIDR string form, e.g. `2001:db8::/32` for
- * `2001:db8::1/32`. For an address with no explicit subnet the prefix
- * is `/128`, e.g. `networkForm()` on `2001:db8::1` returns
- * `2001:db8::1/128`.
- * @returns {string}
- */
- networkForm() {
- return `${this.startAddress().correctForm()}/${this.subnetMask}`;
- }
- /**
- * Return the scope of the address. The 4-bit scope field
- * ([RFC 4291 §2.7](https://datatracker.ietf.org/doc/html/rfc4291#section-2.7))
- * is only defined for multicast addresses; for unicast addresses the scope
- * is derived from the address type per
- * [RFC 4007 §6](https://datatracker.ietf.org/doc/html/rfc4007#section-6).
- * @returns {String}
- */
- getScope() {
- const type = this.getType();
- if (type === 'Multicast' || type.startsWith('Multicast ')) {
- const scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];
- return scope || 'Unknown';
- }
- // RFC 4291 §2.5.3: the loopback address is treated as having Link-Local
- // scope. (Multicast scope 1, "Interface-Local", is a different concept
- // used only for loopback transmission of multicast.)
- if (type === 'Link-local unicast' || type === 'Loopback') {
- return 'Link local';
- }
- // RFC 4007 §6: the unspecified address has no scope.
- if (type === 'Unspecified') {
- return 'Unknown';
- }
- return 'Global';
- }
- /**
- * Return the type of the address
- * @returns {String}
- */
- getType() {
- for (let i = 0; i < TYPE_SUBNETS.length; i++) {
- const entry = TYPE_SUBNETS[i];
- if (this.isInSubnet(entry[0])) {
- return entry[1];
- }
- }
- return 'Global unicast';
- }
- /**
- * Return the bits in the given range as a BigInt
- * @returns {bigint}
- */
- getBits(start, end) {
- return BigInt(`0b${this.getBitsBase2(start, end)}`);
- }
- /**
- * Return the bits in the given range as a base-2 string
- * @returns {String}
- */
- getBitsBase2(start, end) {
- return this.binaryZeroPad().slice(start, end);
- }
- /**
- * Return the bits in the given range as a base-16 string
- * @returns {String}
- */
- getBitsBase16(start, end) {
- const length = end - start;
- if (length % 4 !== 0) {
- throw new Error('Length of bits to retrieve must be divisible by four');
- }
- return this.getBits(start, end)
- .toString(16)
- .padStart(length / 4, '0');
- }
- /**
- * Return the bits that are set past the subnet mask length
- * @returns {String}
- */
- getBitsPastSubnet() {
- return this.getBitsBase2(this.subnetMask, constants6.BITS);
- }
- /**
- * Return the reversed ip6.arpa form of the address
- * @param {Object} options
- * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix
- * @returns {String}
- */
- reverseForm(options) {
- if (!options) {
- options = {};
- }
- const characters = Math.floor(this.subnetMask / 4);
- const reversed = this.canonicalForm()
- .replace(/:/g, '')
- .split('')
- .slice(0, characters)
- .reverse()
- .join('.');
- if (characters > 0) {
- if (options.omitSuffix) {
- return reversed;
- }
- return `${reversed}.ip6.arpa.`;
- }
- if (options.omitSuffix) {
- return '';
- }
- return 'ip6.arpa.';
- }
- /**
- * Returns the address in correct form, per
- * [RFC 5952](https://datatracker.ietf.org/doc/html/rfc5952): leading zeros
- * stripped, the longest run of zero groups collapsed to `::`, and hex digits
- * lowercased (e.g. `2001:db8::1`). This is the recommended form for display.
- */
- correctForm() {
- let i;
- let groups = [];
- let zeroCounter = 0;
- const zeroes = [];
- for (i = 0; i < this.parsedAddress.length; i++) {
- const value = parseInt(this.parsedAddress[i], 16);
- if (value === 0) {
- zeroCounter++;
- }
- if (value !== 0 && zeroCounter > 0) {
- if (zeroCounter > 1) {
- zeroes.push([i - zeroCounter, i - 1]);
- }
- zeroCounter = 0;
- }
- }
- // Do we end with a string of zeroes?
- if (zeroCounter > 1) {
- zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]);
- }
- const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1);
- if (zeroes.length > 0) {
- const index = zeroLengths.indexOf(Math.max(...zeroLengths));
- groups = compact(this.parsedAddress, zeroes[index]);
- }
- else {
- groups = this.parsedAddress;
- }
- for (i = 0; i < groups.length; i++) {
- if (groups[i] !== 'compact') {
- groups[i] = parseInt(groups[i], 16).toString(16);
- }
- }
- let correct = groups.join(':');
- correct = correct.replace(/^compact$/, '::');
- correct = correct.replace(/(^compact)|(compact$)/, ':');
- correct = correct.replace(/compact/, '');
- return correct;
- }
- /**
- * Return a zero-padded base-2 string representation of the address
- * @returns {String}
- * @example
- * var address = new Address6('2001:4860:4001:803::1011');
- * address.binaryZeroPad();
- * // '0010000000000001010010000110000001000000000000010000100000000011
- * // 0000000000000000000000000000000000000000000000000001000000010001'
- */
- binaryZeroPad() {
- if (this._binaryZeroPad === undefined) {
- this._binaryZeroPad = this.bigInt().toString(2).padStart(constants6.BITS, '0');
- }
- return this._binaryZeroPad;
- }
- /**
- * Parses a v4-in-v6 string (e.g. `::ffff:192.168.0.1`) by extracting the
- * trailing IPv4 address into `this.address4` / `this.parsedAddress4` and
- * returning the address with the v4 portion converted to two v6 groups.
- * Used internally by `parse()`.
- */
- // TODO: Improve the semantics of this helper function
- parse4in6(address) {
- if (address.indexOf('.') === -1) {
- return address;
- }
- const groups = address.split(':');
- const lastGroup = groups.slice(-1)[0];
- const address4 = lastGroup.match(constants4.RE_ADDRESS);
- if (address4) {
- this.parsedAddress4 = address4[0];
- this.address4 = new ipv4_1.Address4(this.parsedAddress4);
- for (let i = 0; i < this.address4.groups; i++) {
- if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {
- // The prefix groups haven't been through the bad-character check
- // yet, so escape them before including in the error HTML.
- const highlighted = this.address4.parsedAddress.map(spanLeadingZeroes4).join('.');
- const prefix = groups.slice(0, -1).map(helpers.escapeHtml).join(':');
- const separator = groups.length > 1 ? ':' : '';
- throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", `${prefix}${separator}${highlighted}`);
- }
- }
- this.v4 = true;
- groups[groups.length - 1] = this.address4.toGroup6();
- address = groups.join(':');
- }
- return address;
- }
- /**
- * Parses an IPv6 address string into its 8 hexadecimal groups (expanding
- * any `::` elision and any trailing v4-in-v6 portion) and stores the result
- * on `this.parsedAddress`. Called automatically by the constructor; you
- * typically don't need to call it directly. Throws `AddressError` if the
- * input is malformed.
- */
- // TODO: Make private?
- parse(address) {
- address = this.parse4in6(address);
- const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);
- if (badCharacters) {
- throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? 's' : ''} detected in address: ${badCharacters.join('')}`, address.replace(constants6.RE_BAD_CHARACTERS, '<span class="parse-error">$1</span>'));
- }
- const badAddress = address.match(constants6.RE_BAD_ADDRESS);
- if (badAddress) {
- throw new address_error_1.AddressError(`Address failed regex: ${badAddress.join('')}`, address.replace(constants6.RE_BAD_ADDRESS, '<span class="parse-error">$1</span>'));
- }
- let groups = [];
- const halves = address.split('::');
- if (halves.length === 2) {
- let first = halves[0].split(':');
- let last = halves[1].split(':');
- if (first.length === 1 && first[0] === '') {
- first = [];
- }
- if (last.length === 1 && last[0] === '') {
- last = [];
- }
- const remaining = this.groups - (first.length + last.length);
- if (!remaining) {
- throw new address_error_1.AddressError('Error parsing groups');
- }
- this.elidedGroups = remaining;
- this.elisionBegin = first.length;
- this.elisionEnd = first.length + this.elidedGroups;
- groups = groups.concat(first);
- for (let i = 0; i < remaining; i++) {
- groups.push('0');
- }
- groups = groups.concat(last);
- }
- else if (halves.length === 1) {
- groups = address.split(':');
- this.elidedGroups = 0;
- }
- else {
- throw new address_error_1.AddressError('Too many :: groups found');
- }
- groups = groups.map((group) => parseInt(group, 16).toString(16));
- if (groups.length !== this.groups) {
- throw new address_error_1.AddressError('Incorrect number of groups found');
- }
- return groups;
- }
- /**
- * Returns the canonical (fully expanded) form of the address: all 8 groups,
- * each padded to 4 hex digits, with no `::` collapsing
- * (e.g. `2001:0db8:0000:0000:0000:0000:0000:0001`). Useful for sorting and
- * byte-exact comparison.
- */
- canonicalForm() {
- return this.parsedAddress.map(paddedHex).join(':');
- }
- /**
- * Return the decimal form of the address
- * @returns {String}
- */
- decimal() {
- return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':');
- }
- /**
- * Return the address as a BigInt
- * @returns {bigint}
- */
- bigInt() {
- return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`);
- }
- /**
- * Return the last two groups of this address as an IPv4 address string
- * @returns {Address4}
- * @example
- * var address = new Address6('2001:4860:4001::1825:bf11');
- * address.to4().correctForm(); // '24.37.191.17'
- */
- to4() {
- const binary = this.binaryZeroPad().split('');
- return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16).padStart(8, '0'));
- }
- /**
- * Return the v4-in-v6 form of the address
- * @returns {String}
- */
- to4in6() {
- const address4 = this.to4();
- const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6);
- const correct = address6.correctForm();
- let infix = '';
- if (!/:$/.test(correct)) {
- infix = ':';
- }
- return correct + infix + address4.address;
- }
- /**
- * Decodes the Teredo tunneling fields embedded in this address. Returns the
- * Teredo prefix, server IPv4, client IPv4, raw flag bits, cone-NAT flag,
- * UDP port, and Microsoft-format flag breakdown (reserved, universal/local,
- * group/individual, nonce). Only meaningful for addresses in `2001::/32`.
- */
- inspectTeredo() {
- /*
- - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32).
- - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that
- is used.
- - Bits 64 to 79 can be used to define some flags. Currently only the
- higher order bit is used; it is set to 1 if the Teredo client is
- located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista
- and Windows Server 2008 implementations, more bits are used. In those
- implementations, the format for these 16 bits is "CRAAAAUG AAAAAAAA",
- where "C" remains the "Cone" flag. The "R" bit is reserved for future
- use. The "U" bit is for the Universal/Local flag (set to 0). The "G" bit
- is Individual/Group flag (set to 0). The A bits are set to a 12-bit
- randomly generated number chosen by the Teredo client to introduce
- additional protection for the Teredo node against IPv6-based scanning
- attacks.
- - Bits 80 to 95 contains the obfuscated UDP port number. This is the
- port number that is mapped by the NAT to the Teredo client with all
- bits inverted.
- - Bits 96 to 127 contains the obfuscated IPv4 address. This is the
- public IPv4 address of the NAT with all bits inverted.
- */
- const prefix = this.getBitsBase16(0, 32);
- const bitsForUdpPort = this.getBits(80, 96);
- // eslint-disable-next-line no-bitwise
- const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString();
- const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64));
- const bitsForClient4 = this.getBits(96, 128);
- // eslint-disable-next-line no-bitwise
- const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16).padStart(8, '0'));
- const flagsBase2 = this.getBitsBase2(64, 80);
- const coneNat = (0, common_1.testBit)(flagsBase2, 15);
- const reserved = (0, common_1.testBit)(flagsBase2, 14);
- const groupIndividual = (0, common_1.testBit)(flagsBase2, 8);
- const universalLocal = (0, common_1.testBit)(flagsBase2, 9);
- const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10);
- return {
- prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`,
- server4: server4.address,
- client4: client4.address,
- flags: flagsBase2,
- coneNat,
- microsoft: {
- reserved,
- universalLocal,
- groupIndividual,
- nonce,
- },
- udpPort,
- };
- }
- /**
- * Decodes the 6to4 tunneling fields embedded in this address. Returns the
- * 6to4 prefix and the embedded IPv4 gateway address. Only meaningful for
- * addresses in `2002::/16`.
- */
- inspect6to4() {
- /*
- - Bits 0 to 15 are set to the 6to4 prefix (2002::/16).
- - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used.
- */
- const prefix = this.getBitsBase16(0, 16);
- const gateway = ipv4_1.Address4.fromHex(this.getBitsBase16(16, 48));
- return {
- prefix: prefix.slice(0, 4),
- gateway: gateway.address,
- };
- }
- /**
- * Return a v6 6to4 address from a v6 v4inv6 address
- * @returns {Address6}
- */
- to6to4() {
- if (!this.is4()) {
- return null;
- }
- const addr6to4 = [
- '2002',
- this.getBitsBase16(96, 112),
- this.getBitsBase16(112, 128),
- '',
- '/16',
- ].join(':');
- return new Address6(addr6to4);
- }
- /**
- * Embed an IPv4 address into a NAT64 IPv6 address using the encoding
- * defined by [RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
- * The default prefix is the well-known prefix `64:ff9b::/96`. The prefix
- * length must be one of 32, 40, 48, 56, 64, or 96; for prefixes shorter
- * than /64 the IPv4 octets are split around the reserved bits 64–71.
- * @example
- * Address6.fromAddress4Nat64('192.0.2.33').correctForm(); // '64:ff9b::c000:221'
- * Address6.fromAddress4Nat64('192.0.2.33', '2001:db8::/32').correctForm(); // '2001:db8:c000:221::'
- */
- static fromAddress4Nat64(address, prefix = '64:ff9b::/96') {
- const v4 = new ipv4_1.Address4(address);
- const prefix6 = new Address6(prefix);
- const pl = prefix6.subnetMask;
- if (pl !== 32 && pl !== 40 && pl !== 48 && pl !== 56 && pl !== 64 && pl !== 96) {
- throw new address_error_1.AddressError('NAT64 prefix length must be 32, 40, 48, 56, 64, or 96');
- }
- const prefixBits = prefix6.binaryZeroPad();
- const v4Bits = v4.binaryZeroPad();
- let bits;
- if (pl === 96) {
- bits = prefixBits.slice(0, 96) + v4Bits;
- }
- else {
- const beforeU = 64 - pl;
- bits =
- prefixBits.slice(0, pl) +
- v4Bits.slice(0, beforeU) +
- '00000000' +
- v4Bits.slice(beforeU) +
- '0'.repeat(128 - 72 - (32 - beforeU));
- }
- const hex = BigInt(`0b${bits}`).toString(16).padStart(32, '0');
- const groups = [];
- for (let i = 0; i < 8; i++) {
- groups.push(hex.slice(i * 4, (i + 1) * 4));
- }
- return new Address6(groups.join(':'));
- }
- /**
- * Extract the embedded IPv4 address from a NAT64 IPv6 address using the
- * encoding defined by [RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
- * The default prefix is the well-known prefix `64:ff9b::/96`. Returns
- * `null` if this address is not contained within the given prefix.
- * @example
- * new Address6('64:ff9b::c000:221').toAddress4Nat64()!.correctForm(); // '192.0.2.33'
- */
- toAddress4Nat64(prefix = '64:ff9b::/96') {
- const prefix6 = new Address6(prefix);
- const pl = prefix6.subnetMask;
- if (pl !== 32 && pl !== 40 && pl !== 48 && pl !== 56 && pl !== 64 && pl !== 96) {
- throw new address_error_1.AddressError('NAT64 prefix length must be 32, 40, 48, 56, 64, or 96');
- }
- if (!this.isInSubnet(prefix6)) {
- return null;
- }
- const bits = this.binaryZeroPad();
- let v4Bits;
- if (pl === 96) {
- v4Bits = bits.slice(96, 128);
- }
- else {
- const beforeU = 64 - pl;
- v4Bits = bits.slice(pl, pl + beforeU) + bits.slice(72, 72 + (32 - beforeU));
- }
- const octets = [];
- for (let i = 0; i < 4; i++) {
- octets.push(parseInt(v4Bits.slice(i * 8, (i + 1) * 8), 2).toString());
- }
- return new ipv4_1.Address4(octets.join('.'));
- }
- /**
- * Return a byte array.
- *
- * To get a Node.js `Buffer`, wrap the result: `Buffer.from(address.toByteArray())`.
- * @returns {Array}
- */
- toByteArray() {
- const valueWithoutPadding = this.bigInt().toString(16);
- const leadingPad = '0'.repeat(valueWithoutPadding.length % 2);
- const value = `${leadingPad}${valueWithoutPadding}`;
- const bytes = [];
- for (let i = 0, length = value.length; i < length; i += 2) {
- bytes.push(parseInt(value.substring(i, i + 2), 16));
- }
- return bytes;
- }
- /**
- * Return an unsigned byte array.
- *
- * To get a Node.js `Buffer`, wrap the result: `Buffer.from(address.toUnsignedByteArray())`.
- * @returns {Array}
- */
- toUnsignedByteArray() {
- return this.toByteArray().map(unsignByte);
- }
- /**
- * Convert a byte array to an Address6 object.
- *
- * To convert from a Node.js `Buffer`, spread it: `Address6.fromByteArray([...buf])`.
- * @returns {Address6}
- */
- static fromByteArray(bytes) {
- return this.fromUnsignedByteArray(bytes.map(unsignByte));
- }
- /**
- * Convert an unsigned byte array to an Address6 object.
- *
- * To convert from a Node.js `Buffer`, spread it: `Address6.fromUnsignedByteArray([...buf])`.
- * @returns {Address6}
- */
- static fromUnsignedByteArray(bytes) {
- const BYTE_MAX = BigInt('256');
- let result = BigInt('0');
- let multiplier = BigInt('1');
- for (let i = bytes.length - 1; i >= 0; i--) {
- result += multiplier * BigInt(bytes[i].toString(10));
- multiplier *= BYTE_MAX;
- }
- return Address6.fromBigInt(result);
- }
- /**
- * Returns true if the address is in the canonical form, false otherwise
- * @returns {boolean}
- */
- isCanonical() {
- return this.addressMinusSuffix === this.canonicalForm();
- }
- /**
- * Returns true if the address is a link local address, false otherwise
- * @returns {boolean}
- */
- isLinkLocal() {
- // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10'
- if (this.getBitsBase2(0, 64) ===
- '1111111010000000000000000000000000000000000000000000000000000000') {
- return true;
- }
- return false;
- }
- /**
- * Returns true if the address is a multicast address, false otherwise
- * @returns {boolean}
- */
- isMulticast() {
- const type = this.getType();
- return type === 'Multicast' || type.startsWith('Multicast ');
- }
- /**
- * Returns true if the address was written in v4-in-v6 dotted-quad notation
- * (e.g. `::ffff:127.0.0.1`), false otherwise. This is a notation-level flag
- * and does not reflect whether the address bits lie in the IPv4-mapped
- * (`::ffff:0:0/96`) subnet — for that, see {@link isMapped4}.
- * @returns {boolean}
- */
- is4() {
- return this.v4;
- }
- /**
- * Returns true if the address is an IPv4-mapped IPv6 address in
- * `::ffff:0:0/96` ([RFC 4291 §2.5.5.2](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2)),
- * false otherwise. Unlike {@link is4}, this checks the underlying address
- * bits rather than the textual notation, so `::ffff:127.0.0.1` and
- * `::ffff:7f00:1` both return true.
- * @returns {boolean}
- */
- isMapped4() {
- return this.isInSubnet(IPV4_MAPPED_SUBNET);
- }
- /**
- * Returns true if the address is a Teredo address, false otherwise
- * @returns {boolean}
- */
- isTeredo() {
- return this.isInSubnet(TEREDO_SUBNET);
- }
- /**
- * Returns true if the address is a 6to4 address, false otherwise
- * @returns {boolean}
- */
- is6to4() {
- return this.isInSubnet(SIX_TO_FOUR_SUBNET);
- }
- /**
- * Returns true if the address is a loopback address, false otherwise
- * @returns {boolean}
- */
- isLoopback() {
- return this.getType() === 'Loopback';
- }
- /**
- * Returns true if the address is a Unique Local Address in `fc00::/7` ([RFC 4193](https://datatracker.ietf.org/doc/html/rfc4193)). ULAs are the IPv6 equivalent of IPv4 [RFC 1918](https://datatracker.ietf.org/doc/html/rfc1918) private addresses.
- * @returns {boolean}
- */
- isULA() {
- return this.isInSubnet(ULA_SUBNET);
- }
- /**
- * Returns true if the address is the unspecified address `::`.
- * @returns {boolean}
- */
- isUnspecified() {
- return this.getType() === 'Unspecified';
- }
- /**
- * Returns true if the address is in the documentation prefix `2001:db8::/32` ([RFC 3849](https://datatracker.ietf.org/doc/html/rfc3849)).
- * @returns {boolean}
- */
- isDocumentation() {
- return this.isInSubnet(DOCUMENTATION_SUBNET);
- }
- // #endregion
- // #region HTML
- /**
- * Returns the address as an HTTP URL with the host bracketed, e.g.
- * `http://[2001:db8::1]/`. If `optionalPort` is provided it is appended,
- * e.g. `http://[2001:db8::1]:8080/`.
- */
- href(optionalPort) {
- if (optionalPort === undefined) {
- optionalPort = '';
- }
- else {
- optionalPort = `:${optionalPort}`;
- }
- return `http://[${this.correctForm()}]${optionalPort}/`;
- }
- /**
- * Returns an HTML `<a>` element whose `href` encodes the address in a URL
- * hash fragment (default prefix `/#address=`). Useful for linking between
- * pages of an address-inspector UI.
- * @param options.className - CSS class for the rendered `<a>` element
- * @param options.prefix - hash prefix prepended to the address (default `/#address=`)
- * @param options.v4 - when true, render the address in v4-in-v6 form
- */
- link(options) {
- if (!options) {
- options = {};
- }
- if (options.className === undefined) {
- options.className = '';
- }
- if (options.prefix === undefined) {
- options.prefix = '/#address=';
- }
- if (options.v4 === undefined) {
- options.v4 = false;
- }
- let formFunction = this.correctForm;
- if (options.v4) {
- formFunction = this.to4in6;
- }
- const form = formFunction.call(this);
- const safeHref = helpers.escapeHtml(`${options.prefix}${form}`);
- const safeForm = helpers.escapeHtml(form);
- if (options.className) {
- const safeClass = helpers.escapeHtml(options.className);
- return `<a href="${safeHref}" class="${safeClass}">${safeForm}</a>`;
- }
- return `<a href="${safeHref}">${safeForm}</a>`;
- }
- /**
- * Groups an address
- * @returns {String}
- */
- group() {
- if (this.elidedGroups === 0) {
- // The simple case
- return helpers.simpleGroup(this.addressMinusSuffix).join(':');
- }
- assert(typeof this.elidedGroups === 'number');
- assert(typeof this.elisionBegin === 'number');
- // The elided case
- const output = [];
- const [left, right] = this.addressMinusSuffix.split('::');
- if (left.length) {
- output.push(...helpers.simpleGroup(left));
- }
- else {
- output.push('');
- }
- const classes = ['hover-group'];
- for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) {
- classes.push(`group-${i}`);
- }
- output.push(`<span class="${classes.join(' ')}"></span>`);
- if (right.length) {
- output.push(...helpers.simpleGroup(right, this.elisionEnd));
- }
- else {
- output.push('');
- }
- if (this.is4()) {
- assert(this.address4 instanceof ipv4_1.Address4);
- output.pop();
- output.push(this.address4.groupForV6());
- }
- return output.join(':');
- }
- // #endregion
- // #region Regular expressions
- /**
- * Generate a regular expression string that can be used to find or validate
- * all variations of this address
- * @param {boolean} substringSearch
- * @returns {string}
- */
- regularExpressionString(substringSearch = false) {
- let output = [];
- // TODO: revisit why this is necessary
- const address6 = new Address6(this.correctForm());
- if (address6.elidedGroups === 0) {
- // The simple case
- output.push((0, regular_expressions_1.simpleRegularExpression)(address6.parsedAddress));
- }
- else if (address6.elidedGroups === constants6.GROUPS) {
- // A completely elided address
- output.push((0, regular_expressions_1.possibleElisions)(constants6.GROUPS));
- }
- else {
- // A partially elided address
- const halves = address6.address.split('::');
- if (halves[0].length) {
- output.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(':')));
- }
- assert(typeof address6.elidedGroups === 'number');
- output.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0));
- if (halves[1].length) {
- output.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(':')));
- }
- output = [output.join(':')];
- }
- if (!substringSearch) {
- output = [
- '(?=^|',
- regular_expressions_1.ADDRESS_BOUNDARY,
- '|[^\\w\\:])(',
- ...output,
- ')(?=[^\\w\\:]|',
- regular_expressions_1.ADDRESS_BOUNDARY,
- '|$)',
- ];
- }
- return output.join('');
- }
- /**
- * Generate a regular expression that can be used to find or validate all
- * variations of this address.
- * @param {boolean} substringSearch
- * @returns {RegExp}
- */
- regularExpression(substringSearch = false) {
- return new RegExp(this.regularExpressionString(substringSearch), 'i');
- }
-}
-exports.Address6 = Address6;
-const TYPE_SUBNETS = Object.keys(constants6.TYPES).map((subnet) => [
- new Address6(subnet),
- constants6.TYPES[subnet],
-]);
-const TEREDO_SUBNET = new Address6('2001::/32');
-const SIX_TO_FOUR_SUBNET = new Address6('2002::/16');
-const ULA_SUBNET = new Address6('fc00::/7');
-const DOCUMENTATION_SUBNET = new Address6('2001:db8::/32');
-const IPV4_MAPPED_SUBNET = new Address6('::ffff:0:0/96');
-
-},{"./address-error":1,"./common":2,"./ipv4":3,"./v4/constants":5,"./v6/constants":6,"./v6/helpers":7,"./v6/regular-expressions":8}],5:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.RE_SUBNET_STRING = exports.RE_ADDRESS = exports.GROUPS = exports.BITS = void 0;
-exports.BITS = 32;
-exports.GROUPS = 4;
-exports.RE_ADDRESS = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g;
-exports.RE_SUBNET_STRING = /\/\d{1,2}$/;
-
-},{}],6:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.RE_URL_WITH_PORT = exports.RE_URL = exports.RE_ZONE_STRING = exports.RE_SUBNET_STRING = exports.RE_BAD_ADDRESS = exports.RE_BAD_CHARACTERS = exports.TYPES = exports.SCOPES = exports.GROUPS = exports.BITS = void 0;
-exports.BITS = 128;
-exports.GROUPS = 8;
-/**
- * Represents IPv6 address scopes
- * @memberof Address6
- * @static
- */
-exports.SCOPES = {
- 0: 'Reserved',
- 1: 'Interface local',
- 2: 'Link local',
- 4: 'Admin local',
- 5: 'Site local',
- 8: 'Organization local',
- 14: 'Global',
- 15: 'Reserved',
-};
-/**
- * Represents IPv6 address types
- * @memberof Address6
- * @static
- */
-exports.TYPES = {
- 'ff01::1/128': 'Multicast (All nodes on this interface)',
- 'ff01::2/128': 'Multicast (All routers on this interface)',
- 'ff02::1/128': 'Multicast (All nodes on this link)',
- 'ff02::2/128': 'Multicast (All routers on this link)',
- 'ff05::2/128': 'Multicast (All routers in this site)',
- 'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)',
- 'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)',
- 'ff02::9/128': 'Multicast (RIP routers)',
- 'ff02::a/128': 'Multicast (EIGRP routers)',
- 'ff02::d/128': 'Multicast (PIM routers)',
- 'ff02::16/128': 'Multicast (MLDv2 reports)',
- 'ff01::fb/128': 'Multicast (mDNSv6)',
- 'ff02::fb/128': 'Multicast (mDNSv6)',
- 'ff05::fb/128': 'Multicast (mDNSv6)',
- 'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)',
- 'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)',
- 'ff02::1:3/128': 'Multicast (All DHCP servers on this link)',
- 'ff05::1:3/128': 'Multicast (All DHCP servers in this site)',
- '::/128': 'Unspecified',
- '::1/128': 'Loopback',
- 'ff00::/8': 'Multicast',
- 'fe80::/10': 'Link-local unicast',
- 'fc00::/7': 'Unique local',
- '2002::/16': '6to4',
- '2001:db8::/32': 'Documentation',
- '64:ff9b::/96': 'NAT64 (well-known)',
- '64:ff9b:1::/48': 'NAT64 (local-use)',
-};
-/**
- * A regular expression that matches bad characters in an IPv6 address
- * @memberof Address6
- * @static
- */
-exports.RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi;
-/**
- * A regular expression that matches an incorrect IPv6 address
- * @memberof Address6
- * @static
- */
-exports.RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi;
-/**
- * A regular expression that matches an IPv6 subnet
- * @memberof Address6
- * @static
- */
-exports.RE_SUBNET_STRING = /\/\d{1,3}(?=%|$)/;
-/**
- * A regular expression that matches an IPv6 zone
- * @memberof Address6
- * @static
- */
-exports.RE_ZONE_STRING = /%.*$/;
-exports.RE_URL = /^\[{0,1}([0-9a-f:]+)\]{0,1}/;
-exports.RE_URL_WITH_PORT = /\[([0-9a-f:]+)\]:([0-9]{1,5})/;
-
-},{}],7:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.escapeHtml = escapeHtml;
-exports.spanAllZeroes = spanAllZeroes;
-exports.spanAll = spanAll;
-exports.spanLeadingZeroes = spanLeadingZeroes;
-exports.simpleGroup = simpleGroup;
-function escapeHtml(s) {
- return s
- .replace(/&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&#39;');
-}
-/**
- * @returns {String} the string with all zeroes contained in a <span>
- */
-function spanAllZeroes(s) {
- return escapeHtml(s).replace(/(0+)/g, '<span class="zero">$1</span>');
-}
-/**
- * @returns {String} the string with each character contained in a <span>
- */
-function spanAll(s, offset = 0) {
- const letters = s.split('');
- return letters
- .map((n, i) => `<span class="digit value-${escapeHtml(n)} position-${i + offset}">${spanAllZeroes(n)}</span>`)
- .join('');
-}
-function spanLeadingZeroesSimple(group) {
- return escapeHtml(group).replace(/^(0+)/, '<span class="zero">$1</span>');
-}
-/**
- * @returns {String} the string with leading zeroes contained in a <span>
- */
-function spanLeadingZeroes(address) {
- const groups = address.split(':');
- return groups.map((g) => spanLeadingZeroesSimple(g)).join(':');
-}
-/**
- * Groups an address
- * @returns {String} a grouped address
- */
-function simpleGroup(addressString, offset = 0) {
- const groups = addressString.split(':');
- return groups.map((g, i) => {
- if (/group-v4/.test(g)) {
- return g;
- }
- return `<span class="hover-group group-${i + offset}">${spanLeadingZeroesSimple(g)}</span>`;
- });
-}
-
-},{}],8:[function(require,module,exports){
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.ADDRESS_BOUNDARY = void 0;
-exports.groupPossibilities = groupPossibilities;
-exports.padGroup = padGroup;
-exports.simpleRegularExpression = simpleRegularExpression;
-exports.possibleElisions = possibleElisions;
-const v6 = __importStar(require("./constants"));
-function groupPossibilities(possibilities) {
- return `(${possibilities.join('|')})`;
-}
-function padGroup(group) {
- if (group.length < 4) {
- return `0{0,${4 - group.length}}${group}`;
- }
- return group;
-}
-exports.ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]';
-function simpleRegularExpression(groups) {
- const zeroIndexes = [];
- groups.forEach((group, i) => {
- const groupInteger = parseInt(group, 16);
- if (groupInteger === 0) {
- zeroIndexes.push(i);
- }
- });
- // You can technically elide a single 0, this creates the regular expressions
- // to match that eventuality
- const possibilities = zeroIndexes.map((zeroIndex) => groups
- .map((group, i) => {
- if (i === zeroIndex) {
- const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : '';
- return groupPossibilities([padGroup(group), elision]);
- }
- return padGroup(group);
- })
- .join(':'));
- // The simplest case
- possibilities.push(groups.map(padGroup).join(':'));
- return groupPossibilities(possibilities);
-}
-function possibleElisions(elidedGroups, moreLeft, moreRight) {
- const left = moreLeft ? '' : ':';
- const right = moreRight ? '' : ':';
- const possibilities = [];
- // 1. elision of everything (::)
- if (!moreLeft && !moreRight) {
- possibilities.push('::');
- }
- // 2. complete elision of the middle
- if (moreLeft && moreRight) {
- possibilities.push('');
- }
- if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {
- // 3. complete elision of one side
- possibilities.push(':');
- }
- // 4. elision from the left side
- possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`);
- // 5. elision from the right side
- possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`);
- // 6. no elision
- possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`);
- // 7. elision (including sloppy elision) from the middle
- for (let groups = 1; groups < elidedGroups - 1; groups++) {
- for (let position = 1; position < elidedGroups - groups; position++) {
- possibilities.push(`(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`);
- }
- }
- return groupPossibilities(possibilities);
-}
-
-},{"./constants":6}],"ip-address":[function(require,module,exports){
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.v6 = exports.AddressError = exports.Address6 = exports.Address4 = void 0;
-var ipv4_1 = require("./ipv4");
-Object.defineProperty(exports, "Address4", { enumerable: true, get: function () { return ipv4_1.Address4; } });
-var ipv6_1 = require("./ipv6");
-Object.defineProperty(exports, "Address6", { enumerable: true, get: function () { return ipv6_1.Address6; } });
-var address_error_1 = require("./address-error");
-Object.defineProperty(exports, "AddressError", { enumerable: true, get: function () { return address_error_1.AddressError; } });
-const helpers = __importStar(require("./v6/helpers"));
-exports.v6 = { helpers };
-
-},{"./address-error":1,"./ipv4":3,"./ipv6":4,"./v6/helpers":7}]},{},[]);