Skip to content

Commit

Permalink
Add JSDoc style function documentation and general codebase cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
denizariyan committed Apr 30, 2022
1 parent 479d65e commit 73439df
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 13 deletions.
10 changes: 10 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const env = './.env';

let md5Previous = md5(fs.readFileSync(env));

/**
* Watch the .env file for changes and restart the scanner with new options if there is any change
* @param {string} env - Path to the .env file
* @param {} event - A filesystem event
* @param {} filename - Name of the file for the filesystem event
*/
fs.watch(env, (event, filename) => {
if (filename) {
const md5Current = md5(fs.readFileSync(env));
Expand All @@ -19,4 +25,8 @@ fs.watch(env, (event, filename) => {
}
});

/**
* Start the scanner when the main script is called
* @param {string} "start"
*/
scan("start");
23 changes: 21 additions & 2 deletions scripts/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ const express = require('express');
const fs = require("fs");
const os = require("os");
const app = express();
const bodyParser = require('body-parser')
const bodyParser = require('body-parser');

const port = 8080;
const quarantinePath = "/usr/VSterilizer/infected/";

/**
* Find the line for the given key and splice it to replace with the new value
* @param {string} key - Key for the given env variable
* @param {string} newValue - New value for the given key
*/
async function changeParam(key, newValue) {
const ENV_VARS = fs.readFileSync("./.env", "utf8").split(os.EOL);
const target = ENV_VARS.indexOf(ENV_VARS.find((line) => {
Expand All @@ -16,6 +21,15 @@ async function changeParam(key, newValue) {
fs.writeFileSync("./.env", ENV_VARS.join(os.EOL));
}

/**
* Handle the option changes when a change request comes to the API endpoint
* It is safe to call parameter changer with every new request without checking
* if the given new option is the same with the old one since the watcher function
* which restarts the scanner for changes checks the MD5 hash of the file to ensure
* that there is an actual change in the file
* @param {request} req - The option change request
* @param {response} res - Passed to the function to enable sending responses in the handler function itself
*/
async function optionHandler(req, res) {
if (req.body.quarantineInfected) {
await changeParam("quarantineInfected", quarantinePath);
Expand All @@ -30,9 +44,14 @@ async function optionHandler(req, res) {

app.use(bodyParser.json());

/**
* @param {string} '/options' - API endpoint
* @param {request} req
* @param {response} res
*/
app.post('/options', (req, res) => {
optionHandler(req, res);
});

app.listen(port, () => console.log(`Hello world app listening on port ${port}!`))
app.listen(port, () => console.log(`Listening on port ${port}!`))
app.on("exit", () => server.close())
58 changes: 47 additions & 11 deletions scripts/scan.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ options =
preference: 'clamdscan' // If clamdscan is found and active, it will be used by default
}

// Send every bad file one by one
/**
* Send the results of a scan to the API endpoint in realtime
* @param {array<string>} badFileList=null
*/
async function sendResults(badFileList = null) {
if (badFileList === null) {
sendStatus("Scan completed, no infected files has been detected.")
Expand All @@ -51,15 +54,24 @@ async function sendResults(badFileList = null) {
}
}

/**
* Sends status information to the API endpoint
* This includes data with information level severity such as a new USB being detected, a new scan running etc.
* @param {string} status
*/
async function sendStatus(status) {
let payload = { status: status };
let res = await axios.post('http://httpbin.org/post', payload);
let data = res.data;
console.log(data);
}

/**
* Scan the given directory path for infected files
* Call the result sending function to send the results to the frontend API
* @param {string} path
*/
async function scanDirectory(path) {
// Get instance by resolving ClamScan promise object
const clamscan = await new NodeClam().init(options);
try {
// TODO: Replace hard-coded path with path var it is here for faster testing
Expand All @@ -76,21 +88,29 @@ async function scanDirectory(path) {
}
}

/**
* Add the ability to wait in parts of the code without blocking rest of the program
* @param {integer} ms
*/
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

// Parse log file to find file of interest (foi)
async function parseLog(parser) {
/**
* Parses the scanner log file to get detailed information about infected files
* Takes a keyword parameter which has the path of a given infected file
* @param {string} keyword
*/
async function parseLog(keyword) {
let badFiles = [];
let file = fs.readFileSync(options.scanLog, "utf8");
let arr = file.split(/\r?\n/);
arr.forEach((line, idx) => {
if (line.includes("FOUND")) {
line = line.split(/[ ]+/);
let fname = line[0].split(parser);
let fname = line[0].split(keyword);
fname = fname.pop().slice(0, -1);
let badFileEntry = {
filename: fname,
Expand All @@ -102,31 +122,43 @@ async function parseLog(parser) {
return badFiles;
}

// To reload env vars have a script that the config file editor API one kill and re-start this one
/**
* Get the mounting point for a given serial number
* @param {string} serialNumber
*/
async function getMountPoint(serialNumber) {
sendStatus("Accessing the USB Device...");
await sleep(5000); // Wait for device to be mounted by kernel
let out = child_process.spawnSync('/home/deari/projects/VSterilizer/getMountPoint.sh', [serialNumber]);
let length = out.stdout.toString('utf8').split("\n")[0].length;
// Use this to check if the found addy ends with number try other one if doesnt
mount(out.stdout.toString('utf8').split("\n")[0]);
}

/**
* Mount the given device to a auto-generated dir under the
* products own mounting directory
* @param {string} source
*/
function mount(source) {
let uuid = uuidv4();
child_process.execSync(`mkdir -p /media/VSterilizer/${uuid}`);
child_process.execSync(`mount ${source} /media/VSterilizer/${uuid}`);
console.log(`/media/VSterilizer/${uuid}`);
// Remove Windows specific un-usable files which should never been generated anyways. Windows Search service bug causes this file
fs.rmSync(`/media/VSterilizer/${uuid}/System\ Volume\ Information/`, { recursive: true, force: true });
scanDirectory(`/media/VSterilizer/${uuid}/`);
}

// Send this to helper script
/**
* Enable watcher to detect newly plugged USB devices
* Calls the mounting point getter function when a new device is detected
* @param {string} 'add'
*/
USBWatch.on('add', function (device) {
getMountPoint(device.serialNumber);
});

/**
* Starting point of the scanner script
* Handles clean-up and starts the USB monitoring
*/
function start() {
fs.writeFileSync(options.scanLog, ''); // Clear the logs
console.log("Started to monitor for USB inserts!");
Expand All @@ -135,6 +167,10 @@ function start() {
//scanDirectory("/home/deari/Downloads/"); // Enable for testing
}

/**
* Helper script to end the USB monitoring
* Utilized while stopping or restarting the service
*/
function endWatch() {
USBWatch.stopMonitoring();
}
Expand Down

0 comments on commit 73439df

Please sign in to comment.