import * as common from './common' ; import * as constants from './v4/constants' ; import { AddressError } from './address-error' ; import { BigInteger } from 'jsbn' ; import { sprintf } from 'sprintf-js' ; class param { string } address export class Address4 { address : string ; addressMinusSuffix ? : string ; groups : number = constants . GROUPS ; parsedAddress : string [ ] = [ ] ; parsedSubnet : string = '' ; subnet : string = '/32' ; subnetMask : number = 32 ; v4 : boolean = true ; constructor ( address ) { 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 AddressError ( 'Invalid subnet mask.' ) ; } address = address . replace ( constants . RE_SUBNET_STRING , '' ) ; } this . addressMinusSuffix = address ; this . parsedAddress = this . parse ( address ) ; } static isValid ( address ) { try { new Address4 ( address ) ; return true ; } catch ( e ) { return false ; } } parse ( address ) { const groups = address . split ( '.' ) ; if ( ! address . match ( constants . RE_ADDRESS ) ) { throw new AddressError ( 'Invalid IPv4 address.' ) ; } return groups ; } memberof instance returns { String } correctForm ( ) { return this . parsedAddress . map ( ( part ) => parseInt ( part , 10 ) ) . join ( '.' ) ; } memberof instance returns { Boolean } isCorrect = common . isCorrect ( constants . BITS ) ; memberof static param { string } hex returns { Address4 } static fromHex ( hex ) { const padded = hex . replace ( /:/g , '' ) . padStart ( 8 , '0' ) ; const groups = [ ] ; let i ; for ( i = 0 ; i < 8 ; i += 2 ) { const h = padded . slice ( i , i + 2 ) ; groups . push ( parseInt ( h , 16 ) ) ; } return new Address4 ( groups . join ( '.' ) ) ; } memberof static param { integer } integer returns { Address4 } static fromInteger ( integer ) { return Address4 . fromHex ( integer . toString ( 16 ) ) ; } memberof static param { string } arpaFormAddress returns { Adress4 } example static fromArpa ( arpaFormAddress ) { const leader = arpaFormAddress . replace ( /(\.in-addr\.arpa)?\.$/ , '' ) ; const address = leader . split ( '.' ) . reverse ( ) . join ( '.' ) ; return new Address4 ( address ) ; } memberof instance returns { String } toHex ( ) { return this . parsedAddress . map ( ( part ) => sprintf ( '%02x' , parseInt ( part , 10 ) ) ) . join ( ':' ) ; } memberof instance returns { Array } toArray ( ) { return this . parsedAddress . map ( ( part ) => parseInt ( part , 10 ) ) ; } memberof instance returns { String } toGroup6 ( ) { const output = [ ] ; let i ; for ( i = 0 ; i < constants . GROUPS ; i += 2 ) { const hex = sprintf ( '%02x%02x' , parseInt ( this . parsedAddress [ i ] , 10 ) , parseInt ( this . parsedAddress [ i + 1 ] , 10 ) ) ; output . push ( sprintf ( '%x' , parseInt ( hex , 16 ) ) ) ; } return output . join ( ':' ) ; } memberof instance returns { BigInteger } bigInteger ( ) { return new BigInteger ( this . parsedAddress . map ( ( n ) => sprintf ( '%02x' , parseInt ( n , 10 ) ) ) . join ( '' ) , 16 ) ; } memberof instance returns { BigInteger } _startAddress ( ) { return new BigInteger ( this . mask ( ) + '0' . repeat ( constants . BITS - this . subnetMask ) , 2 ) ; } memberof instance returns { Address4 } startAddress ( ) { return Address4 . fromBigInteger ( this . _startAddress ( ) ) ; } memberof instance returns { Address4 } startAddressExclusive ( ) { const adjust = new BigInteger ( '1' ) ; return Address4 . fromBigInteger ( this . _startAddress ( ) . add ( adjust ) ) ; } memberof instance returns { BigInteger } _endAddress ( ) { return new BigInteger ( this . mask ( ) + '1' . repeat ( constants . BITS - this . subnetMask ) , 2 ) ; } memberof instance returns { Address4 } endAddress ( ) { return Address4 . fromBigInteger ( this . _endAddress ( ) ) ; } memberof instance returns { Address4 } endAddressExclusive ( ) { const adjust = new BigInteger ( '1' ) ; return Address4 . fromBigInteger ( this . _endAddress ( ) . subtract ( adjust ) ) ; } memberof static param { BigInteger } bigInteger returns { Address4 } static fromBigInteger ( bigInteger ) { return Address4 . fromInteger ( parseInt ( bigInteger . toString ( ) , 10 ) ) ; } memberof instance returns { String } mask ( mask ? ) { if ( mask === undefined ) { mask = this . subnetMask ; } return this . getBitsBase2 ( 0 , mask ) ; } memberof instance returns { string } getBitsBase2 ( start , end ) { return this . binaryZeroPad ( ) . slice ( start , end ) ; } memberof param options param { boolean } options . omitSuffix instance returns { String } reverseForm ( options ? ) { if ( ! options ) { options = { } ; } const reversed = this . correctForm ( ) . split ( '.' ) . reverse ( ) . join ( '.' ) ; if ( options . omitSuffix ) { return reversed ; } return sprintf ( '%s.in-addr.arpa.' , reversed ) ; } memberof instance returns { boolean } isInSubnet = common . isInSubnet ; memberof instance returns { boolean } isMulticast ( ) { return this . isInSubnet ( new Address4 ( '224.0.0.0/4' ) ) ; } memberof instance returns { string } binaryZeroPad ( ) { return this . bigInteger ( ) . toString ( 2 ) . padStart ( constants . BITS , '0' ) ; } returns { String } groupForV6 ( ) { const segments = this . parsedAddress ; return this . address . replace ( constants . RE_ADDRESS , 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 ( '.' ) ) ) ; } }