diff --git a/src/core/lib/Delim.mjs b/src/core/lib/Delim.mjs new file mode 100644 index 00000000..ab84f276 --- /dev/null +++ b/src/core/lib/Delim.mjs @@ -0,0 +1,17 @@ +/** + * Various delimiters + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +/** + * Generic sequence delimiters. + */ +export const DELIM_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF"]; + +/** + * Binary sequence delimiters. + */ +export const BIN_DELIM_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"]; diff --git a/src/core/operations/FromBinary.mjs b/src/core/operations/FromBinary.mjs new file mode 100644 index 00000000..ee585bc1 --- /dev/null +++ b/src/core/operations/FromBinary.mjs @@ -0,0 +1,87 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {BIN_DELIM_OPTIONS} from "../lib/Delim"; + +/** + * From Binary operation + */ +class FromBinary extends Operation { + + /** + * FromBinary constructor + */ + constructor() { + super(); + + this.name = "From Binary"; + this.module = "Default"; + this.description = "Converts a binary string back into its raw form.

e.g. 01001000 01101001 becomes Hi"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": BIN_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delimRegex = Utils.regexRep(args[0] || "Space"); + input = input.replace(delimRegex, ""); + + const output = []; + const byteLen = 8; + for (let i = 0; i < input.length; i += byteLen) { + output.push(parseInt(input.substr(i, byteLen), 2)); + } + return output; + } + + /** + * Highlight From Binary + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const delim = Utils.charRep(args[0] || "Space"); + pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length)); + pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length)); + return pos; + } + + /** + * Highlight From Binary in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const delim = Utils.charRep(args[0] || "Space"); + pos[0].start = pos[0].start * (8 + delim.length); + pos[0].end = pos[0].end * (8 + delim.length) - delim.length; + return pos; + } + +} + +export default FromBinary; diff --git a/src/core/operations/FromCharcode.mjs b/src/core/operations/FromCharcode.mjs new file mode 100644 index 00000000..ed2197bc --- /dev/null +++ b/src/core/operations/FromCharcode.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + +/** + * From Charcode operation + */ +class FromCharcode extends Operation { + + /** + * FromCharcode constructor + */ + constructor() { + super(); + + this.name = "From Charcode"; + this.module = "Default"; + this.description = "Converts unicode character codes back into text.

e.g. 0393 03b5 03b9 03ac 20 03c3 03bf 03c5 becomes Γειά σου"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": DELIM_OPTIONS + }, + { + "name": "Base", + "type": "number", + "value": 16 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"), + base = args[1]; + let bites = input.split(delim), + i = 0; + + if (base < 2 || base > 36) { + throw "Error: Base argument must be between 2 and 36"; + } + + if (input.length === 0) { + return []; + } + + if (base !== 16 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); + + // Split into groups of 2 if the whole string is concatenated and + // too long to be a single character + if (bites.length === 1 && input.length > 17) { + bites = []; + for (i = 0; i < input.length; i += 2) { + bites.push(input.slice(i, i+2)); + } + } + + let latin1 = ""; + for (i = 0; i < bites.length; i++) { + latin1 += Utils.chr(parseInt(bites[i], base)); + } + return Utils.strToByteArray(latin1); + } + +} + +export default FromCharcode; diff --git a/src/core/operations/FromDecimal.mjs b/src/core/operations/FromDecimal.mjs new file mode 100644 index 00000000..4577a65d --- /dev/null +++ b/src/core/operations/FromDecimal.mjs @@ -0,0 +1,56 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + +/** + * From Decimal operation + */ +class FromDecimal extends Operation { + + /** + * FromDecimal constructor + */ + constructor() { + super(); + + this.name = "From Decimal"; + this.module = "Default"; + this.description = "Converts the data from an ordinal integer array back into its raw form.

e.g. 72 101 108 108 111 becomes Hello"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = Utils.charRep(args[0]), + output = []; + let byteStr = input.split(delim); + if (byteStr[byteStr.length-1] === "") + byteStr = byteStr.slice(0, byteStr.length-1); + + for (let i = 0; i < byteStr.length; i++) { + output[i] = parseInt(byteStr[i], 10); + } + return output; + } + +} + +export default FromDecimal; diff --git a/src/core/operations/FromHexContent.mjs b/src/core/operations/FromHexContent.mjs new file mode 100644 index 00000000..9de085db --- /dev/null +++ b/src/core/operations/FromHexContent.mjs @@ -0,0 +1,66 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {fromHex} from "../lib/Hex"; + +/** + * From Hex Content operation + */ +class FromHexContent extends Operation { + + /** + * FromHexContent constructor + */ + constructor() { + super(); + + this.name = "From Hex Content"; + this.module = "Default"; + this.description = "Translates hexadecimal bytes in text back to raw bytes.

e.g. foo|3d|bar becomes foo=bar."; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const regex = /\|([a-f\d ]{2,})\|/gi, + output = []; + let m, i = 0; + while ((m = regex.exec(input))) { + // Add up to match + for (; i < m.index;) + output.push(Utils.ord(input[i++])); + + // Add match + const bytes = fromHex(m[1]); + if (bytes) { + for (let a = 0; a < bytes.length;) + output.push(bytes[a++]); + } else { + // Not valid hex, print as normal + for (; i < regex.lastIndex;) + output.push(Utils.ord(input[i++])); + } + + i = regex.lastIndex; + } + // Add all after final match + for (; i < input.length;) + output.push(Utils.ord(input[i++])); + + return output; + } + +} + +export default FromHexContent; diff --git a/src/core/operations/FromOctal.mjs b/src/core/operations/FromOctal.mjs new file mode 100644 index 00000000..131e97c5 --- /dev/null +++ b/src/core/operations/FromOctal.mjs @@ -0,0 +1,49 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + +/** + * From Octal operation + */ +class FromOctal extends Operation { + + /** + * FromOctal constructor + */ + constructor() { + super(); + + this.name = "From Octal"; + this.module = "Default"; + this.description = "Converts an octal byte string back into its raw value.

e.g. 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205 becomes the UTF-8 encoded string Γειά σου"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"); + if (input.length === 0) return []; + return input.split(delim).map(val => parseInt(val, 8)); + } + +} + +export default FromOctal; diff --git a/src/core/operations/ToBinary.mjs b/src/core/operations/ToBinary.mjs new file mode 100644 index 00000000..f10f66a7 --- /dev/null +++ b/src/core/operations/ToBinary.mjs @@ -0,0 +1,91 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {BIN_DELIM_OPTIONS} from "../lib/Delim"; + +/** + * To Binary operation + */ +class ToBinary extends Operation { + + /** + * ToBinary constructor + */ + constructor() { + super(); + + this.name = "To Binary"; + this.module = "Default"; + this.description = "Displays the input data as a binary string.

e.g. Hi becomes 01001000 01101001"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": BIN_DELIM_OPTIONS + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"), + padding = 8; + let output = ""; + + for (let i = 0; i < input.length; i++) { + output += input[i].toString(2).padStart(padding, "0") + delim; + } + + if (delim.length) { + return output.slice(0, -delim.length); + } else { + return output; + } + } + + /** + * Highlight To Binary + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const delim = Utils.charRep(args[0] || "Space"); + pos[0].start = pos[0].start * (8 + delim.length); + pos[0].end = pos[0].end * (8 + delim.length) - delim.length; + return pos; + } + + /** + * Highlight To Binary in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const delim = Utils.charRep(args[0] || "Space"); + pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length)); + pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length)); + return pos; + } + +} + +export default ToBinary; diff --git a/src/core/operations/ToCharcode.mjs b/src/core/operations/ToCharcode.mjs new file mode 100644 index 00000000..c6943e90 --- /dev/null +++ b/src/core/operations/ToCharcode.mjs @@ -0,0 +1,82 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + +/** + * To Charcode operation + */ +class ToCharcode extends Operation { + + /** + * ToCharcode constructor + */ + constructor() { + super(); + + this.name = "To Charcode"; + this.module = "Default"; + this.description = "Converts text to its unicode character code equivalent.

e.g. Γειά σου becomes 0393 03b5 03b9 03ac 20 03c3 03bf 03c5"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": DELIM_OPTIONS + }, + { + "name": "Base", + "type": "number", + "value": 16 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"), + base = args[1]; + let output = "", + padding = 2, + ordinal; + + if (base < 2 || base > 36) { + throw "Error: Base argument must be between 2 and 36"; + } + + const charcode = Utils.strToCharcode(input); + for (let i = 0; i < charcode.length; i++) { + ordinal = charcode[i]; + + if (base === 16) { + if (ordinal < 256) padding = 2; + else if (ordinal < 65536) padding = 4; + else if (ordinal < 16777216) padding = 6; + else if (ordinal < 4294967296) padding = 8; + else padding = 2; + + if (padding > 2 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); + + output += Utils.hex(ordinal, padding) + delim; + } else { + if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); + output += ordinal.toString(base) + delim; + } + } + + return output.slice(0, -delim.length); + } + +} + +export default ToCharcode; diff --git a/src/core/operations/ToDecimal.mjs b/src/core/operations/ToDecimal.mjs new file mode 100644 index 00000000..cad8dc18 --- /dev/null +++ b/src/core/operations/ToDecimal.mjs @@ -0,0 +1,49 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + + +/** + * To Decimal operation + */ +class ToDecimal extends Operation { + + /** + * ToDecimal constructor + */ + constructor() { + super(); + + this.name = "To Decimal"; + this.module = "Default"; + this.description = "Converts the input data to an ordinal integer array.

e.g. Hello becomes 72 101 108 108 111"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]); + return input.join(delim); + } + +} + +export default ToDecimal; diff --git a/src/core/operations/ToHexContent.mjs b/src/core/operations/ToHexContent.mjs new file mode 100644 index 00000000..af9ae22c --- /dev/null +++ b/src/core/operations/ToHexContent.mjs @@ -0,0 +1,81 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {toHex} from "../lib/Hex"; + +/** + * To Hex Content operation + */ +class ToHexContent extends Operation { + + /** + * ToHexContent constructor + */ + constructor() { + super(); + + this.name = "To Hex Content"; + this.module = "Default"; + this.description = "Converts special characters in a string to hexadecimal.

e.g. foo=bar becomes foo|3d|bar."; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + "name": "Convert", + "type": "option", + "value": ["Only special chars", "Only special chars including spaces", "All chars"] + }, + { + "name": "Print spaces between bytes", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const convert = args[0]; + const spaces = args[1]; + if (convert === "All chars") { + let result = "|" + toHex(input) + "|"; + if (!spaces) result = result.replace(/ /g, ""); + return result; + } + + let output = "", + inHex = false, + b; + const convertSpaces = convert === "Only special chars including spaces"; + for (let i = 0; i < input.length; i++) { + b = input[i]; + if ((b === 32 && convertSpaces) || (b < 48 && b !== 32) || (b > 57 && b < 65) || (b > 90 && b < 97) || b > 122) { + if (!inHex) { + output += "|"; + inHex = true; + } else if (spaces) output += " "; + output += toHex([b]); + } else { + if (inHex) { + output += "|"; + inHex = false; + } + output += Utils.chr(input[i]); + } + } + if (inHex) output += "|"; + return output; + } + +} + +export default ToHexContent; diff --git a/src/core/operations/ToOctal.mjs b/src/core/operations/ToOctal.mjs new file mode 100644 index 00000000..7cfb4736 --- /dev/null +++ b/src/core/operations/ToOctal.mjs @@ -0,0 +1,49 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + + +/** + * To Octal operation + */ +class ToOctal extends Operation { + + /** + * ToOctal constructor + */ + constructor() { + super(); + + this.name = "To Octal"; + this.module = "Default"; + this.description = "Converts the input string to octal bytes separated by the specified delimiter.

e.g. The UTF-8 encoded string Γειά σου becomes 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"); + return input.map(val => val.toString(8)).join(delim); + } + +} + +export default ToOctal;