• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2/* eslint-disable no-param-reassign */
3var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4    if (k2 === undefined) k2 = k;
5    var desc = Object.getOwnPropertyDescriptor(m, k);
6    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7      desc = { enumerable: true, get: function() { return m[k]; } };
8    }
9    Object.defineProperty(o, k2, desc);
10}) : (function(o, m, k, k2) {
11    if (k2 === undefined) k2 = k;
12    o[k2] = m[k];
13}));
14var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15    Object.defineProperty(o, "default", { enumerable: true, value: v });
16}) : function(o, v) {
17    o["default"] = v;
18});
19var __importStar = (this && this.__importStar) || function (mod) {
20    if (mod && mod.__esModule) return mod;
21    var result = {};
22    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23    __setModuleDefault(result, mod);
24    return result;
25};
26Object.defineProperty(exports, "__esModule", { value: true });
27exports.Address4 = void 0;
28const common = __importStar(require("./common"));
29const constants = __importStar(require("./v4/constants"));
30const address_error_1 = require("./address-error");
31const jsbn_1 = require("jsbn");
32const sprintf_js_1 = require("sprintf-js");
33/**
34 * Represents an IPv4 address
35 * @class Address4
36 * @param {string} address - An IPv4 address string
37 */
38class Address4 {
39    constructor(address) {
40        this.groups = constants.GROUPS;
41        this.parsedAddress = [];
42        this.parsedSubnet = '';
43        this.subnet = '/32';
44        this.subnetMask = 32;
45        this.v4 = true;
46        /**
47         * Returns true if the address is correct, false otherwise
48         * @memberof Address4
49         * @instance
50         * @returns {Boolean}
51         */
52        this.isCorrect = common.isCorrect(constants.BITS);
53        /**
54         * Returns true if the given address is in the subnet of the current address
55         * @memberof Address4
56         * @instance
57         * @returns {boolean}
58         */
59        this.isInSubnet = common.isInSubnet;
60        this.address = address;
61        const subnet = constants.RE_SUBNET_STRING.exec(address);
62        if (subnet) {
63            this.parsedSubnet = subnet[0].replace('/', '');
64            this.subnetMask = parseInt(this.parsedSubnet, 10);
65            this.subnet = `/${this.subnetMask}`;
66            if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {
67                throw new address_error_1.AddressError('Invalid subnet mask.');
68            }
69            address = address.replace(constants.RE_SUBNET_STRING, '');
70        }
71        this.addressMinusSuffix = address;
72        this.parsedAddress = this.parse(address);
73    }
74    static isValid(address) {
75        try {
76            // eslint-disable-next-line no-new
77            new Address4(address);
78            return true;
79        }
80        catch (e) {
81            return false;
82        }
83    }
84    /*
85     * Parses a v4 address
86     */
87    parse(address) {
88        const groups = address.split('.');
89        if (!address.match(constants.RE_ADDRESS)) {
90            throw new address_error_1.AddressError('Invalid IPv4 address.');
91        }
92        return groups;
93    }
94    /**
95     * Returns the correct form of an address
96     * @memberof Address4
97     * @instance
98     * @returns {String}
99     */
100    correctForm() {
101        return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');
102    }
103    /**
104     * Converts a hex string to an IPv4 address object
105     * @memberof Address4
106     * @static
107     * @param {string} hex - a hex string to convert
108     * @returns {Address4}
109     */
110    static fromHex(hex) {
111        const padded = hex.replace(/:/g, '').padStart(8, '0');
112        const groups = [];
113        let i;
114        for (i = 0; i < 8; i += 2) {
115            const h = padded.slice(i, i + 2);
116            groups.push(parseInt(h, 16));
117        }
118        return new Address4(groups.join('.'));
119    }
120    /**
121     * Converts an integer into a IPv4 address object
122     * @memberof Address4
123     * @static
124     * @param {integer} integer - a number to convert
125     * @returns {Address4}
126     */
127    static fromInteger(integer) {
128        return Address4.fromHex(integer.toString(16));
129    }
130    /**
131     * Return an address from in-addr.arpa form
132     * @memberof Address4
133     * @static
134     * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address
135     * @returns {Adress4}
136     * @example
137     * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)
138     * address.correctForm(); // '192.0.2.42'
139     */
140    static fromArpa(arpaFormAddress) {
141        // remove ending ".in-addr.arpa." or just "."
142        const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, '');
143        const address = leader.split('.').reverse().join('.');
144        return new Address4(address);
145    }
146    /**
147     * Converts an IPv4 address object to a hex string
148     * @memberof Address4
149     * @instance
150     * @returns {String}
151     */
152    toHex() {
153        return this.parsedAddress.map((part) => (0, sprintf_js_1.sprintf)('%02x', parseInt(part, 10))).join(':');
154    }
155    /**
156     * Converts an IPv4 address object to an array of bytes
157     * @memberof Address4
158     * @instance
159     * @returns {Array}
160     */
161    toArray() {
162        return this.parsedAddress.map((part) => parseInt(part, 10));
163    }
164    /**
165     * Converts an IPv4 address object to an IPv6 address group
166     * @memberof Address4
167     * @instance
168     * @returns {String}
169     */
170    toGroup6() {
171        const output = [];
172        let i;
173        for (i = 0; i < constants.GROUPS; i += 2) {
174            const hex = (0, sprintf_js_1.sprintf)('%02x%02x', parseInt(this.parsedAddress[i], 10), parseInt(this.parsedAddress[i + 1], 10));
175            output.push((0, sprintf_js_1.sprintf)('%x', parseInt(hex, 16)));
176        }
177        return output.join(':');
178    }
179    /**
180     * Returns the address as a BigInteger
181     * @memberof Address4
182     * @instance
183     * @returns {BigInteger}
184     */
185    bigInteger() {
186        return new jsbn_1.BigInteger(this.parsedAddress.map((n) => (0, sprintf_js_1.sprintf)('%02x', parseInt(n, 10))).join(''), 16);
187    }
188    /**
189     * Helper function getting start address.
190     * @memberof Address4
191     * @instance
192     * @returns {BigInteger}
193     */
194    _startAddress() {
195        return new jsbn_1.BigInteger(this.mask() + '0'.repeat(constants.BITS - this.subnetMask), 2);
196    }
197    /**
198     * The first address in the range given by this address' subnet.
199     * Often referred to as the Network Address.
200     * @memberof Address4
201     * @instance
202     * @returns {Address4}
203     */
204    startAddress() {
205        return Address4.fromBigInteger(this._startAddress());
206    }
207    /**
208     * The first host address in the range given by this address's subnet ie
209     * the first address after the Network Address
210     * @memberof Address4
211     * @instance
212     * @returns {Address4}
213     */
214    startAddressExclusive() {
215        const adjust = new jsbn_1.BigInteger('1');
216        return Address4.fromBigInteger(this._startAddress().add(adjust));
217    }
218    /**
219     * Helper function getting end address.
220     * @memberof Address4
221     * @instance
222     * @returns {BigInteger}
223     */
224    _endAddress() {
225        return new jsbn_1.BigInteger(this.mask() + '1'.repeat(constants.BITS - this.subnetMask), 2);
226    }
227    /**
228     * The last address in the range given by this address' subnet
229     * Often referred to as the Broadcast
230     * @memberof Address4
231     * @instance
232     * @returns {Address4}
233     */
234    endAddress() {
235        return Address4.fromBigInteger(this._endAddress());
236    }
237    /**
238     * The last host address in the range given by this address's subnet ie
239     * the last address prior to the Broadcast Address
240     * @memberof Address4
241     * @instance
242     * @returns {Address4}
243     */
244    endAddressExclusive() {
245        const adjust = new jsbn_1.BigInteger('1');
246        return Address4.fromBigInteger(this._endAddress().subtract(adjust));
247    }
248    /**
249     * Converts a BigInteger to a v4 address object
250     * @memberof Address4
251     * @static
252     * @param {BigInteger} bigInteger - a BigInteger to convert
253     * @returns {Address4}
254     */
255    static fromBigInteger(bigInteger) {
256        return Address4.fromInteger(parseInt(bigInteger.toString(), 10));
257    }
258    /**
259     * Returns the first n bits of the address, defaulting to the
260     * subnet mask
261     * @memberof Address4
262     * @instance
263     * @returns {String}
264     */
265    mask(mask) {
266        if (mask === undefined) {
267            mask = this.subnetMask;
268        }
269        return this.getBitsBase2(0, mask);
270    }
271    /**
272     * Returns the bits in the given range as a base-2 string
273     * @memberof Address4
274     * @instance
275     * @returns {string}
276     */
277    getBitsBase2(start, end) {
278        return this.binaryZeroPad().slice(start, end);
279    }
280    /**
281     * Return the reversed ip6.arpa form of the address
282     * @memberof Address4
283     * @param {Object} options
284     * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix
285     * @instance
286     * @returns {String}
287     */
288    reverseForm(options) {
289        if (!options) {
290            options = {};
291        }
292        const reversed = this.correctForm().split('.').reverse().join('.');
293        if (options.omitSuffix) {
294            return reversed;
295        }
296        return (0, sprintf_js_1.sprintf)('%s.in-addr.arpa.', reversed);
297    }
298    /**
299     * Returns true if the given address is a multicast address
300     * @memberof Address4
301     * @instance
302     * @returns {boolean}
303     */
304    isMulticast() {
305        return this.isInSubnet(new Address4('224.0.0.0/4'));
306    }
307    /**
308     * Returns a zero-padded base-2 string representation of the address
309     * @memberof Address4
310     * @instance
311     * @returns {string}
312     */
313    binaryZeroPad() {
314        return this.bigInteger().toString(2).padStart(constants.BITS, '0');
315    }
316    /**
317     * Groups an IPv4 address for inclusion at the end of an IPv6 address
318     * @returns {String}
319     */
320    groupForV6() {
321        const segments = this.parsedAddress;
322        return this.address.replace(constants.RE_ADDRESS, (0, sprintf_js_1.sprintf)('<span class="hover-group group-v4 group-6">%s</span>.<span class="hover-group group-v4 group-7">%s</span>', segments.slice(0, 2).join('.'), segments.slice(2, 4).join('.')));
323    }
324}
325exports.Address4 = Address4;
326//# sourceMappingURL=ipv4.js.map