mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2025-12-09 22:42:07 +01:00
Add support of IP addresses (#15)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -21,3 +21,5 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
debug.log
|
||||
|
||||
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import HelpResult from './models/HelpResult';
|
||||
import AboutResult from './models/AboutResult';
|
||||
import UnknownCommandResult from './models/UnknownCommandResult';
|
||||
import ExpressionResult from './models/ExpressionResult';
|
||||
import ErrorResult from './models/ErrorResult';
|
||||
import {UnhandledErrorResult, ErrorResult} from './models/ErrorResults';
|
||||
import WahtsnewResult from './models/WhatsnewResult';
|
||||
import StringResult from './models/StringResult';
|
||||
import * as expression from './expression/expression';
|
||||
@@ -10,6 +10,9 @@ import uuid from 'uuid/v4';
|
||||
import { CommandInput, CmdShell } from './core/cmd';
|
||||
import { ExpressionInput } from './expression/expression-interfaces';
|
||||
import AppState from './core/AppState';
|
||||
import {ParsingError, IpAddress, ipAddressParser, IpAddressWithSubnetMask, ParsedIpObject} from './ipaddress/ip'
|
||||
import IpAddressResult from './models/IpAddressResult';
|
||||
import { isGetAccessor, isPrefixUnaryExpression } from 'typescript';
|
||||
|
||||
export default {
|
||||
initialize (cmd: CmdShell, appState: AppState) {
|
||||
@@ -32,11 +35,43 @@ export default {
|
||||
appState.addCommandResult(new StringResult(c.input, `Debug Mode: ${appState.debugMode}`))
|
||||
});
|
||||
|
||||
|
||||
// Ip Addresses
|
||||
cmd.command({
|
||||
canHandle: (input:string) => ipAddressParser.parse(input) != null,
|
||||
handle: function(c: CommandInput) {
|
||||
var result = ipAddressParser.parse(c.input);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
if(result instanceof ParsingError) {
|
||||
appState.addCommandResult(new ErrorResult(c.input, result.errorMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
const ipAddresses : IpAddress[] = [];
|
||||
|
||||
(result as ParsedIpObject[]).forEach(r => {
|
||||
if(r instanceof IpAddressWithSubnetMask)
|
||||
{
|
||||
ipAddresses.push(r.ipAddress);
|
||||
ipAddresses.push(r.createSubnetMaskIp());
|
||||
}
|
||||
else if(r instanceof IpAddress) {
|
||||
ipAddresses.push(r);
|
||||
}
|
||||
});
|
||||
|
||||
appState.addCommandResult(new IpAddressResult(c.input, ipAddresses));
|
||||
}
|
||||
})
|
||||
|
||||
// Bitwise Expressions
|
||||
cmd.command({
|
||||
canHandle: (input:string) => expression.parser.canParse(input),
|
||||
handle: function(c: CommandInput) {
|
||||
var expr = expression.parser.parse(c.input);
|
||||
appState.toggleDebugMode();
|
||||
appState.addCommandResult(new ExpressionResult(c.input, expr as ExpressionInput));
|
||||
}
|
||||
})
|
||||
@@ -47,6 +82,6 @@ export default {
|
||||
handle: (c: CommandInput) => appState.addCommandResult(new UnknownCommandResult(c.input))
|
||||
});
|
||||
|
||||
cmd.onError((input: string, err: Error) => appState.addCommandResult(new ErrorResult(input, err)));
|
||||
cmd.onError((input: string, err: Error) => appState.addCommandResult(new UnhandledErrorResult(input, err)));
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,13 @@ import ExpressionResult from '../models/ExpressionResult';
|
||||
import BitwiseOperationExpressionView from './results/expressions/BitwiseOperationExpressionView';
|
||||
import WhatsnewResult from '../models/WhatsnewResult';
|
||||
import WhatsnewResultView from './results/WhatsNewResultView';
|
||||
import ErrorResult from '../models/ErrorResult';
|
||||
import {UnhandledErrorResult, ErrorResult} from '../models/ErrorResults';
|
||||
import StringResult from '../models/StringResult';
|
||||
import IpAddressView from './results/IpAddressView';
|
||||
|
||||
import CommandResult from '../models/CommandResult';
|
||||
import AppState from '../core/AppState';
|
||||
import IpAddressResult from '../models/IpAddressResult';
|
||||
|
||||
type DisplayResultProps = {
|
||||
content : CommandResult,
|
||||
@@ -54,12 +56,24 @@ export default class DisplayResult extends React.Component<DisplayResultProps> {
|
||||
return <p>{result.value}</p>
|
||||
}
|
||||
|
||||
if (result instanceof ErrorResult) {
|
||||
if (result instanceof UnhandledErrorResult) {
|
||||
return <div className="result">
|
||||
<div className="error">(X_X) Ooops.. Something ain' right: <strong>{result.error.message}</strong></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
if (result instanceof ErrorResult) {
|
||||
return <div className="result">
|
||||
<div className="error">{result.errorMessage}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
if(result instanceof IpAddressResult) {
|
||||
const ipResult = result as IpAddressResult;
|
||||
|
||||
return <IpAddressView ipAddresses={ipResult.ipAddresses} />
|
||||
}
|
||||
|
||||
return <div className="result">
|
||||
<div className="error">¯\_(ツ)_/¯ Sorry, i don′t know what <strong>{this.props.content.input}</strong> is</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
export type BinaryStringViewProps = {
|
||||
allowFlipBits: boolean;
|
||||
binaryString: string;
|
||||
onFlipBit: (input: FlipBitEventArg) => void;
|
||||
onFlipBit?: (input: FlipBitEventArg) => void;
|
||||
emphasizeBytes: boolean;
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ export type FlipBitEventArg = {
|
||||
index: number;
|
||||
binaryString: string;
|
||||
$event: any;
|
||||
newBinaryString: string
|
||||
};
|
||||
|
||||
export default class BinaryStringView extends React.Component<BinaryStringViewProps> {
|
||||
@@ -19,13 +20,19 @@ export default class BinaryStringView extends React.Component<BinaryStringViewPr
|
||||
}
|
||||
|
||||
onBitClick(index: number, e : any) {
|
||||
if(!this.props.allowFlipBits) {
|
||||
if(!this.props.allowFlipBits || !this.props.onFlipBit) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.props.onFlipBit) {
|
||||
this.props.onFlipBit({ index: index, binaryString: this.props.binaryString, $event: e });
|
||||
if(!this.props.onFlipBit) {
|
||||
|
||||
}
|
||||
|
||||
const arr = this.props.binaryString.split('');
|
||||
arr[index] = arr[index] == '0' ? '1' : '0';
|
||||
const newBinaryString = arr.join('');
|
||||
|
||||
this.props.onFlipBit({ index: index, binaryString: this.props.binaryString, $event: e, newBinaryString });
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
|
||||
1
src/components/results/IpAddressView.css
Normal file
1
src/components/results/IpAddressView.css
Normal file
@@ -0,0 +1 @@
|
||||
.ip-address-info { padding-top: 1em; font-size: 0.85em; vertical-align: middle;}
|
||||
78
src/components/results/IpAddressView.tsx
Normal file
78
src/components/results/IpAddressView.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import React from 'react';
|
||||
import { IpAddress, OctetNumber, getNetworkClass } from '../../ipaddress/ip';
|
||||
import formatter from '../../core/formatter'
|
||||
import BinaryStringView from './BinaryString';
|
||||
import './IpAddressView.css';
|
||||
type IpAddressViewProps = {
|
||||
ipAddresses: IpAddress[]
|
||||
};
|
||||
|
||||
export class IpAddressView extends React.Component<IpAddressViewProps>
|
||||
{
|
||||
|
||||
render() {
|
||||
if(this.props.ipAddresses.length === 1)
|
||||
return this.renderSingleIp(this.props.ipAddresses[0]);
|
||||
|
||||
return this.renderMultipleIps();
|
||||
}
|
||||
|
||||
renderMultipleIps() {
|
||||
return <table className="expression">
|
||||
<tbody>
|
||||
{this.props.ipAddresses.map((ip, i) => <tr key={i}>
|
||||
<td>{ip.toString()}</td>
|
||||
<td>
|
||||
{this.bin(ip.firstByte, 1, ip)}.{this.bin(ip.secondByte, 2, ip)}.{this.bin(ip.thirdByte, 3, ip)}.{this.bin(ip.fourthByte, 4, ip)}
|
||||
</td>
|
||||
</tr>)}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
renderSingleIp(ip: IpAddress) {
|
||||
return <table className="expression">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{ip.firstByte}</th>
|
||||
<th>{ip.secondByte}</th>
|
||||
<th>{ip.thirdByte}</th>
|
||||
<th>{ip.fourthByte}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{this.bin(ip.firstByte, 1, ip)}</td>
|
||||
<td>{this.bin(ip.secondByte, 2, ip)}</td>
|
||||
<td>{this.bin(ip.thirdByte, 3, ip)}</td>
|
||||
<td>{this.bin(ip.fourthByte, 4, ip)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2} className="ip-address-info">
|
||||
<a href="https://www.wikiwand.com/en/Classful_network" target="_blank">Network Class: {getNetworkClass(ip).toUpperCase()}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>;
|
||||
}
|
||||
|
||||
bin(value: number, octetNumber: OctetNumber, ip: IpAddress) {
|
||||
return <BinaryStringView
|
||||
binaryString={fmt(value)}
|
||||
key={octetNumber}
|
||||
emphasizeBytes={false}
|
||||
allowFlipBits={true}
|
||||
onFlipBit={e => this.onFlippedBit(e.newBinaryString, octetNumber, ip)} />;
|
||||
}
|
||||
|
||||
onFlippedBit(binaryString: string, number: OctetNumber, ip : IpAddress) {
|
||||
ip.setOctet(number, parseInt(binaryString, 2));
|
||||
this.forceUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
function fmt(num: number) : string {
|
||||
return formatter.padLeft(formatter.formatString(num, 'bin'), 8, '0');
|
||||
}
|
||||
|
||||
export default IpAddressView;
|
||||
@@ -25,17 +25,17 @@ code { font-size: 1.2em; font-weight: bold; }
|
||||
|
||||
.expression .label { font-weight: bold; padding-right: 5px; text-align: right; }
|
||||
.expression .bin { letter-spacing: 3px; }
|
||||
.expression .flipable { cursor: pointer; opacity: 1 }
|
||||
.expression .flipable:hover { opacity: 0.8 }
|
||||
.expression .byte { margin: 0 3px; }
|
||||
.expression .flipable { cursor: pointer; opacity: 1 }
|
||||
.expression .flipable:hover { opacity: 0.8 }
|
||||
.expression-result td { border-top: dotted 1px gray; }
|
||||
.expression { font-size: 1.5em; font-family: monospace }
|
||||
.expression .prefix { font-weight: normal; display: none; font-size: 0.9em }
|
||||
.expression .other { font-size: 0.9em}
|
||||
.expression .sign { text-align: right}
|
||||
|
||||
.flipable { cursor: pointer; opacity: 1 }
|
||||
.flipable { cursor: pointer; opacity: 1 }
|
||||
.flipable:hover { opacity: 0.8 }
|
||||
|
||||
.hex .prefix { display: inline; }
|
||||
|
||||
.help { padding: 10px; }
|
||||
|
||||
104
src/ipaddress/ip.test.ts
Normal file
104
src/ipaddress/ip.test.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import {IpAddress, ipAddressParser, getNetworkClass, ParsingError, IpAddressWithSubnetMask, ParsedIpObject} from './ip';
|
||||
|
||||
|
||||
describe('parser tests', () => {
|
||||
it('can parse correct ip address', () => {
|
||||
const actual = ipAddressParser.parse('127.1.2.3');
|
||||
expect(actual).not.toBe(null);
|
||||
expect(actual).not.toBeInstanceOf(ParsingError);
|
||||
|
||||
const obj = (actual as ParsedIpObject[])[0];
|
||||
const expected = new IpAddress(127, 1, 2, 3);
|
||||
expect(obj).not.toBe(null);
|
||||
expect(obj.toString()).toBe(expected.toString());
|
||||
});
|
||||
|
||||
it('cannot parse incorrect ip address', () => {
|
||||
expect(ipAddressParser.parse('abc')).toBe(null);
|
||||
expect(ipAddressParser.parse('')).toBe(null);
|
||||
});
|
||||
|
||||
it('should parse invalid ip address', () => {
|
||||
expect(ipAddressParser.parse('256.0.0.0')).toBeInstanceOf(ParsingError);
|
||||
expect(ipAddressParser.parse('0.256.0.0')).toBeInstanceOf(ParsingError);
|
||||
expect(ipAddressParser.parse('0.0.256.0')).toBeInstanceOf(ParsingError);
|
||||
expect(ipAddressParser.parse('0.0.0.256')).toBeInstanceOf(ParsingError);
|
||||
expect(ipAddressParser.parse('0.0.0.255 asd')).toBeInstanceOf(ParsingError);
|
||||
expect(ipAddressParser.parse('0.0.0.255/99')).toBeInstanceOf(ParsingError);
|
||||
});
|
||||
|
||||
it('parses correct ip and subnet mask', () => {
|
||||
const actual = ipAddressParser.parse('127.0.0.1/24');
|
||||
|
||||
expect(actual).not.toBe(null);
|
||||
expect(actual).not.toBeInstanceOf(ParsingError);
|
||||
|
||||
const obj = (actual as ParsedIpObject[])[0];
|
||||
expect(obj).toBeInstanceOf(IpAddressWithSubnetMask);
|
||||
expect(obj!.toString()).toBe('127.0.0.1/24');
|
||||
expect((obj as IpAddressWithSubnetMask).maskBits).toBe(24);
|
||||
});
|
||||
|
||||
it('parses list of ip addresses', () => {
|
||||
const actual = ipAddressParser.parse('127.0.0.1/24 255.255.1.1');
|
||||
|
||||
expect(actual).not.toBe(null);
|
||||
expect(actual).not.toBeInstanceOf(ParsingError);
|
||||
|
||||
const first = (actual as ParsedIpObject[])[0];
|
||||
expect(first).toBeInstanceOf(IpAddressWithSubnetMask);
|
||||
expect(first!.toString()).toBe('127.0.0.1/24');
|
||||
expect((first as IpAddressWithSubnetMask).maskBits).toBe(24);
|
||||
|
||||
const second = (actual as ParsedIpObject[])[1];
|
||||
expect(second).toBeInstanceOf(IpAddress);
|
||||
expect(second!.toString()).toBe('255.255.1.1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNetworkClass tests', () => {
|
||||
it('detects class a', () => {
|
||||
expect(getNetworkClass(new IpAddress(1, 0, 0, 0))).toBe('a');
|
||||
expect(getNetworkClass(new IpAddress(55, 0, 0, 0))).toBe('a');
|
||||
expect(getNetworkClass(new IpAddress(97, 0, 0, 0))).toBe('a');
|
||||
expect(getNetworkClass(new IpAddress(127, 0, 0, 0))).toBe('a');
|
||||
});
|
||||
|
||||
it('detects class b', () => {
|
||||
expect(getNetworkClass(new IpAddress(128, 0, 0, 0))).toBe('b');
|
||||
expect(getNetworkClass(new IpAddress(134, 0, 0, 0))).toBe('b');
|
||||
expect(getNetworkClass(new IpAddress(180, 0, 0, 0))).toBe('b');
|
||||
expect(getNetworkClass(new IpAddress(191, 0, 0, 0))).toBe('b');
|
||||
});
|
||||
|
||||
it('detects class c', () => {
|
||||
expect(getNetworkClass(new IpAddress(192, 0, 0, 0))).toBe('c');
|
||||
expect(getNetworkClass(new IpAddress(218, 0, 0, 0))).toBe('c');
|
||||
expect(getNetworkClass(new IpAddress(223, 0, 0, 0))).toBe('c');
|
||||
});
|
||||
|
||||
it('detects class d', () => {
|
||||
expect(getNetworkClass(new IpAddress(224, 0, 0, 0))).toBe('d');
|
||||
expect(getNetworkClass(new IpAddress(234, 0, 0, 0))).toBe('d');
|
||||
expect(getNetworkClass(new IpAddress(239, 0, 0, 0))).toBe('d');
|
||||
});
|
||||
|
||||
it('detects class e', () => {
|
||||
expect(getNetworkClass(new IpAddress(240, 0, 0, 0))).toBe('e');
|
||||
expect(getNetworkClass(new IpAddress(241, 0, 0, 0))).toBe('e');
|
||||
expect(getNetworkClass(new IpAddress(255, 0, 0, 0))).toBe('e');
|
||||
});
|
||||
});
|
||||
|
||||
describe('IpAddressWithSubnetMask tests', () => {
|
||||
|
||||
it('creates subnetmask ip', () => {
|
||||
const ip = new IpAddress(127, 0, 0, 1);
|
||||
expect(new IpAddressWithSubnetMask(ip, 1).createSubnetMaskIp().toString()).toBe('128.0.0.0');
|
||||
expect(new IpAddressWithSubnetMask(ip, 8).createSubnetMaskIp().toString()).toBe('255.0.0.0');
|
||||
expect(new IpAddressWithSubnetMask(ip, 10).createSubnetMaskIp().toString()).toBe('255.192.0.0');
|
||||
expect(new IpAddressWithSubnetMask(ip, 20).createSubnetMaskIp().toString()).toBe('255.255.240.0');
|
||||
expect(new IpAddressWithSubnetMask(ip, 30).createSubnetMaskIp().toString()).toBe('255.255.255.252');
|
||||
expect(new IpAddressWithSubnetMask(ip, 32).createSubnetMaskIp().toString()).toBe('255.255.255.255');
|
||||
});
|
||||
});
|
||||
183
src/ipaddress/ip.ts
Normal file
183
src/ipaddress/ip.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
import formatter from '../core/formatter';
|
||||
|
||||
|
||||
export type OctetNumber = 1 | 2 | 3 | 4;
|
||||
export type NetworkClass = 'a' | 'b' | 'c' | 'd' | 'e';
|
||||
export type ParsedIpObject = IpAddress | IpAddressWithSubnetMask;
|
||||
|
||||
const ipAddressParser = {
|
||||
parse: function(input: string) : ParsedIpObject[] | ParsingError | null {
|
||||
|
||||
const matches = this.getMaches(input);
|
||||
const correctInputs = matches.filter(m => m.matches != null);
|
||||
const incorrectInputs = matches.filter(m => m.matches == null);
|
||||
|
||||
if(correctInputs.length == 0)
|
||||
return null;
|
||||
|
||||
if(incorrectInputs.length > 0) {
|
||||
return new ParsingError(`Value(s) ${incorrectInputs.map(v => v.input).join(',')} was not recognized as valid ip address or ip address with a subnet mask`);
|
||||
}
|
||||
|
||||
const parsedObjects = matches.map(m => this.parseSingle(m.matches!, m.input));
|
||||
const parsingErrors = parsedObjects.filter(p => p instanceof ParsingError);
|
||||
|
||||
if(parsingErrors.length > 0) {
|
||||
return parsingErrors[0] as ParsingError;
|
||||
}
|
||||
|
||||
return parsedObjects as ParsedIpObject[];
|
||||
|
||||
},
|
||||
|
||||
getMaches(input : string) : { matches: RegExpExecArray | null, input: string }[] {
|
||||
|
||||
return input.
|
||||
replace(/[\t\s]+/g, ' ')
|
||||
.split(' ')
|
||||
.filter(s => s.length>0)
|
||||
.map(s => {
|
||||
const ipV4Regex = /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\/\d+)?$/;
|
||||
const matches = ipV4Regex.exec(s);
|
||||
|
||||
if(matches == null || matches.length === 0)
|
||||
return {matches: null, input: s};
|
||||
|
||||
return {matches, input: s};
|
||||
});
|
||||
},
|
||||
|
||||
parseSingle(matches : RegExpExecArray, input: string) : ParsedIpObject | ParsingError {
|
||||
const invalid = (n: number) => n < 0 || n > 255;
|
||||
|
||||
const first = parseInt(matches[1]);
|
||||
const second = parseInt(matches[2]);
|
||||
const third = parseInt(matches[3]);
|
||||
const fourth = parseInt(matches[4]);
|
||||
|
||||
if(invalid(first) || invalid(second) || invalid(third) || invalid(fourth))
|
||||
return new ParsingError(`${input} value doesn't fall within the valid range of the IP address space`);
|
||||
|
||||
const ipAddress = new IpAddress(first, second, third, fourth);
|
||||
|
||||
if(matches[5]) {
|
||||
const maskPart = matches[5].substr(1);
|
||||
const maskBits = parseInt(maskPart);
|
||||
|
||||
if(maskBits > 32) {
|
||||
return new ParsingError(`Subnet mask value in ${input} is out of range`);
|
||||
}
|
||||
|
||||
return new IpAddressWithSubnetMask(ipAddress, maskBits);
|
||||
}
|
||||
|
||||
return ipAddress;
|
||||
}
|
||||
}
|
||||
|
||||
export class ParsingError {
|
||||
errorMessage: string;
|
||||
constructor(message: string) {
|
||||
this.errorMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
export class IpAddressWithSubnetMask {
|
||||
maskBits: number;
|
||||
ipAddress: IpAddress;
|
||||
|
||||
constructor(ipAddress : IpAddress, maskBits : number) {
|
||||
this.ipAddress = ipAddress;
|
||||
this.maskBits = maskBits;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.ipAddress.toString()}/${this.maskBits}`;
|
||||
}
|
||||
|
||||
createSubnetMaskIp() : IpAddress {
|
||||
|
||||
const mask = (bits: number) => 255<<(8-bits)&255;
|
||||
|
||||
if(this.maskBits <= 8) {
|
||||
return new IpAddress(mask(this.maskBits), 0, 0, 0);
|
||||
}
|
||||
else if(this.maskBits <= 16) {
|
||||
return new IpAddress(255, mask(this.maskBits-8), 0, 0);
|
||||
}
|
||||
else if(this.maskBits <= 24) {
|
||||
return new IpAddress(255, 255, mask(this.maskBits-16), 0);
|
||||
}
|
||||
else {
|
||||
return new IpAddress(255, 255, 255, mask(this.maskBits-24));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class IpAddress {
|
||||
|
||||
firstByte : number;
|
||||
secondByte: number;
|
||||
thirdByte : number;
|
||||
fourthByte: number
|
||||
|
||||
constructor(firstByte : number, secondByte: number, thirdByte : number, fourthByte: number) {
|
||||
this.firstByte = firstByte;
|
||||
this.secondByte = secondByte;
|
||||
this.thirdByte = thirdByte;
|
||||
this.fourthByte = fourthByte;
|
||||
}
|
||||
|
||||
toString() : string {
|
||||
return `${this.firstByte}.${this.secondByte}.${this.thirdByte}.${this.fourthByte}`;
|
||||
}
|
||||
|
||||
setOctet(octet: OctetNumber, value : number) {
|
||||
switch(octet) {
|
||||
case 1:
|
||||
this.firstByte = value;
|
||||
break;
|
||||
case 2:
|
||||
this.secondByte = value;
|
||||
break;
|
||||
case 3:
|
||||
this.thirdByte = value;
|
||||
break;
|
||||
case 4:
|
||||
this.fourthByte = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getNetworkClass = function (ipAddress: IpAddress) : NetworkClass {
|
||||
const byte = ipAddress.firstByte;
|
||||
const bineryRep = formatter.formatString(ipAddress.firstByte, 'bin');
|
||||
|
||||
const firstBitOne = (byte & 128) === 128;
|
||||
const firstBitZero = (byte & 128) === 0;
|
||||
const secondBitOne = (byte & 64) === 64;
|
||||
|
||||
const thirdBitOne = (byte & 32) === 32;
|
||||
const thirdBitZero = (byte & 32) === 0;
|
||||
|
||||
const forthBitZero = (byte & 16) === 0;
|
||||
const forthBitOne = (byte & 16) === 16;
|
||||
|
||||
// e: 1111
|
||||
|
||||
if(firstBitOne && secondBitOne && thirdBitOne && forthBitOne)
|
||||
return 'e';
|
||||
|
||||
if(firstBitOne && secondBitOne && thirdBitOne && forthBitZero) // Start bits: 1110;
|
||||
return 'd';
|
||||
|
||||
if(firstBitOne && secondBitOne && thirdBitZero) // Start bits: 110;
|
||||
return 'c';
|
||||
|
||||
return firstBitOne ? 'b' : 'a';
|
||||
};
|
||||
|
||||
export {ipAddressParser, getNetworkClass};
|
||||
@@ -1,9 +0,0 @@
|
||||
import CommandResult from './CommandResult';
|
||||
|
||||
export default class ErrorResult extends CommandResult {
|
||||
error: Error;
|
||||
constructor(input: string, error : Error) {
|
||||
super(input);
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
17
src/models/ErrorResults.ts
Normal file
17
src/models/ErrorResults.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import CommandResult from './CommandResult';
|
||||
|
||||
export class UnhandledErrorResult extends CommandResult {
|
||||
error: Error;
|
||||
constructor(input: string, error : Error) {
|
||||
super(input);
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorResult extends CommandResult {
|
||||
errorMessage: string;
|
||||
constructor(input: string, errorMessage : string) {
|
||||
super(input);
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
}
|
||||
10
src/models/IpAddressResult.ts
Normal file
10
src/models/IpAddressResult.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { IpAddress, ipAddressParser, IpAddressWithSubnetMask } from '../ipaddress/ip';
|
||||
import CommandResult from './CommandResult';
|
||||
|
||||
export default class IpAddressResult extends CommandResult {
|
||||
ipAddresses: IpAddress[];
|
||||
constructor(input: string, ipAddresses: IpAddress[]) {
|
||||
super(input);
|
||||
this.ipAddresses = ipAddresses;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user