diff --git a/index.js b/index.js index badf58f..8a05da1 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,8 @@ const fs = require('fs'); const exec = require('child_process').exec; +const async = require('async'); +const _ = require('lodash'); // The tools const airport = require('./lib/airport'); const iwlist = require('./lib/iwlist'); @@ -14,25 +16,50 @@ var scanner; // Initializing the tools function initTools(callback) { - fs.stat(airport.tool, function (err, stats) { - if (stats) { - return callback(null, airport); - } - fs.stat(iwlist.tool, function (err, stats) { - if (stats) { - return callback(null, iwlist); + // When a command is not found, an error is issued and async would finish. Therefore we pack + // the error into the result and check it later on. + async.parallel([ + function (cb) { + exec(airport.detector, function (err) { + cb(null, {err: err, scanner: airport} + ) + } + ); + }, + function (cb) { + exec(iwlist.detector, function (err) { + cb(null, {err: err, scanner: iwlist} + ) + } + ); + }, + function (cb) { + exec(netsh.detector, function (err) { + cb(null, {err: err, scanner: netsh} + ) + } + ); } - fs.stat(netsh.tool, function (err, stats) { - if (stats) { - return callback(null, netsh); - } - callback(new Error('No scanner found')); - }); - }); - }); + ], + function (err, results) { + var res = _.find(results, + function (f) { + return !f.err + }); + + if (res) { + return callback(null, res.scanner); + } + callback(new Error('No scanner found')); + } + ); } +/** + * Scan the networks with the scanner detected before + * @param callback + */ function scanNetworks(callback) { exec(scanner.cmdLine, function (err, stdout) { if (err) { @@ -50,7 +77,7 @@ module.exports = { */ scan: function (callback) { if (!scanner) { - initTools((err, s) => { + initTools(function (err, s) { if (err) { return callback(err); } @@ -61,4 +88,4 @@ module.exports = { } scanNetworks(callback); } -}; \ No newline at end of file +}; diff --git a/lib/airport.js b/lib/airport.js index 739d449..86a37c4 100644 --- a/lib/airport.js +++ b/lib/airport.js @@ -5,6 +5,7 @@ const tool = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport'; const cmdLine = tool + ' -s'; +const detector = tool + ' -getInfo'; const macRegex = /([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}/; /** @@ -30,7 +31,7 @@ function parseOutput(str, callback) { 'ssid' : lines[i].substr(0, macStart).trim(), 'mac' : elements[0].trim(), 'channel' : parseInt(elements[2].trim(), 10), - 'rssi' : parseInt(elements[1].trim()) + 'rssi' : parseInt(elements[1].trim(), 10) }); } } @@ -45,5 +46,6 @@ function parseOutput(str, callback) { module.exports = { parseOutput: parseOutput, cmdLine : cmdLine, + detector : detector, tool : tool }; diff --git a/lib/iwlist.js b/lib/iwlist.js index 627a95c..a8dd1ab 100644 --- a/lib/iwlist.js +++ b/lib/iwlist.js @@ -4,8 +4,12 @@ */ const _ = require('lodash'); -const tool = '/usr/bin/iwlist'; +// usually located in /usr/bin/ but as it could be at another location, allow all found in PATH (but we're in trouble +// when the default location, /usr/bin/ is not in the PATH!). GitHub issue #1 +const tool = 'iwlist'; const cmdLine = tool + ' scan'; +const detector = tool + ' --help'; + const macRegex = /([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}/; const cellRegex = /Cell [0-9]{2,} - Address:/; @@ -79,5 +83,6 @@ function parseOutput(str, callback) { module.exports = { parseOutput: parseOutput, cmdLine : cmdLine, + detector : detector, tool : tool }; diff --git a/lib/netsh.js b/lib/netsh.js index 0c0c753..53ed0cf 100644 --- a/lib/netsh.js +++ b/lib/netsh.js @@ -6,6 +6,7 @@ const systemRoot = process.env.SystemRoot || 'C:\\Windows'; const tool = systemRoot + '\\System32\\netsh.exe'; const cmdLine = tool + ' wlan show networks mode=Bssid'; +const detector = tool + ' show alias'; /** * Parsing netnsh output. Unfortunately netsh supplies the network information @@ -71,7 +72,7 @@ function parseOutput(str, callback) { // A tricky one: the channel is the first one having just ONE number. Set only // if the channel is not already set ("Basic Rates" can be a single number also) if (regexChannel.exec(lines[t].trim())) { - network.channel = parseInt(lines[t].split(':')[1].trim()); + network.channel = parseInt(lines[t].split(':')[1].trim(), 10); } } } @@ -90,5 +91,6 @@ function parseOutput(str, callback) { module.exports = { parseOutput: parseOutput, cmdLine : cmdLine, + detector : detector, tool : tool }; diff --git a/package.json b/package.json index c6b627b..d325494 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-wifi-scanner", - "version": "1.0.0", + "version": "1.1.0", "description": "node.js module for WiFi network detection", "main": "index.js", "keywords": [ @@ -35,7 +35,8 @@ "test": "mocha test" }, "dependencies": { - "lodash": "4.8.1" + "async": "2.1.4", + "lodash": "4.17.2" }, "devDependencies": { "grunt": "0.4.5",