Compare commits

..

No commits in common. "master" and "develop" have entirely different histories.

8 changed files with 115 additions and 168 deletions

View File

@ -1,43 +1,4 @@
# Fork of node-wifi-scanner #node-wifi-scanner
This fork is used to add the ability to scan as sudo under linux.
Why the fork?
- Add ability to execute command with prefix 'sudo' to get iwlist working on linux!
- Uses promise instead of callback in module exports to make it easier and prevent callback hells.
- Add `encrypted:boolean` to the output, to determine if the network is encrypted (Currently only works under iwlist/linux, otherwise just returns false)
To use sudo, just pass `true` to the scan method and it will use sudo.
For ex.
```js
const wifiScan = require("node-wifi-scanner");
let result = await wifiScan.scan(true);
```
Beforehand you should add the iwlist scan command to the sudoers file.
`%mygroup ALL = (root) NOPASSWD: iwlist wlanX scan` [src](https://stackoverflow.com/questions/53710368/how-do-i-add-typescript-types-to-a-javascript-module-without-switching-to-typesc)
### Installation
`yarn add git+https://github.com/Tobstr02/node-wifi-scanner.git`
or `npm install git+https://github.com/Tobstr02/node-wifi-scanner.git`
### Type definitions
I also tried to add type definitions (see /types/index.d.ts), but as far as i know i did it wrong haha.
Since this is my first ever module (-fork) i don't really know how to do it. - Let me know in the issues tab or create a pull request :)
But i added jsdoc to the functions to add the ability to make the coding process a bit cleaner.
<br>
<i>Fork from: [Node-Wifi-Scanner Github](https://github.com/ancasicolica/node-wifi-scanner/)</i>
<br><br>
----
# Node-Wifi-Scanner
[![Build Status](https://travis-ci.org/ancasicolica/node-wifi-scanner.svg?branch=master)](https://travis-ci.org/ancasicolica/node-wifi-scanner) [![Build Status](https://travis-ci.org/ancasicolica/node-wifi-scanner.svg?branch=master)](https://travis-ci.org/ancasicolica/node-wifi-scanner)
[![npm](https://img.shields.io/npm/v/node-wifi-scanner.svg)]() [![npm](https://img.shields.io/npm/v/node-wifi-scanner.svg)]()
@ -55,24 +16,39 @@ system language. The adaptions needed would have been too comprehensive for a pu
## Operating Systems ## Operating Systems
It was tested with the following operating systems: It was tested with the following operating systems:
* Mac OS-X [Not tested by fork author] * Mac OS-X
* Windows 10 [Not tested by fork author] * Windows 10
* Ubuntu 14.04 [Tested by fork author] * Ubuntu 14.04
* Raspbian "Jessie" [Tested by fork author] * Raspbian "Jessie"
## Installation ## Installation
yarn add git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner npm i node-wifi-scanner
## Usage ## Usage
### Command Line
Run the script ```scan``` in the bin folder.
### Code
const scanner = require('node-wifi-scanner');
scanner.scan((err, networks) => {
if (err) {
console.error(err);
return;
}
console.log(networks);
});
The tool returns an array with objects, each object representing a network with the following properties: The tool returns an array with objects, each object representing a network with the following properties:
* channel: WiFi channel * channel: WiFi channel
* ssid: SSID of the network (if available) * ssid: SSID of the network (if available)
* mac: MAC Address of the network access point (if available, otherwise empty string) * mac: MAC Address of the network access point (if available, otherwise empty string)
* rssi: signal strength * rssi: signal strength
* encrypted: boolean - Is network encrypted?
In contrary to other wifi scanners no information about security is returned. This is due to the very different implementation In contrary to other wifi scanners no information about security is returned. This is due to the very different implementation
of the command line tools which do not allow a flawless detection. of the command line tools which do not allow a flawless detection.
@ -98,7 +74,7 @@ the operating system. Please note the following restrictions
before using this tool in a productive system. before using this tool in a productive system.
**Linux**: iwlist does only return all found networks if run as sudo! Otherwise you'll **Linux**: iwlist does only return all found networks if run as sudo! Otherwise you'll
get only the network you're connected to. <i>That's where my fork comes in!!</i> get only the network you're connected to.
**Windows**: there are some network cards which do not **Windows**: there are some network cards which do not
return the MAC address and other parameters of the found networks. In this case return the MAC address and other parameters of the found networks. In this case
@ -110,7 +86,7 @@ card, OS,...) as available. Thanks
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2016-2024 Christian Kuster, Tobias Hopp Copyright (c) 2016 Christian Kuster
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,20 +1,9 @@
/**
* @typedef {Object} WifiNetwork
* @property {string} ssid - SSID of the wifi
* @property {string} mac - MAC-Address of the wifi
* @property {number} channel - Channel of the wifi
* @property {number} rssi - Signalstrength of Wifi-Network (RSSI)
* @property {boolean} encrypted - Encrypted
*/
/** /**
* node-wifi-scanner * node-wifi-scanner
* Created by kc on 04.04.16. - Forked and updated by Tobias Hopp 27.03.2024 * Created by kc on 04.04.16.
*/ */
const {exec, spawn} = require('child_process'); const exec = require('child_process').exec;
const async = require('async'); const async = require('async');
const _ = require('lodash'); const _ = require('lodash');
// The tools // The tools
@ -68,76 +57,34 @@ function initTools(callback) {
/** /**
* Scan the networks with the scanner detected before * Scan the networks with the scanner detected before
* @param {Function|any} callback * @param callback
* @param {boolean} useSudo - Use sudo for access?
*/ */
function scanNetworks(callback, useSudo) { function scanNetworks(callback) {
const cmd = scanner.cmdLine.split(" "); exec(scanner.cmdLine, function (err, stdout) {
let args = cmd.slice(1);
if(useSudo)
args.unshift(cmd[0]);
const child = spawn(useSudo ? "sudo" : cmd[0], args, { stdio: ['ignore', 'pipe', 'pipe'], detached: true });
child.on("error", (err) => callback(err, null) );
let stdoutData = '';
child.stdout.on('data', (data) => {
stdoutData += data;
});
child.on('close', (code) => {
if (code === 0) {
// Prozess erfolgreich beendet, Ausgabe verarbeiten
scanner.parseOutput(stdoutData, callback);
} else {
// Prozess mit Fehler beendet
callback(new Error(`Exited with code ${code}`), null);
}
});
/*exec((useSudo ? "sudo ":"") + scanner.cmdLine, { shell: true }, function (err, stdout) {
if (err) { if (err) {
callback(err, null); callback(err, null);
return; return;
} }
scanner.parseOutput(stdout, callback); scanner.parseOutput(stdout, callback);
});*/ });
} }
module.exports = { module.exports = {
/** /**
* Scan for wifi networks * Scan for wifis
* @param {boolean} useSudo? - Defaults to false | Should sudo be used to get the output? * @param callback
* @return {Promise<WifiNetwork[]|null>} WiFinetwork Array or null */
* @rejects Returns error on reject scan: function (callback) {
*/ if (!scanner) {
scan: function (useSudo = false) { initTools(function (err, s) {
return new Promise( (resolve, reject) => {
if (!scanner) {
initTools(function (err, s) {
if (err) { if (err) {
return reject(err); return callback(err);
} }
scanner = s; scanner = s;
scanNetworks((err, result) => { scanNetworks(callback);
if(err)
return reject(err);
if(!result)
result = [];
resolve(result);
}, useSudo && scanner == iwlist);
}); });
return; return;
} }
scanNetworks((err, result) => { scanNetworks(callback);
if(err)
return reject(err);
if(!result)
result = [];
resolve(result);
}, useSudo && scanner == iwlist);
} );
} }
}; };

View File

@ -26,8 +26,7 @@ function parseOutput(str, callback) {
'ssid' : lines[i].substring(0, 32).trim(), 'ssid' : lines[i].substring(0, 32).trim(),
'mac' : '', // There is no more mac on a mac 'mac' : '', // There is no more mac on a mac
'channel': parseInt(elements[1].trim(), 10), 'channel': parseInt(elements[1].trim(), 10),
'rssi' : parseInt(elements[0].trim(), 10), 'rssi' : parseInt(elements[0].trim(), 10)
'encrypted': false,
}); });
} }
} }

