/*    Copyright 2016 Rottiesoft LLC 
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

var debugging = false;
var log = function () {
    if (debugging) {
        console.log(Array.prototype.slice.call(arguments));
    }
};

module.exports = class {

    // ID can be port
    constructor(range, debug) {
        this.range = range;
        debugging = debug;
    }

    parsePort(hostuid, portjson) {
        let port = {};
        log("PARSING: ", portjson);
        port.protocol = portjson.protocol;
        port.hostId = hostuid;
        port.uid = hostuid + '.' + portjson.portid;
        port.portid = portjson.portid;
        if (portjson['service']) {
            port.serviceName = portjson['service']['name'];
            port.lastActiveTimestamp = Date.now() / 1000;
        }
        if (portjson['state']) {
            port.state = portjson['state']['state'];
        }
        return port;
    }

    scan(range, fast, callback) {
        let cmdline = 'sudo nmap -sU --host-timeout 200s --script nbstat.nse -p 137 ' + range + ' -oX - | xml-json host';
        if (fast == true) {
            cmdline = 'sudo nmap -sn -PO --host-timeout 30s  ' + range + ' -oX - | xml-json host';
        }
        console.log("Running commandline: ", cmdline);

        if (this.process) {
            console.log("======================= Warning Previous instance running====");
            return;
        }

        this.nmapScan(cmdline,true,callback);
     }

     nmapScan(cmdline,requiremac,callback) {

        this.process = require('child_process').exec(cmdline, (err, out, code) => {
            let outarray = out.split("\n");
            let hosts = [];
            let ports = [];
            for (let a in outarray) {
                try {
                    let hostjson = JSON.parse(outarray[a]);
                    let host = {};
                    if (hostjson.hostnames && hostjson.hostnames.constructor == Object) {
                        host.hostname = hostjson.hostnames.hostname.name;
                        host.hostnameType = hostjson.hostnames.hostname.type;
                    }
                    /*
                    console.log(hostjson.hostnames);
                    if (hostjson.hostnames && Array.isArray(hostjson.hostname) && hostjson.hostname.length>0) {
                        host.hostname = hostjson.hostnames[0].hostname.name;
                        host.hostnameType = hostjson.hostnames[0].hostname.type;
                    }
                    */

                    let ipaddr = "";
                    for (let h in hostjson['address']) {
                        let addr = hostjson['address'][h];
                        if (addr['addrtype'] == 'ipv4') {
                            host.ipv4Addr = addr.addr;
                            ipaddr = addr.addr;
                        } else if (addr['addrtype'] == 'mac') {
                            host.mac = addr.addr;
                            if (addr.vendor != null) {
                                host.macVendor = addr.vendor;
                            }
                        }
                    }

                    if (host.mac == null && requiremac == true) {
                        console.log("skipping host, no mac address", host);
                        continue;
                    }

                    host.uid = ipaddr;
                    let now = Date.now() / 1000;
                    host.lastActiveTimestamp = now;
                    host.firstFoundTimestamp = now;

                    if (hostjson['ports']) {
                        if (Array.isArray(hostjson['ports']['port'])) {
                            for (let i in hostjson['ports']['port']) {
                                let portjson = hostjson['ports']['port'][i];
                                let port = this.parsePort(host.uid, portjson);
                                if (port) {
                                    log(port);
                                    ports.push(port);
                                }
                            }
                        } else {
                            let port = this.parsePort(host.uid, hostjson['ports']['port']);
                            if (port) {
                                log(port);
                                ports.push(port);
                            }
                        }
                    }

                    if (hostjson['os'] && hostjson['os']['osmatch']) {
                        host['os_match'] = hostjson['os']['osmatch']['name'];
                        host['os_accuracy'] = hostjson['os']['osmatch']['accuracy'];
                        host['os_class'] = JSON.stringify(hostjson['os']['osmatch']['osclass']);
                    }

                    if (hostjson['uptime']) {
                        host['uptime'] = hostjson['uptime']['seconds'];
                    }

                    try {
                        if (hostjson.hostscript) {
                        }
                        if (hostjson.hostscript && hostjson.hostscript.script && hostjson.hostscript.script.id == "nbstat") {
                            let scriptout = hostjson.hostscript.script;
                            if (scriptout.elem) {
                                for (let i in scriptout.elem) {
                                    if (scriptout.elem[i].key == "server_name") {
                                        host.nname = scriptout.elem[i]["_"];
                                        break;
                                    }
                                }
                            }
                        }
                    } catch(e) {
                        console.log("Discovery:Nmap:Netbios:Error",e,host);
                    }

                    hosts.push(host);
                } catch (e) {}
            }
            callback(null, hosts, ports);
        });
        this.process.on('close', (code, signal) => {
            console.log("NMAP Closed");
            this.process = null;
        });
    }
}

@@ -682,16 +682,40 @@
 strict';
+%0Avar ip = require('ip');
 %0A%0Avar de
@@ -1564,24 +1564,442 @@
 callback) %7B%0A
+        if (false == ip.isV4Format(range)) %7B%0A            try %7B%0A               let ip_info = ip.cidrSubnet(range);%0A               if (ip_info) %7B%0A                   if(ip_info.subnetMaskLength%3C24) %7B%0A                       callback(null,null); %0A                       return;%0A                   %7D%0A               %7D%0A            %7D catch(e) %7B%0A               log.error(%22Nmap:Scan:Error%22,range,fast,e);%0A            %7D%0A        %7D%0A
         let 

add code to prevent scanning of subnetmask length <24