import { Component, EventEmitter, Input, Output, OnChanges, SimpleChanges } from '@angular/core'; import { ProbeHost } from '@overflow/commons-typescript/model/probe'; import * as CIDR from 'ip-cidr'; import * as ipRangeCheck from 'ip-range-check'; import { DiscoverPort, DiscoverService, DiscoverZone } from '@overflow/commons-typescript/model/discovery'; import { Checkbox } from 'primeng/primeng'; import { MetaCrawler } from '@overflow/commons-typescript/model/meta'; @Component({ selector: 'of-discovery-search-config', templateUrl: './search-config.component.html', }) export class SearchConfigComponent implements OnChanges { SUPPORT_V6 = false; @Input() probeHost: ProbeHost; @Output() requestDiscovery = new EventEmitter(); ipVer: string; startIP: string; endIP: string; startPort: string; endPort: string; excludeIPs = []; excludePorts = []; includeServices = []; hostChecked = true; portChecked = true; serviceChecked = true; tcpChecked = true; udpChecked = true; validation = false; ipErrMsg: string; portErrMsg: string; fixedIPrange: number; ipArray = []; portExcludeDisplay = false; portChips = []; constructor( ) { } ngOnChanges(changes: SimpleChanges): void { if (changes['probeHost']) { this.initByProbe(); } this.validation = true; } initByProbe() { const cidr = new CIDR(this.probeHost.probe.cidr); if (!cidr.isValid()) { return; } this.ipVer = 'v4'; this.startIP = cidr.start(); this.endIP = cidr.end(); this.startPort = '1'; this.endPort = '1024'; // TODO: Initialize services this.checkEditableIPrange(cidr); } onIPExcludeFocus() { const cidr = new CIDR(this.probeHost.probe.cidr); this.ipArray = cidr.toArray().filter((value) => { return this.inRange(value) || this.excludeIPs.find(obj => obj.ip === value); }).map(value => { return { ip: value }; }); } inRange(value) { const min = this.startIP; const max = this.endIP; if (this.ipToNum(min) <= this.ipToNum(value) && this.ipToNum(max) >= this.ipToNum(value)) { return true; } return false; } ipToNum(ip) { return Number( ip.split('.') .map(d => ('000' + d).substr(-3)) .join('') ); } onRequestDiscovery() { let discoverPort: DiscoverPort = null; let discoverService: DiscoverService = null; if (this.serviceChecked) { const services = []; for (const service of this.includeServices) { services.push(service.description); } discoverService = { includeServices: services, }; } if (this.portChecked) { discoverPort = { firstScanRange: Number(this.startPort), lastScanRange: Number(this.endPort), includeTCP: this.tcpChecked, includeUDP: this.udpChecked, excludePorts: this.excludePorts, discoverService: discoverService }; } const discoverZone: DiscoverZone = { discoverHost: { firstScanRangev4: this.startIP, lastScanRangev4: this.endIP, discoverPort: discoverPort, excludeHostsv4: this.excludeIPs, }, }; console.log(discoverZone); this.requestDiscovery.emit(discoverZone); } checkEditableIPrange(cidr) { const startIPArray = cidr.addressStart.parsedAddress; const endIPArray = cidr.addressEnd.parsedAddress; let count = 0; endIPArray.forEach((element, idx) => { if (element === startIPArray[idx]) { count++; } }); this.fixedIPrange = count; } onPortCheckChange(serviceCheckbox: Checkbox, checked: boolean) { if (!checked) { serviceCheckbox.checked = false; this.serviceChecked = false; } else { if (!this.tcpChecked && !this.udpChecked) { this.tcpChecked = true; this.udpChecked = true; } } } onServiceCheckChange(portCheckbox: Checkbox, checked: boolean) { if (checked) { portCheckbox.checked = true; this.portChecked = true; } } onPortTypeCheck(portCheckbox: Checkbox, serviceCheckbox: Checkbox): void { if (!this.tcpChecked && !this.udpChecked) { this.portChecked = false; portCheckbox.checked = false; this.serviceChecked = false; serviceCheckbox.checked = false; } } onInputIP(e, idx: number) { const value = e.value; if (idx === 0) { this.startIP = value; } else { this.endIP = value; } this.ipErrMsg = this.validateIP(value, idx); if (this.ipErrMsg) { this.validation = false; } else { this.validation = true; } } validateIP(value: string, idx): string { if (!this.isValidIPregex(value)) { return 'Not valid IP format.'; } if (!ipRangeCheck(value, this.probeHost.probe.cidr)) { return 'Not valid IP range.'; } const ipArray = [this.startIP, this.endIP]; const sortedIpArray = this.sortIP([this.startIP, this.endIP]); if (ipArray[0] !== sortedIpArray[0]) { return 'Not valiad range'; } return null; } isValidIPregex(ip: string): boolean { if (this.ipVer === 'v4') { return /^(?=\d+\.\d+\.\d+\.\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4}$/.test(ip); } return false; } sortIP(ipAddressArray) { return ipAddressArray.sort((a, b) => { a = a.split('.'); b = b.split('.'); for (let i = 0; i < a.length; i++) { // tslint:disable-next-line:radix if ((a[i] = parseInt(a[i])) < (b[i] = parseInt(b[i]))) { return -1; } else if (a[i] > b[i]) { return 1; } } return 0; }); } onInputPort(portNum: string, idx: number) { if (idx === 0) { this.startPort = portNum; } else { this.endPort = portNum; } this.portErrMsg = this.validatePort(portNum); if (this.portErrMsg) { this.validation = false; } else { this.validation = true; } } validatePort(portNum): string { if (Number(this.startPort) > Number(this.endPort)) { return 'Not valid port range.'; } if (Number(portNum) <= 0 || Number(portNum) > 65535) { return 'Not valid port range.'; } return null; } onAddExcludePort(event) { const port = event.value.replace(/\s/g, ''); if (port.indexOf('~') > 0) { // e.g. 1~3000 const splited = port.split('~'); this.portChips.pop(); const from = Number(splited[0]); const to = Number(splited[1]); if (this.checkInvalidPort(from) || this.checkInvalidPort(to) || !Number.isInteger(from) || !Number.isInteger(to)) { return; } const chipItem = 'All ' + from + ' ~ ' + to; this.portChips.push(chipItem); for (let i = from; i <= to; i++) { this.excludePorts.push(String(i)); } } else { const num = Number(event.value); if (!Number.isInteger(num) || this.checkInvalidPort(num) || this.checkExistExcludePort(event.value)) { this.portChips.pop(); return; } this.excludePorts.push(event.value); } } onRemoveExcludePort(event) { if (event.value.indexOf('~') > 0) { // e.g. 'All 1 ~ 30' const splited = event.value.replace(/\s/g, '').replace('All', '').split('~'); for (let i = Number(splited[0]); i <= Number(splited[1]); i++) { console.log(String(i)); const index = this.excludePorts.indexOf(String(i)); this.excludePorts.splice(index, 1); } return; } const idx = this.excludePorts.indexOf(event.value); this.excludePorts.splice(idx, 1); } checkExistExcludePort(portNum) { return this.excludePorts.find((value) => { return value === portNum; }); } checkInvalidPort(port) { return port <= 0 || port > 65535; } }