import { Component, Input, OnInit, ViewChild, Output, EventEmitter } from '@angular/core'; import { DropdownPanelComponent } from '@overflow/commons/ui/component/primeng'; import { DiscoverHost, Zone } from '@overflow/model/discovery'; import { toMetaIPType, MetaIPTypeEnum, MetaPortTypeEnum } from '@overflow/model/meta'; import { DiscoveryConfigService } from '../service/discovery-config.service'; const IPCIDR = require('ip-cidr'); @Component({ selector: 'app-scanner-setting-dropdown', templateUrl: './scanner-setting-dropdown.component.html', styleUrls: ['./scanner-setting-dropdown.component.scss'], }) export class ScannerSettingDropdownComponent implements OnInit { @Input() blockTarget: any; @Output() ready = new EventEmitter(); @ViewChild('panel') panel: DropdownPanelComponent; valid: boolean; ipSummary: string; portSummary: string; ipType: MetaIPTypeEnum; firstIP: string; lastIP: string; includePortType: MetaPortTypeEnum[]; firstPort: string; lastPort: string; ipErrMsg: string; portErrMsg: string; zone: Zone; lastCondition: Condition = null; validIPArray: string[]; constructor( private discoveryConfigService: DiscoveryConfigService ) { } ngOnInit(): void { this.discoveryConfigService.zone.subscribe(res => { this.zone = res as Zone; this.setDefault(); }); } setDefault(): void { if (this.zone === null) { return; } const cidrUtil = new IPCIDR(this.zone.network); this.validIPArray = cidrUtil.toArray(); this.ipType = MetaIPTypeEnum.V4; this.firstIP = cidrUtil.start(); this.lastIP = cidrUtil.end(); this.includePortType = [MetaPortTypeEnum.TCP, MetaPortTypeEnum.UDP]; this.firstPort = '1'; this.lastPort = '65535'; this.ipErrMsg = ''; this.portErrMsg = ''; this.setSummary(); } validateIP(value: string, idx: number) { this.ipErrMsg = ''; switch (this.ipType) { case 'V4': if (!(/^(?=\d+\.\d+\.\d+\.\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4}$/.test(value))) { this.ipErrMsg = 'Invalid IP format.'; return; } if (this.validIPArray.indexOf(value) === -1) { this.ipErrMsg = 'Invalid IP range.'; return; } const from = idx === 0 ? value : this.firstIP; const to = idx === 1 ? value : this.lastIP; if (this.ipToNum(from) > this.ipToNum(to)) { this.ipErrMsg = 'Invalid IP range.'; return; } break; case 'V6': break; default: break; } } ipPressed(evt: KeyboardEvent) { if (!Number.isInteger(Number(evt.key)) && evt.key !== '.') { return false; } } portPressed(evt: KeyboardEvent) { if (!Number.isInteger(Number(evt.key))) { return false; } } ipToNum(ip: string): number { return ip.split('.').map((octet, index, array) => { // tslint:disable-next-line:radix return parseInt(octet) * Math.pow(256, (array.length - index - 1)); }).reduce((prev, curr) => { return prev + curr; }); } validatePort(value: string, idx: number) { this.portErrMsg = ''; const fromStr = idx === 0 ? value : this.firstPort; const toStr = idx === 1 ? value : this.lastPort; const from = Number(fromStr); const to = Number(toStr); if (from === NaN || to === NaN) { this.portErrMsg = 'Invalid Port Type.'; return; } if (from <= 0) { this.firstPort = '1'; return; } if (to > 65535) { this.lastPort = '65535'; return; } if (from > to) { this.portErrMsg = 'Invalid Port range.'; return; } } validateTCP(checked: boolean) { if (!checked && this.includePortType.indexOf(MetaPortTypeEnum.UDP) === -1) { this.includePortType = [MetaPortTypeEnum.TCP]; } } validateUDP(checked: boolean) { if (!checked && this.includePortType.indexOf(MetaPortTypeEnum.TCP) === -1) { this.includePortType = [MetaPortTypeEnum.UDP]; } } done() { // TODO: re-validation this.saveLastCondition(); this.setSummary(); this.panel.hide(); } cancel() { if (null === this.lastCondition) { this.setDefault(); } else { this.restore(); } } saveLastCondition() { const c: Condition = { ipType: this.ipType, firstIP: this.firstIP, lastIP: this.lastIP, includePortType: this.includePortType, firstPort: this.firstPort, lastPort: this.lastPort, }; this.lastCondition = c; } restore() { this.ipType = this.lastCondition.ipType; this.firstIP = this.lastCondition.firstIP; this.lastIP = this.lastCondition.lastIP; this.includePortType = this.lastCondition.includePortType; this.firstPort = this.lastCondition.firstPort; this.lastPort = this.lastCondition.lastPort; this.ipErrMsg = ''; this.portErrMsg = ''; } setSummary(): void { this.ipSummary = this.ipType + ' (' + this.firstIP + ' - ' + this.lastIP + ')'; this.portSummary = this.includePortType.join(','); this.portSummary += ' (' + this.firstPort + ' - ' + this.lastPort + ')'; this.configDiscoverHost(); } configDiscoverHost(): void { const discoverHost: DiscoverHost = { metaIPType: toMetaIPType(this.ipType), firstScanRange: this.firstIP, lastScanRange: this.lastIP, discoveryConfig: {}, discoverPort: { firstScanRange: Number(this.firstPort), lastScanRange: Number(this.lastPort), includeTCP: this.includePortType.indexOf(MetaPortTypeEnum.TCP) !== -1 ? true : false, includeUDP: this.includePortType.indexOf(MetaPortTypeEnum.UDP) !== -1 ? true : false, discoverService: { includeServices: null, } } }; this.ready.emit(discoverHost); } } class Condition { ipType: MetaIPTypeEnum; firstIP: string; lastIP: string; includePortType: MetaPortTypeEnum[]; firstPort: string; lastPort: string; }