Address feedback so far in MR #1043

* Remove TCP server feature; this area is better served by the
  CyberChef-server project
* Increase required version of commander to one which provides
  `requiredOption()`
* Print the error message that is captured when failing to parse the
  command line

Also use `fs.readFileSync()` to read the recipe file.
This commit is contained in:
David Perry 2020-05-29 11:16:12 -04:00
parent 6805f90e05
commit 50a66c1910
2 changed files with 32 additions and 93 deletions

93
cli.js
View file

@ -49,26 +49,9 @@ const slurp = (fname) => { // {{{1
return slurpStream(istream); return slurpStream(istream);
}; // }}}1 }; // }}}1
/**
* Get a valid port number from the command line
*
* Used by commander
*
* @param {String} value
* @param {String} dummyPrevious
*/
const getPort = (value, dummyPrevious) => { // {{{1
const ret = parseInt(value, 10);
if (ret < 1 || ret > 65535) {
throw new Error("invalid port number");
}
return ret;
};
// }}}1
/* * * * * MAIN * * * * */ // {{{1 /* * * * * MAIN * * * * */ // {{{1
const chef = require("cyberchef"); const chef = require("./src/node/cjs.js");
const program = require("commander"); const program = require("commander");
program program
@ -78,24 +61,30 @@ program
.usage("[options] [file [file ...]]") .usage("[options] [file [file ...]]")
.requiredOption("-r, --recipe-file <file>", .requiredOption("-r, --recipe-file <file>",
"recipe JSON file") "recipe JSON file")
.option("-l, --listen [port]",
"listen on TCP port for data (random if not given)", getPort, false)
.option("-o, --output <file-or-dir>", .option("-o, --output <file-or-dir>",
"where to write result (file input only; default:stdout)"); "where to write result (file input only; default:stdout)");
try { try {
program.exitOverride().parse(process.argv); program.exitOverride().parse(process.argv);
} catch (e) { } catch (e) {
console.error(e.message);
if (e.code !== "commander.helpDisplayed") { if (e.code !== "commander.helpDisplayed") {
console.error("Run with \"--help\" for usage"); console.error("Run with \"--help\" for usage");
} }
process.exit(1); process.exit(1);
} }
// If we get no inputs and we aren't running a server, let recipe;
// make stdin our single input try {
recipe = JSON.parse(fs.readFileSync(program.recipeFile));
} catch (err) {
console.error(err.message);
process.exit(3);
}
// If we get no inputs, make stdin our single input
let inputs = program.args; let inputs = program.args;
if (inputs.length === 0 && !program.listen) { if (inputs.length === 0) {
inputs = ["-"]; inputs = ["-"];
} }
@ -103,16 +92,16 @@ if (inputs.length === 0 && !program.listen) {
let ostream; let ostream;
let path; let path;
let outputIsDir = false; let outputIsDir = false;
if (program.output === undefined && !program.listen) { if (program.output === undefined) {
ostream = process.stdout; ostream = process.stdout;
} else if (inputs.length > 0) { } else {
// See if our output is a directory // See if our output is a directory
let st; let st;
try { try {
st = fs.statSync(program.output); st = fs.statSync(program.output);
outputIsDir = st.isDirectory(); outputIsDir = st.isDirectory();
} catch (err) { } catch (err) {
// We"re fine if the output doesn"t exist yet // We"re fine if the output doesn't exist yet
if (err.code !== "ENOENT") throw err; if (err.code !== "ENOENT") throw err;
} }
if (!outputIsDir) { if (!outputIsDir) {
@ -121,16 +110,7 @@ if (program.output === undefined && !program.listen) {
} }
if (outputIsDir) path = require("path"); if (outputIsDir) path = require("path");
let recipe; // Deal with any files we want to read
slurp(program.recipeFile).then((data) => {
recipe = JSON.parse(data);
})
.catch((err) => {
console.error(`Error parsing recipe: ${err.message}`);
process.exit(2);
})
.then(() => {
// First, deal with any files we want to read
for (const i of inputs) { for (const i of inputs) {
slurp(i).then((data) => { slurp(i).then((data) => {
const output = chef.bake(data, recipe); const output = chef.bake(data, recipe);
@ -142,50 +122,9 @@ slurp(program.recipeFile).then((data) => {
} }
ostream.write(output.presentAs("string", true)); ostream.write(output.presentAs("string", true));
if (outputIsDir) ostream.end(); if (outputIsDir) ostream.end();
},
(err) => {
console.error(err.message);
process.exitCode = 2;
}) })
.catch((err) => { .catch((err) => {
console.error(err.message); console.error(err.message);
process.exitCode = 2; process.exitCode = 2;
}); });
} }
// Next, listen for TCP requests.
// This is intentionally hardcoded to localhost to discourage
// the use of this script as a production system.
if (program.listen) {
const net = require("net");
const server = net.createServer((socket) => {
slurpStream(socket).then((data) => {
const output = chef.bake(data, recipe);
socket.write(output.presentAs("string", true));
socket.end();
})
.catch((err) => {
console.error(err);
});
});
// If no port given by user, let the OS choose one
if (program.listen === true) program.listen = 0;
server.listen(program.listen, "127.0.0.1")
.on("listening", () => {
console.log("Now listening on " +
server.address().address +
":" + server.address().port);
});
// Exit gracefully
process.on("SIGINT", () => {
console.log("Exiting");
server.close();
});
}
})
.catch((err) => {
console.error(err);
process.exit(3);
});

View file

@ -101,7 +101,7 @@
"bson": "^4.0.3", "bson": "^4.0.3",
"chi-squared": "^1.1.0", "chi-squared": "^1.1.0",
"codepage": "^1.14.0", "codepage": "^1.14.0",
"commander": "^2.14.1", "commander": "^5.1.0",
"core-js": "^3.6.4", "core-js": "^3.6.4",
"crypto-api": "^0.8.5", "crypto-api": "^0.8.5",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",