diff --git a/src/core/operations/AESDecrypt.mjs b/src/core/operations/AESDecrypt.mjs index 01415ddc..7d9ac5ca 100644 --- a/src/core/operations/AESDecrypt.mjs +++ b/src/core/operations/AESDecrypt.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import forge from "node-forge/dist/forge.min.js"; +import OperationError from "../errors/OperationError"; /** * AES Decrypt operation @@ -65,6 +66,8 @@ class AESDecrypt extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if cannot decrypt input or invalid key length */ run(input, args) { const key = Utils.convertToByteArray(args[0].string, args[0].option), @@ -75,12 +78,12 @@ class AESDecrypt extends Operation { gcmTag = Utils.convertToByteString(args[5].string, args[5].option); if ([16, 24, 32].indexOf(key.length) < 0) { - return `Invalid key length: ${key.length} bytes + throw new OperationError(`Invalid key length: ${key.length} bytes The following algorithms will be used based on the size of the key: 16 bytes = AES-128 24 bytes = AES-192 - 32 bytes = AES-256`; + 32 bytes = AES-256`); } input = Utils.convertToByteString(input, inputType); @@ -96,7 +99,7 @@ The following algorithms will be used based on the size of the key: if (result) { return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); } else { - return "Unable to decrypt input with these parameters."; + throw new OperationError("Unable to decrypt input with these parameters."); } } diff --git a/src/core/operations/AESEncrypt.mjs b/src/core/operations/AESEncrypt.mjs index 62763c5f..98a4c259 100644 --- a/src/core/operations/AESEncrypt.mjs +++ b/src/core/operations/AESEncrypt.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import forge from "node-forge/dist/forge.min.js"; +import OperationError from "../errors/OperationError"; /** * AES Encrypt operation @@ -59,6 +60,8 @@ class AESEncrypt extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if invalid key length */ run(input, args) { const key = Utils.convertToByteArray(args[0].string, args[0].option), @@ -68,12 +71,12 @@ class AESEncrypt extends Operation { outputType = args[4]; if ([16, 24, 32].indexOf(key.length) < 0) { - return `Invalid key length: ${key.length} bytes + throw new OperationError(`Invalid key length: ${key.length} bytes The following algorithms will be used based on the size of the key: 16 bytes = AES-128 24 bytes = AES-192 - 32 bytes = AES-256`; + 32 bytes = AES-256`); } input = Utils.convertToByteString(input, inputType); diff --git a/src/core/operations/AffineCipherDecode.mjs b/src/core/operations/AffineCipherDecode.mjs index 184fa67c..3f65c150 100644 --- a/src/core/operations/AffineCipherDecode.mjs +++ b/src/core/operations/AffineCipherDecode.mjs @@ -42,6 +42,8 @@ class AffineCipherDecode extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if a or b values are invalid */ run(input, args) { const alphabet = "abcdefghijklmnopqrstuvwxyz", diff --git a/src/core/operations/BifidCipherDecode.mjs b/src/core/operations/BifidCipherDecode.mjs index dbfc7628..f5e2ad47 100644 --- a/src/core/operations/BifidCipherDecode.mjs +++ b/src/core/operations/BifidCipherDecode.mjs @@ -37,6 +37,8 @@ class BifidCipherDecode extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if invalid key */ run(input, args) { const keywordStr = args[0].toUpperCase().replace("J", "I"), diff --git a/src/core/operations/BifidCipherEncode.mjs b/src/core/operations/BifidCipherEncode.mjs index 11050349..41c29db0 100644 --- a/src/core/operations/BifidCipherEncode.mjs +++ b/src/core/operations/BifidCipherEncode.mjs @@ -37,6 +37,8 @@ class BifidCipherEncode extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if key is invalid */ run(input, args) { const keywordStr = args[0].toUpperCase().replace("J", "I"), diff --git a/src/core/operations/CartesianProduct.mjs b/src/core/operations/CartesianProduct.mjs index 5125511b..0d5346fb 100644 --- a/src/core/operations/CartesianProduct.mjs +++ b/src/core/operations/CartesianProduct.mjs @@ -41,7 +41,7 @@ class CartesianProduct extends Operation { * Validate input length * * @param {Object[]} sets - * @throws {Error} if fewer than 2 sets + * @throws {OperationError} if fewer than 2 sets */ validateSampleNumbers(sets) { if (!sets || sets.length < 2) { diff --git a/src/core/operations/DisassembleX86.mjs b/src/core/operations/DisassembleX86.mjs index 00fe6083..602f281c 100644 --- a/src/core/operations/DisassembleX86.mjs +++ b/src/core/operations/DisassembleX86.mjs @@ -6,6 +6,8 @@ import Operation from "../Operation"; import * as disassemble from "../vendor/DisassembleX86-64"; +import OperationError from "../errors/OperationError"; + /** * Disassemble x86 operation */ @@ -68,6 +70,8 @@ class DisassembleX86 extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if invalid mode value */ run(input, args) { const mode = args[0], @@ -88,7 +92,7 @@ class DisassembleX86 extends Operation { disassemble.setBitMode(0); break; default: - throw "Invalid mode value"; + throw new OperationError("Invalid mode value"); } switch (compatibility) { diff --git a/src/core/operations/DropBytes.mjs b/src/core/operations/DropBytes.mjs index f62ac1bf..e697f4e9 100644 --- a/src/core/operations/DropBytes.mjs +++ b/src/core/operations/DropBytes.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation"; +import OperationError from "../errors/OperationError"; /** * Drop bytes operation @@ -45,6 +46,8 @@ class DropBytes extends Operation { * @param {ArrayBuffer} input * @param {Object[]} args * @returns {ArrayBuffer} + * + * @throws {OperationError} if invalid input */ run(input, args) { const start = args[0], @@ -52,7 +55,7 @@ class DropBytes extends Operation { applyToEachLine = args[2]; if (start < 0 || length < 0) - throw "Error: Invalid value"; + throw new OperationError("Error: Invalid value"); if (!applyToEachLine) { const left = input.slice(0, start), diff --git a/src/core/operations/Filter.mjs b/src/core/operations/Filter.mjs index 1782b38c..aaf53f0f 100644 --- a/src/core/operations/Filter.mjs +++ b/src/core/operations/Filter.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import {INPUT_DELIM_OPTIONS} from "../lib/Delim"; +import OperationError from "../errors/OperationError"; /** * Filter operation @@ -56,7 +57,7 @@ class Filter extends Operation { try { regex = new RegExp(args[1]); } catch (err) { - return "Invalid regex. Details: " + err.message; + throw new OperationError(`Invalid regex. Details: ${err.message}`); } const regexFilter = function(value) { diff --git a/src/core/operations/FromCharcode.mjs b/src/core/operations/FromCharcode.mjs index ed2197bc..2dee72f2 100644 --- a/src/core/operations/FromCharcode.mjs +++ b/src/core/operations/FromCharcode.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import {DELIM_OPTIONS} from "../lib/Delim"; +import OperationError from "../errors/OperationError"; /** * From Charcode operation @@ -42,6 +43,8 @@ class FromCharcode extends Operation { * @param {string} input * @param {Object[]} args * @returns {byteArray} + * + * @throws {OperationError} if base out of range */ run(input, args) { const delim = Utils.charRep(args[0] || "Space"), @@ -50,7 +53,7 @@ class FromCharcode extends Operation { i = 0; if (base < 2 || base > 36) { - throw "Error: Base argument must be between 2 and 36"; + throw new OperationError("Error: Base argument must be between 2 and 36"); } if (input.length === 0) { diff --git a/src/core/operations/FromUNIXTimestamp.mjs b/src/core/operations/FromUNIXTimestamp.mjs index 90c7f120..258b6808 100644 --- a/src/core/operations/FromUNIXTimestamp.mjs +++ b/src/core/operations/FromUNIXTimestamp.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import moment from "moment-timezone"; import {UNITS} from "../lib/DateTime"; +import OperationError from "../errors/OperationError"; /** * From UNIX Timestamp operation @@ -37,6 +38,8 @@ class FromUNIXTimestamp extends Operation { * @param {number} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if invalid unit */ run(input, args) { const units = args[0]; @@ -57,7 +60,7 @@ class FromUNIXTimestamp extends Operation { d = moment(input / 1000000); return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC"; } else { - throw "Unrecognised unit"; + throw new OperationError("Unrecognised unit"); } } diff --git a/src/core/operations/HammingDistance.mjs b/src/core/operations/HammingDistance.mjs index 9e2a4550..173ca3e7 100644 --- a/src/core/operations/HammingDistance.mjs +++ b/src/core/operations/HammingDistance.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import {fromHex} from "../lib/Hex"; +import OperationError from "../errors/OperationError"; /** * Hamming Distance operation @@ -55,11 +56,11 @@ class HammingDistance extends Operation { samples = input.split(delim); if (samples.length !== 2) { - return "Error: You can only calculae the edit distance between 2 strings. Please ensure exactly two inputs are provided, separated by the specified delimiter."; + throw new OperationError("Error: You can only calculae the edit distance between 2 strings. Please ensure exactly two inputs are provided, separated by the specified delimiter."); } if (samples[0].length !== samples[1].length) { - return "Error: Both inputs must be of the same length."; + throw new OperationError("Error: Both inputs must be of the same length."); } if (inputType === "Hex") { diff --git a/src/core/operations/OffsetChecker.mjs b/src/core/operations/OffsetChecker.mjs index c49fdd1a..07b15d2f 100644 --- a/src/core/operations/OffsetChecker.mjs +++ b/src/core/operations/OffsetChecker.mjs @@ -6,6 +6,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; +import OperationError from "../errors/OperationError"; /** * Offset checker operation @@ -48,7 +49,7 @@ class OffsetChecker extends Operation { chr; if (!samples || samples.length < 2) { - return "Not enough samples, perhaps you need to modify the sample delimiter or add more data?"; + throw new OperationError("Not enough samples, perhaps you need to modify the sample delimiter or add more data?"); } // Initialise output strings diff --git a/src/core/operations/PGPDecrypt.mjs b/src/core/operations/PGPDecrypt.mjs index ba94fa9a..4402a457 100644 --- a/src/core/operations/PGPDecrypt.mjs +++ b/src/core/operations/PGPDecrypt.mjs @@ -7,9 +7,11 @@ import Operation from "../Operation"; import kbpgp from "kbpgp"; import { ASP, importPrivateKey } from "../lib/PGP"; +import OperationError from "../errors/OperationError"; import promisifyDefault from "es6-promisify"; const promisify = promisifyDefault.promisify; + /** * PGP Decrypt operation */ @@ -44,6 +46,8 @@ class PGPDecrypt extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if invalid private key */ async run(input, args) { const encryptedMessage = input, @@ -52,7 +56,7 @@ class PGPDecrypt extends Operation { keyring = new kbpgp.keyring.KeyRing(); let plaintextMessage; - if (!privateKey) return "Enter the private key of the recipient."; + if (!privateKey) throw new OperationError("Enter the private key of the recipient."); const key = await importPrivateKey(privateKey, passphrase); keyring.add_key_manager(key); @@ -64,7 +68,7 @@ class PGPDecrypt extends Operation { asp: ASP }); } catch (err) { - throw `Couldn't decrypt message with provided private key: ${err}`; + throw new OperationError(`Couldn't decrypt message with provided private key: ${err}`); } return plaintextMessage.toString(); diff --git a/src/core/operations/PGPDecryptAndVerify.mjs b/src/core/operations/PGPDecryptAndVerify.mjs index 63a16019..b7874f83 100644 --- a/src/core/operations/PGPDecryptAndVerify.mjs +++ b/src/core/operations/PGPDecryptAndVerify.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import kbpgp from "kbpgp"; import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP"; +import OperationError from "../errors/OperationError"; import promisifyDefault from "es6-promisify"; const promisify = promisifyDefault.promisify; @@ -58,8 +59,8 @@ class PGPDecryptAndVerify extends Operation { keyring = new kbpgp.keyring.KeyRing(); let unboxedLiterals; - if (!publicKey) return "Enter the public key of the signer."; - if (!privateKey) return "Enter the private key of the recipient."; + if (!publicKey) throw new OperationError("Enter the public key of the signer."); + if (!privateKey) throw new OperationError("Enter the private key of the recipient."); const privKey = await importPrivateKey(privateKey, passphrase); const pubKey = await importPublicKey(publicKey); keyring.add_key_manager(privKey); @@ -97,13 +98,13 @@ class PGPDecryptAndVerify extends Operation { text += unboxedLiterals.toString(); return text.trim(); } else { - return "Could not identify a key manager."; + throw new OperationError("Could not identify a key manager."); } } else { - return "The data does not appear to be signed."; + throw new OperationError("The data does not appear to be signed."); } } catch (err) { - return `Couldn't verify message: ${err}`; + throw new OperationError(`Couldn't verify message: ${err}`); } } diff --git a/src/core/operations/PGPEncrypt.mjs b/src/core/operations/PGPEncrypt.mjs index b2aa50dc..ef0a4d28 100644 --- a/src/core/operations/PGPEncrypt.mjs +++ b/src/core/operations/PGPEncrypt.mjs @@ -7,8 +7,10 @@ import Operation from "../Operation"; import kbpgp from "kbpgp"; import { ASP } from "../lib/PGP"; +import OperationError from "../errors/OperationError"; import promisifyDefault from "es6-promisify"; const promisify = promisifyDefault.promisify; + /** * PGP Encrypt operation */ @@ -38,6 +40,8 @@ class PGPEncrypt extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if failed private key import or failed encryption */ async run(input, args) { const plaintextMessage = input, @@ -45,14 +49,14 @@ class PGPEncrypt extends Operation { let key, encryptedMessage; - if (!plainPubKey) return "Enter the public key of the recipient."; + if (!plainPubKey) throw new OperationError("Enter the public key of the recipient."); try { key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({ armored: plainPubKey, }); } catch (err) { - throw `Could not import public key: ${err}`; + throw new OperationError(`Could not import public key: ${err}`); } try { @@ -62,7 +66,7 @@ class PGPEncrypt extends Operation { "asp": ASP }); } catch (err) { - throw `Couldn't encrypt message with provided public key: ${err}`; + throw new OperationError(`Couldn't encrypt message with provided public key: ${err}`); } return encryptedMessage.toString(); diff --git a/src/core/operations/PGPEncryptAndSign.mjs b/src/core/operations/PGPEncryptAndSign.mjs index 72631987..5b03c937 100644 --- a/src/core/operations/PGPEncryptAndSign.mjs +++ b/src/core/operations/PGPEncryptAndSign.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import kbpgp from "kbpgp"; import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP"; +import OperationError from "../errors/OperationError"; import promisifyDefault from "es6-promisify"; const promisify = promisifyDefault.promisify; @@ -49,6 +50,8 @@ class PGPEncryptAndSign extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if failure to sign message */ async run(input, args) { const message = input, @@ -57,8 +60,8 @@ class PGPEncryptAndSign extends Operation { publicKey = args[2]; let signedMessage; - if (!privateKey) return "Enter the private key of the signer."; - if (!publicKey) return "Enter the public key of the recipient."; + if (!privateKey) throw new OperationError("Enter the private key of the signer."); + if (!publicKey) throw new OperationError("Enter the public key of the recipient."); const privKey = await importPrivateKey(privateKey, passphrase); const pubKey = await importPublicKey(publicKey); @@ -70,7 +73,7 @@ class PGPEncryptAndSign extends Operation { "asp": ASP }); } catch (err) { - throw `Couldn't sign message: ${err}`; + throw new OperationError(`Couldn't sign message: ${err}`); } return signedMessage; diff --git a/src/core/operations/ParseDateTime.mjs b/src/core/operations/ParseDateTime.mjs index c48f848b..bb88c95d 100644 --- a/src/core/operations/ParseDateTime.mjs +++ b/src/core/operations/ParseDateTime.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import moment from "moment-timezone"; import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime"; +import OperationError from "../errors/OperationError"; /** * Parse DateTime operation @@ -59,7 +60,7 @@ class ParseDateTime extends Operation { date = moment.tz(input, inputFormat, inputTimezone); if (!date || date.format() === "Invalid date") throw Error; } catch (err) { - return "Invalid format.\n\n" + FORMAT_EXAMPLES; + throw new OperationError(`Invalid format.\n\n${FORMAT_EXAMPLES}`); } output += "Date: " + date.format("dddd Do MMMM YYYY") + diff --git a/src/core/operations/ParseUNIXFilePermissions.mjs b/src/core/operations/ParseUNIXFilePermissions.mjs index 829dda76..a86ed9ce 100644 --- a/src/core/operations/ParseUNIXFilePermissions.mjs +++ b/src/core/operations/ParseUNIXFilePermissions.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation"; +import OperationError from "../errors/OperationError"; /** * Parse UNIX file permissions operation @@ -169,7 +170,7 @@ class ParseUNIXFilePermissions extends Operation { } } } else { - return "Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format."; + throw new OperationError("Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format."); } output += "Textual representation: " + permsToStr(perms); diff --git a/src/core/operations/RawInflate.mjs b/src/core/operations/RawInflate.mjs index 93a7b91f..f1a5341b 100644 --- a/src/core/operations/RawInflate.mjs +++ b/src/core/operations/RawInflate.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import {INFLATE_BUFFER_TYPE} from "../lib/Zlib"; import rawinflate from "zlibjs/bin/rawinflate.min"; +import OperationError from "../errors/OperationError"; const Zlib = rawinflate.Zlib; @@ -90,7 +91,7 @@ class RawInflate extends Operation { } if (!valid) { - throw "Error: Unable to inflate data"; + throw new OperationError("Error: Unable to inflate data"); } } // This seems to be the easiest way... diff --git a/src/core/operations/ShowBase64Offsets.mjs b/src/core/operations/ShowBase64Offsets.mjs index 2f44296f..43bcbbba 100644 --- a/src/core/operations/ShowBase64Offsets.mjs +++ b/src/core/operations/ShowBase64Offsets.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import {fromBase64, toBase64} from "../lib/Base64"; +import OperationError from "../errors/OperationError"; /** * Show Base64 offsets operation @@ -58,7 +59,7 @@ class ShowBase64Offsets extends Operation { script = ""; if (input.length < 1) { - return "Please enter a string."; + throw new OperationError("Please enter a string."); } // Highlight offset 0 diff --git a/src/core/operations/TakeBytes.mjs b/src/core/operations/TakeBytes.mjs index 1fec3997..5806ee87 100644 --- a/src/core/operations/TakeBytes.mjs +++ b/src/core/operations/TakeBytes.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation"; +import OperationError from "../errors/OperationError"; /** * Take bytes operation @@ -45,6 +46,8 @@ class TakeBytes extends Operation { * @param {ArrayBuffer} input * @param {Object[]} args * @returns {ArrayBuffer} + * + * @throws {OperationError} if invalid value */ run(input, args) { const start = args[0], @@ -52,7 +55,7 @@ class TakeBytes extends Operation { applyToEachLine = args[2]; if (start < 0 || length < 0) - throw "Error: Invalid value"; + throw new OperationError("Error: Invalid value"); if (!applyToEachLine) return input.slice(start, start+length); diff --git a/src/core/operations/ToCharcode.mjs b/src/core/operations/ToCharcode.mjs index c6943e90..db043d79 100644 --- a/src/core/operations/ToCharcode.mjs +++ b/src/core/operations/ToCharcode.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; import {DELIM_OPTIONS} from "../lib/Delim"; +import OperationError from "../errors/OperationError"; /** * To Charcode operation @@ -42,6 +43,8 @@ class ToCharcode extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if base argument out of range */ run(input, args) { const delim = Utils.charRep(args[0] || "Space"), @@ -51,7 +54,7 @@ class ToCharcode extends Operation { ordinal; if (base < 2 || base > 36) { - throw "Error: Base argument must be between 2 and 36"; + throw new OperationError("Error: Base argument must be between 2 and 36"); } const charcode = Utils.strToCharcode(input); diff --git a/src/core/operations/ToUNIXTimestamp.mjs b/src/core/operations/ToUNIXTimestamp.mjs index 1907b5a6..6983d617 100644 --- a/src/core/operations/ToUNIXTimestamp.mjs +++ b/src/core/operations/ToUNIXTimestamp.mjs @@ -7,6 +7,7 @@ import Operation from "../Operation"; import moment from "moment-timezone"; import {UNITS} from "../lib/DateTime"; +import OperationError from "../errors/OperationError"; /** * To UNIX Timestamp operation @@ -47,6 +48,8 @@ class ToUNIXTimestamp extends Operation { * @param {string} input * @param {Object[]} args * @returns {string} + * + * @throws {OperationError} if unit unrecognised */ run(input, args) { const [units, treatAsUTC, showDateTime] = args, @@ -63,7 +66,7 @@ class ToUNIXTimestamp extends Operation { } else if (units === "Nanoseconds (ns)") { result = d.valueOf() * 1000000; } else { - throw "Unrecognised unit"; + throw new OperationError("Unrecognised unit"); } return showDateTime ? `${result} (${d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss")} UTC)` : result.toString(); diff --git a/src/core/operations/TranslateDateTimeFormat.mjs b/src/core/operations/TranslateDateTimeFormat.mjs index b3895978..bd59ea6f 100644 --- a/src/core/operations/TranslateDateTimeFormat.mjs +++ b/src/core/operations/TranslateDateTimeFormat.mjs @@ -67,7 +67,7 @@ class TranslateDateTimeFormat extends Operation { date = moment.tz(input, inputFormat, inputTimezone); if (!date || date.format() === "Invalid date") throw Error; } catch (err) { - return "Invalid format.\n\n" + FORMAT_EXAMPLES; + throw new OperationError(`Invalid format.\n\n${FORMAT_EXAMPLES}`); } return date.tz(outputTimezone).format(outputFormat);