View File

@ -13,7 +13,6 @@ 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 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:/; const cellRegex = /Cell [0-9]{2,} - Address:/;
const encryptedRegex = /Encryption key:on/g;
/** /**
* Parsing the output of iwlist, tool having a lot of different faces :-( * Parsing the output of iwlist, tool having a lot of different faces :-(
@ -28,8 +27,7 @@ function parseOutput(str, callback) {
let blocks = str.split(cellRegex); let blocks = str.split(cellRegex);
blocks.forEach(block => { blocks.forEach(block => {
let network = {encrypted: encryptedRegex.test(block)}; let network = {};
let lines = block.split('\n'); let lines = block.split('\n');
if (macRegex.exec(lines[0])) { if (macRegex.exec(lines[0])) {
// First line is the mac address (always! (?)) // First line is the mac address (always! (?))

View File

@ -41,7 +41,7 @@ function parseOutput(str, callback) {
// Basic rates (MBit/s) : 1 2 5.5 11 // Basic rates (MBit/s) : 1 2 5.5 11
// Other rates (MBit/s) : 6 9 12 18 24 36 48 54 // Other rates (MBit/s) : 6 9 12 18 24 36 48 54
for (let i = 1, l = blocks.length; i < l; i++) { for (let i = 1, l = blocks.length; i < l; i++) {
let network = {encrypted: false}; let network = {};
let lines = blocks[i].split('\n'); let lines = blocks[i].split('\n');
let regexChannel = /[a-zA-Z0-9()\s]+:[\s]*[0-9]+$/g; let regexChannel = /[a-zA-Z0-9()\s]+:[\s]*[0-9]+$/g;
if (!lines || lines.length < 2) { if (!lines || lines.length < 2) {

View File

@ -13,18 +13,19 @@
"nmcli" "nmcli"
], ],
"author": { "author": {
"name": "Christian Kuster, Tobias Hopp", "name": "Christian Kuster, CH-8342 Wernetshausen",
"email": "tobi@gaminggeneration.de" "email": "info@kusti.ch",
"url": "http://www.kusti.ch/"
}, },
"homepage": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner/", "homepage": "https://github.com/ancasicolica/node-wifi-scanner",
"bugs": { "bugs": {
"url": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner/issues/", "url": "https://github.com/ancasicolica/node-wifi-scanner/issues",
"email": "info@ancasicolica.ch" "email": "info@ancasicolica.ch"
}, },
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner.git" "url": "https://github.com/ancasicolica/node-wifi-scanner.git"
}, },
"engines": { "engines": {
"node": ">= 4.0.0", "node": ">= 4.0.0",

67
test/airport.js Normal file
View File

@ -0,0 +1,67 @@
/**
* Airport unit test
* Created by kc on 04.04.16.
*/
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const airport = require('../lib/airport');
describe('airport', () => {
it('parses the output of file 1', function(done) {
airport.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','airport','airport01.txt'), { encoding: 'utf8' }), (err, info) => {
assert.ok(info);
assert.equal(info.length, 36);
let ap = info[0];
assert.equal(ap.mac, '');
assert.equal(ap.ssid, 'OurTest');
assert.equal(ap.rssi, -70);
assert.strictEqual(ap.channel, 112);
ap = info[19];
assert.equal(ap.mac, '00:35:1a:5b:45:b6');
assert.equal(ap.ssid, 'PDANet1');
assert.equal(ap.rssi, -78);
assert.strictEqual(ap.channel, 11);
ap = info[25];
assert.equal(ap.mac, '10:bd:18:ab:4d:8f');
assert.equal(ap.ssid, 'TEST Training');
assert.equal(ap.rssi, -71);
assert.strictEqual(ap.channel, 6);
ap = info[35];
assert.equal(ap.mac, '00:35:1a:90:56:00');
assert.equal(ap.ssid, 'TEST-Wifi');
assert.equal(ap.rssi, -67);
assert.strictEqual(ap.channel, 1);
done(err);
});
});
it('parses the output of file 2', function(done) {
airport.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','airport','airport02.txt'), { encoding: 'utf8' }), (err, info) => {
assert.ok(info);
assert.equal(info.length, 4);
let ap = info[0];
assert.equal(ap.mac, '7c:b7:33:ae:3b:06');
assert.equal(ap.ssid, 'Raupo');
assert.equal(ap.rssi, -80);
assert.strictEqual(ap.channel, 64);
ap = info[3];
assert.equal(ap.mac, '7c:b7:33:ae:3b:04');
assert.equal(ap.ssid, 'Visitor Raupo');
assert.equal(ap.rssi, -66);
assert.strictEqual(ap.channel, 9);
done(err);
});
});
});

41
types/index.d.ts vendored
View File

@ -1,41 +0,0 @@
declare module 'node-wifi-scanner' {
type Callback<T> = (error: Error | null, result: T | null) => void;
interface WifiNetwork {
ssid: string;
mac: string;
channel: number;
rssi: number;
}
interface Scanner {
cmdLine: string;
parseOutput(output: string, callback: Callback<WifiNetwork[]>): void;
}
interface Tool {
detector: string;
}
const airport: Tool;
const iwlist: Tool;
const netsh: Tool;
/**
* Initialize the scanner tools
* @param callback Callback function
*/
function initTools(callback: Callback<Scanner>): void;
/**
* Scan the networks
* @param callback Callback function
*/
function scanNetworks(callback: Callback<WifiNetwork[]>): void;
/**
* Scan for WiFi networks
* @param callback Callback function
*/
function scan(callback: Callback<WifiNetwork[]>): void;
}