ESM: Removed legacy files
This commit is contained in:
parent
be0fc7591d
commit
60340fc8ae
@ -1,2 +1 @@
|
||||
src/core/vendor/**
|
||||
src/core/operations/legacy/**
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,259 +0,0 @@
|
||||
/**
|
||||
* @author d98762625 [d98762625@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Utils from "../Utils.js";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
|
||||
/**
|
||||
* Math operations on numbers.
|
||||
*
|
||||
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Arithmetic = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIM_OPTIONS: ["Line feed", "Space", "Comma", "Semi-colon", "Colon", "CRLF"],
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and calculates the sum of numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runSum: function(input, args) {
|
||||
const val = Arithmetic._sum(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and subtracts all the numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runSub: function(input, args) {
|
||||
let val = Arithmetic._sub(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and multiplies the numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMulti: function(input, args) {
|
||||
let val = Arithmetic._multi(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and divides the numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runDiv: function(input, args) {
|
||||
let val = Arithmetic._div(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and computes the mean (average).
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMean: function(input, args) {
|
||||
let val = Arithmetic._mean(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and finds the median.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMedian: function(input, args) {
|
||||
let val = Arithmetic._median(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* splits a string based on a delimiter and computes the standard deviation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runStdDev: function(input, args) {
|
||||
let val = Arithmetic._stdDev(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts a string array to a number array.
|
||||
*
|
||||
* @private
|
||||
* @param {string[]} input
|
||||
* @param {string} delim
|
||||
* @returns {BigNumber[]}
|
||||
*/
|
||||
_createNumArray: function(input, delim) {
|
||||
delim = Utils.charRep(delim || "Space");
|
||||
let splitNumbers = input.split(delim),
|
||||
numbers = [],
|
||||
num;
|
||||
|
||||
for (let i = 0; i < splitNumbers.length; i++) {
|
||||
try {
|
||||
num = BigNumber(splitNumbers[i].trim());
|
||||
if (!num.isNaN()) {
|
||||
numbers.push(num);
|
||||
}
|
||||
} catch (err) {
|
||||
// This line is not a valid number
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_sum: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.plus(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Subtracts an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_sub: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.minus(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Multiplies an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_multi: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.times(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Divides an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_div: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.div(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Computes mean of a number array and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_mean: function(data) {
|
||||
if (data.length > 0) {
|
||||
return Arithmetic._sum(data).div(data.length);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Computes median of a number array and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_median: function (data) {
|
||||
if ((data.length % 2) === 0 && data.length > 0) {
|
||||
let first, second;
|
||||
data.sort(function(a, b){
|
||||
return a.minus(b);
|
||||
});
|
||||
first = data[Math.floor(data.length / 2)];
|
||||
second = data[Math.floor(data.length / 2) - 1];
|
||||
return Arithmetic._mean([first, second]);
|
||||
} else {
|
||||
return data[Math.floor(data.length / 2)];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Computes standard deviation of a number array and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_stdDev: function (data) {
|
||||
if (data.length > 0) {
|
||||
let avg = Arithmetic._mean(data);
|
||||
let devSum = new BigNumber(0);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
devSum = devSum.plus(data[i].minus(avg).pow(2));
|
||||
}
|
||||
return devSum.div(data.length).sqrt();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default Arithmetic;
|
@ -1,215 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
|
||||
/**
|
||||
* Binary-Coded Decimal operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const BCD = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENCODING_SCHEME: [
|
||||
"8 4 2 1",
|
||||
"7 4 2 1",
|
||||
"4 2 2 1",
|
||||
"2 4 2 1",
|
||||
"8 4 -2 -1",
|
||||
"Excess-3",
|
||||
"IBM 8 4 2 1",
|
||||
],
|
||||
|
||||
/**
|
||||
* Lookup table for the binary value of each digit representation.
|
||||
*
|
||||
* I wrote a very nice algorithm to generate 8 4 2 1 encoding programatically,
|
||||
* but unfortunately it's much easier (if less elegant) to use lookup tables
|
||||
* when supporting multiple encoding schemes.
|
||||
*
|
||||
* "Practicality beats purity" - PEP 20
|
||||
*
|
||||
* In some schemes it is possible to represent the same value in multiple ways.
|
||||
* For instance, in 4 2 2 1 encoding, 0100 and 0010 both represent 2. Support
|
||||
* has not yet been added for this.
|
||||
*
|
||||
* @constant
|
||||
*/
|
||||
ENCODING_LOOKUP: {
|
||||
"8 4 2 1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
"7 4 2 1": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10],
|
||||
"4 2 2 1": [0, 1, 4, 5, 8, 9, 12, 13, 14, 15],
|
||||
"2 4 2 1": [0, 1, 2, 3, 4, 11, 12, 13, 14, 15],
|
||||
"8 4 -2 -1": [0, 7, 6, 5, 4, 11, 10, 9, 8, 15],
|
||||
"Excess-3": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||
"IBM 8 4 2 1": [10, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
},
|
||||
|
||||
/**
|
||||
* @default
|
||||
* @constant
|
||||
*/
|
||||
FORMAT: ["Nibbles", "Bytes", "Raw"],
|
||||
|
||||
|
||||
/**
|
||||
* To BCD operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToBCD: function(input, args) {
|
||||
if (input.isNaN())
|
||||
return "Invalid input";
|
||||
if (!input.integerValue(BigNumber.ROUND_DOWN).isEqualTo(input))
|
||||
return "Fractional values are not supported by BCD";
|
||||
|
||||
const encoding = BCD.ENCODING_LOOKUP[args[0]],
|
||||
packed = args[1],
|
||||
signed = args[2],
|
||||
outputFormat = args[3];
|
||||
|
||||
// Split input number up into separate digits
|
||||
const digits = input.toFixed().split("");
|
||||
|
||||
if (digits[0] === "-" || digits[0] === "+") {
|
||||
digits.shift();
|
||||
}
|
||||
|
||||
let nibbles = [];
|
||||
|
||||
digits.forEach(d => {
|
||||
const n = parseInt(d, 10);
|
||||
nibbles.push(encoding[n]);
|
||||
});
|
||||
|
||||
if (signed) {
|
||||
if (packed && digits.length % 2 === 0) {
|
||||
// If there are an even number of digits, we add a leading 0 so
|
||||
// that the sign nibble doesn't sit in its own byte, leading to
|
||||
// ambiguity around whether the number ends with a 0 or not.
|
||||
nibbles.unshift(encoding[0]);
|
||||
}
|
||||
|
||||
nibbles.push(input > 0 ? 12 : 13);
|
||||
// 12 ("C") for + (credit)
|
||||
// 13 ("D") for - (debit)
|
||||
}
|
||||
|
||||
let bytes = [];
|
||||
|
||||
if (packed) {
|
||||
let encoded = 0,
|
||||
little = false;
|
||||
|
||||
nibbles.forEach(n => {
|
||||
encoded ^= little ? n : (n << 4);
|
||||
if (little) {
|
||||
bytes.push(encoded);
|
||||
encoded = 0;
|
||||
}
|
||||
little = !little;
|
||||
});
|
||||
|
||||
if (little) bytes.push(encoded);
|
||||
} else {
|
||||
bytes = nibbles;
|
||||
|
||||
// Add null high nibbles
|
||||
nibbles = nibbles.map(n => {
|
||||
return [0, n];
|
||||
}).reduce((a, b) => {
|
||||
return a.concat(b);
|
||||
});
|
||||
}
|
||||
|
||||
// Output
|
||||
switch (outputFormat) {
|
||||
case "Nibbles":
|
||||
return nibbles.map(n => {
|
||||
return n.toString(2).padStart(4, "0");
|
||||
}).join(" ");
|
||||
case "Bytes":
|
||||
return bytes.map(b => {
|
||||
return b.toString(2).padStart(8, "0");
|
||||
}).join(" ");
|
||||
case "Raw":
|
||||
default:
|
||||
return Utils.byteArrayToChars(bytes);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From BCD operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runFromBCD: function(input, args) {
|
||||
const encoding = BCD.ENCODING_LOOKUP[args[0]],
|
||||
packed = args[1],
|
||||
signed = args[2],
|
||||
inputFormat = args[3];
|
||||
|
||||
let nibbles = [],
|
||||
output = "",
|
||||
byteArray;
|
||||
|
||||
// Normalise the input
|
||||
switch (inputFormat) {
|
||||
case "Nibbles":
|
||||
case "Bytes":
|
||||
input = input.replace(/\s/g, "");
|
||||
for (let i = 0; i < input.length; i += 4) {
|
||||
nibbles.push(parseInt(input.substr(i, 4), 2));
|
||||
}
|
||||
break;
|
||||
case "Raw":
|
||||
default:
|
||||
byteArray = Utils.strToByteArray(input);
|
||||
byteArray.forEach(b => {
|
||||
nibbles.push(b >>> 4);
|
||||
nibbles.push(b & 15);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if (!packed) {
|
||||
// Discard each high nibble
|
||||
for (let i = 0; i < nibbles.length; i++) {
|
||||
nibbles.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (signed) {
|
||||
const sign = nibbles.pop();
|
||||
if (sign === 13 ||
|
||||
sign === 11) {
|
||||
// Negative
|
||||
output += "-";
|
||||
}
|
||||
}
|
||||
|
||||
nibbles.forEach(n => {
|
||||
if (isNaN(n)) throw "Invalid input";
|
||||
let val = encoding.indexOf(n);
|
||||
if (val < 0) throw `Value ${Utils.bin(n, 4)} not in encoding scheme`;
|
||||
output += val.toString();
|
||||
});
|
||||
|
||||
return new BigNumber(output);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default BCD;
|
@ -1,59 +0,0 @@
|
||||
import bsonjs from "bson";
|
||||
import {Buffer} from "buffer";
|
||||
|
||||
|
||||
/**
|
||||
* BSON operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const BSON = {
|
||||
|
||||
/**
|
||||
* BSON serialise operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runBSONSerialise(input, args) {
|
||||
if (!input) return new ArrayBuffer();
|
||||
|
||||
const bson = new bsonjs();
|
||||
|
||||
try {
|
||||
const data = JSON.parse(input);
|
||||
return bson.serialize(data).buffer;
|
||||
} catch (err) {
|
||||
throw err.toString();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* BSON deserialise operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
*/
|
||||
runBSONDeserialise(input, args) {
|
||||
if (!input.byteLength) return "";
|
||||
|
||||
const bson = new bsonjs();
|
||||
|
||||
try {
|
||||
const data = bson.deserialize(new Buffer(input));
|
||||
return JSON.stringify(data, null, 2);
|
||||
} catch (err) {
|
||||
return err.toString();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default BSON;
|
@ -1,68 +0,0 @@
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* Numerical base operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Base = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DEFAULT_RADIX: 36,
|
||||
|
||||
/**
|
||||
* To Base operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
if (!input) {
|
||||
throw ("Error: Input must be a number");
|
||||
}
|
||||
const radix = args[0] || Base.DEFAULT_RADIX;
|
||||
if (radix < 2 || radix > 36) {
|
||||
throw "Error: Radix argument must be between 2 and 36";
|
||||
}
|
||||
return input.toString(radix);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Base operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
const radix = args[0] || Base.DEFAULT_RADIX;
|
||||
if (radix < 2 || radix > 36) {
|
||||
throw "Error: Radix argument must be between 2 and 36";
|
||||
}
|
||||
|
||||
let number = input.replace(/\s/g, "").split("."),
|
||||
result = new BigNumber(number[0], radix) || 0;
|
||||
|
||||
if (number.length === 1) return result;
|
||||
|
||||
// Fractional part
|
||||
for (let i = 0; i < number[1].length; i++) {
|
||||
const digit = new BigNumber(number[1][i], radix);
|
||||
result += digit.div(Math.pow(radix, i+1));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Base;
|
@ -1,137 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Base58 operations.
|
||||
*
|
||||
* @author tlwr [toby@toby.codes]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Base58 = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ALPHABET_OPTIONS: [
|
||||
{
|
||||
name: "Bitcoin",
|
||||
value: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
|
||||
},
|
||||
{
|
||||
name: "Ripple",
|
||||
value: "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz",
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_NON_ALPH_CHARS: true,
|
||||
|
||||
/**
|
||||
* To Base58 operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
let alphabet = args[0] || Base58.ALPHABET_OPTIONS[0].value,
|
||||
result = [0];
|
||||
|
||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||
|
||||
if (alphabet.length !== 58 ||
|
||||
[].unique.call(alphabet).length !== 58) {
|
||||
throw ("Error: alphabet must be of length 58");
|
||||
}
|
||||
|
||||
if (input.length === 0) return "";
|
||||
|
||||
input.forEach(function(b) {
|
||||
let carry = (result[0] << 8) + b;
|
||||
result[0] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
carry += result[i] << 8;
|
||||
result[i] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
}
|
||||
|
||||
while (carry > 0) {
|
||||
result.push(carry % 58);
|
||||
carry = (carry / 58) | 0;
|
||||
}
|
||||
});
|
||||
|
||||
result = result.map(function(b) {
|
||||
return alphabet[b];
|
||||
}).reverse().join("");
|
||||
|
||||
while (result.length < input.length) {
|
||||
result = alphabet[0] + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Base58 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
let alphabet = args[0] || Base58.ALPHABET_OPTIONS[0].value,
|
||||
removeNonAlphaChars = args[1] === undefined ? true : args[1],
|
||||
result = [0];
|
||||
|
||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||
|
||||
if (alphabet.length !== 58 ||
|
||||
[].unique.call(alphabet).length !== 58) {
|
||||
throw ("Alphabet must be of length 58");
|
||||
}
|
||||
|
||||
if (input.length === 0) return [];
|
||||
|
||||
[].forEach.call(input, function(c, charIndex) {
|
||||
const index = alphabet.indexOf(c);
|
||||
|
||||
if (index === -1) {
|
||||
if (removeNonAlphaChars) {
|
||||
return;
|
||||
} else {
|
||||
throw ("Char '" + c + "' at position " + charIndex + " not in alphabet");
|
||||
}
|
||||
}
|
||||
|
||||
let carry = result[0] * 58 + index;
|
||||
result[0] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
carry += result[i] * 58;
|
||||
result[i] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
}
|
||||
|
||||
while (carry > 0) {
|
||||
result.push(carry & 0xFF);
|
||||
carry = carry >> 8;
|
||||
}
|
||||
});
|
||||
|
||||
return result.reverse();
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Base58;
|
@ -1,355 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import {toHex, fromHex} from "../lib/Hex";
|
||||
|
||||
|
||||
/**
|
||||
* Byte representation operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const ByteRepr = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TO_HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FROM_HEX_DELIM_OPTIONS: ["Auto", "Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BIN_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"],
|
||||
|
||||
|
||||
/**
|
||||
* To Octal operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToOct: function(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space");
|
||||
return input.map(val => val.toString(8)).join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Octal operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromOct: function(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space");
|
||||
if (input.length === 0) return [];
|
||||
return input.split(delim).map(val => parseInt(val, 8));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CHARCODE_BASE: 16,
|
||||
|
||||
/**
|
||||
* To Charcode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToCharcode: function(input, args) {
|
||||
let delim = Utils.charRep(args[0] || "Space"),
|
||||
base = args[1],
|
||||
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);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Charcode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromCharcode: function(input, args) {
|
||||
let delim = Utils.charRep(args[0] || "Space"),
|
||||
base = args[1],
|
||||
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);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Decimal operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToDecimal: function(input, args) {
|
||||
const delim = Utils.charRep(args[0]);
|
||||
return input.join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Decimal operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromDecimal: function(input, args) {
|
||||
const delim = Utils.charRep(args[0]);
|
||||
let byteStr = input.split(delim), output = [];
|
||||
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;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Binary operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToBinary: function(input, args) {
|
||||
let delim = Utils.charRep(args[0] || "Space"),
|
||||
output = "",
|
||||
padding = 8;
|
||||
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Binary operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromBinary: function(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 to binary
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightToBinary: function(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 from binary
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFromBinary: function(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;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HEX_CONTENT_CONVERT_WHICH: ["Only special chars", "Only special chars including spaces", "All chars"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HEX_CONTENT_SPACES_BETWEEN_BYTES: false,
|
||||
|
||||
/**
|
||||
* To Hex Content operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToHexContent: function(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,
|
||||
convertSpaces = convert === "Only special chars including spaces",
|
||||
b;
|
||||
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;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Hex Content operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromHexContent: function(input, args) {
|
||||
const regex = /\|([a-f\d ]{2,})\|/gi;
|
||||
let output = [], 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 ByteRepr;
|
@ -1,97 +0,0 @@
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
|
||||
|
||||
/**
|
||||
* Character encoding operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const CharEnc = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IO_FORMAT: {
|
||||
"UTF-8 (65001)": 65001,
|
||||
"UTF-7 (65000)": 65000,
|
||||
"UTF16LE (1200)": 1200,
|
||||
"UTF16BE (1201)": 1201,
|
||||
"UTF16 (1201)": 1201,
|
||||
"IBM EBCDIC International (500)": 500,
|
||||
"IBM EBCDIC US-Canada (37)": 37,
|
||||
"Windows-874 Thai (874)": 874,
|
||||
"Japanese Shift-JIS (932)": 932,
|
||||
"Simplified Chinese GBK (936)": 936,
|
||||
"Korean (949)": 949,
|
||||
"Traditional Chinese Big5 (950)": 950,
|
||||
"Windows-1250 Central European (1250)": 1250,
|
||||
"Windows-1251 Cyrillic (1251)": 1251,
|
||||
"Windows-1252 Latin (1252)": 1252,
|
||||
"Windows-1253 Greek (1253)": 1253,
|
||||
"Windows-1254 Turkish (1254)": 1254,
|
||||
"Windows-1255 Hebrew (1255)": 1255,
|
||||
"Windows-1256 Arabic (1256)": 1256,
|
||||
"Windows-1257 Baltic (1257)": 1257,
|
||||
"Windows-1258 Vietnam (1258)": 1258,
|
||||
"US-ASCII (20127)": 20127,
|
||||
"Simplified Chinese GB2312 (20936)": 20936,
|
||||
"KOI8-R Russian Cyrillic (20866)": 20866,
|
||||
"KOI8-U Ukrainian Cyrillic (21866)": 21866,
|
||||
"ISO-8859-1 Latin 1 Western European (28591)": 28591,
|
||||
"ISO-8859-2 Latin 2 Central European (28592)": 28592,
|
||||
"ISO-8859-3 Latin 3 South European (28593)": 28593,
|
||||
"ISO-8859-4 Latin 4 North European (28594)": 28594,
|
||||
"ISO-8859-5 Latin/Cyrillic (28595)": 28595,
|
||||
"ISO-8859-6 Latin/Arabic (28596)": 28596,
|
||||
"ISO-8859-7 Latin/Greek (28597)": 28597,
|
||||
"ISO-8859-8 Latin/Hebrew (28598)": 28598,
|
||||
"ISO-8859-9 Latin 5 Turkish (28599)": 28599,
|
||||
"ISO-8859-10 Latin 6 Nordic (28600)": 28600,
|
||||
"ISO-8859-11 Latin/Thai (28601)": 28601,
|
||||
"ISO-8859-13 Latin 7 Baltic Rim (28603)": 28603,
|
||||
"ISO-8859-14 Latin 8 Celtic (28604)": 28604,
|
||||
"ISO-8859-15 Latin 9 (28605)": 28605,
|
||||
"ISO-8859-16 Latin 10 (28606)": 28606,
|
||||
"ISO-2022 JIS Japanese (50222)": 50222,
|
||||
"EUC Japanese (51932)": 51932,
|
||||
"EUC Korean (51949)": 51949,
|
||||
"Simplified Chinese GB18030 (54936)": 54936,
|
||||
},
|
||||
|
||||
/**
|
||||
* Encode text operation.
|
||||
* @author tlwr [toby@toby.codes]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runEncode: function(input, args) {
|
||||
const format = CharEnc.IO_FORMAT[args[0]];
|
||||
let encoded = cptable.utils.encode(format, input);
|
||||
encoded = Array.from(encoded);
|
||||
return encoded;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Decode text operation.
|
||||
* @author tlwr [toby@toby.codes]
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDecode: function(input, args) {
|
||||
const format = CharEnc.IO_FORMAT[args[0]];
|
||||
let decoded = cptable.utils.decode(format, input);
|
||||
return decoded;
|
||||
},
|
||||
};
|
||||
|
||||
export default CharEnc;
|
@ -1,179 +0,0 @@
|
||||
import * as CRC from "js-crc";
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Checksum operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Checksum = {
|
||||
|
||||
/**
|
||||
* Fletcher-8 Checksum operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher8: function(input, args) {
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xf;
|
||||
b = (b + a) % 0xf;
|
||||
}
|
||||
|
||||
return Utils.hex(((b << 4) | a) >>> 0, 2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Fletcher-16 Checksum operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher16: function(input, args) {
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xff;
|
||||
b = (b + a) % 0xff;
|
||||
}
|
||||
|
||||
return Utils.hex(((b << 8) | a) >>> 0, 4);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Fletcher-32 Checksum operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher32: function(input, args) {
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xffff;
|
||||
b = (b + a) % 0xffff;
|
||||
}
|
||||
|
||||
return Utils.hex(((b << 16) | a) >>> 0, 8);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Fletcher-64 Checksum operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher64: function(input, args) {
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xffffffff;
|
||||
b = (b + a) % 0xffffffff;
|
||||
}
|
||||
|
||||
return Utils.hex(b >>> 0, 8) + Utils.hex(a >>> 0, 8);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adler-32 Checksum operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAdler32: function(input, args) {
|
||||
let MOD_ADLER = 65521,
|
||||
a = 1,
|
||||
b = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a += input[i];
|
||||
b += a;
|
||||
}
|
||||
|
||||
a %= MOD_ADLER;
|
||||
b %= MOD_ADLER;
|
||||
|
||||
return Utils.hex(((b << 16) | a) >>> 0, 8);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CRC-32 Checksum operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCRC32: function(input, args) {
|
||||
return CRC.crc32(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CRC-16 Checksum operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCRC16: function(input, args) {
|
||||
return CRC.crc16(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* TCP/IP Checksum operation.
|
||||
*
|
||||
* @author GCHQ Contributor [1]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns '3f2c'
|
||||
* Checksum.runTcpIp([0x45,0x00,0x00,0x87,0xa3,0x1b,0x40,0x00,0x40,0x06,
|
||||
* 0x00,0x00,0xac,0x11,0x00,0x04,0xac,0x11,0x00,0x03])
|
||||
*
|
||||
* // returns 'a249'
|
||||
* Checksum.runTcpIp([0x45,0x00,0x01,0x11,0x3f,0x74,0x40,0x00,0x40,0x06,
|
||||
* 0x00,0x00,0xac,0x11,0x00,0x03,0xac,0x11,0x00,0x04])
|
||||
*/
|
||||
runTCPIP: function(input, args) {
|
||||
let csum = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
if (i % 2 === 0) {
|
||||
csum += (input[i] << 8);
|
||||
} else {
|
||||
csum += input[i];
|
||||
}
|
||||
}
|
||||
|
||||
csum = (csum >> 16) + (csum & 0xffff);
|
||||
|
||||
return Utils.hex(0xffff - csum);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Checksum;
|
@ -1,243 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import bzip2 from "exports-loader?bzip2!../vendor/bzip2.js";
|
||||
|
||||
|
||||
/**
|
||||
* Compression operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Compress = {
|
||||
|
||||
/**
|
||||
* Bzip2 Decompress operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBzip2Decompress: function(input, args) {
|
||||
let compressed = new Uint8Array(input),
|
||||
bzip2Reader,
|
||||
plain = "";
|
||||
|
||||
bzip2Reader = bzip2.array(compressed);
|
||||
plain = bzip2.simple(bzip2Reader);
|
||||
return plain;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TAR_FILENAME: "file.txt",
|
||||
|
||||
|
||||
/**
|
||||
* Tar pack operation.
|
||||
*
|
||||
* @author tlwr [toby@toby.codes]
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runTar: function(input, args) {
|
||||
const Tarball = function() {
|
||||
this.bytes = new Array(512);
|
||||
this.position = 0;
|
||||
};
|
||||
|
||||
Tarball.prototype.addEmptyBlock = function() {
|
||||
const filler = new Array(512);
|
||||
filler.fill(0);
|
||||
this.bytes = this.bytes.concat(filler);
|
||||
};
|
||||
|
||||
Tarball.prototype.writeBytes = function(bytes) {
|
||||
const self = this;
|
||||
|
||||
if (this.position + bytes.length > this.bytes.length) {
|
||||
this.addEmptyBlock();
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(bytes, function(b, i) {
|
||||
if (typeof b.charCodeAt !== "undefined") {
|
||||
b = b.charCodeAt();
|
||||
}
|
||||
|
||||
self.bytes[self.position] = b;
|
||||
self.position += 1;
|
||||
});
|
||||
};
|
||||
|
||||
Tarball.prototype.writeEndBlocks = function() {
|
||||
const numEmptyBlocks = 2;
|
||||
for (let i = 0; i < numEmptyBlocks; i++) {
|
||||
this.addEmptyBlock();
|
||||
}
|
||||
};
|
||||
|
||||
const fileSize = input.length.toString(8).padStart(11, "0");
|
||||
const currentUnixTimestamp = Math.floor(Date.now() / 1000);
|
||||
const lastModTime = currentUnixTimestamp.toString(8).padStart(11, "0");
|
||||
|
||||
const file = {
|
||||
fileName: Utils.padBytesRight(args[0], 100),
|
||||
fileMode: Utils.padBytesRight("0000664", 8),
|
||||
ownerUID: Utils.padBytesRight("0", 8),
|
||||
ownerGID: Utils.padBytesRight("0", 8),
|
||||
size: Utils.padBytesRight(fileSize, 12),
|
||||
lastModTime: Utils.padBytesRight(lastModTime, 12),
|
||||
checksum: " ",
|
||||
type: "0",
|
||||
linkedFileName: Utils.padBytesRight("", 100),
|
||||
USTARFormat: Utils.padBytesRight("ustar", 6),
|
||||
version: "00",
|
||||
ownerUserName: Utils.padBytesRight("", 32),
|
||||
ownerGroupName: Utils.padBytesRight("", 32),
|
||||
deviceMajor: Utils.padBytesRight("", 8),
|
||||
deviceMinor: Utils.padBytesRight("", 8),
|
||||
fileNamePrefix: Utils.padBytesRight("", 155),
|
||||
};
|
||||
|
||||
let checksum = 0;
|
||||
for (const key in file) {
|
||||
const bytes = file[key];
|
||||
Array.prototype.forEach.call(bytes, function(b) {
|
||||
if (typeof b.charCodeAt !== "undefined") {
|
||||
checksum += b.charCodeAt();
|
||||
} else {
|
||||
checksum += b;
|
||||
}
|
||||
});
|
||||
}
|
||||
checksum = Utils.padBytesRight(checksum.toString(8).padStart(7, "0"), 8);
|
||||
file.checksum = checksum;
|
||||
|
||||
const tarball = new Tarball();
|
||||
tarball.writeBytes(file.fileName);
|
||||
tarball.writeBytes(file.fileMode);
|
||||
tarball.writeBytes(file.ownerUID);
|
||||
tarball.writeBytes(file.ownerGID);
|
||||
tarball.writeBytes(file.size);
|
||||
tarball.writeBytes(file.lastModTime);
|
||||
tarball.writeBytes(file.checksum);
|
||||
tarball.writeBytes(file.type);
|
||||
tarball.writeBytes(file.linkedFileName);
|
||||
tarball.writeBytes(file.USTARFormat);
|
||||
tarball.writeBytes(file.version);
|
||||
tarball.writeBytes(file.ownerUserName);
|
||||
tarball.writeBytes(file.ownerGroupName);
|
||||
tarball.writeBytes(file.deviceMajor);
|
||||
tarball.writeBytes(file.deviceMinor);
|
||||
tarball.writeBytes(file.fileNamePrefix);
|
||||
tarball.writeBytes(Utils.padBytesRight("", 12));
|
||||
tarball.writeBytes(input);
|
||||
tarball.writeEndBlocks();
|
||||
|
||||
return tarball.bytes;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Untar unpack operation.
|
||||
*
|
||||
* @author tlwr [toby@toby.codes]
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runUntar: function(input, args) {
|
||||
const Stream = function(input) {
|
||||
this.bytes = input;
|
||||
this.position = 0;
|
||||
};
|
||||
|
||||
Stream.prototype.getBytes = function(bytesToGet) {
|
||||
const newPosition = this.position + bytesToGet;
|
||||
const bytes = this.bytes.slice(this.position, newPosition);
|
||||
this.position = newPosition;
|
||||
return bytes;
|
||||
};
|
||||
|
||||
Stream.prototype.readString = function(numBytes) {
|
||||
let result = "";
|
||||
for (let i = this.position; i < this.position + numBytes; i++) {
|
||||
const currentByte = this.bytes[i];
|
||||
if (currentByte === 0) break;
|
||||
result += String.fromCharCode(currentByte);
|
||||
}
|
||||
this.position += numBytes;
|
||||
return result;
|
||||
};
|
||||
|
||||
Stream.prototype.readInt = function(numBytes, base) {
|
||||
const string = this.readString(numBytes);
|
||||
return parseInt(string, base);
|
||||
};
|
||||
|
||||
Stream.prototype.hasMore = function() {
|
||||
return this.position < this.bytes.length;
|
||||
};
|
||||
|
||||
let stream = new Stream(input),
|
||||
files = [];
|
||||
|
||||
while (stream.hasMore()) {
|
||||
const dataPosition = stream.position + 512;
|
||||
|
||||
const file = {
|
||||
fileName: stream.readString(100),
|
||||
fileMode: stream.readString(8),
|
||||
ownerUID: stream.readString(8),
|
||||
ownerGID: stream.readString(8),
|
||||
size: parseInt(stream.readString(12), 8), // Octal
|
||||
lastModTime: new Date(1000 * stream.readInt(12, 8)), // Octal
|
||||
checksum: stream.readString(8),
|
||||
type: stream.readString(1),
|
||||
linkedFileName: stream.readString(100),
|
||||
USTARFormat: stream.readString(6).indexOf("ustar") >= 0,
|
||||
};
|
||||
|
||||
if (file.USTARFormat) {
|
||||
file.version = stream.readString(2);
|
||||
file.ownerUserName = stream.readString(32);
|
||||
file.ownerGroupName = stream.readString(32);
|
||||
file.deviceMajor = stream.readString(8);
|
||||
file.deviceMinor = stream.readString(8);
|
||||
file.filenamePrefix = stream.readString(155);
|
||||
}
|
||||
|
||||
stream.position = dataPosition;
|
||||
|
||||
if (file.type === "0") {
|
||||
// File
|
||||
files.push(file);
|
||||
let endPosition = stream.position + file.size;
|
||||
if (file.size % 512 !== 0) {
|
||||
endPosition += 512 - (file.size % 512);
|
||||
}
|
||||
|
||||
file.bytes = stream.getBytes(file.size);
|
||||
file.contents = Utils.byteArrayToUtf8(file.bytes);
|
||||
stream.position = endPosition;
|
||||
} else if (file.type === "5") {
|
||||
// Directory
|
||||
files.push(file);
|
||||
} else {
|
||||
// Symlink or empty bytes
|
||||
}
|
||||
}
|
||||
|
||||
return Utils.displayFilesAsHTML(files);
|
||||
},
|
||||
};
|
||||
|
||||
export default Compress;
|
@ -1,413 +0,0 @@
|
||||
/**
|
||||
* Unit conversion operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Convert = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISTANCE_UNITS: [
|
||||
"[Metric]", "Nanometres (nm)", "Micrometres (µm)", "Millimetres (mm)", "Centimetres (cm)", "Metres (m)", "Kilometers (km)", "[/Metric]",
|
||||
"[Imperial]", "Thou (th)", "Inches (in)", "Feet (ft)", "Yards (yd)", "Chains (ch)", "Furlongs (fur)", "Miles (mi)", "Leagues (lea)", "[/Imperial]",
|
||||
"[Maritime]", "Fathoms (ftm)", "Cables", "Nautical miles", "[/Maritime]",
|
||||
"[Comparisons]", "Cars (4m)", "Buses (8.4m)", "American football fields (91m)", "Football pitches (105m)", "[/Comparisons]",
|
||||
"[Astronomical]", "Earth-to-Moons", "Earth's equators", "Astronomical units (au)", "Light-years (ly)", "Parsecs (pc)", "[/Astronomical]",
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISTANCE_FACTOR: { // Multiples of a metre
|
||||
"Nanometres (nm)": 1e-9,
|
||||
"Micrometres (µm)": 1e-6,
|
||||
"Millimetres (mm)": 1e-3,
|
||||
"Centimetres (cm)": 1e-2,
|
||||
"Metres (m)": 1,
|
||||
"Kilometers (km)": 1e3,
|
||||
|
||||
"Thou (th)": 0.0000254,
|
||||
"Inches (in)": 0.0254,
|
||||
"Feet (ft)": 0.3048,
|
||||
"Yards (yd)": 0.9144,
|
||||
"Chains (ch)": 20.1168,
|
||||
"Furlongs (fur)": 201.168,
|
||||
"Miles (mi)": 1609.344,
|
||||
"Leagues (lea)": 4828.032,
|
||||
|
||||
"Fathoms (ftm)": 1.853184,
|
||||
"Cables": 185.3184,
|
||||
"Nautical miles": 1853.184,
|
||||
|
||||
"Cars (4m)": 4,
|
||||
"Buses (8.4m)": 8.4,
|
||||
"American football fields (91m)": 91,
|
||||
"Football pitches (105m)": 105,
|
||||
|
||||
"Earth-to-Moons": 380000000,
|
||||
"Earth's equators": 40075016.686,
|
||||
"Astronomical units (au)": 149597870700,
|
||||
"Light-years (ly)": 9460730472580800,
|
||||
"Parsecs (pc)": 3.0856776e16
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert distance operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runDistance: function (input, args) {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.times(Convert.DISTANCE_FACTOR[inputUnits]);
|
||||
return input.div(Convert.DISTANCE_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DATA_UNITS: [
|
||||
"Bits (b)", "Nibbles", "Octets", "Bytes (B)",
|
||||
"[Binary bits (2^n)]", "Kibibits (Kib)", "Mebibits (Mib)", "Gibibits (Gib)", "Tebibits (Tib)", "Pebibits (Pib)", "Exbibits (Eib)", "Zebibits (Zib)", "Yobibits (Yib)", "[/Binary bits (2^n)]",
|
||||
"[Decimal bits (10^n)]", "Decabits", "Hectobits", "Kilobits (kb)", "Megabits (Mb)", "Gigabits (Gb)", "Terabits (Tb)", "Petabits (Pb)", "Exabits (Eb)", "Zettabits (Zb)", "Yottabits (Yb)", "[/Decimal bits (10^n)]",
|
||||
"[Binary bytes (8 x 2^n)]", "Kibibytes (KiB)", "Mebibytes (MiB)", "Gibibytes (GiB)", "Tebibytes (TiB)", "Pebibytes (PiB)", "Exbibytes (EiB)", "Zebibytes (ZiB)", "Yobibytes (YiB)", "[/Binary bytes (8 x 2^n)]",
|
||||
"[Decimal bytes (8 x 10^n)]", "Kilobytes (KB)", "Megabytes (MB)", "Gigabytes (GB)", "Terabytes (TB)", "Petabytes (PB)", "Exabytes (EB)", "Zettabytes (ZB)", "Yottabytes (YB)", "[/Decimal bytes (8 x 10^n)]"
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DATA_FACTOR: { // Multiples of a bit
|
||||
"Bits (b)": 1,
|
||||
"Nibbles": 4,
|
||||
"Octets": 8,
|
||||
"Bytes (B)": 8,
|
||||
|
||||
// Binary bits (2^n)
|
||||
"Kibibits (Kib)": 1024,
|
||||
"Mebibits (Mib)": 1048576,
|
||||
"Gibibits (Gib)": 1073741824,
|
||||
"Tebibits (Tib)": 1099511627776,
|
||||
"Pebibits (Pib)": 1125899906842624,
|
||||
"Exbibits (Eib)": 1152921504606846976,
|
||||
"Zebibits (Zib)": 1180591620717411303424,
|
||||
"Yobibits (Yib)": 1208925819614629174706176,
|
||||
|
||||
// Decimal bits (10^n)
|
||||
"Decabits": 10,
|
||||
"Hectobits": 100,
|
||||
"Kilobits (Kb)": 1e3,
|
||||
"Megabits (Mb)": 1e6,
|
||||
"Gigabits (Gb)": 1e9,
|
||||
"Terabits (Tb)": 1e12,
|
||||
"Petabits (Pb)": 1e15,
|
||||
"Exabits (Eb)": 1e18,
|
||||
"Zettabits (Zb)": 1e21,
|
||||
"Yottabits (Yb)": 1e24,
|
||||
|
||||
// Binary bytes (8 x 2^n)
|
||||
"Kibibytes (KiB)": 8192,
|
||||
"Mebibytes (MiB)": 8388608,
|
||||
"Gibibytes (GiB)": 8589934592,
|
||||
"Tebibytes (TiB)": 8796093022208,
|
||||
"Pebibytes (PiB)": 9007199254740992,
|
||||
"Exbibytes (EiB)": 9223372036854775808,
|
||||
"Zebibytes (ZiB)": 9444732965739290427392,
|
||||
"Yobibytes (YiB)": 9671406556917033397649408,
|
||||
|
||||
// Decimal bytes (8 x 10^n)
|
||||
"Kilobytes (KB)": 8e3,
|
||||
"Megabytes (MB)": 8e6,
|
||||
"Gigabytes (GB)": 8e9,
|
||||
"Terabytes (TB)": 8e12,
|
||||
"Petabytes (PB)": 8e15,
|
||||
"Exabytes (EB)": 8e18,
|
||||
"Zettabytes (ZB)": 8e21,
|
||||
"Yottabytes (YB)": 8e24,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert data units operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runDataSize: function (input, args) {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.times(Convert.DATA_FACTOR[inputUnits]);
|
||||
return input.div(Convert.DATA_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
AREA_UNITS: [
|
||||
"[Metric]", "Square metre (sq m)", "Square kilometre (sq km)", "Centiare (ca)", "Deciare (da)", "Are (a)", "Decare (daa)", "Hectare (ha)", "[/Metric]",
|
||||
"[Imperial]", "Square inch (sq in)", "Square foot (sq ft)", "Square yard (sq yd)", "Square mile (sq mi)", "Perch (sq per)", "Rood (ro)", "International acre (ac)", "[/Imperial]",
|
||||
"[US customary units]", "US survey acre (ac)", "US survey square mile (sq mi)", "US survey township", "[/US customary units]",
|
||||
"[Nuclear physics]", "Yoctobarn (yb)", "Zeptobarn (zb)", "Attobarn (ab)", "Femtobarn (fb)", "Picobarn (pb)", "Nanobarn (nb)", "Microbarn (μb)", "Millibarn (mb)", "Barn (b)", "Kilobarn (kb)", "Megabarn (Mb)", "Outhouse", "Shed", "Planck area", "[/Nuclear physics]",
|
||||
"[Comparisons]", "Washington D.C.", "Isle of Wight", "Wales", "Texas", "[/Comparisons]",
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
AREA_FACTOR: { // Multiples of a square metre
|
||||
// Metric
|
||||
"Square metre (sq m)": 1,
|
||||
"Square kilometre (sq km)": 1e6,
|
||||
|
||||
"Centiare (ca)": 1,
|
||||
"Deciare (da)": 10,
|
||||
"Are (a)": 100,
|
||||
"Decare (daa)": 1e3,
|
||||
"Hectare (ha)": 1e4,
|
||||
|
||||
// Imperial
|
||||
"Square inch (sq in)": 0.00064516,
|
||||
"Square foot (sq ft)": 0.09290304,
|
||||
"Square yard (sq yd)": 0.83612736,
|
||||
"Square mile (sq mi)": 2589988.110336,
|
||||
"Perch (sq per)": 42.21,
|
||||
"Rood (ro)": 1011,
|
||||
"International acre (ac)": 4046.8564224,
|
||||
|
||||
// US customary units
|
||||
"US survey acre (ac)": 4046.87261,
|
||||
"US survey square mile (sq mi)": 2589998.470305239,
|
||||
"US survey township": 93239944.9309886,
|
||||
|
||||
// Nuclear physics
|
||||
"Yoctobarn (yb)": 1e-52,
|
||||
"Zeptobarn (zb)": 1e-49,
|
||||
"Attobarn (ab)": 1e-46,
|
||||
"Femtobarn (fb)": 1e-43,
|
||||
"Picobarn (pb)": 1e-40,
|
||||
"Nanobarn (nb)": 1e-37,
|
||||
"Microbarn (μb)": 1e-34,
|
||||
"Millibarn (mb)": 1e-31,
|
||||
"Barn (b)": 1e-28,
|
||||
"Kilobarn (kb)": 1e-25,
|
||||
"Megabarn (Mb)": 1e-22,
|
||||
|
||||
"Planck area": 2.6e-70,
|
||||
"Shed": 1e-52,
|
||||
"Outhouse": 1e-34,
|
||||
|
||||
// Comparisons
|
||||
"Washington D.C.": 176119191.502848,
|
||||
"Isle of Wight": 380000000,
|
||||
"Wales": 20779000000,
|
||||
"Texas": 696241000000,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert area operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runArea: function (input, args) {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.times(Convert.AREA_FACTOR[inputUnits]);
|
||||
return input.div(Convert.AREA_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MASS_UNITS: [
|
||||
"[Metric]", "Yoctogram (yg)", "Zeptogram (zg)", "Attogram (ag)", "Femtogram (fg)", "Picogram (pg)", "Nanogram (ng)", "Microgram (μg)", "Milligram (mg)", "Centigram (cg)", "Decigram (dg)", "Gram (g)", "Decagram (dag)", "Hectogram (hg)", "Kilogram (kg)", "Megagram (Mg)", "Tonne (t)", "Gigagram (Gg)", "Teragram (Tg)", "Petagram (Pg)", "Exagram (Eg)", "Zettagram (Zg)", "Yottagram (Yg)", "[/Metric]",
|
||||
"[Imperial Avoirdupois]", "Grain (gr)", "Dram (dr)", "Ounce (oz)", "Pound (lb)", "Nail", "Stone (st)", "Quarter (gr)", "Tod", "US hundredweight (cwt)", "Imperial hundredweight (cwt)", "US ton (t)", "Imperial ton (t)", "[/Imperial Avoirdupois]",
|
||||
"[Imperial Troy]", "Grain (gr)", "Pennyweight (dwt)", "Troy dram (dr t)", "Troy ounce (oz t)", "Troy pound (lb t)", "Mark", "[/Imperial Troy]",
|
||||
"[Archaic]", "Wey", "Wool wey", "Suffolk wey", "Wool sack", "Coal sack", "Load", "Last", "Flax or feather last", "Gunpowder last", "Picul", "Rice last", "[/Archaic]",
|
||||
"[Comparisons]", "Big Ben (14 tonnes)", "Blue whale (180 tonnes)", "International Space Station (417 tonnes)", "Space Shuttle (2,041 tonnes)", "RMS Titanic (52,000 tonnes)", "Great Pyramid of Giza (6,000,000 tonnes)", "Earth's oceans (1.4 yottagrams)", "[/Comparisons]",
|
||||
"[Astronomical]", "A teaspoon of neutron star (5,500 million tonnes)", "Lunar mass (ML)", "Earth mass (M⊕)", "Jupiter mass (MJ)", "Solar mass (M☉)", "Sagittarius A* (7.5 x 10^36 kgs-ish)", "Milky Way galaxy (1.2 x 10^42 kgs)", "The observable universe (1.45 x 10^53 kgs)", "[/Astronomical]",
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MASS_FACTOR: { // Multiples of a gram
|
||||
// Metric
|
||||
"Yoctogram (yg)": 1e-24,
|
||||
"Zeptogram (zg)": 1e-21,
|
||||
"Attogram (ag)": 1e-18,
|
||||
"Femtogram (fg)": 1e-15,
|
||||
"Picogram (pg)": 1e-12,
|
||||
"Nanogram (ng)": 1e-9,
|
||||
"Microgram (μg)": 1e-6,
|
||||
"Milligram (mg)": 1e-3,
|
||||
"Centigram (cg)": 1e-2,
|
||||
"Decigram (dg)": 1e-1,
|
||||
"Gram (g)": 1,
|
||||
"Decagram (dag)": 10,
|
||||
"Hectogram (hg)": 100,
|
||||
"Kilogram (kg)": 1000,
|
||||
"Megagram (Mg)": 1e6,
|
||||
"Tonne (t)": 1e6,
|
||||
"Gigagram (Gg)": 1e9,
|
||||
"Teragram (Tg)": 1e12,
|
||||
"Petagram (Pg)": 1e15,
|
||||
"Exagram (Eg)": 1e18,
|
||||
"Zettagram (Zg)": 1e21,
|
||||
"Yottagram (Yg)": 1e24,
|
||||
|
||||
// Imperial Avoirdupois
|
||||
"Grain (gr)": 64.79891e-3,
|
||||
"Dram (dr)": 1.7718451953125,
|
||||
"Ounce (oz)": 28.349523125,
|
||||
"Pound (lb)": 453.59237,
|
||||
"Nail": 3175.14659,
|
||||
"Stone (st)": 6.35029318e3,
|
||||
"Quarter (gr)": 12700.58636,
|
||||
"Tod": 12700.58636,
|
||||
"US hundredweight (cwt)": 45.359237e3,
|
||||
"Imperial hundredweight (cwt)": 50.80234544e3,
|
||||
"US ton (t)": 907.18474e3,
|
||||
"Imperial ton (t)": 1016.0469088e3,
|
||||
|
||||
// Imperial Troy
|
||||
"Pennyweight (dwt)": 1.55517384,
|
||||
"Troy dram (dr t)": 3.8879346,
|
||||
"Troy ounce (oz t)": 31.1034768,
|
||||
"Troy pound (lb t)": 373.2417216,
|
||||
"Mark": 248.8278144,
|
||||
|
||||
// Archaic
|
||||
"Wey": 76.5e3,
|
||||
"Wool wey": 101.7e3,
|
||||
"Suffolk wey": 161.5e3,
|
||||
"Wool sack": 153000,
|
||||
"Coal sack": 50.80234544e3,
|
||||
"Load": 918000,
|
||||
"Last": 1836000,
|
||||
"Flax or feather last": 770e3,
|
||||
"Gunpowder last": 1090e3,
|
||||
"Picul": 60.478982e3,
|
||||
"Rice last": 1200e3,
|
||||
|
||||
// Comparisons
|
||||
"Big Ben (14 tonnes)": 14e6,
|
||||
"Blue whale (180 tonnes)": 180e6,
|
||||
"International Space Station (417 tonnes)": 417e6,
|
||||
"Space Shuttle (2,041 tonnes)": 2041e6,
|
||||
"RMS Titanic (52,000 tonnes)": 52000e6,
|
||||
"Great Pyramid of Giza (6,000,000 tonnes)": 6e12,
|
||||
"Earth's oceans (1.4 yottagrams)": 1.4e24,
|
||||
|
||||
// Astronomical
|
||||
"A teaspoon of neutron star (5,500 million tonnes)": 5.5e15,
|
||||
"Lunar mass (ML)": 7.342e25,
|
||||
"Earth mass (M⊕)": 5.97219e27,
|
||||
"Jupiter mass (MJ)": 1.8981411476999997e30,
|
||||
"Solar mass (M☉)": 1.98855e33,
|
||||
"Sagittarius A* (7.5 x 10^36 kgs-ish)": 7.5e39,
|
||||
"Milky Way galaxy (1.2 x 10^42 kgs)": 1.2e45,
|
||||
"The observable universe (1.45 x 10^53 kgs)": 1.45e56,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert mass operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMass: function (input, args) {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.times(Convert.MASS_FACTOR[inputUnits]);
|
||||
return input.div(Convert.MASS_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SPEED_UNITS: [
|
||||
"[Metric]", "Metres per second (m/s)", "Kilometres per hour (km/h)", "[/Metric]",
|
||||
"[Imperial]", "Miles per hour (mph)", "Knots (kn)", "[/Imperial]",
|
||||
"[Comparisons]", "Human hair growth rate", "Bamboo growth rate", "World's fastest snail", "Usain Bolt's top speed", "Jet airliner cruising speed", "Concorde", "SR-71 Blackbird", "Space Shuttle", "International Space Station", "[/Comparisons]",
|
||||
"[Scientific]", "Sound in standard atmosphere", "Sound in water", "Lunar escape velocity", "Earth escape velocity", "Earth's solar orbit", "Solar system's Milky Way orbit", "Milky Way relative to the cosmic microwave background", "Solar escape velocity", "Neutron star escape velocity (0.3c)", "Light in a diamond (0.4136c)", "Signal in an optical fibre (0.667c)", "Light (c)", "[/Scientific]",
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SPEED_FACTOR: { // Multiples of m/s
|
||||
// Metric
|
||||
"Metres per second (m/s)": 1,
|
||||
"Kilometres per hour (km/h)": 0.2778,
|
||||
|
||||
// Imperial
|
||||
"Miles per hour (mph)": 0.44704,
|
||||
"Knots (kn)": 0.5144,
|
||||
|
||||
// Comparisons
|
||||
"Human hair growth rate": 4.8e-9,
|
||||
"Bamboo growth rate": 1.4e-5,
|
||||
"World's fastest snail": 0.00275,
|
||||
"Usain Bolt's top speed": 12.42,
|
||||
"Jet airliner cruising speed": 250,
|
||||
"Concorde": 603,
|
||||
"SR-71 Blackbird": 981,
|
||||
"Space Shuttle": 1400,
|
||||
"International Space Station": 7700,
|
||||
|
||||
// Scientific
|
||||
"Sound in standard atmosphere": 340.3,
|
||||
"Sound in water": 1500,
|
||||
"Lunar escape velocity": 2375,
|
||||
"Earth escape velocity": 11200,
|
||||
"Earth's solar orbit": 29800,
|
||||
"Solar system's Milky Way orbit": 200000,
|
||||
"Milky Way relative to the cosmic microwave background": 552000,
|
||||
"Solar escape velocity": 617700,
|
||||
"Neutron star escape velocity (0.3c)": 100000000,
|
||||
"Light in a diamond (0.4136c)": 124000000,
|
||||
"Signal in an optical fibre (0.667c)": 200000000,
|
||||
"Light (c)": 299792458,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert speed operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runSpeed: function (input, args) {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.times(Convert.SPEED_FACTOR[inputUnits]);
|
||||
return input.div(Convert.SPEED_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Convert;
|
@ -1,484 +0,0 @@
|
||||
import moment from "moment-timezone";
|
||||
|
||||
|
||||
/**
|
||||
* Date and time operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const DateTime = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
|
||||
|
||||
/**
|
||||
* From UNIX Timestamp operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFromUnixTimestamp: function(input, args) {
|
||||
let units = args[0],
|
||||
d;
|
||||
|
||||
input = parseFloat(input);
|
||||
|
||||
if (units === "Seconds (s)") {
|
||||
d = moment.unix(input);
|
||||
return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss") + " UTC";
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
d = moment(input);
|
||||
return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
d = moment(input / 1000);
|
||||
return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
d = moment(input / 1000000);
|
||||
return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TREAT_AS_UTC: true,
|
||||
|
||||
/**
|
||||
* To UNIX Timestamp operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToUnixTimestamp: function(input, args) {
|
||||
const units = args[0],
|
||||
treatAsUTC = args[1],
|
||||
showDateTime = args[2],
|
||||
d = treatAsUTC ? moment.utc(input) : moment(input);
|
||||
|
||||
let result = "";
|
||||
|
||||
if (units === "Seconds (s)") {
|
||||
result = d.unix();
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
result = d.valueOf();
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
result = d.valueOf() * 1000;
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
result = d.valueOf() * 1000000;
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
return showDateTime ? `${result} (${d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss")} UTC)` : result.toString();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DATETIME_FORMATS: [
|
||||
{
|
||||
name: "Standard date and time",
|
||||
value: "DD/MM/YYYY HH:mm:ss"
|
||||
},
|
||||
{
|
||||
name: "American-style date and time",
|
||||
value: "MM/DD/YYYY HH:mm:ss"
|
||||
},
|
||||
{
|
||||
name: "International date and time",
|
||||
value: "YYYY-MM-DD HH:mm:ss"
|
||||
},
|
||||
{
|
||||
name: "Verbose date and time",
|
||||
value: "dddd Do MMMM YYYY HH:mm:ss Z z"
|
||||
},
|
||||
{
|
||||
name: "UNIX timestamp (seconds)",
|
||||
value: "X"
|
||||
},
|
||||
{
|
||||
name: "UNIX timestamp offset (milliseconds)",
|
||||
value: "x"
|
||||
},
|
||||
{
|
||||
name: "Automatic",
|
||||
value: ""
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INPUT_FORMAT_STRING: "DD/MM/YYYY HH:mm:ss",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_FORMAT_STRING: "dddd Do MMMM YYYY HH:mm:ss Z z",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TIMEZONES: ["UTC"].concat(moment.tz.names()),
|
||||
|
||||
/**
|
||||
* Translate DateTime Format operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runTranslateFormat: function(input, args) {
|
||||
let inputFormat = args[1],
|
||||
inputTimezone = args[2],
|
||||
outputFormat = args[3],
|
||||
outputTimezone = args[4],
|
||||
date;
|
||||
|
||||
try {
|
||||
date = moment.tz(input, inputFormat, inputTimezone);
|
||||
if (!date || date.format() === "Invalid date") throw Error;
|
||||
} catch (err) {
|
||||
return "Invalid format.\n\n" + DateTime.FORMAT_EXAMPLES;
|
||||
}
|
||||
|
||||
return date.tz(outputTimezone).format(outputFormat);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse DateTime operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runParse: function(input, args) {
|
||||
let inputFormat = args[1],
|
||||
inputTimezone = args[2],
|
||||
date,
|
||||
output = "";
|
||||
|
||||
try {
|
||||
date = moment.tz(input, inputFormat, inputTimezone);
|
||||
if (!date || date.format() === "Invalid date") throw Error;
|
||||
} catch (err) {
|
||||
return "Invalid format.\n\n" + DateTime.FORMAT_EXAMPLES;
|
||||
}
|
||||
|
||||
output += "Date: " + date.format("dddd Do MMMM YYYY") +
|
||||
"\nTime: " + date.format("HH:mm:ss") +
|
||||
"\nPeriod: " + date.format("A") +
|
||||
"\nTimezone: " + date.format("z") +
|
||||
"\nUTC offset: " + date.format("ZZ") +
|
||||
"\n\nDaylight Saving Time: " + date.isDST() +
|
||||
"\nLeap year: " + date.isLeapYear() +
|
||||
"\nDays in this month: " + date.daysInMonth() +
|
||||
"\n\nDay of year: " + date.dayOfYear() +
|
||||
"\nWeek number: " + date.weekYear() +
|
||||
"\nQuarter: " + date.quarter();
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sleep operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runSleep: async function(input, args) {
|
||||
const ms = args[0];
|
||||
await new Promise(r => setTimeout(r, ms));
|
||||
return input;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
*/
|
||||
FORMAT_EXAMPLES: `Format string tokens:
|
||||
|
||||
|
||||
<table class="table table-striped table-hover table-condensed table-bordered" style="font-family: sans-serif">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th>Token</th>
|
||||
<th>Output</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>Month</b></td>
|
||||
<td>M</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Mo</td>
|
||||
<td>1st 2nd ... 11th 12th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MM</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMM</td>
|
||||
<td>Jan Feb ... Nov Dec</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMMM</td>
|
||||
<td>January February ... November December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Quarter</b></td>
|
||||
<td>Q</td>
|
||||
<td>1 2 3 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Month</b></td>
|
||||
<td>D</td>
|
||||
<td>1 2 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Do</td>
|
||||
<td>1st 2nd ... 30th 31st</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DD</td>
|
||||
<td>01 02 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Year</b></td>
|
||||
<td>DDD</td>
|
||||
<td>1 2 ... 364 365</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DDDo</td>
|
||||
<td>1st 2nd ... 364th 365th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DDDD</td>
|
||||
<td>001 002 ... 364 365</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week</b></td>
|
||||
<td>d</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>do</td>
|
||||
<td>0th 1st ... 5th 6th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dd</td>
|
||||
<td>Su Mo ... Fr Sa</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ddd</td>
|
||||
<td>Sun Mon ... Fri Sat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dddd</td>
|
||||
<td>Sunday Monday ... Friday Saturday</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week (Locale)</b></td>
|
||||
<td>e</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week (ISO)</b></td>
|
||||
<td>E</td>
|
||||
<td>1 2 ... 6 7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week of Year</b></td>
|
||||
<td>w</td>
|
||||
<td>1 2 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>wo</td>
|
||||
<td>1st 2nd ... 52nd 53rd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ww</td>
|
||||
<td>01 02 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week of Year (ISO)</b></td>
|
||||
<td>W</td>
|
||||
<td>1 2 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Wo</td>
|
||||
<td>1st 2nd ... 52nd 53rd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>WW</td>
|
||||
<td>01 02 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Year</b></td>
|
||||
<td>YY</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>YYYY</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week Year</b></td>
|
||||
<td>gg</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>gggg</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week Year (ISO)</b></td>
|
||||
<td>GG</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>GGGG</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>AM/PM</b></td>
|
||||
<td>A</td>
|
||||
<td>AM PM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>a</td>
|
||||
<td>am pm</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hour</b></td>
|
||||
<td>H</td>
|
||||
<td>0 1 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>HH</td>
|
||||
<td>00 01 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>h</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>hh</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Minute</b></td>
|
||||
<td>m</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>mm</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Second</b></td>
|
||||
<td>s</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ss</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Fractional Second</b></td>
|
||||
<td>S</td>
|
||||
<td>0 1 ... 8 9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SS</td>
|
||||
<td>00 01 ... 98 99</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSS</td>
|
||||
<td>000 001 ... 998 999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSSS ... SSSSSSSSS</td>
|
||||
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Timezone</b></td>
|
||||
<td>z or zz</td>
|
||||
<td>EST CST ... MST PST</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Z</td>
|
||||
<td>-07:00 -06:00 ... +06:00 +07:00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ZZ</td>
|
||||
<td>-0700 -0600 ... +0600 +0700</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Unix Timestamp</b></td>
|
||||
<td>X</td>
|
||||
<td>1360013296</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Unix Millisecond Timestamp</b></td>
|
||||
<td>x</td>
|
||||
<td>1360013296123</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>`,
|
||||
|
||||
};
|
||||
|
||||
export default DateTime;
|
@ -1,94 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import * as JsDiff from "diff";
|
||||
|
||||
|
||||
/**
|
||||
* Diff operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Diff = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DIFF_SAMPLE_DELIMITER: "\\n\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
|
||||
|
||||
/**
|
||||
* Diff operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runDiff: function(input, args) {
|
||||
let sampleDelim = args[0],
|
||||
diffBy = args[1],
|
||||
showAdded = args[2],
|
||||
showRemoved = args[3],
|
||||
ignoreWhitespace = args[4],
|
||||
samples = input.split(sampleDelim),
|
||||
output = "",
|
||||
diff;
|
||||
|
||||
if (!samples || samples.length !== 2) {
|
||||
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
|
||||
}
|
||||
|
||||
switch (diffBy) {
|
||||
case "Character":
|
||||
diff = JsDiff.diffChars(samples[0], samples[1]);
|
||||
break;
|
||||
case "Word":
|
||||
if (ignoreWhitespace) {
|
||||
diff = JsDiff.diffWords(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Line":
|
||||
if (ignoreWhitespace) {
|
||||
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffLines(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Sentence":
|
||||
diff = JsDiff.diffSentences(samples[0], samples[1]);
|
||||
break;
|
||||
case "CSS":
|
||||
diff = JsDiff.diffCss(samples[0], samples[1]);
|
||||
break;
|
||||
case "JSON":
|
||||
diff = JsDiff.diffJson(samples[0], samples[1]);
|
||||
break;
|
||||
default:
|
||||
return "Invalid 'Diff by' option.";
|
||||
}
|
||||
|
||||
for (let i = 0; i < diff.length; i++) {
|
||||
if (diff[i].added) {
|
||||
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else if (diff[i].removed) {
|
||||
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else {
|
||||
output += Utils.escapeHtml(diff[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Diff;
|
@ -1,100 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import {toHex, fromHex} from "../lib/Hex";
|
||||
|
||||
|
||||
/**
|
||||
* Endian operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Endian = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DATA_FORMAT: ["Hex", "Raw"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WORD_LENGTH: 4,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_INCOMPLETE_WORDS: true,
|
||||
|
||||
/**
|
||||
* Swap endianness operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSwapEndianness: function(input, args) {
|
||||
let dataFormat = args[0],
|
||||
wordLength = args[1],
|
||||
padIncompleteWords = args[2],
|
||||
data = [],
|
||||
result = [],
|
||||
words = [],
|
||||
i = 0,
|
||||
j = 0;
|
||||
|
||||
if (wordLength <= 0) {
|
||||
return "Word length must be greater than 0";
|
||||
}
|
||||
|
||||
// Convert input to raw data based on specified data format
|
||||
switch (dataFormat) {
|
||||
case "Hex":
|
||||
data = fromHex(input);
|
||||
break;
|
||||
case "Raw":
|
||||
data = Utils.strToByteArray(input);
|
||||
break;
|
||||
default:
|
||||
data = input;
|
||||
}
|
||||
|
||||
// Split up into words
|
||||
for (i = 0; i < data.length; i += wordLength) {
|
||||
const word = data.slice(i, i + wordLength);
|
||||
|
||||
// Pad word if too short
|
||||
if (padIncompleteWords && word.length < wordLength){
|
||||
for (j = word.length; j < wordLength; j++) {
|
||||
word.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
words.push(word);
|
||||
}
|
||||
|
||||
// Swap endianness and flatten
|
||||
for (i = 0; i < words.length; i++) {
|
||||
j = words[i].length;
|
||||
while (j--) {
|
||||
result.push(words[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert data back to specified data format
|
||||
switch (dataFormat) {
|
||||
case "Hex":
|
||||
return toHex(result);
|
||||
case "Raw":
|
||||
return Utils.byteArrayToUtf8(result);
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Endian;
|
@ -1,195 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Entropy operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Entropy = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CHUNK_SIZE: 1000,
|
||||
|
||||
/**
|
||||
* Entropy operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runEntropy: function(input, args) {
|
||||
let chunkSize = args[0],
|
||||
output = "",
|
||||
entropy = Entropy._calcEntropy(input);
|
||||
|
||||
output += "Shannon entropy: " + entropy + "\n" +
|
||||
"<br><canvas id='chart-area'></canvas><br>\n" +
|
||||
"- 0 represents no randomness (i.e. all the bytes in the data have the same value) whereas 8, the maximum, represents a completely random string.\n" +
|
||||
"- Standard English text usually falls somewhere between 3.5 and 5.\n" +
|
||||
"- Properly encrypted or compressed data of a reasonable length should have an entropy of over 7.5.\n\n" +
|
||||
"The following results show the entropy of chunks of the input data. Chunks with particularly high entropy could suggest encrypted or compressed sections.\n\n" +
|
||||
"<br><script>\
|
||||
var canvas = document.getElementById('chart-area'),\
|
||||
parentRect = canvas.parentNode.getBoundingClientRect(),\
|
||||
entropy = " + entropy + ",\
|
||||
height = parentRect.height * 0.25;\
|
||||
\
|
||||
canvas.width = parentRect.width * 0.95;\
|
||||
canvas.height = height > 150 ? 150 : height;\
|
||||
\
|
||||
CanvasComponents.drawScaleBar(canvas, entropy, 8, [\
|
||||
{\
|
||||
label: 'English text',\
|
||||
min: 3.5,\
|
||||
max: 5\
|
||||
},{\
|
||||
label: 'Encrypted/compressed',\
|
||||
min: 7.5,\
|
||||
max: 8\
|
||||
}\
|
||||
]);\
|
||||
</script>";
|
||||
|
||||
let chunkEntropy = 0;
|
||||
if (chunkSize !== 0) {
|
||||
for (let i = 0; i < input.length; i += chunkSize) {
|
||||
chunkEntropy = Entropy._calcEntropy(input.slice(i, i+chunkSize));
|
||||
output += "Bytes " + i + " to " + (i+chunkSize) + ": " + chunkEntropy + "\n";
|
||||
}
|
||||
} else {
|
||||
output += "Chunk size cannot be 0.";
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FREQ_ZEROS: false,
|
||||
|
||||
/**
|
||||
* Frequency distribution operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runFreqDistrib: function (input, args) {
|
||||
const data = new Uint8Array(input);
|
||||
if (!data.length) return "No data";
|
||||
|
||||
let distrib = new Array(256).fill(0),
|
||||
percentages = new Array(256),
|
||||
len = data.length,
|
||||
showZeroes = args[0],
|
||||
i;
|
||||
|
||||
// Count bytes
|
||||
for (i = 0; i < len; i++) {
|
||||
distrib[data[i]]++;
|
||||
}
|
||||
|
||||
// Calculate percentages
|
||||
let repr = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (distrib[i] > 0) repr++;
|
||||
percentages[i] = distrib[i] / len * 100;
|
||||
}
|
||||
|
||||
// Print
|
||||
let output = "<canvas id='chart-area'></canvas><br>" +
|
||||
"Total data length: " + len +
|
||||
"\nNumber of bytes represented: " + repr +
|
||||
"\nNumber of bytes not represented: " + (256-repr) +
|
||||
"\n\nByte Percentage\n" +
|
||||
"<script>\
|
||||
var canvas = document.getElementById('chart-area'),\
|
||||
parentRect = canvas.parentNode.getBoundingClientRect(),\
|
||||
scores = " + JSON.stringify(percentages) + ";\
|
||||
\
|
||||
canvas.width = parentRect.width * 0.95;\
|
||||
canvas.height = parentRect.height * 0.9;\
|
||||
\
|
||||
CanvasComponents.drawBarChart(canvas, scores, 'Byte', 'Frequency %', 16, 6);\
|
||||
</script>";
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (distrib[i] || showZeroes) {
|
||||
output += " " + Utils.hex(i, 2) + " (" +
|
||||
(percentages[i].toFixed(2).replace(".00", "") + "%)").padEnd(8, " ") +
|
||||
Array(Math.ceil(percentages[i])+1).join("|") + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Chi Square operation.
|
||||
*
|
||||
* @param {ArrayBuffer} data
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runChiSq: function(input, args) {
|
||||
const data = new Uint8Array(input);
|
||||
let distArray = new Array(256).fill(0),
|
||||
total = 0;
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
distArray[data[i]]++;
|
||||
}
|
||||
|
||||
for (let i = 0; i < distArray.length; i++) {
|
||||
if (distArray[i] > 0) {
|
||||
total += Math.pow(distArray[i] - data.length / 256, 2) / (data.length / 256);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Shannon entropy for a given chunk of data.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} data
|
||||
* @returns {number}
|
||||
*/
|
||||
_calcEntropy: function(data) {
|
||||
let prob = [],
|
||||
uniques = data.unique(),
|
||||
str = Utils.byteArrayToChars(data),
|
||||
i;
|
||||
|
||||
for (i = 0; i < uniques.length; i++) {
|
||||
prob.push(str.count(Utils.chr(uniques[i])) / data.length);
|
||||
}
|
||||
|
||||
let entropy = 0,
|
||||
p;
|
||||
|
||||
for (i = 0; i < prob.length; i++) {
|
||||
p = prob[i];
|
||||
entropy += p * Math.log(p) / Math.log(2);
|
||||
}
|
||||
|
||||
return -entropy;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Entropy;
|
@ -1,542 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* File type operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const FileType = {
|
||||
|
||||
/**
|
||||
* Detect File Type operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDetect: function(input, args) {
|
||||
const data = new Uint8Array(input),
|
||||
type = FileType.magicType(data);
|
||||
|
||||
if (!type) {
|
||||
return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
|
||||
} else {
|
||||
let output = "File extension: " + type.ext + "\n" +
|
||||
"MIME type: " + type.mime;
|
||||
|
||||
if (type.desc && type.desc.length) {
|
||||
output += "\nDescription: " + type.desc;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IGNORE_COMMON_BYTE_SEQUENCES: true,
|
||||
|
||||
/**
|
||||
* Scan for Embedded Files operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runScanForEmbeddedFiles: function(input, args) {
|
||||
let output = "Scanning data for 'magic bytes' which may indicate embedded files. The following results may be false positives and should not be treat as reliable. Any suffiently long file is likely to contain these magic bytes coincidentally.\n",
|
||||
type,
|
||||
numFound = 0,
|
||||
numCommonFound = 0;
|
||||
const ignoreCommon = args[0],
|
||||
commonExts = ["ico", "ttf", ""],
|
||||
data = new Uint8Array(input);
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
type = FileType.magicType(data.slice(i));
|
||||
if (type) {
|
||||
if (ignoreCommon && commonExts.indexOf(type.ext) > -1) {
|
||||
numCommonFound++;
|
||||
continue;
|
||||
}
|
||||
numFound++;
|
||||
output += "\nOffset " + i + " (0x" + Utils.hex(i) + "):\n" +
|
||||
" File extension: " + type.ext + "\n" +
|
||||
" MIME type: " + type.mime + "\n";
|
||||
|
||||
if (type.desc && type.desc.length) {
|
||||
output += " Description: " + type.desc + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numFound === 0) {
|
||||
output += "\nNo embedded files were found.";
|
||||
}
|
||||
|
||||
if (numCommonFound > 0) {
|
||||
output += "\n\n" + numCommonFound;
|
||||
output += numCommonFound === 1 ?
|
||||
" file type was detected that has a common byte sequence. This is likely to be a false positive." :
|
||||
" file types were detected that have common byte sequences. These are likely to be false positives.";
|
||||
output += " Run this operation with the 'Ignore common byte sequences' option unchecked to see details.";
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Given a buffer, detects magic byte sequences at specific positions and returns the
|
||||
* extension and mime type.
|
||||
*
|
||||
* @param {Uint8Array} buf
|
||||
* @returns {Object} type
|
||||
* @returns {string} type.ext - File extension
|
||||
* @returns {string} type.mime - Mime type
|
||||
* @returns {string} [type.desc] - Description
|
||||
*/
|
||||
magicType: function (buf) {
|
||||
if (!(buf && buf.length > 1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF) {
|
||||
return {
|
||||
ext: "jpg",
|
||||
mime: "image/jpeg"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47) {
|
||||
return {
|
||||
ext: "png",
|
||||
mime: "image/png"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46) {
|
||||
return {
|
||||
ext: "gif",
|
||||
mime: "image/gif"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) {
|
||||
return {
|
||||
ext: "webp",
|
||||
mime: "image/webp"
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `tif` check
|
||||
if (((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) && buf[8] === 0x43 && buf[9] === 0x52) {
|
||||
return {
|
||||
ext: "cr2",
|
||||
mime: "image/x-canon-cr2"
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) {
|
||||
return {
|
||||
ext: "tif",
|
||||
mime: "image/tiff"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x42 && buf[1] === 0x4D) {
|
||||
return {
|
||||
ext: "bmp",
|
||||
mime: "image/bmp"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0xBC) {
|
||||
return {
|
||||
ext: "jxr",
|
||||
mime: "image/vnd.ms-photo"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x38 && buf[1] === 0x42 && buf[2] === 0x50 && buf[3] === 0x53) {
|
||||
return {
|
||||
ext: "psd",
|
||||
mime: "image/vnd.adobe.photoshop"
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `zip` check
|
||||
if (buf[0] === 0x50 && buf[1] === 0x4B && buf[2] === 0x3 && buf[3] === 0x4 && buf[30] === 0x6D && buf[31] === 0x69 && buf[32] === 0x6D && buf[33] === 0x65 && buf[34] === 0x74 && buf[35] === 0x79 && buf[36] === 0x70 && buf[37] === 0x65 && buf[38] === 0x61 && buf[39] === 0x70 && buf[40] === 0x70 && buf[41] === 0x6C && buf[42] === 0x69 && buf[43] === 0x63 && buf[44] === 0x61 && buf[45] === 0x74 && buf[46] === 0x69 && buf[47] === 0x6F && buf[48] === 0x6E && buf[49] === 0x2F && buf[50] === 0x65 && buf[51] === 0x70 && buf[52] === 0x75 && buf[53] === 0x62 && buf[54] === 0x2B && buf[55] === 0x7A && buf[56] === 0x69 && buf[57] === 0x70) {
|
||||
return {
|
||||
ext: "epub",
|
||||
mime: "application/epub+zip"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x50 && buf[1] === 0x4B && (buf[2] === 0x3 || buf[2] === 0x5 || buf[2] === 0x7) && (buf[3] === 0x4 || buf[3] === 0x6 || buf[3] === 0x8)) {
|
||||
return {
|
||||
ext: "zip",
|
||||
mime: "application/zip"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[257] === 0x75 && buf[258] === 0x73 && buf[259] === 0x74 && buf[260] === 0x61 && buf[261] === 0x72) {
|
||||
return {
|
||||
ext: "tar",
|
||||
mime: "application/x-tar"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x52 && buf[1] === 0x61 && buf[2] === 0x72 && buf[3] === 0x21 && buf[4] === 0x1A && buf[5] === 0x7 && (buf[6] === 0x0 || buf[6] === 0x1)) {
|
||||
return {
|
||||
ext: "rar",
|
||||
mime: "application/x-rar-compressed"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x1F && buf[1] === 0x8B && buf[2] === 0x8) {
|
||||
return {
|
||||
ext: "gz",
|
||||
mime: "application/gzip"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x42 && buf[1] === 0x5A && buf[2] === 0x68) {
|
||||
return {
|
||||
ext: "bz2",
|
||||
mime: "application/x-bzip2"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x37 && buf[1] === 0x7A && buf[2] === 0xBC && buf[3] === 0xAF && buf[4] === 0x27 && buf[5] === 0x1C) {
|
||||
return {
|
||||
ext: "7z",
|
||||
mime: "application/x-7z-compressed"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x78 && buf[1] === 0x01) {
|
||||
return {
|
||||
ext: "dmg, zlib",
|
||||
mime: "application/x-apple-diskimage, application/x-deflate"
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && (buf[3] === 0x18 || buf[3] === 0x20) && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) || (buf[0] === 0x33 && buf[1] === 0x67 && buf[2] === 0x70 && buf[3] === 0x35) || (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x6D && buf[9] === 0x70 && buf[10] === 0x34 && buf[11] === 0x32 && buf[16] === 0x6D && buf[17] === 0x70 && buf[18] === 0x34 && buf[19] === 0x31 && buf[20] === 0x6D && buf[21] === 0x70 && buf[22] === 0x34 && buf[23] === 0x32 && buf[24] === 0x69 && buf[25] === 0x73 && buf[26] === 0x6F && buf[27] === 0x6D)) {
|
||||
return {
|
||||
ext: "mp4",
|
||||
mime: "video/mp4"
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x4D && buf[9] === 0x34 && buf[10] === 0x56)) {
|
||||
return {
|
||||
ext: "m4v",
|
||||
mime: "video/x-m4v"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4D && buf[1] === 0x54 && buf[2] === 0x68 && buf[3] === 0x64) {
|
||||
return {
|
||||
ext: "mid",
|
||||
mime: "audio/midi"
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before the `webm` check
|
||||
if (buf[31] === 0x6D && buf[32] === 0x61 && buf[33] === 0x74 && buf[34] === 0x72 && buf[35] === 0x6f && buf[36] === 0x73 && buf[37] === 0x6B && buf[38] === 0x61) {
|
||||
return {
|
||||
ext: "mkv",
|
||||
mime: "video/x-matroska"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x1A && buf[1] === 0x45 && buf[2] === 0xDF && buf[3] === 0xA3) {
|
||||
return {
|
||||
ext: "webm",
|
||||
mime: "video/webm"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x14 && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) {
|
||||
return {
|
||||
ext: "mov",
|
||||
mime: "video/quicktime"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x41 && buf[9] === 0x56 && buf[10] === 0x49) {
|
||||
return {
|
||||
ext: "avi",
|
||||
mime: "video/x-msvideo"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x30 && buf[1] === 0x26 && buf[2] === 0xB2 && buf[3] === 0x75 && buf[4] === 0x8E && buf[5] === 0x66 && buf[6] === 0xCF && buf[7] === 0x11 && buf[8] === 0xA6 && buf[9] === 0xD9) {
|
||||
return {
|
||||
ext: "wmv",
|
||||
mime: "video/x-ms-wmv"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x1 && buf[3].toString(16)[0] === "b") {
|
||||
return {
|
||||
ext: "mpg",
|
||||
mime: "video/mpeg"
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x49 && buf[1] === 0x44 && buf[2] === 0x33) || (buf[0] === 0xFF && buf[1] === 0xfb)) {
|
||||
return {
|
||||
ext: "mp3",
|
||||
mime: "audio/mpeg"
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x4D && buf[9] === 0x34 && buf[10] === 0x41) || (buf[0] === 0x4D && buf[1] === 0x34 && buf[2] === 0x41 && buf[3] === 0x20)) {
|
||||
return {
|
||||
ext: "m4a",
|
||||
mime: "audio/m4a"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4F && buf[1] === 0x67 && buf[2] === 0x67 && buf[3] === 0x53) {
|
||||
return {
|
||||
ext: "ogg",
|
||||
mime: "audio/ogg"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x66 && buf[1] === 0x4C && buf[2] === 0x61 && buf[3] === 0x43) {
|
||||
return {
|
||||
ext: "flac",
|
||||
mime: "audio/x-flac"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45) {
|
||||
return {
|
||||
ext: "wav",
|
||||
mime: "audio/x-wav"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x23 && buf[1] === 0x21 && buf[2] === 0x41 && buf[3] === 0x4D && buf[4] === 0x52 && buf[5] === 0x0A) {
|
||||
return {
|
||||
ext: "amr",
|
||||
mime: "audio/amr"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x25 && buf[1] === 0x50 && buf[2] === 0x44 && buf[3] === 0x46) {
|
||||
return {
|
||||
ext: "pdf",
|
||||
mime: "application/pdf"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4D && buf[1] === 0x5A) {
|
||||
return {
|
||||
ext: "exe",
|
||||
mime: "application/x-msdownload"
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x43 || buf[0] === 0x46) && buf[1] === 0x57 && buf[2] === 0x53) {
|
||||
return {
|
||||
ext: "swf",
|
||||
mime: "application/x-shockwave-flash"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x7B && buf[1] === 0x5C && buf[2] === 0x72 && buf[3] === 0x74 && buf[4] === 0x66) {
|
||||
return {
|
||||
ext: "rtf",
|
||||
mime: "application/rtf"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x77 && buf[1] === 0x4F && buf[2] === 0x46 && buf[3] === 0x46 && buf[4] === 0x00 && buf[5] === 0x01 && buf[6] === 0x00 && buf[7] === 0x00) {
|
||||
return {
|
||||
ext: "woff",
|
||||
mime: "application/font-woff"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x77 && buf[1] === 0x4F && buf[2] === 0x46 && buf[3] === 0x32 && buf[4] === 0x00 && buf[5] === 0x01 && buf[6] === 0x00 && buf[7] === 0x00) {
|
||||
return {
|
||||
ext: "woff2",
|
||||
mime: "application/font-woff"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[34] === 0x4C && buf[35] === 0x50 && ((buf[8] === 0x02 && buf[9] === 0x00 && buf[10] === 0x01) || (buf[8] === 0x01 && buf[9] === 0x00 && buf[10] === 0x00) || (buf[8] === 0x02 && buf[9] === 0x00 && buf[10] === 0x02))) {
|
||||
return {
|
||||
ext: "eot",
|
||||
mime: "application/octet-stream"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x00 && buf[1] === 0x01 && buf[2] === 0x00 && buf[3] === 0x00 && buf[4] === 0x00) {
|
||||
return {
|
||||
ext: "ttf",
|
||||
mime: "application/font-sfnt"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4F && buf[1] === 0x54 && buf[2] === 0x54 && buf[3] === 0x4F && buf[4] === 0x00) {
|
||||
return {
|
||||
ext: "otf",
|
||||
mime: "application/font-sfnt"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x00 && buf[1] === 0x00 && buf[2] === 0x01 && buf[3] === 0x00) {
|
||||
return {
|
||||
ext: "ico",
|
||||
mime: "image/x-icon"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x46 && buf[1] === 0x4C && buf[2] === 0x56 && buf[3] === 0x01) {
|
||||
return {
|
||||
ext: "flv",
|
||||
mime: "video/x-flv"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x25 && buf[1] === 0x21) {
|
||||
return {
|
||||
ext: "ps",
|
||||
mime: "application/postscript"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xFD && buf[1] === 0x37 && buf[2] === 0x7A && buf[3] === 0x58 && buf[4] === 0x5A && buf[5] === 0x00) {
|
||||
return {
|
||||
ext: "xz",
|
||||
mime: "application/x-xz"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x53 && buf[1] === 0x51 && buf[2] === 0x4C && buf[3] === 0x69) {
|
||||
return {
|
||||
ext: "sqlite",
|
||||
mime: "application/x-sqlite3"
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Added by n1474335 [n1474335@gmail.com] from here on
|
||||
*
|
||||
*/
|
||||
if ((buf[0] === 0x1F && buf[1] === 0x9D) || (buf[0] === 0x1F && buf[1] === 0xA0)) {
|
||||
return {
|
||||
ext: "z, tar.z",
|
||||
mime: "application/x-gtar"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x7F && buf[1] === 0x45 && buf[2] === 0x4C && buf[3] === 0x46) {
|
||||
return {
|
||||
ext: "none, axf, bin, elf, o, prx, puff, so",
|
||||
mime: "application/x-executable",
|
||||
desc: "Executable and Linkable Format file. No standard file extension."
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xCA && buf[1] === 0xFE && buf[2] === 0xBA && buf[3] === 0xBE) {
|
||||
return {
|
||||
ext: "class",
|
||||
mime: "application/java-vm"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) {
|
||||
return {
|
||||
ext: "txt",
|
||||
mime: "text/plain",
|
||||
desc: "UTF-8 encoded Unicode byte order mark detected, commonly but not exclusively seen in text files."
|
||||
};
|
||||
}
|
||||
|
||||
// Must be before Little-endian UTF-16 BOM
|
||||
if (buf[0] === 0xFF && buf[1] === 0xFE && buf[2] === 0x00 && buf[3] === 0x00) {
|
||||
return {
|
||||
ext: "UTF32LE",
|
||||
mime: "charset/utf32le",
|
||||
desc: "Little-endian UTF-32 encoded Unicode byte order mark detected."
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xFF && buf[1] === 0xFE) {
|
||||
return {
|
||||
ext: "UTF16LE",
|
||||
mime: "charset/utf16le",
|
||||
desc: "Little-endian UTF-16 encoded Unicode byte order mark detected."
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0x8001] === 0x43 && buf[0x8002] === 0x44 && buf[0x8003] === 0x30 && buf[0x8004] === 0x30 && buf[0x8005] === 0x31) ||
|
||||
(buf[0x8801] === 0x43 && buf[0x8802] === 0x44 && buf[0x8803] === 0x30 && buf[0x8804] === 0x30 && buf[0x8805] === 0x31) ||
|
||||
(buf[0x9001] === 0x43 && buf[0x9002] === 0x44 && buf[0x9003] === 0x30 && buf[0x9004] === 0x30 && buf[0x9005] === 0x31)) {
|
||||
return {
|
||||
ext: "iso",
|
||||
mime: "application/octet-stream",
|
||||
desc: "ISO 9660 CD/DVD image file"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xD0 && buf[1] === 0xCF && buf[2] === 0x11 && buf[3] === 0xE0 && buf[4] === 0xA1 && buf[5] === 0xB1 && buf[6] === 0x1A && buf[7] === 0xE1) {
|
||||
return {
|
||||
ext: "doc, xls, ppt",
|
||||
mime: "application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint",
|
||||
desc: "Microsoft Office documents"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x64 && buf[1] === 0x65 && buf[2] === 0x78 && buf[3] === 0x0A && buf[4] === 0x30 && buf[5] === 0x33 && buf[6] === 0x35 && buf[7] === 0x00) {
|
||||
return {
|
||||
ext: "dex",
|
||||
mime: "application/octet-stream",
|
||||
desc: "Dalvik Executable (Android)"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4B && buf[1] === 0x44 && buf[2] === 0x4D) {
|
||||
return {
|
||||
ext: "vmdk",
|
||||
mime: "application/vmdk, application/x-virtualbox-vmdk"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x43 && buf[1] === 0x72 && buf[2] === 0x32 && buf[3] === 0x34) {
|
||||
return {
|
||||
ext: "crx",
|
||||
mime: "application/crx",
|
||||
desc: "Google Chrome extension or packaged app"
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x78 && (buf[1] === 0x01 || buf[1] === 0x9C || buf[1] === 0xDA || buf[1] === 0x5e)) {
|
||||
return {
|
||||
ext: "zlib",
|
||||
mime: "application/x-deflate"
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default FileType;
|
@ -1,103 +0,0 @@
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* Windows Filetime operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Filetime = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FILETIME_FORMATS: ["Decimal", "Hex"],
|
||||
|
||||
/**
|
||||
* Windows Filetime to Unix Timestamp operation.
|
||||
*
|
||||
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFromFiletimeToUnix: function(input, args) {
|
||||
let units = args[0],
|
||||
format = args[1];
|
||||
|
||||
if (!input) return "";
|
||||
|
||||
if (format === "Hex") {
|
||||
input = new BigNumber(input, 16);
|
||||
} else {
|
||||
input = new BigNumber(input);
|
||||
}
|
||||
|
||||
input = input.minus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.dividedBy(new BigNumber("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
input = input.dividedBy(new BigNumber("10000"));
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
input = input.dividedBy(new BigNumber("10"));
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
input = input.multipliedBy(new BigNumber("100"));
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
return input.toFixed();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Unix Timestamp to Windows Filetime operation.
|
||||
*
|
||||
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToFiletimeFromUnix: function(input, args) {
|
||||
let units = args[0],
|
||||
format = args[1];
|
||||
|
||||
if (!input) return "";
|
||||
|
||||
input = new BigNumber(input);
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.multipliedBy(new BigNumber("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
input = input.multipliedBy(new BigNumber("10000"));
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
input = input.multiplyiedBy(new BigNumber("10"));
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
input = input.dividedBy(new BigNumber("100"));
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
input = input.plus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (format === "Hex"){
|
||||
return input.toString(16);
|
||||
} else {
|
||||
return input.toFixed();
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Filetime;
|
@ -1,857 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* HTML operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const HTML = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CONVERT_ALL: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CONVERT_OPTIONS: ["Named entities where possible", "Numeric entities", "Hex entities"],
|
||||
|
||||
/**
|
||||
* To HTML Entity operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToEntity: function(input, args) {
|
||||
let convertAll = args[0],
|
||||
numeric = args[1] === "Numeric entities",
|
||||
hexa = args[1] === "Hex entities";
|
||||
|
||||
const charcodes = Utils.strToCharcode(input);
|
||||
let output = "";
|
||||
|
||||
for (let i = 0; i < charcodes.length; i++) {
|
||||
if (convertAll && numeric) {
|
||||
output += "&#" + charcodes[i] + ";";
|
||||
} else if (convertAll && hexa) {
|
||||
output += "&#x" + Utils.hex(charcodes[i]) + ";";
|
||||
} else if (convertAll) {
|
||||
output += HTML._byteToEntity[charcodes[i]] || "&#" + charcodes[i] + ";";
|
||||
} else if (numeric) {
|
||||
if (charcodes[i] > 255 || HTML._byteToEntity.hasOwnProperty(charcodes[i])) {
|
||||
output += "&#" + charcodes[i] + ";";
|
||||
} else {
|
||||
output += Utils.chr(charcodes[i]);
|
||||
}
|
||||
} else if (hexa) {
|
||||
if (charcodes[i] > 255 || HTML._byteToEntity.hasOwnProperty(charcodes[i])) {
|
||||
output += "&#x" + Utils.hex(charcodes[i]) + ";";
|
||||
} else {
|
||||
output += Utils.chr(charcodes[i]);
|
||||
}
|
||||
} else {
|
||||
output += HTML._byteToEntity[charcodes[i]] || (
|
||||
charcodes[i] > 255 ?
|
||||
"&#" + charcodes[i] + ";" :
|
||||
Utils.chr(charcodes[i])
|
||||
);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From HTML Entity operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFromEntity: function(input, args) {
|
||||
let regex = /&(#?x?[a-zA-Z0-9]{1,8});/g,
|
||||
output = "",
|
||||
m,
|
||||
i = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Add up to match
|
||||
for (; i < m.index;)
|
||||
output += input[i++];
|
||||
|
||||
// Add match
|
||||
const bite = HTML._entityToByte[m[1]];
|
||||
if (bite) {
|
||||
output += Utils.chr(bite);
|
||||
} else if (!bite && m[1][0] === "#" && m[1].length > 1 && /^#\d{1,6}$/.test(m[1])) {
|
||||
// Numeric entity (e.g. )
|
||||
const num = m[1].slice(1, m[1].length);
|
||||
output += Utils.chr(parseInt(num, 10));
|
||||
} else if (!bite && m[1][0] === "#" && m[1].length > 3 && /^#x[\dA-F]{2,8}$/i.test(m[1])) {
|
||||
// Hex entity (e.g. :)
|
||||
const hex = m[1].slice(2, m[1].length);
|
||||
output += Utils.chr(parseInt(hex, 16));
|
||||
} else {
|
||||
// Not a valid entity, print as normal
|
||||
for (; i < regex.lastIndex;)
|
||||
output += input[i++];
|
||||
}
|
||||
|
||||
i = regex.lastIndex;
|
||||
}
|
||||
// Add all after final match
|
||||
for (; i < input.length;)
|
||||
output += input[i++];
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_INDENTATION: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_LINE_BREAKS: true,
|
||||
|
||||
/**
|
||||
* Strip HTML tags operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runStripTags: function(input, args) {
|
||||
let removeIndentation = args[0],
|
||||
removeLineBreaks = args[1];
|
||||
|
||||
input = Utils.stripHtmlTags(input);
|
||||
|
||||
if (removeIndentation) {
|
||||
input = input.replace(/\n[ \f\t]+/g, "\n");
|
||||
}
|
||||
|
||||
if (removeLineBreaks) {
|
||||
input = input
|
||||
.replace(/^\s*\n/, "") // first line
|
||||
.replace(/(\n\s*){2,}/g, "\n"); // all others
|
||||
}
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse colour code operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runParseColourCode: function(input, args) {
|
||||
let m = null,
|
||||
r = 0, g = 0, b = 0, a = 1;
|
||||
|
||||
// Read in the input
|
||||
if ((m = input.match(/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i))) {
|
||||
// Hex - #d9edf7
|
||||
r = parseInt(m[1], 16);
|
||||
g = parseInt(m[2], 16);
|
||||
b = parseInt(m[3], 16);
|
||||
} else if ((m = input.match(/rgba?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)(?:,\s?(\d(?:\.\d+)?))?\)/i))) {
|
||||
// RGB or RGBA - rgb(217,237,247) or rgba(217,237,247,1)
|
||||
r = parseFloat(m[1]);
|
||||
g = parseFloat(m[2]);
|
||||
b = parseFloat(m[3]);
|
||||
a = m[4] ? parseFloat(m[4]) : 1;
|
||||
} else if ((m = input.match(/hsla?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)%,\s?(\d{1,3}(?:\.\d+)?)%(?:,\s?(\d(?:\.\d+)?))?\)/i))) {
|
||||
// HSL or HSLA - hsl(200, 65%, 91%) or hsla(200, 65%, 91%, 1)
|
||||
let h_ = parseFloat(m[1]) / 360,
|
||||
s_ = parseFloat(m[2]) / 100,
|
||||
l_ = parseFloat(m[3]) / 100,
|
||||
rgb_ = HTML._hslToRgb(h_, s_, l_);
|
||||
|
||||
r = rgb_[0];
|
||||
g = rgb_[1];
|
||||
b = rgb_[2];
|
||||
a = m[4] ? parseFloat(m[4]) : 1;
|
||||
} else if ((m = input.match(/cmyk\((\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?)\)/i))) {
|
||||
// CMYK - cmyk(0.12, 0.04, 0.00, 0.03)
|
||||
let c_ = parseFloat(m[1]),
|
||||
m_ = parseFloat(m[2]),
|
||||
y_ = parseFloat(m[3]),
|
||||
k_ = parseFloat(m[4]);
|
||||
|
||||
r = Math.round(255 * (1 - c_) * (1 - k_));
|
||||
g = Math.round(255 * (1 - m_) * (1 - k_));
|
||||
b = Math.round(255 * (1 - y_) * (1 - k_));
|
||||
}
|
||||
|
||||
let hsl_ = HTML._rgbToHsl(r, g, b),
|
||||
h = Math.round(hsl_[0] * 360),
|
||||
s = Math.round(hsl_[1] * 100),
|
||||
l = Math.round(hsl_[2] * 100),
|
||||
k = 1 - Math.max(r/255, g/255, b/255),
|
||||
c = (1 - r/255 - k) / (1 - k),
|
||||
y = (1 - b/255 - k) / (1 - k);
|
||||
|
||||
m = (1 - g/255 - k) / (1 - k);
|
||||
|
||||
c = isNaN(c) ? "0" : c.toFixed(2);
|
||||
m = isNaN(m) ? "0" : m.toFixed(2);
|
||||
y = isNaN(y) ? "0" : y.toFixed(2);
|
||||
k = k.toFixed(2);
|
||||
|
||||
let hex = "#" +
|
||||
Math.round(r).toString(16).padStart(2, "0") +
|
||||
Math.round(g).toString(16).padStart(2, "0") +
|
||||
Math.round(b).toString(16).padStart(2, "0"),
|
||||
rgb = "rgb(" + r + ", " + g + ", " + b + ")",
|
||||
rgba = "rgba(" + r + ", " + g + ", " + b + ", " + a + ")",
|
||||
hsl = "hsl(" + h + ", " + s + "%, " + l + "%)",
|
||||
hsla = "hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")",
|
||||
cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")";
|
||||
|
||||
// Generate output
|
||||
return `<div id="colorpicker" style="display: inline-block"></div>
|
||||
Hex: ${hex}
|
||||
RGB: ${rgb}
|
||||
RGBA: ${rgba}
|
||||
HSL: ${hsl}
|
||||
HSLA: ${hsla}
|
||||
CMYK: ${cmyk}
|
||||
<script>
|
||||
$('#colorpicker').colorpicker({
|
||||
format: 'rgba',
|
||||
color: '${rgba}',
|
||||
container: true,
|
||||
inline: true,
|
||||
}).on('changeColor', function(e) {
|
||||
var color = e.color.toRGB();
|
||||
document.getElementById('input-text').value = 'rgba(' +
|
||||
color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';
|
||||
window.app.autoBake();
|
||||
});
|
||||
</script>`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts an HSL color value to RGB. Conversion formula
|
||||
* adapted from http://en.wikipedia.org/wiki/HSL_colorSpace.
|
||||
* Assumes h, s, and l are contained in the set [0, 1] and
|
||||
* returns r, g, and b in the set [0, 255].
|
||||
*
|
||||
* @private
|
||||
* @author Mohsen (http://stackoverflow.com/a/9493060)
|
||||
*
|
||||
* @param {number} h - The hue
|
||||
* @param {number} s - The saturation
|
||||
* @param {number} l - The lightness
|
||||
* @return {Array} The RGB representation
|
||||
*/
|
||||
_hslToRgb: function(h, s, l){
|
||||
let r, g, b;
|
||||
|
||||
if (s === 0){
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
const hue2rgb = function hue2rgb(p, q, t) {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1/6) return p + (q - p) * 6 * t;
|
||||
if (t < 1/2) return q;
|
||||
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
|
||||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
const p = 2 * l - q;
|
||||
r = hue2rgb(p, q, h + 1/3);
|
||||
g = hue2rgb(p, q, h);
|
||||
b = hue2rgb(p, q, h - 1/3);
|
||||
}
|
||||
|
||||
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts an RGB color value to HSL. Conversion formula
|
||||
* adapted from http://en.wikipedia.org/wiki/HSL_colorSpace.
|
||||
* Assumes r, g, and b are contained in the set [0, 255] and
|
||||
* returns h, s, and l in the set [0, 1].
|
||||
*
|
||||
* @private
|
||||
* @author Mohsen (http://stackoverflow.com/a/9493060)
|
||||
*
|
||||
* @param {number} r - The red color value
|
||||
* @param {number} g - The green color value
|
||||
* @param {number} b - The blue color value
|
||||
* @return {Array} The HSL representation
|
||||
*/
|
||||
_rgbToHsl: function(r, g, b) {
|
||||
r /= 255; g /= 255; b /= 255;
|
||||
let max = Math.max(r, g, b),
|
||||
min = Math.min(r, g, b),
|
||||
h, s, l = (max + min) / 2;
|
||||
|
||||
if (max === min) {
|
||||
h = s = 0; // achromatic
|
||||
} else {
|
||||
const d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
switch (max) {
|
||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||
case g: h = (b - r) / d + 2; break;
|
||||
case b: h = (r - g) / d + 4; break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return [h, s, l];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Lookup table to translate byte values to their HTML entity codes.
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_byteToEntity: {
|
||||
34: """,
|
||||
38: "&",
|
||||
39: "'",
|
||||
60: "<",
|
||||
62: ">",
|
||||
160: " ",
|
||||
161: "¡",
|
||||
162: "¢",
|
||||
163: "£",
|
||||
164: "¤",
|
||||
165: "¥",
|
||||
166: "¦",
|
||||
167: "§",
|
||||
168: "¨",
|
||||
169: "©",
|
||||
170: "ª",
|
||||
171: "«",
|
||||
172: "¬",
|
||||
173: "­",
|
||||
174: "®",
|
||||
175: "¯",
|
||||
176: "°",
|
||||
177: "±",
|
||||
178: "²",
|
||||
179: "³",
|
||||
180: "´",
|
||||
181: "µ",
|
||||
182: "¶",
|
||||
183: "·",
|
||||
184: "¸",
|
||||
185: "¹",
|
||||
186: "º",
|
||||
187: "»",
|
||||
188: "¼",
|
||||
189: "½",
|
||||
190: "¾",
|
||||
191: "¿",
|
||||
192: "À",
|
||||
193: "Á",
|
||||
194: "Â",
|
||||
195: "Ã",
|
||||
196: "Ä",
|
||||
197: "Å",
|
||||
198: "Æ",
|
||||
199: "Ç",
|
||||
200: "È",
|
||||
201: "É",
|
||||
202: "Ê",
|
||||
203: "Ë",
|
||||
204: "Ì",
|
||||
205: "Í",
|
||||
206: "Î",
|
||||
207: "Ï",
|
||||
208: "Ð",
|
||||
209: "Ñ",
|
||||
210: "Ò",
|
||||
211: "Ó",
|
||||
212: "Ô",
|
||||
213: "Õ",
|
||||
214: "Ö",
|
||||
215: "×",
|
||||
216: "Ø",
|
||||
217: "Ù",
|
||||
218: "Ú",
|
||||
219: "Û",
|
||||
220: "Ü",
|
||||
221: "Ý",
|
||||
222: "Þ",
|
||||
223: "ß",
|
||||
224: "à",
|
||||
225: "á",
|
||||
226: "â",
|
||||
227: "ã",
|
||||
228: "ä",
|
||||
229: "å",
|
||||
230: "æ",
|
||||
231: "ç",
|
||||
232: "è",
|
||||
233: "é",
|
||||
234: "ê",
|
||||
235: "ë",
|
||||
236: "ì",
|
||||
237: "í",
|
||||
238: "î",
|
||||
239: "ï",
|
||||
240: "ð",
|
||||
241: "ñ",
|
||||
242: "ò",
|
||||
243: "ó",
|
||||
244: "ô",
|
||||
245: "õ",
|
||||
246: "ö",
|
||||
247: "÷",
|
||||
248: "ø",
|
||||
249: "ù",
|
||||
250: "ú",
|
||||
251: "û",
|
||||
252: "ü",
|
||||
253: "ý",
|
||||
254: "þ",
|
||||
255: "ÿ",
|
||||
338: "Œ",
|
||||
339: "œ",
|
||||
352: "Š",
|
||||
353: "š",
|
||||
376: "Ÿ",
|
||||
402: "ƒ",
|
||||
710: "ˆ",
|
||||
732: "˜",
|
||||
913: "Α",
|
||||
914: "Β",
|
||||
915: "Γ",
|
||||
916: "Δ",
|
||||
917: "Ε",
|
||||
918: "Ζ",
|
||||
919: "Η",
|
||||
920: "Θ",
|
||||
921: "Ι",
|
||||
922: "Κ",
|
||||
923: "Λ",
|
||||
924: "Μ",
|
||||
925: "Ν",
|
||||
926: "Ξ",
|
||||
927: "Ο",
|
||||
928: "Π",
|
||||
929: "Ρ",
|
||||
931: "Σ",
|
||||
932: "Τ",
|
||||
933: "Υ",
|
||||
934: "Φ",
|
||||
935: "Χ",
|
||||
936: "Ψ",
|
||||
937: "Ω",
|
||||
945: "α",
|
||||
946: "β",
|
||||
947: "γ",
|
||||
948: "δ",
|
||||
949: "ε",
|
||||
950: "ζ",
|
||||
951: "η",
|
||||
952: "θ",
|
||||
953: "ι",
|
||||
954: "κ",
|
||||
955: "λ",
|
||||
956: "μ",
|
||||
957: "ν",
|
||||
958: "ξ",
|
||||
959: "ο",
|
||||
960: "π",
|
||||
961: "ρ",
|
||||
962: "ς",
|
||||
963: "σ",
|
||||
964: "τ",
|
||||
965: "υ",
|
||||
966: "φ",
|
||||
967: "χ",
|
||||
968: "ψ",
|
||||
969: "ω",
|
||||
977: "ϑ",
|
||||
978: "ϒ",
|
||||
982: "ϖ",
|
||||
8194: " ",
|
||||
8195: " ",
|
||||
8201: " ",
|
||||
8204: "‌",
|
||||
8205: "‍",
|
||||
8206: "‎",
|
||||
8207: "‏",
|
||||
8211: "–",
|
||||
8212: "—",
|
||||
8216: "‘",
|
||||
8217: "’",
|
||||
8218: "‚",
|
||||
8220: "“",
|
||||
8221: "”",
|
||||
8222: "„",
|
||||
8224: "†",
|
||||
8225: "‡",
|
||||
8226: "•",
|
||||
8230: "…",
|
||||
8240: "‰",
|
||||
8242: "′",
|
||||
8243: "″",
|
||||
8249: "‹",
|
||||
8250: "›",
|
||||
8254: "‾",
|
||||
8260: "⁄",
|
||||
8364: "€",
|
||||
8465: "ℑ",
|
||||
8472: "℘",
|
||||
8476: "ℜ",
|
||||
8482: "™",
|
||||
8501: "ℵ",
|
||||
8592: "←",
|
||||
8593: "↑",
|
||||
8594: "→",
|
||||
8595: "↓",
|
||||
8596: "↔",
|
||||
8629: "↵",
|
||||
8656: "⇐",
|
||||
8657: "⇑",
|
||||
8658: "⇒",
|
||||
8659: "⇓",
|
||||
8660: "⇔",
|
||||
8704: "∀",
|
||||
8706: "∂",
|
||||
8707: "∃",
|
||||
8709: "∅",
|
||||
8711: "∇",
|
||||
8712: "∈",
|
||||
8713: "∉",
|
||||
8715: "∋",
|
||||
8719: "∏",
|
||||
8721: "∑",
|
||||
8722: "−",
|
||||
8727: "∗",
|
||||
8730: "√",
|
||||
8733: "∝",
|
||||
8734: "∞",
|
||||
8736: "∠",
|
||||
8743: "∧",
|
||||
8744: "∨",
|
||||
8745: "∩",
|
||||
8746: "∪",
|
||||
8747: "∫",
|
||||
8756: "∴",
|
||||
8764: "∼",
|
||||
8773: "≅",
|
||||
8776: "≈",
|
||||
8800: "≠",
|
||||
8801: "≡",
|
||||
8804: "≤",
|
||||
8805: "≥",
|
||||
8834: "⊂",
|
||||
8835: "⊃",
|
||||
8836: "⊄",
|
||||
8838: "⊆",
|
||||
8839: "⊇",
|
||||
8853: "⊕",
|
||||
8855: "⊗",
|
||||
8869: "⊥",
|
||||
8901: "⋅",
|
||||
8942: "⋮",
|
||||
8968: "⌈",
|
||||
8969: "⌉",
|
||||
8970: "⌊",
|
||||
8971: "⌋",
|
||||
9001: "⟨",
|
||||
9002: "⟩",
|
||||
9674: "◊",
|
||||
9824: "♠",
|
||||
9827: "♣",
|
||||
9829: "♥",
|
||||
9830: "♦",
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Lookup table to translate HTML entity codes to their byte values.
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_entityToByte: {
|
||||
"quot": 34,
|
||||
"amp": 38,
|
||||
"apos": 39,
|
||||
"lt": 60,
|
||||
"gt": 62,
|
||||
"nbsp": 160,
|
||||
"iexcl": 161,
|
||||
"cent": 162,
|
||||
"pound": 163,
|
||||
"curren": 164,
|
||||
"yen": 165,
|
||||
"brvbar": 166,
|
||||
"sect": 167,
|
||||
"uml": 168,
|
||||
"copy": 169,
|
||||
"ordf": 170,
|
||||
"laquo": 171,
|
||||
"not": 172,
|
||||
"shy": 173,
|
||||
"reg": 174,
|
||||
"macr": 175,
|
||||
"deg": 176,
|
||||
"plusmn": 177,
|
||||
"sup2": 178,
|
||||
"sup3": 179,
|
||||
"acute": 180,
|
||||
"micro": 181,
|
||||
"para": 182,
|
||||
"middot": 183,
|
||||
"cedil": 184,
|
||||
"sup1": 185,
|
||||
"ordm": 186,
|
||||
"raquo": 187,
|
||||
"frac14": 188,
|
||||
"frac12": 189,
|
||||
"frac34": 190,
|
||||
"iquest": 191,
|
||||
"Agrave": 192,
|
||||
"Aacute": 193,
|
||||
"Acirc": 194,
|
||||
"Atilde": 195,
|
||||
"Auml": 196,
|
||||
"Aring": 197,
|
||||
"AElig": 198,
|
||||
"Ccedil": 199,
|
||||
"Egrave": 200,
|
||||
"Eacute": 201,
|
||||
"Ecirc": 202,
|
||||
"Euml": 203,
|
||||
"Igrave": 204,
|
||||
"Iacute": 205,
|
||||
"Icirc": 206,
|
||||
"Iuml": 207,
|
||||
"ETH": 208,
|
||||
"Ntilde": 209,
|
||||
"Ograve": 210,
|
||||
"Oacute": 211,
|
||||
"Ocirc": 212,
|
||||
"Otilde": 213,
|
||||
"Ouml": 214,
|
||||
"times": 215,
|
||||
"Oslash": 216,
|
||||
"Ugrave": 217,
|
||||
"Uacute": 218,
|
||||
"Ucirc": 219,
|
||||
"Uuml": 220,
|
||||
"Yacute": 221,
|
||||
"THORN": 222,
|
||||
"szlig": 223,
|
||||
"agrave": 224,
|
||||
"aacute": 225,
|
||||
"acirc": 226,
|
||||
"atilde": 227,
|
||||
"auml": 228,
|
||||
"aring": 229,
|
||||
"aelig": 230,
|
||||
"ccedil": 231,
|
||||
"egrave": 232,
|
||||
"eacute": 233,
|
||||
"ecirc": 234,
|
||||
"euml": 235,
|
||||
"igrave": 236,
|
||||
"iacute": 237,
|
||||
"icirc": 238,
|
||||
"iuml": 239,
|
||||
"eth": 240,
|
||||
"ntilde": 241,
|
||||
"ograve": 242,
|
||||
"oacute": 243,
|
||||
"ocirc": 244,
|
||||
"otilde": 245,
|
||||
"ouml": 246,
|
||||
"divide": 247,
|
||||
"oslash": 248,
|
||||
"ugrave": 249,
|
||||
"uacute": 250,
|
||||
"ucirc": 251,
|
||||
"uuml": 252,
|
||||
"yacute": 253,
|
||||
"thorn": 254,
|
||||
"yuml": 255,
|
||||
"OElig": 338,
|
||||
"oelig": 339,
|
||||
"Scaron": 352,
|
||||
"scaron": 353,
|
||||
"Yuml": 376,
|
||||
"fnof": 402,
|
||||
"circ": 710,
|
||||
"tilde": 732,
|
||||
"Alpha": 913,
|
||||
"Beta": 914,
|
||||
"Gamma": 915,
|
||||
"Delta": 916,
|
||||
"Epsilon": 917,
|
||||
"Zeta": 918,
|
||||
"Eta": 919,
|
||||
"Theta": 920,
|
||||
"Iota": 921,
|
||||
"Kappa": 922,
|
||||
"Lambda": 923,
|
||||
"Mu": 924,
|
||||
"Nu": 925,
|
||||
"Xi": 926,
|
||||
"Omicron": 927,
|
||||
"Pi": 928,
|
||||
"Rho": 929,
|
||||
"Sigma": 931,
|
||||
"Tau": 932,
|
||||
"Upsilon": 933,
|
||||
"Phi": 934,
|
||||
"Chi": 935,
|
||||
"Psi": 936,
|
||||
"Omega": 937,
|
||||
"alpha": 945,
|
||||
"beta": 946,
|
||||
"gamma": 947,
|
||||
"delta": 948,
|
||||
"epsilon": 949,
|
||||
"zeta": 950,
|
||||
"eta": 951,
|
||||
"theta": 952,
|
||||
"iota": 953,
|
||||
"kappa": 954,
|
||||
"lambda": 955,
|
||||
"mu": 956,
|
||||
"nu": 957,
|
||||
"xi": 958,
|
||||
"omicron": 959,
|
||||
"pi": 960,
|
||||
"rho": 961,
|
||||
"sigmaf": 962,
|
||||
"sigma": 963,
|
||||
"tau": 964,
|
||||
"upsilon": 965,
|
||||
"phi": 966,
|
||||
"chi": 967,
|
||||
"psi": 968,
|
||||
"omega": 969,
|
||||
"thetasym": 977,
|
||||
"upsih": 978,
|
||||
"piv": 982,
|
||||
"ensp": 8194,
|
||||
"emsp": 8195,
|
||||
"thinsp": 8201,
|
||||
"zwnj": 8204,
|
||||
"zwj": 8205,
|
||||
"lrm": 8206,
|
||||
"rlm": 8207,
|
||||
"ndash": 8211,
|
||||
"mdash": 8212,
|
||||
"lsquo": 8216,
|
||||
"rsquo": 8217,
|
||||
"sbquo": 8218,
|
||||
"ldquo": 8220,
|
||||
"rdquo": 8221,
|
||||
"bdquo": 8222,
|
||||
"dagger": 8224,
|
||||
"Dagger": 8225,
|
||||
"bull": 8226,
|
||||
"hellip": 8230,
|
||||
"permil": 8240,
|
||||
"prime": 8242,
|
||||
"Prime": 8243,
|
||||
"lsaquo": 8249,
|
||||
"rsaquo": 8250,
|
||||
"oline": 8254,
|
||||
"frasl": 8260,
|
||||
"euro": 8364,
|
||||
"image": 8465,
|
||||
"weierp": 8472,
|
||||
"real": 8476,
|
||||
"trade": 8482,
|
||||
"alefsym": 8501,
|
||||
"larr": 8592,
|
||||
"uarr": 8593,
|
||||
"rarr": 8594,
|
||||
"darr": 8595,
|
||||
"harr": 8596,
|
||||
"crarr": 8629,
|
||||
"lArr": 8656,
|
||||
"uArr": 8657,
|
||||
"rArr": 8658,
|
||||
"dArr": 8659,
|
||||
"hArr": 8660,
|
||||
"forall": 8704,
|
||||
"part": 8706,
|
||||
"exist": 8707,
|
||||
"empty": 8709,
|
||||
"nabla": 8711,
|
||||
"isin": 8712,
|
||||
"notin": 8713,
|
||||
"ni": 8715,
|
||||
"prod": 8719,
|
||||
"sum": 8721,
|
||||
"minus": 8722,
|
||||
"lowast": 8727,
|
||||
"radic": 8730,
|
||||
"prop": 8733,
|
||||
"infin": 8734,
|
||||
"ang": 8736,
|
||||
"and": 8743,
|
||||
"or": 8744,
|
||||
"cap": 8745,
|
||||
"cup": 8746,
|
||||
"int": 8747,
|
||||
"there4": 8756,
|
||||
"sim": 8764,
|
||||
"cong": 8773,
|
||||
"asymp": 8776,
|
||||
"ne": 8800,
|
||||
"equiv": 8801,
|
||||
"le": 8804,
|
||||
"ge": 8805,
|
||||
"sub": 8834,
|
||||
"sup": 8835,
|
||||
"nsub": 8836,
|
||||
"sube": 8838,
|
||||
"supe": 8839,
|
||||
"oplus": 8853,
|
||||
"otimes": 8855,
|
||||
"perp": 8869,
|
||||
"sdot": 8901,
|
||||
"vellip": 8942,
|
||||
"lceil": 8968,
|
||||
"rceil": 8969,
|
||||
"lfloor": 8970,
|
||||
"rfloor": 8971,
|
||||
"lang": 9001,
|
||||
"rang": 9002,
|
||||
"loz": 9674,
|
||||
"spades": 9824,
|
||||
"clubs": 9827,
|
||||
"hearts": 9829,
|
||||
"diams": 9830,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default HTML;
|
@ -1,158 +0,0 @@
|
||||
import UAParser from "ua-parser-js";
|
||||
|
||||
|
||||
/**
|
||||
* HTTP operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const HTTP = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
METHODS: [
|
||||
"GET", "POST", "HEAD",
|
||||
"PUT", "PATCH", "DELETE",
|
||||
"CONNECT", "TRACE", "OPTIONS"
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* Strip HTTP headers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runStripHeaders: function(input, args) {
|
||||
let headerEnd = input.indexOf("\r\n\r\n");
|
||||
headerEnd = (headerEnd < 0) ? input.indexOf("\n\n") + 2 : headerEnd + 4;
|
||||
|
||||
return (headerEnd < 2) ? input : input.slice(headerEnd, input.length);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse User Agent operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseUserAgent: function(input, args) {
|
||||
const ua = UAParser(input);
|
||||
return `Browser
|
||||
Name: ${ua.browser.name || "unknown"}
|
||||
Version: ${ua.browser.version || "unknown"}
|
||||
Device
|
||||
Model: ${ua.device.model || "unknown"}
|
||||
Type: ${ua.device.type || "unknown"}
|
||||
Vendor: ${ua.device.vendor || "unknown"}
|
||||
Engine
|
||||
Name: ${ua.engine.name || "unknown"}
|
||||
Version: ${ua.engine.version || "unknown"}
|
||||
OS
|
||||
Name: ${ua.os.name || "unknown"}
|
||||
Version: ${ua.os.version || "unknown"}
|
||||
CPU
|
||||
Architecture: ${ua.cpu.architecture || "unknown"}`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MODE: [
|
||||
"Cross-Origin Resource Sharing",
|
||||
"No CORS (limited to HEAD, GET or POST)",
|
||||
],
|
||||
|
||||
/**
|
||||
* Lookup table for HTTP modes
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_modeLookup: {
|
||||
"Cross-Origin Resource Sharing": "cors",
|
||||
"No CORS (limited to HEAD, GET or POST)": "no-cors",
|
||||
},
|
||||
|
||||
/**
|
||||
* HTTP request operation.
|
||||
*
|
||||
* @author tlwr [toby@toby.codes]
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHTTPRequest(input, args) {
|
||||
const method = args[0],
|
||||
url = args[1],
|
||||
headersText = args[2],
|
||||
mode = args[3],
|
||||
showResponseMetadata = args[4];
|
||||
|
||||
if (url.length === 0) return "";
|
||||
|
||||
let headers = new Headers();
|
||||
headersText.split(/\r?\n/).forEach(line => {
|
||||
line = line.trim();
|
||||
|
||||
if (line.length === 0) return;
|
||||
|
||||
let split = line.split(":");
|
||||
if (split.length !== 2) throw `Could not parse header in line: ${line}`;
|
||||
|
||||
headers.set(split[0].trim(), split[1].trim());
|
||||
});
|
||||
|
||||
let config = {
|
||||
method: method,
|
||||
headers: headers,
|
||||
mode: HTTP._modeLookup[mode],
|
||||
cache: "no-cache",
|
||||
};
|
||||
|
||||
if (method !== "GET" && method !== "HEAD") {
|
||||
config.body = input;
|
||||
}
|
||||
|
||||
return fetch(url, config)
|
||||
.then(r => {
|
||||
if (r.status === 0 && r.type === "opaque") {
|
||||
return "Error: Null response. Try setting the connection mode to CORS.";
|
||||
}
|
||||
|
||||
if (showResponseMetadata) {
|
||||
let headers = "";
|
||||
for (let pair of r.headers.entries()) {
|
||||
headers += " " + pair[0] + ": " + pair[1] + "\n";
|
||||
}
|
||||
return r.text().then(b => {
|
||||
return "####\n Status: " + r.status + " " + r.statusText +
|
||||
"\n Exposed headers:\n" + headers + "####\n\n" + b;
|
||||
});
|
||||
}
|
||||
return r.text();
|
||||
})
|
||||
.catch(e => {
|
||||
return e.toString() +
|
||||
"\n\nThis error could be caused by one of the following:\n" +
|
||||
" - An invalid URL\n" +
|
||||
" - Making a request to an insecure resource (HTTP) from a secure source (HTTPS)\n" +
|
||||
" - Making a cross-origin request to a server which does not support CORS\n";
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default HTTP;
|
@ -1,785 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import CryptoApi from "babel-loader!crypto-api";
|
||||
import MD6 from "node-md6";
|
||||
import * as SHA3 from "js-sha3";
|
||||
import Checksum from "./Checksum.js";
|
||||
import ctph from "ctph.js";
|
||||
import ssdeep from "ssdeep.js";
|
||||
import bcrypt from "bcryptjs";
|
||||
import scrypt from "scryptsy";
|
||||
|
||||
|
||||
/**
|
||||
* Hashing operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Hash = {
|
||||
|
||||
/**
|
||||
* Generic hash function.
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object} [options={}]
|
||||
* @returns {string}
|
||||
*/
|
||||
runHash: function(name, input, options={}) {
|
||||
const msg = Utils.arrayBufferToStr(input, false),
|
||||
hasher = CryptoApi.getHasher(name, options);
|
||||
hasher.update(msg);
|
||||
return CryptoApi.encoder.toHex(hasher.finalize());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD2 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD2: function (input, args) {
|
||||
return Hash.runHash("md2", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD4 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD4: function (input, args) {
|
||||
return Hash.runHash("md4", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD5 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD5: function (input, args) {
|
||||
return Hash.runHash("md5", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MD6_SIZE: 256,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MD6_LEVELS: 64,
|
||||
|
||||
/**
|
||||
* MD6 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD6: function (input, args) {
|
||||
const size = args[0],
|
||||
levels = args[1],
|
||||
key = args[2];
|
||||
|
||||
if (size < 0 || size > 512)
|
||||
return "Size must be between 0 and 512";
|
||||
if (levels < 0)
|
||||
return "Levels must be greater than 0";
|
||||
|
||||
return MD6.getHashOfText(input, size, key, levels);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA0 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA0: function (input, args) {
|
||||
return Hash.runHash("sha0", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA1 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA1: function (input, args) {
|
||||
return Hash.runHash("sha1", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
|
||||
|
||||
/**
|
||||
* SHA2 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA2: function (input, args) {
|
||||
const size = args[0];
|
||||
return Hash.runHash("sha" + size, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHA3_SIZE: ["512", "384", "256", "224"],
|
||||
|
||||
/**
|
||||
* SHA3 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA3: function (input, args) {
|
||||
const size = parseInt(args[0], 10);
|
||||
let algo;
|
||||
|
||||
switch (size) {
|
||||
case 224:
|
||||
algo = SHA3.sha3_224;
|
||||
break;
|
||||
case 384:
|
||||
algo = SHA3.sha3_384;
|
||||
break;
|
||||
case 256:
|
||||
algo = SHA3.sha3_256;
|
||||
break;
|
||||
case 512:
|
||||
algo = SHA3.sha3_512;
|
||||
break;
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
|
||||
return algo(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KECCAK_SIZE: ["512", "384", "256", "224"],
|
||||
|
||||
/**
|
||||
* Keccak operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runKeccak: function (input, args) {
|
||||
const size = parseInt(args[0], 10);
|
||||
let algo;
|
||||
|
||||
switch (size) {
|
||||
case 224:
|
||||
algo = SHA3.keccak224;
|
||||
break;
|
||||
case 384:
|
||||
algo = SHA3.keccak384;
|
||||
break;
|
||||
case 256:
|
||||
algo = SHA3.keccak256;
|
||||
break;
|
||||
case 512:
|
||||
algo = SHA3.keccak512;
|
||||
break;
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
|
||||
return algo(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHAKE_CAPACITY: ["256", "128"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHAKE_SIZE: 512,
|
||||
|
||||
/**
|
||||
* Shake operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runShake: function (input, args) {
|
||||
const capacity = parseInt(args[0], 10),
|
||||
size = args[1];
|
||||
let algo;
|
||||
|
||||
if (size < 0)
|
||||
return "Size must be greater than 0";
|
||||
|
||||
switch (capacity) {
|
||||
case 128:
|
||||
algo = SHA3.shake128;
|
||||
break;
|
||||
case 256:
|
||||
algo = SHA3.shake256;
|
||||
break;
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
|
||||
return algo(input, size);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
RIPEMD_SIZE: ["320", "256", "160", "128"],
|
||||
|
||||
/**
|
||||
* RIPEMD operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRIPEMD: function (input, args) {
|
||||
const size = args[0];
|
||||
return Hash.runHash("ripemd" + size, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* HAS-160 operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHAS: function (input, args) {
|
||||
return Hash.runHash("has160", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WHIRLPOOL_VARIANT: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"],
|
||||
|
||||
/**
|
||||
* Whirlpool operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runWhirlpool: function (input, args) {
|
||||
const variant = args[0].toLowerCase();
|
||||
return Hash.runHash(variant, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SNEFRU_ROUNDS: ["8", "4", "2"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SNEFRU_SIZE: ["256", "128"],
|
||||
|
||||
/**
|
||||
* Snefru operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSnefru: function (input, args) {
|
||||
return Hash.runHash("snefru", input, {
|
||||
rounds: args[0],
|
||||
length: args[1]
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CTPH operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCTPH: function (input, args) {
|
||||
return ctph.digest(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SSDEEP operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSSDEEP: function (input, args) {
|
||||
return ssdeep.digest(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIM_OPTIONS: ["Line feed", "CRLF", "Space", "Comma"],
|
||||
|
||||
/**
|
||||
* Compare CTPH hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {Number}
|
||||
*/
|
||||
runCompareCTPH: function (input, args) {
|
||||
const samples = input.split(Utils.charRep(args[0]));
|
||||
if (samples.length !== 2) throw "Incorrect number of samples.";
|
||||
return ctph.similarity(samples[0], samples[1]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Compare SSDEEP hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {Number}
|
||||
*/
|
||||
runCompareSSDEEP: function (input, args) {
|
||||
const samples = input.split(Utils.charRep(args[0]));
|
||||
if (samples.length !== 2) throw "Incorrect number of samples.";
|
||||
return ssdeep.similarity(samples[0], samples[1]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HMAC_FUNCTIONS: [
|
||||
"MD2",
|
||||
"MD4",
|
||||
"MD5",
|
||||
"SHA0",
|
||||
"SHA1",
|
||||
"SHA224",
|
||||
"SHA256",
|
||||
"SHA384",
|
||||
"SHA512",
|
||||
"SHA512/224",
|
||||
"SHA512/256",
|
||||
"RIPEMD128",
|
||||
"RIPEMD160",
|
||||
"RIPEMD256",
|
||||
"RIPEMD320",
|
||||
"HAS160",
|
||||
"Whirlpool",
|
||||
"Whirlpool-0",
|
||||
"Whirlpool-T",
|
||||
"Snefru"
|
||||
],
|
||||
|
||||
/**
|
||||
* HMAC operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHMAC: function (input, args) {
|
||||
const key = args[0],
|
||||
hashFunc = args[1].toLowerCase(),
|
||||
msg = Utils.arrayBufferToStr(input, false),
|
||||
hasher = CryptoApi.getHasher(hashFunc);
|
||||
|
||||
// Horrible shim to fix constructor bug. Reported in nf404/crypto-api#8
|
||||
hasher.reset = () => {
|
||||
hasher.state = {};
|
||||
const tmp = new hasher.constructor();
|
||||
hasher.state = tmp.state;
|
||||
};
|
||||
|
||||
const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
|
||||
mac.update(msg);
|
||||
return CryptoApi.encoder.toHex(mac.finalize());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BCRYPT_ROUNDS: 10,
|
||||
|
||||
/**
|
||||
* Bcrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBcrypt: async function (input, args) {
|
||||
const rounds = args[0];
|
||||
const salt = await bcrypt.genSalt(rounds);
|
||||
|
||||
return await bcrypt.hash(input, salt, null, p => {
|
||||
// Progress callback
|
||||
if (ENVIRONMENT_IS_WORKER())
|
||||
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Bcrypt compare operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBcryptCompare: async function (input, args) {
|
||||
const hash = args[0];
|
||||
|
||||
const match = await bcrypt.compare(input, hash, null, p => {
|
||||
// Progress callback
|
||||
if (ENVIRONMENT_IS_WORKER())
|
||||
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
||||
});
|
||||
|
||||
return match ? "Match: " + input : "No match";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Bcrypt parse operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBcryptParse: async function (input, args) {
|
||||
try {
|
||||
return `Rounds: ${bcrypt.getRounds(input)}
|
||||
Salt: ${bcrypt.getSalt(input)}
|
||||
Password hash: ${input.split(bcrypt.getSalt(input))[1]}
|
||||
Full hash: ${input}`;
|
||||
} catch (err) {
|
||||
return "Error: " + err.toString();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KEY_FORMAT: ["Hex", "Base64", "UTF8", "Latin1"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SCRYPT_ITERATIONS: 16384,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SCRYPT_MEM_FACTOR: 8,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SCRYPT_PARALLEL_FACTOR: 1,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SCRYPT_KEY_LENGTH: 64,
|
||||
|
||||
/**
|
||||
* Scrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runScrypt: function (input, args) {
|
||||
const salt = Utils.convertToByteString(args[0].string || "", args[0].option),
|
||||
iterations = args[1],
|
||||
memFactor = args[2],
|
||||
parallelFactor = args[3],
|
||||
keyLength = args[4];
|
||||
|
||||
try {
|
||||
const data = scrypt(
|
||||
input, salt, iterations, memFactor, parallelFactor, keyLength,
|
||||
p => {
|
||||
// Progress callback
|
||||
if (ENVIRONMENT_IS_WORKER())
|
||||
self.sendStatusMessage(`Progress: ${p.percent.toFixed(0)}%`);
|
||||
}
|
||||
);
|
||||
|
||||
return data.toString("hex");
|
||||
} catch (err) {
|
||||
return "Error: " + err.toString();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generate all hashes operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAll: function (input, args) {
|
||||
const arrayBuffer = input,
|
||||
str = Utils.arrayBufferToStr(arrayBuffer, false),
|
||||
byteArray = new Uint8Array(arrayBuffer),
|
||||
output = "MD2: " + Hash.runMD2(arrayBuffer, []) +
|
||||
"\nMD4: " + Hash.runMD4(arrayBuffer, []) +
|
||||
"\nMD5: " + Hash.runMD5(arrayBuffer, []) +
|
||||
"\nMD6: " + Hash.runMD6(str, []) +
|
||||
"\nSHA0: " + Hash.runSHA0(arrayBuffer, []) +
|
||||
"\nSHA1: " + Hash.runSHA1(arrayBuffer, []) +
|
||||
"\nSHA2 224: " + Hash.runSHA2(arrayBuffer, ["224"]) +
|
||||
"\nSHA2 256: " + Hash.runSHA2(arrayBuffer, ["256"]) +
|
||||
"\nSHA2 384: " + Hash.runSHA2(arrayBuffer, ["384"]) +
|
||||
"\nSHA2 512: " + Hash.runSHA2(arrayBuffer, ["512"]) +
|
||||
"\nSHA3 224: " + Hash.runSHA3(arrayBuffer, ["224"]) +
|
||||
"\nSHA3 256: " + Hash.runSHA3(arrayBuffer, ["256"]) +
|
||||
"\nSHA3 384: " + Hash.runSHA3(arrayBuffer, ["384"]) +
|
||||
"\nSHA3 512: " + Hash.runSHA3(arrayBuffer, ["512"]) +
|
||||
"\nKeccak 224: " + Hash.runKeccak(arrayBuffer, ["224"]) +
|
||||
"\nKeccak 256: " + Hash.runKeccak(arrayBuffer, ["256"]) +
|
||||
"\nKeccak 384: " + Hash.runKeccak(arrayBuffer, ["384"]) +
|
||||
"\nKeccak 512: " + Hash.runKeccak(arrayBuffer, ["512"]) +
|
||||
"\nShake 128: " + Hash.runShake(arrayBuffer, ["128", 256]) +
|
||||
"\nShake 256: " + Hash.runShake(arrayBuffer, ["256", 512]) +
|
||||
"\nRIPEMD-128: " + Hash.runRIPEMD(arrayBuffer, ["128"]) +
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD(arrayBuffer, ["160"]) +
|
||||
"\nRIPEMD-256: " + Hash.runRIPEMD(arrayBuffer, ["256"]) +
|
||||
"\nRIPEMD-320: " + Hash.runRIPEMD(arrayBuffer, ["320"]) +
|
||||
"\nHAS-160: " + Hash.runHAS(arrayBuffer, []) +
|
||||
"\nWhirlpool-0: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-0"]) +
|
||||
"\nWhirlpool-T: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-T"]) +
|
||||
"\nWhirlpool: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool"]) +
|
||||
"\nSSDEEP: " + Hash.runSSDEEP(str) +
|
||||
"\nCTPH: " + Hash.runCTPH(str) +
|
||||
"\n\nChecksums:" +
|
||||
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
|
||||
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
|
||||
"\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
|
||||
"\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
|
||||
"\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
|
||||
"\nCRC-16: " + Checksum.runCRC16(str, []) +
|
||||
"\nCRC-32: " + Checksum.runCRC32(str, []);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Analyse hash operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAnalyse: function(input, args) {
|
||||
input = input.replace(/\s/g, "");
|
||||
|
||||
let output = "",
|
||||
byteLength = input.length / 2,
|
||||
bitLength = byteLength * 8,
|
||||
possibleHashFunctions = [];
|
||||
|
||||
if (!/^[a-f0-9]+$/i.test(input)) {
|
||||
return "Invalid hash";
|
||||
}
|
||||
|
||||
output += "Hash length: " + input.length + "\n" +
|
||||
"Byte length: " + byteLength + "\n" +
|
||||
"Bit length: " + bitLength + "\n\n" +
|
||||
"Based on the length, this hash could have been generated by one of the following hashing functions:\n";
|
||||
|
||||
switch (bitLength) {
|
||||
case 4:
|
||||
possibleHashFunctions = [
|
||||
"Fletcher-4",
|
||||
"Luhn algorithm",
|
||||
"Verhoeff algorithm",
|
||||
];
|
||||
break;
|
||||
case 8:
|
||||
possibleHashFunctions = [
|
||||
"Fletcher-8",
|
||||
];
|
||||
break;
|
||||
case 16:
|
||||
possibleHashFunctions = [
|
||||
"BSD checksum",
|
||||
"CRC-16",
|
||||
"SYSV checksum",
|
||||
"Fletcher-16"
|
||||
];
|
||||
break;
|
||||
case 32:
|
||||
possibleHashFunctions = [
|
||||
"CRC-32",
|
||||
"Fletcher-32",
|
||||
"Adler-32",
|
||||
];
|
||||
break;
|
||||
case 64:
|
||||
possibleHashFunctions = [
|
||||
"CRC-64",
|
||||
"RIPEMD-64",
|
||||
"SipHash",
|
||||
];
|
||||
break;
|
||||
case 128:
|
||||
possibleHashFunctions = [
|
||||
"MD5",
|
||||
"MD4",
|
||||
"MD2",
|
||||
"HAVAL-128",
|
||||
"RIPEMD-128",
|
||||
"Snefru",
|
||||
"Tiger-128",
|
||||
];
|
||||
break;
|
||||
case 160:
|
||||
possibleHashFunctions = [
|
||||
"SHA-1",
|
||||
"SHA-0",
|
||||
"FSB-160",
|
||||
"HAS-160",
|
||||
"HAVAL-160",
|
||||
"RIPEMD-160",
|
||||
"Tiger-160",
|
||||
];
|
||||
break;
|
||||
case 192:
|
||||
possibleHashFunctions = [
|
||||
"Tiger",
|
||||
"HAVAL-192",
|
||||
];
|
||||
break;
|
||||
case 224:
|
||||
possibleHashFunctions = [
|
||||
"SHA-224",
|
||||
"SHA3-224",
|
||||
"ECOH-224",
|
||||
"FSB-224",
|
||||
"HAVAL-224",
|
||||
];
|
||||
break;
|
||||
case 256:
|
||||
possibleHashFunctions = [
|
||||
"SHA-256",
|
||||
"SHA3-256",
|
||||
"BLAKE-256",
|
||||
"ECOH-256",
|
||||
"FSB-256",
|
||||
"GOST",
|
||||
"Grøstl-256",
|
||||
"HAVAL-256",
|
||||
"PANAMA",
|
||||
"RIPEMD-256",
|
||||
"Snefru",
|
||||
];
|
||||
break;
|
||||
case 320:
|
||||
possibleHashFunctions = [
|
||||
"RIPEMD-320",
|
||||
];
|
||||
break;
|
||||
case 384:
|
||||
possibleHashFunctions = [
|
||||
"SHA-384",
|
||||
"SHA3-384",
|
||||
"ECOH-384",
|
||||
"FSB-384",
|
||||
];
|
||||
break;
|
||||
case 512:
|
||||
possibleHashFunctions = [
|
||||
"SHA-512",
|
||||
"SHA3-512",
|
||||
"BLAKE-512",
|
||||
"ECOH-512",
|
||||
"FSB-512",
|
||||
"Grøstl-512",
|
||||
"JH",
|
||||
"MD6",
|
||||
"Spectral Hash",
|
||||
"SWIFFT",
|
||||
"Whirlpool",
|
||||
];
|
||||
break;
|
||||
case 1024:
|
||||
possibleHashFunctions = [
|
||||
"Fowler-Noll-Vo",
|
||||
];
|
||||
break;
|
||||
default:
|
||||
possibleHashFunctions = [
|
||||
"Unknown"
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
return output + possibleHashFunctions.join("\n");
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Hash;
|
@ -1,203 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import {fromHex} from "../lib/Hex";
|
||||
|
||||
|
||||
/**
|
||||
* Hexdump operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Hexdump = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WIDTH: 16,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
UPPER_CASE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_FINAL_LENGTH: false,
|
||||
|
||||
/**
|
||||
* To Hexdump operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
const data = new Uint8Array(input);
|
||||
const length = args[0] || Hexdump.WIDTH;
|
||||
const upperCase = args[1];
|
||||
const includeFinalLength = args[2];
|
||||
|
||||
let output = "", padding = 2;
|
||||
for (let i = 0; i < data.length; i += length) {
|
||||
const buff = data.slice(i, i+length);
|
||||
let hexa = "";
|
||||
for (let j = 0; j < buff.length; j++) {
|
||||
hexa += Utils.hex(buff[j], padding) + " ";
|
||||
}
|
||||
|
||||
let lineNo = Utils.hex(i, 8);
|
||||
|
||||
if (upperCase) {
|
||||
hexa = hexa.toUpperCase();
|
||||
lineNo = lineNo.toUpperCase();
|
||||
}
|
||||
|
||||
output += lineNo + " " +
|
||||
hexa.padEnd(length*(padding+1), " ") +
|
||||
" |" + Utils.printable(Utils.byteArrayToChars(buff)).padEnd(buff.length, " ") + "|\n";
|
||||
|
||||
if (includeFinalLength && i+buff.length === data.length) {
|
||||
output += Utils.hex(i+buff.length, 8) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, -1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Hexdump operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
let output = [],
|
||||
regex = /^\s*(?:[\dA-F]{4,16}h?:?)?\s*((?:[\dA-F]{2}\s){1,8}(?:\s|[\dA-F]{2}-)(?:[\dA-F]{2}\s){1,8}|(?:[\dA-F]{2}\s|[\dA-F]{4}\s)+)/igm,
|
||||
block, line;
|
||||
|
||||
while ((block = regex.exec(input))) {
|
||||
line = fromHex(block[1].replace(/-/g, " "));
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
output.push(line[i]);
|
||||
}
|
||||
}
|
||||
// Is this a CyberChef hexdump or is it from a different tool?
|
||||
const width = input.indexOf("\n");
|
||||
const w = (width - 13) / 4;
|
||||
// w should be the specified width of the hexdump and therefore a round number
|
||||
if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) {
|
||||
if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to hexdump
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightTo: function(pos, args) {
|
||||
// Calculate overall selection
|
||||
let w = args[0] || 16,
|
||||
width = 14 + (w*4),
|
||||
line = Math.floor(pos[0].start / w),
|
||||
offset = pos[0].start % w,
|
||||
start = 0,
|
||||
end = 0;
|
||||
|
||||
pos[0].start = line*width + 10 + offset*3;
|
||||
|
||||
line = Math.floor(pos[0].end / w);
|
||||
offset = pos[0].end % w;
|
||||
if (offset === 0) {
|
||||
line--;
|
||||
offset = w;
|
||||
}
|
||||
pos[0].end = line*width + 10 + offset*3 - 1;
|
||||
|
||||
// Set up multiple selections for bytes
|
||||
let startLineNum = Math.floor(pos[0].start / width);
|
||||
const endLineNum = Math.floor(pos[0].end / width);
|
||||
|
||||
if (startLineNum === endLineNum) {
|
||||
pos.push(pos[0]);
|
||||
} else {
|
||||
start = pos[0].start;
|
||||
end = (startLineNum+1) * width - w - 5;
|
||||
pos.push({ start: start, end: end });
|
||||
while (end < pos[0].end) {
|
||||
startLineNum++;
|
||||
start = startLineNum * width + 10;
|
||||
end = (startLineNum+1) * width - w - 5;
|
||||
if (end > pos[0].end) end = pos[0].end;
|
||||
pos.push({ start: start, end: end });
|
||||
}
|
||||
}
|
||||
|
||||
// Set up multiple selections for ASCII
|
||||
let len = pos.length, lineNum = 0;
|
||||
start = 0;
|
||||
end = 0;
|
||||
for (let i = 1; i < len; i++) {
|
||||
lineNum = Math.floor(pos[i].start / width);
|
||||
start = (((pos[i].start - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width);
|
||||
end = (((pos[i].end + 1 - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width);
|
||||
pos.push({ start: start, end: end });
|
||||
}
|
||||
return pos;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight from hexdump
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFrom: function(pos, args) {
|
||||
const w = args[0] || 16;
|
||||
const width = 14 + (w*4);
|
||||
|
||||
let line = Math.floor(pos[0].start / width);
|
||||
let offset = pos[0].start % width;
|
||||
|
||||
if (offset < 10) { // In line number section
|
||||
pos[0].start = line*w;
|
||||
} else if (offset > 10+(w*3)) { // In ASCII section
|
||||
pos[0].start = (line+1)*w;
|
||||
} else { // In byte section
|
||||
pos[0].start = line*w + Math.floor((offset-10)/3);
|
||||
}
|
||||
|
||||
line = Math.floor(pos[0].end / width);
|
||||
offset = pos[0].end % width;
|
||||
|
||||
if (offset < 10) { // In line number section
|
||||
pos[0].end = line*w;
|
||||
} else if (offset > 10+(w*3)) { // In ASCII section
|
||||
pos[0].end = (line+1)*w;
|
||||
} else { // In byte section
|
||||
pos[0].end = line*w + Math.ceil((offset-10)/3);
|
||||
}
|
||||
|
||||
return pos;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Hexdump;
|
File diff suppressed because it is too large
Load Diff
@ -1,105 +0,0 @@
|
||||
/**
|
||||
* MAC address operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const MAC = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_CASE: ["Both", "Upper only", "Lower only"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
NO_DELIM: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DASH_DELIM: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
COLON_DELIM: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CISCO_STYLE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IPV6_INTERFACE_ID: false,
|
||||
|
||||
/**
|
||||
* Format MAC addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFormat: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
let outputCase = args[0],
|
||||
noDelim = args[1],
|
||||
dashDelim = args[2],
|
||||
colonDelim = args[3],
|
||||
ciscoStyle = args[4],
|
||||
ipv6IntID = args[5],
|
||||
outputList = [],
|
||||
macs = input.toLowerCase().split(/[,\s\r\n]+/);
|
||||
|
||||
macs.forEach(function(mac) {
|
||||
let cleanMac = mac.replace(/[:.-]+/g, ""),
|
||||
macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"),
|
||||
macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"),
|
||||
macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1."),
|
||||
macIPv6 = cleanMac.slice(0, 6) + "fffe" + cleanMac.slice(6);
|
||||
|
||||
macIPv6 = macIPv6.replace(/(.{4}(?=.))/g, "$1:");
|
||||
let bite = parseInt(macIPv6.slice(0, 2), 16) ^ 2;
|
||||
bite = bite.toString(16).padStart(2, "0");
|
||||
macIPv6 = bite + macIPv6.slice(2);
|
||||
|
||||
if (outputCase === "Lower only") {
|
||||
if (noDelim) outputList.push(cleanMac);
|
||||
if (dashDelim) outputList.push(macHyphen);
|
||||
if (colonDelim) outputList.push(macColon);
|
||||
if (ciscoStyle) outputList.push(macCisco);
|
||||
if (ipv6IntID) outputList.push(macIPv6);
|
||||
} else if (outputCase === "Upper only") {
|
||||
if (noDelim) outputList.push(cleanMac.toUpperCase());
|
||||
if (dashDelim) outputList.push(macHyphen.toUpperCase());
|
||||
if (colonDelim) outputList.push(macColon.toUpperCase());
|
||||
if (ciscoStyle) outputList.push(macCisco.toUpperCase());
|
||||
if (ipv6IntID) outputList.push(macIPv6.toUpperCase());
|
||||
} else {
|
||||
if (noDelim) outputList.push(cleanMac, cleanMac.toUpperCase());
|
||||
if (dashDelim) outputList.push(macHyphen, macHyphen.toUpperCase());
|
||||
if (colonDelim) outputList.push(macColon, macColon.toUpperCase());
|
||||
if (ciscoStyle) outputList.push(macCisco, macCisco.toUpperCase());
|
||||
if (ipv6IntID) outputList.push(macIPv6, macIPv6.toUpperCase());
|
||||
}
|
||||
|
||||
outputList.push(
|
||||
"" // Empty line to delimit groups
|
||||
);
|
||||
});
|
||||
|
||||
// Return the data as a string
|
||||
return outputList.join("\n");
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default MAC;
|
@ -1,213 +0,0 @@
|
||||
/**
|
||||
* Microsoft operations.
|
||||
*
|
||||
* @author bmwhitn [brian.m.whitney@outlook.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const MS = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
D_DECODE: [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"\x57\x6E\x7B",
|
||||
"\x4A\x4C\x41",
|
||||
"\x0B\x0B\x0B",
|
||||
"\x0C\x0C\x0C",
|
||||
"\x4A\x4C\x41",
|
||||
"\x0E\x0E\x0E",
|
||||
"\x0F\x0F\x0F",
|
||||
"\x10\x10\x10",
|
||||
"\x11\x11\x11",
|
||||
"\x12\x12\x12",
|
||||
"\x13\x13\x13",
|
||||
"\x14\x14\x14",
|
||||
"\x15\x15\x15",
|
||||
"\x16\x16\x16",
|
||||
"\x17\x17\x17",
|
||||
"\x18\x18\x18",
|
||||
"\x19\x19\x19",
|
||||
"\x1A\x1A\x1A",
|
||||
"\x1B\x1B\x1B",
|
||||
"\x1C\x1C\x1C",
|
||||
"\x1D\x1D\x1D",
|
||||
"\x1E\x1E\x1E",
|
||||
"\x1F\x1F\x1F",
|
||||
"\x2E\x2D\x32",
|
||||
"\x47\x75\x30",
|
||||
"\x7A\x52\x21",
|
||||
"\x56\x60\x29",
|
||||
"\x42\x71\x5B",
|
||||
"\x6A\x5E\x38",
|
||||
"\x2F\x49\x33",
|
||||
"\x26\x5C\x3D",
|
||||
"\x49\x62\x58",
|
||||
"\x41\x7D\x3A",
|
||||
"\x34\x29\x35",
|
||||
"\x32\x36\x65",
|
||||
"\x5B\x20\x39",
|
||||
"\x76\x7C\x5C",
|
||||
"\x72\x7A\x56",
|
||||
"\x43\x7F\x73",
|
||||
"\x38\x6B\x66",
|
||||
"\x39\x63\x4E",
|
||||
"\x70\x33\x45",
|
||||
"\x45\x2B\x6B",
|
||||
"\x68\x68\x62",
|
||||
"\x71\x51\x59",
|
||||
"\x4F\x66\x78",
|
||||
"\x09\x76\x5E",
|
||||
"\x62\x31\x7D",
|
||||
"\x44\x64\x4A",
|
||||
"\x23\x54\x6D",
|
||||
"\x75\x43\x71",
|
||||
"\x4A\x4C\x41",
|
||||
"\x7E\x3A\x60",
|
||||
"\x4A\x4C\x41",
|
||||
"\x5E\x7E\x53",
|
||||
"\x40\x4C\x40",
|
||||
"\x77\x45\x42",
|
||||
"\x4A\x2C\x27",
|
||||
"\x61\x2A\x48",
|
||||
"\x5D\x74\x72",
|
||||
"\x22\x27\x75",
|
||||
"\x4B\x37\x31",
|
||||
"\x6F\x44\x37",
|
||||
"\x4E\x79\x4D",
|
||||
"\x3B\x59\x52",
|
||||
"\x4C\x2F\x22",
|
||||
"\x50\x6F\x54",
|
||||
"\x67\x26\x6A",
|
||||
"\x2A\x72\x47",
|
||||
"\x7D\x6A\x64",
|
||||
"\x74\x39\x2D",
|
||||
"\x54\x7B\x20",
|
||||
"\x2B\x3F\x7F",
|
||||
"\x2D\x38\x2E",
|
||||
"\x2C\x77\x4C",
|
||||
"\x30\x67\x5D",
|
||||
"\x6E\x53\x7E",
|
||||
"\x6B\x47\x6C",
|
||||
"\x66\x34\x6F",
|
||||
"\x35\x78\x79",
|
||||
"\x25\x5D\x74",
|
||||
"\x21\x30\x43",
|
||||
"\x64\x23\x26",
|
||||
"\x4D\x5A\x76",
|
||||
"\x52\x5B\x25",
|
||||
"\x63\x6C\x24",
|
||||
"\x3F\x48\x2B",
|
||||
"\x7B\x55\x28",
|
||||
"\x78\x70\x23",
|
||||
"\x29\x69\x41",
|
||||
"\x28\x2E\x34",
|
||||
"\x73\x4C\x09",
|
||||
"\x59\x21\x2A",
|
||||
"\x33\x24\x44",
|
||||
"\x7F\x4E\x3F",
|
||||
"\x6D\x50\x77",
|
||||
"\x55\x09\x3B",
|
||||
"\x53\x56\x55",
|
||||
"\x7C\x73\x69",
|
||||
"\x3A\x35\x61",
|
||||
"\x5F\x61\x63",
|
||||
"\x65\x4B\x50",
|
||||
"\x46\x58\x67",
|
||||
"\x58\x3B\x51",
|
||||
"\x31\x57\x49",
|
||||
"\x69\x22\x4F",
|
||||
"\x6C\x6D\x46",
|
||||
"\x5A\x4D\x68",
|
||||
"\x48\x25\x7C",
|
||||
"\x27\x28\x36",
|
||||
"\x5C\x46\x70",
|
||||
"\x3D\x4A\x6E",
|
||||
"\x24\x32\x7A",
|
||||
"\x79\x41\x2F",
|
||||
"\x37\x3D\x5F",
|
||||
"\x60\x5F\x4B",
|
||||
"\x51\x4F\x5A",
|
||||
"\x20\x42\x2C",
|
||||
"\x36\x65\x57"
|
||||
],
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
D_COMBINATION: [
|
||||
0, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 2, 0, 0, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1,
|
||||
0, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 2, 1
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* Decodes Microsoft Encoded Script files that can be read and executed by cscript.exe/wscript.exe.
|
||||
* This is a conversion of a Python script that was originally created by Didier Stevens
|
||||
* (https://DidierStevens.com).
|
||||
*
|
||||
* @private
|
||||
* @param {string} data
|
||||
* @returns {string}
|
||||
*/
|
||||
_decode: function (data) {
|
||||
let result = [];
|
||||
let index = -1;
|
||||
data = data.replace(/@&/g, String.fromCharCode(10))
|
||||
.replace(/@#/g, String.fromCharCode(13))
|
||||
.replace(/@\*/g, ">")
|
||||
.replace(/@!/g, "<")
|
||||
.replace(/@\$/g, "@");
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let byte = data.charCodeAt(i);
|
||||
let char = data.charAt(i);
|
||||
if (byte < 128) {
|
||||
index++;
|
||||
}
|
||||
|
||||
if ((byte === 9 || byte > 31 && byte < 128) &&
|
||||
byte !== 60 &&
|
||||
byte !== 62 &&
|
||||
byte !== 64) {
|
||||
char = MS.D_DECODE[byte].charAt(MS.D_COMBINATION[index % 64]);
|
||||
}
|
||||
result.push(char);
|
||||
}
|
||||
return result.join("");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Microsoft Script Decoder operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDecodeScript: function (input, args) {
|
||||
let matcher = /#@~\^.{6}==(.+).{6}==\^#~@/;
|
||||
let encodedData = matcher.exec(input);
|
||||
if (encodedData){
|
||||
return MS._decode(encodedData[1]);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default MS;
|
@ -1,190 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Morse Code translation operations.
|
||||
*
|
||||
* @author tlwr [toby@toby.codes]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const MorseCode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FORMAT_OPTIONS: ["-/.", "_/.", "Dash/Dot", "DASH/DOT", "dash/dot"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LETTER_DELIM_OPTIONS: ["Space", "Line feed", "CRLF", "Forward slash", "Backslash", "Comma", "Semi-colon", "Colon"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WORD_DELIM_OPTIONS: ["Line feed", "CRLF", "Forward slash", "Backslash", "Comma", "Semi-colon", "Colon"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MORSE_TABLE: {
|
||||
"A": "<dot><dash>",
|
||||
"B": "<dash><dot><dot><dot>",
|
||||
"C": "<dash><dot><dash><dot>",
|
||||
"D": "<dash><dot><dot>",
|
||||
"E": "<dot>",
|
||||
"F": "<dot><dot><dash><dot>",
|
||||
"G": "<dash><dash><dot>",
|
||||
"H": "<dot><dot><dot><dot>",
|
||||
"I": "<dot><dot>",
|
||||
"J": "<dot><dash><dash><dash>",
|
||||
"K": "<dash><dot><dash>",
|
||||
"L": "<dot><dash><dot><dot>",
|
||||
"M": "<dash><dash>",
|
||||
"N": "<dash><dot>",
|
||||
"O": "<dash><dash><dash>",
|
||||
"P": "<dot><dash><dash><dot>",
|
||||
"Q": "<dash><dash><dot><dash>",
|
||||
"R": "<dot><dash><dot>",
|
||||
"S": "<dot><dot><dot>",
|
||||
"T": "<dash>",
|
||||
"U": "<dot><dot><dash>",
|
||||
"V": "<dot><dot><dot><dash>",
|
||||
"W": "<dot><dash><dash>",
|
||||
"X": "<dash><dot><dot><dash>",
|
||||
"Y": "<dash><dot><dash><dash>",
|
||||
"Z": "<dash><dash><dot><dot>",
|
||||
"1": "<dot><dash><dash><dash><dash>",
|
||||
"2": "<dot><dot><dash><dash><dash>",
|
||||
"3": "<dot><dot><dot><dash><dash>",
|
||||
"4": "<dot><dot><dot><dot><dash>",
|
||||
"5": "<dot><dot><dot><dot><dot>",
|
||||
"6": "<dash><dot><dot><dot><dot>",
|
||||
"7": "<dash><dash><dot><dot><dot>",
|
||||
"8": "<dash><dash><dash><dot><dot>",
|
||||
"9": "<dash><dash><dash><dash><dot>",
|
||||
"0": "<dash><dash><dash><dash><dash>",
|
||||
".": "<dot><dash><dot><dash><dot><dash>",
|
||||
",": "<dash><dash><dot><dot><dash><dash>",
|
||||
":": "<dash><dash><dash><dot><dot><dot>",
|
||||
";": "<dash><dot><dash><dot><dash><dot>",
|
||||
"!": "<dash><dot><dash><dot><dash><dash>",
|
||||
"?": "<dot><dot><dash><dash><dot><dot>",
|
||||
"'": "<dot><dash><dash><dash><dash><dot>",
|
||||
"\"": "<dot><dash><dot><dot><dash><dot>",
|
||||
"/": "<dash><dot><dot><dash><dot>",
|
||||
"-": "<dash><dot><dot><dot><dot><dash>",
|
||||
"+": "<dot><dash><dot><dash><dot>",
|
||||
"(": "<dash><dot><dash><dash><dot>",
|
||||
")": "<dash><dot><dash><dash><dot><dash>",
|
||||
"@": "<dot><dash><dash><dot><dash><dot>",
|
||||
"=": "<dash><dot><dot><dot><dash>",
|
||||
"&": "<dot><dash><dot><dot><dot>",
|
||||
"_": "<dot><dot><dash><dash><dot><dash>",
|
||||
"$": "<dot><dot><dot><dash><dot><dot><dash>"
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Morse Code operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
const format = args[0].split("/");
|
||||
const dash = format[0];
|
||||
const dot = format[1];
|
||||
|
||||
const letterDelim = Utils.charRep(args[1]);
|
||||
const wordDelim = Utils.charRep(args[2]);
|
||||
|
||||
input = input.split(/\r?\n/);
|
||||
input = Array.prototype.map.call(input, function(line) {
|
||||
let words = line.split(/ +/);
|
||||
words = Array.prototype.map.call(words, function(word) {
|
||||
const letters = Array.prototype.map.call(word, function(character) {
|
||||
const letter = character.toUpperCase();
|
||||
if (typeof MorseCode.MORSE_TABLE[letter] == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return MorseCode.MORSE_TABLE[letter];
|
||||
});
|
||||
|
||||
return letters.join("<ld>");
|
||||
});
|
||||
line = words.join("<wd>");
|
||||
return line;
|
||||
});
|
||||
input = input.join("\n");
|
||||
|
||||
input = input.replace(
|
||||
/<dash>|<dot>|<ld>|<wd>/g,
|
||||
function(match) {
|
||||
switch (match) {
|
||||
case "<dash>": return dash;
|
||||
case "<dot>": return dot;
|
||||
case "<ld>": return letterDelim;
|
||||
case "<wd>": return wordDelim;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Morse Code operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFrom: (function() {
|
||||
let reversedTable = null;
|
||||
const reverseTable = function() {
|
||||
reversedTable = {};
|
||||
|
||||
for (const letter in MorseCode.MORSE_TABLE) {
|
||||
const signal = MorseCode.MORSE_TABLE[letter];
|
||||
reversedTable[signal] = letter;
|
||||
}
|
||||
};
|
||||
|
||||
return function(input, args) {
|
||||
if (reversedTable === null) {
|
||||
reverseTable();
|
||||
}
|
||||
|
||||
const letterDelim = Utils.charRep(args[0]);
|
||||
const wordDelim = Utils.charRep(args[1]);
|
||||
|
||||
input = input.replace(/-|‐|−|_|–|—|dash/ig, "<dash>"); //hyphen-minus|hyphen|minus-sign|undersore|en-dash|em-dash
|
||||
input = input.replace(/\.|·|dot/ig, "<dot>");
|
||||
|
||||
let words = input.split(wordDelim);
|
||||
words = Array.prototype.map.call(words, function(word) {
|
||||
const signals = word.split(letterDelim);
|
||||
|
||||
const letters = signals.map(function(signal) {
|
||||
return reversedTable[signal];
|
||||
});
|
||||
|
||||
return letters.join("");
|
||||
});
|
||||
words = words.join(" ");
|
||||
|
||||
return words;
|
||||
};
|
||||
})(),
|
||||
|
||||
};
|
||||
|
||||
export default MorseCode;
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* NetBIOS operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const NetBIOS = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OFFSET: 65,
|
||||
|
||||
/**
|
||||
* Encode NetBIOS Name operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runEncodeName: function(input, args) {
|
||||
let output = [],
|
||||
offset = args[0];
|
||||
|
||||
if (input.length <= 16) {
|
||||
let len = input.length;
|
||||
input.length = 16;
|
||||
input.fill(32, len, 16);
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
output.push((input[i] >> 4) + offset);
|
||||
output.push((input[i] & 0xf) + offset);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Decode NetBIOS Name operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runDecodeName: function(input, args) {
|
||||
let output = [],
|
||||
offset = args[0];
|
||||
|
||||
if (input.length <= 32 && (input.length % 2) === 0) {
|
||||
for (let i = 0; i < input.length; i += 2) {
|
||||
output.push((((input[i] & 0xff) - offset) << 4) |
|
||||
(((input[i + 1] & 0xff) - offset) & 0xf));
|
||||
}
|
||||
for (let i = output.length - 1; i > 0; i--) {
|
||||
if (output[i] === 32) output.splice(i, i);
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default NetBIOS;
|
@ -1,85 +0,0 @@
|
||||
/**
|
||||
* Numberwang operations.
|
||||
*
|
||||
* @author Unknown Male 282
|
||||
* @namespace
|
||||
*/
|
||||
const Numberwang = {
|
||||
|
||||
/**
|
||||
* Numberwang operation. Remain indoors.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run: function(input, args) {
|
||||
let output;
|
||||
if (!input) {
|
||||
output = "Let's play Wangernumb!";
|
||||
} else {
|
||||
const match = input.match(/(f0rty-s1x|shinty-six|filth-hundred and neeb|-?√?\d+(\.\d+)?i?([a-z]?)%?)/i);
|
||||
if (match) {
|
||||
if (match[3]) output = match[0] + "! That's AlphaNumericWang!";
|
||||
else output = match[0] + "! That's Numberwang!";
|
||||
} else {
|
||||
// That's a bad miss!
|
||||
output = "Sorry, that's not Numberwang. Let's rotate the board!";
|
||||
}
|
||||
}
|
||||
|
||||
const rand = Math.floor(Math.random() * Numberwang._didYouKnow.length);
|
||||
return output + "\n\nDid you know: " + Numberwang._didYouKnow[rand];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Taken from http://numberwang.wikia.com/wiki/Numberwang_Wikia
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_didYouKnow: [
|
||||
"Numberwang, contrary to popular belief, is a fruit and not a vegetable.",
|
||||
"Robert Webb once got WordWang while presenting an episode of Numberwang.",
|
||||
"The 6705th digit of pi is Numberwang.",
|
||||
"Numberwang was invented on a Sevenday.",
|
||||
"Contrary to popular belief, Albert Einstein always got good grades in Numberwang at school. He once scored ^4$ on a test.",
|
||||
"680 asteroids have been named after Numberwang.",
|
||||
"Archimedes is most famous for proclaiming \"That's Numberwang!\" during an epiphany about water displacement he had while taking a bath.",
|
||||
"Numberwang Day is celebrated in Japan on every day of the year apart from June 6.",
|
||||
"Biologists recently discovered Numberwang within a strand of human DNA.",
|
||||
"Numbernot is a special type of non-Numberwang number. It is divisible by 3 and the letter \"y\".",
|
||||
"Julie once got 612.04 Numberwangs in a single episode of Emmerdale.",
|
||||
"In India, it is traditional to shout out \"Numberwang!\" instead of checkmate during games of chess.",
|
||||
"There is a rule on Countdown which states that if you get Numberwang in the numbers round, you automatically win. It has only ever been invoked twice.",
|
||||
"\"Numberwang\" was the third-most common baby name for a brief period in 1722.",
|
||||
"\"The Lion King\" was loosely based on Numberwang.",
|
||||
"\"A Numberwang a day keeps the doctor away\" is how Donny Cosy, the oldest man in the world, explained how he was in such good health at the age of 136.",
|
||||
"The \"number lock\" button on a keyboard is based on the popular round of the same name in \"Numberwang\".",
|
||||
"Cambridge became the first university to offer a course in Numberwang in 1567.",
|
||||
"Schrödinger's Numberwang is a number that has been confusing dentists for centuries.",
|
||||
"\"Harry Potter and the Numberwang of Numberwang\" was rejected by publishers -41 times before it became a bestseller.",
|
||||
"\"Numberwang\" is the longest-running British game show in history; it has aired 226 seasons, each containing 19 episodes, which makes a grand total of 132 episodes.",
|
||||
"The triple Numberwang bonus was discovered by archaeologist Thomas Jefferson in Somerset.",
|
||||
"Numberwang is illegal in parts of Czechoslovakia.",
|
||||
"Numberwang was discovered in India in the 12th century.",
|
||||
"Numberwang has the chemical formula Zn4SO2(HgEs)3.",
|
||||
"The first pack of cards ever created featured two \"Numberwang\" cards instead of jokers.",
|
||||
"Julius Caesar was killed by an overdose of Numberwang.",
|
||||
"The most Numberwang musical note is G#.",
|
||||
"In 1934, the forty-third Google Doodle promoted the upcoming television show \"Numberwang on Ice\".",
|
||||
"A recent psychology study found that toddlers were 17% faster at identifying numbers which were Numberwang.",
|
||||
"There are 700 ways to commit a foul in the television show \"Numberwang\". All 700 of these fouls were committed by Julie in one single episode in 1473.",
|
||||
"Astronomers suspect God is Numberwang.",
|
||||
"Numberwang is the official beverage of Canada.",
|
||||
"In the pilot episode of \"The Price is Right\", if a contestant got the value of an item exactly right they were told \"That's Numberwang!\" and immediately won ₹5.7032.",
|
||||
"The first person to get three Numberwangs in a row was Madonna.",
|
||||
"\"Numberwang\" has the code U+46402 in Unicode.",
|
||||
"The musical note \"Numberwang\" is between D# and E♮.",
|
||||
"Numberwang was first played on the moon in 1834.",
|
||||
],
|
||||
|
||||
};
|
||||
|
||||
export default Numberwang;
|
@ -1,311 +0,0 @@
|
||||
/**
|
||||
* Operating system operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const OS = {
|
||||
|
||||
/**
|
||||
* Parse UNIX file permissions operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseUnixPerms: function(input, args) {
|
||||
let perms = {
|
||||
d: false, // directory
|
||||
sl: false, // symbolic link
|
||||
np: false, // named pipe
|
||||
s: false, // socket
|
||||
cd: false, // character device
|
||||
bd: false, // block device
|
||||
dr: false, // door
|
||||
sb: false, // sticky bit
|
||||
su: false, // setuid
|
||||
sg: false, // setgid
|
||||
ru: false, // read user
|
||||
wu: false, // write user
|
||||
eu: false, // execute user
|
||||
rg: false, // read group
|
||||
wg: false, // write group
|
||||
eg: false, // execute group
|
||||
ro: false, // read other
|
||||
wo: false, // write other
|
||||
eo: false // execute other
|
||||
},
|
||||
d = 0,
|
||||
u = 0,
|
||||
g = 0,
|
||||
o = 0,
|
||||
output = "",
|
||||
octal = null,
|
||||
textual = null;
|
||||
|
||||
if (input.search(/\s*[0-7]{1,4}\s*/i) === 0) {
|
||||
// Input is octal
|
||||
octal = input.match(/\s*([0-7]{1,4})\s*/i)[1];
|
||||
|
||||
if (octal.length === 4) {
|
||||
d = parseInt(octal[0], 8);
|
||||
u = parseInt(octal[1], 8);
|
||||
g = parseInt(octal[2], 8);
|
||||
o = parseInt(octal[3], 8);
|
||||
} else {
|
||||
if (octal.length > 0) u = parseInt(octal[0], 8);
|
||||
if (octal.length > 1) g = parseInt(octal[1], 8);
|
||||
if (octal.length > 2) o = parseInt(octal[2], 8);
|
||||
}
|
||||
|
||||
perms.su = d >> 2 & 0x1;
|
||||
perms.sg = d >> 1 & 0x1;
|
||||
perms.sb = d & 0x1;
|
||||
|
||||
perms.ru = u >> 2 & 0x1;
|
||||
perms.wu = u >> 1 & 0x1;
|
||||
perms.eu = u & 0x1;
|
||||
|
||||
perms.rg = g >> 2 & 0x1;
|
||||
perms.wg = g >> 1 & 0x1;
|
||||
perms.eg = g & 0x1;
|
||||
|
||||
perms.ro = o >> 2 & 0x1;
|
||||
perms.wo = o >> 1 & 0x1;
|
||||
perms.eo = o & 0x1;
|
||||
} else if (input.search(/\s*[dlpcbDrwxsStT-]{1,10}\s*/) === 0) {
|
||||
// Input is textual
|
||||
textual = input.match(/\s*([dlpcbDrwxsStT-]{1,10})\s*/)[1];
|
||||
|
||||
switch (textual[0]) {
|
||||
case "d":
|
||||
perms.d = true;
|
||||
break;
|
||||
case "l":
|
||||
perms.sl = true;
|
||||
break;
|
||||
case "p":
|
||||
perms.np = true;
|
||||
break;
|
||||
case "s":
|
||||
perms.s = true;
|
||||
break;
|
||||
case "c":
|
||||
perms.cd = true;
|
||||
break;
|
||||
case "b":
|
||||
perms.bd = true;
|
||||
break;
|
||||
case "D":
|
||||
perms.dr = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (textual.length > 1) perms.ru = textual[1] === "r";
|
||||
if (textual.length > 2) perms.wu = textual[2] === "w";
|
||||
if (textual.length > 3) {
|
||||
switch (textual[3]) {
|
||||
case "x":
|
||||
perms.eu = true;
|
||||
break;
|
||||
case "s":
|
||||
perms.eu = true;
|
||||
perms.su = true;
|
||||
break;
|
||||
case "S":
|
||||
perms.su = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (textual.length > 4) perms.rg = textual[4] === "r";
|
||||
if (textual.length > 5) perms.wg = textual[5] === "w";
|
||||
if (textual.length > 6) {
|
||||
switch (textual[6]) {
|
||||
case "x":
|
||||
perms.eg = true;
|
||||
break;
|
||||
case "s":
|
||||
perms.eg = true;
|
||||
perms.sg = true;
|
||||
break;
|
||||
case "S":
|
||||
perms.sg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (textual.length > 7) perms.ro = textual[7] === "r";
|
||||
if (textual.length > 8) perms.wo = textual[8] === "w";
|
||||
if (textual.length > 9) {
|
||||
switch (textual[9]) {
|
||||
case "x":
|
||||
perms.eo = true;
|
||||
break;
|
||||
case "t":
|
||||
perms.eo = true;
|
||||
perms.sb = true;
|
||||
break;
|
||||
case "T":
|
||||
perms.sb = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return "Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.";
|
||||
}
|
||||
|
||||
output += "Textual representation: " + OS._permsToStr(perms);
|
||||
output += "\nOctal representation: " + OS._permsToOctal(perms);
|
||||
|
||||
// File type
|
||||
if (textual) {
|
||||
output += "\nFile type: " + OS._ftFromPerms(perms);
|
||||
}
|
||||
|
||||
// setuid, setgid
|
||||
if (perms.su) {
|
||||
output += "\nThe setuid flag is set";
|
||||
}
|
||||
if (perms.sg) {
|
||||
output += "\nThe setgid flag is set";
|
||||
}
|
||||
|
||||
// sticky bit
|
||||
if (perms.sb) {
|
||||
output += "\nThe sticky bit is set";
|
||||
}
|
||||
|
||||
// Permission matrix
|
||||
output += "\n\n +---------+-------+-------+-------+\n" +
|
||||
" | | User | Group | Other |\n" +
|
||||
" +---------+-------+-------+-------+\n" +
|
||||
" | Read | " + (perms.ru ? "X" : " ") + " | " + (perms.rg ? "X" : " ") + " | " + (perms.ro ? "X" : " ") + " |\n" +
|
||||
" +---------+-------+-------+-------+\n" +
|
||||
" | Write | " + (perms.wu ? "X" : " ") + " | " + (perms.wg ? "X" : " ") + " | " + (perms.wo ? "X" : " ") + " |\n" +
|
||||
" +---------+-------+-------+-------+\n" +
|
||||
" | Execute | " + (perms.eu ? "X" : " ") + " | " + (perms.eg ? "X" : " ") + " | " + (perms.eo ? "X" : " ") + " |\n" +
|
||||
" +---------+-------+-------+-------+\n";
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Given a permissions object dictionary, generates a textual permissions string.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} perms
|
||||
* @returns {string}
|
||||
*/
|
||||
_permsToStr: function(perms) {
|
||||
let str = "",
|
||||
type = "-";
|
||||
|
||||
if (perms.d) type = "d";
|
||||
if (perms.sl) type = "l";
|
||||
if (perms.np) type = "p";
|
||||
if (perms.s) type = "s";
|
||||
if (perms.cd) type = "c";
|
||||
if (perms.bd) type = "b";
|
||||
if (perms.dr) type = "D";
|
||||
|
||||
str = type;
|
||||
|
||||
str += perms.ru ? "r" : "-";
|
||||
str += perms.wu ? "w" : "-";
|
||||
if (perms.eu && perms.su) {
|
||||
str += "s";
|
||||
} else if (perms.su) {
|
||||
str += "S";
|
||||
} else if (perms.eu) {
|
||||
str += "x";
|
||||
} else {
|
||||
str += "-";
|
||||
}
|
||||
|
||||
str += perms.rg ? "r" : "-";
|
||||
str += perms.wg ? "w" : "-";
|
||||
if (perms.eg && perms.sg) {
|
||||
str += "s";
|
||||
} else if (perms.sg) {
|
||||
str += "S";
|
||||
} else if (perms.eg) {
|
||||
str += "x";
|
||||
} else {
|
||||
str += "-";
|
||||
}
|
||||
|
||||
str += perms.ro ? "r" : "-";
|
||||
str += perms.wo ? "w" : "-";
|
||||
if (perms.eo && perms.sb) {
|
||||
str += "t";
|
||||
} else if (perms.sb) {
|
||||
str += "T";
|
||||
} else if (perms.eo) {
|
||||
str += "x";
|
||||
} else {
|
||||
str += "-";
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Given a permissions object dictionary, generates an octal permissions string.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} perms
|
||||
* @returns {string}
|
||||
*/
|
||||
_permsToOctal: function(perms) {
|
||||
let d = 0,
|
||||
u = 0,
|
||||
g = 0,
|
||||
o = 0;
|
||||
|
||||
if (perms.su) d += 4;
|
||||
if (perms.sg) d += 2;
|
||||
if (perms.sb) d += 1;
|
||||
|
||||
if (perms.ru) u += 4;
|
||||
if (perms.wu) u += 2;
|
||||
if (perms.eu) u += 1;
|
||||
|
||||
if (perms.rg) g += 4;
|
||||
if (perms.wg) g += 2;
|
||||
if (perms.eg) g += 1;
|
||||
|
||||
if (perms.ro) o += 4;
|
||||
if (perms.wo) o += 2;
|
||||
if (perms.eo) o += 1;
|
||||
|
||||
return d.toString() + u.toString() + g.toString() + o.toString();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Given a permissions object dictionary, returns the file type.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} perms
|
||||
* @returns {string}
|
||||
*/
|
||||
_ftFromPerms: function(perms) {
|
||||
if (perms.d) return "Directory";
|
||||
if (perms.sl) return "Symbolic link";
|
||||
if (perms.np) return "Named pipe";
|
||||
if (perms.s) return "Socket";
|
||||
if (perms.cd) return "Character device";
|
||||
if (perms.bd) return "Block device";
|
||||
if (perms.dr) return "Door";
|
||||
return "Regular file";
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default OS;
|
@ -1,56 +0,0 @@
|
||||
import otp from "otp";
|
||||
import Base64 from "./Base64.js";
|
||||
|
||||
|
||||
/**
|
||||
* One-Time Password operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const OTP = {
|
||||
|
||||
/**
|
||||
* Generate TOTP operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTOTP: function(input, args) {
|
||||
const otpObj = otp({
|
||||
name: args[0],
|
||||
keySize: args[1],
|
||||
codeLength: args[2],
|
||||
secret: Base64.runTo32(input, []),
|
||||
epoch: args[3],
|
||||
timeSlice: args[4]
|
||||
});
|
||||
return `URI: ${otpObj.totpURL}\n\nPassword: ${otpObj.totp()}`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generate HOTP operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHOTP: function(input, args) {
|
||||
const otpObj = otp({
|
||||
name: args[0],
|
||||
keySize: args[1],
|
||||
codeLength: args[2],
|
||||
secret: Base64.runTo32(input, []),
|
||||
});
|
||||
const counter = args[3];
|
||||
return `URI: ${otpObj.hotpURL}\n\nPassword: ${otpObj.hotp(counter)}`;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default OTP;
|
@ -1,160 +0,0 @@
|
||||
/**
|
||||
* PHP operations.
|
||||
*
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Jarmo van Lenthe
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const PHP = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_VALID_JSON: true,
|
||||
|
||||
/**
|
||||
* PHP Deserialize operation.
|
||||
*
|
||||
* This Javascript implementation is based on the Python implementation by
|
||||
* Armin Ronacher (2016), who released it under the 3-Clause BSD license.
|
||||
* See: https://github.com/mitsuhiko/phpserialize/
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDeserialize: function (input, args) {
|
||||
/**
|
||||
* Recursive method for deserializing.
|
||||
* @returns {*}
|
||||
*/
|
||||
function handleInput() {
|
||||
/**
|
||||
* Read `length` characters from the input, shifting them out the input.
|
||||
* @param length
|
||||
* @returns {string}
|
||||
*/
|
||||
function read(length) {
|
||||
let result = "";
|
||||
for (let idx = 0; idx < length; idx++) {
|
||||
let char = inputPart.shift();
|
||||
if (char === undefined) {
|
||||
throw "End of input reached before end of script";
|
||||
}
|
||||
result += char;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from the input until `until` is found.
|
||||
* @param until
|
||||
* @returns {string}
|
||||
*/
|
||||
function readUntil(until) {
|
||||
let result = "";
|
||||
for (;;) {
|
||||
let char = read(1);
|
||||
if (char === until) {
|
||||
break;
|
||||
} else {
|
||||
result += char;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from the input that must be equal to `expect`
|
||||
* @param expect
|
||||
* @returns {string}
|
||||
*/
|
||||
function expect(expect) {
|
||||
let result = read(expect.length);
|
||||
if (result !== expect) {
|
||||
throw "Unexpected input found";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to handle deserialized arrays.
|
||||
* @returns {Array}
|
||||
*/
|
||||
function handleArray() {
|
||||
let items = parseInt(readUntil(":"), 10) * 2;
|
||||
expect("{");
|
||||
let result = [];
|
||||
let isKey = true;
|
||||
let lastItem = null;
|
||||
for (let idx = 0; idx < items; idx++) {
|
||||
let item = handleInput();
|
||||
if (isKey) {
|
||||
lastItem = item;
|
||||
isKey = false;
|
||||
} else {
|
||||
let numberCheck = lastItem.match(/[0-9]+/);
|
||||
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
|
||||
result.push("\"" + lastItem + "\": " + item);
|
||||
} else {
|
||||
result.push(lastItem + ": " + item);
|
||||
}
|
||||
isKey = true;
|
||||
}
|
||||
}
|
||||
expect("}");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
let kind = read(1).toLowerCase();
|
||||
|
||||
switch (kind) {
|
||||
case "n":
|
||||
expect(";");
|
||||
return "";
|
||||
|
||||
case "i":
|
||||
case "d":
|
||||
case "b": {
|
||||
expect(":");
|
||||
let data = readUntil(";");
|
||||
if (kind === "b") {
|
||||
return (parseInt(data, 10) !== 0);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
case "a":
|
||||
expect(":");
|
||||
return "{" + handleArray() + "}";
|
||||
|
||||
case "s": {
|
||||
expect(":");
|
||||
let length = readUntil(":");
|
||||
expect("\"");
|
||||
let value = read(length);
|
||||
expect("\";");
|
||||
if (args[0]) {
|
||||
return "\"" + value.replace(/"/g, "\\\"") + "\"";
|
||||
} else {
|
||||
return "\"" + value + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
throw "Unknown type: " + kind;
|
||||
}
|
||||
}
|
||||
|
||||
let inputPart = input.split("");
|
||||
return handleInput();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default PHP;
|
@ -1,348 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import {fromBase64} from "../lib/Base64";
|
||||
import {toHex, fromHex} from "../lib/Hex";
|
||||
import * as r from "jsrsasign";
|
||||
|
||||
|
||||
/**
|
||||
* Public Key operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const PublicKey = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
X509_INPUT_FORMAT: ["PEM", "DER Hex", "Base64", "Raw"],
|
||||
|
||||
/**
|
||||
* Parse X.509 certificate operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseX509: function (input, args) {
|
||||
if (!input.length) {
|
||||
return "No input";
|
||||
}
|
||||
|
||||
let cert = new r.X509(),
|
||||
inputFormat = args[0];
|
||||
|
||||
switch (inputFormat) {
|
||||
case "DER Hex":
|
||||
input = input.replace(/\s/g, "");
|
||||
cert.readCertHex(input);
|
||||
break;
|
||||
case "PEM":
|
||||
cert.readCertPEM(input);
|
||||
break;
|
||||
case "Base64":
|
||||
cert.readCertHex(toHex(fromBase64(input, null, "byteArray"), ""));
|
||||
break;
|
||||
case "Raw":
|
||||
cert.readCertHex(toHex(Utils.strToByteArray(input), ""));
|
||||
break;
|
||||
default:
|
||||
throw "Undefined input format";
|
||||
}
|
||||
|
||||
let sn = cert.getSerialNumberHex(),
|
||||
issuer = cert.getIssuerString(),
|
||||
subject = cert.getSubjectString(),
|
||||
pk = cert.getPublicKey(),
|
||||
pkFields = [],
|
||||
pkStr = "",
|
||||
sig = cert.getSignatureValueHex(),
|
||||
sigStr = "",
|
||||
extensions = "";
|
||||
|
||||
// Public Key fields
|
||||
pkFields.push({
|
||||
key: "Algorithm",
|
||||
value: pk.type
|
||||
});
|
||||
|
||||
if (pk.type === "EC") { // ECDSA
|
||||
pkFields.push({
|
||||
key: "Curve Name",
|
||||
value: pk.curveName
|
||||
});
|
||||
pkFields.push({
|
||||
key: "Length",
|
||||
value: (((new r.BigInteger(pk.pubKeyHex, 16)).bitLength()-3) /2) + " bits"
|
||||
});
|
||||
pkFields.push({
|
||||
key: "pub",
|
||||
value: PublicKey._formatByteStr(pk.pubKeyHex, 16, 18)
|
||||
});
|
||||
} else if (pk.type === "DSA") { // DSA
|
||||
pkFields.push({
|
||||
key: "pub",
|
||||
value: PublicKey._formatByteStr(pk.y.toString(16), 16, 18)
|
||||
});
|
||||
pkFields.push({
|
||||
key: "P",
|
||||
value: PublicKey._formatByteStr(pk.p.toString(16), 16, 18)
|
||||
});
|
||||
pkFields.push({
|
||||
key: "Q",
|
||||
value: PublicKey._formatByteStr(pk.q.toString(16), 16, 18)
|
||||
});
|
||||
pkFields.push({
|
||||
key: "G",
|
||||
value: PublicKey._formatByteStr(pk.g.toString(16), 16, 18)
|
||||
});
|
||||
} else if (pk.e) { // RSA
|
||||
pkFields.push({
|
||||
key: "Length",
|
||||
value: pk.n.bitLength() + " bits"
|
||||
});
|
||||
pkFields.push({
|
||||
key: "Modulus",
|
||||
value: PublicKey._formatByteStr(pk.n.toString(16), 16, 18)
|
||||
});
|
||||
pkFields.push({
|
||||
key: "Exponent",
|
||||
value: pk.e + " (0x" + pk.e.toString(16) + ")"
|
||||
});
|
||||
} else {
|
||||
pkFields.push({
|
||||
key: "Error",
|
||||
value: "Unknown Public Key type"
|
||||
});
|
||||
}
|
||||
|
||||
// Format Public Key fields
|
||||
for (let i = 0; i < pkFields.length; i++) {
|
||||
pkStr += " " + pkFields[i].key + ":" +
|
||||
(pkFields[i].value + "\n").padStart(
|
||||
18 - (pkFields[i].key.length + 3) + pkFields[i].value.length + 1,
|
||||
" "
|
||||
);
|
||||
}
|
||||
|
||||
// Signature fields
|
||||
let breakoutSig = false;
|
||||
try {
|
||||
breakoutSig = r.ASN1HEX.dump(sig).indexOf("SEQUENCE") === 0;
|
||||
} catch (err) {
|
||||
// Error processing signature, output without further breakout
|
||||
}
|
||||
|
||||
if (breakoutSig) { // DSA or ECDSA
|
||||
sigStr = " r: " + PublicKey._formatByteStr(r.ASN1HEX.getV(sig, 4), 16, 18) + "\n" +
|
||||
" s: " + PublicKey._formatByteStr(r.ASN1HEX.getV(sig, 48), 16, 18);
|
||||
} else { // RSA or unknown
|
||||
sigStr = " Signature: " + PublicKey._formatByteStr(sig, 16, 18);
|
||||
}
|
||||
|
||||
// Extensions
|
||||
try {
|
||||
extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0];
|
||||
} catch (err) {}
|
||||
|
||||
let issuerStr = PublicKey._formatDnStr(issuer, 2),
|
||||
nbDate = PublicKey._formatDate(cert.getNotBefore()),
|
||||
naDate = PublicKey._formatDate(cert.getNotAfter()),
|
||||
subjectStr = PublicKey._formatDnStr(subject, 2);
|
||||
|
||||
return `Version: ${cert.version} (0x${Utils.hex(cert.version - 1)})
|
||||
Serial number: ${new r.BigInteger(sn, 16).toString()} (0x${sn})
|
||||
Algorithm ID: ${cert.getSignatureAlgorithmField()}
|
||||
Validity
|
||||
Not Before: ${nbDate} (dd-mm-yy hh:mm:ss) (${cert.getNotBefore()})
|
||||
Not After: ${naDate} (dd-mm-yy hh:mm:ss) (${cert.getNotAfter()})
|
||||
Issuer
|
||||
${issuerStr}
|
||||
Subject
|
||||
${subjectStr}
|
||||
Public Key
|
||||
${pkStr.slice(0, -1)}
|
||||
Certificate Signature
|
||||
Algorithm: ${cert.getSignatureAlgorithmName()}
|
||||
${sigStr}
|
||||
|
||||
Extensions
|
||||
${extensions}`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* PEM to Hex operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runPemToHex: function(input, args) {
|
||||
if (input.indexOf("-----BEGIN") < 0) {
|
||||
// Add header so that the KEYUTIL function works
|
||||
input = "-----BEGIN CERTIFICATE-----" + input;
|
||||
}
|
||||
if (input.indexOf("-----END") < 0) {
|
||||
// Add footer so that the KEYUTIL function works
|
||||
input = input + "-----END CERTIFICATE-----";
|
||||
}
|
||||
let cert = new r.X509();
|
||||
cert.readCertPEM(input);
|
||||
return cert.hex;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PEM_HEADER_STRING: "CERTIFICATE",
|
||||
|
||||
/**
|
||||
* Hex to PEM operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHexToPem: function(input, args) {
|
||||
return r.KJUR.asn1.ASN1Util.getPEMStringFromHex(input.replace(/\s/g, ""), args[0]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Hex to Object Identifier operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHexToObjectIdentifier: function(input, args) {
|
||||
return r.KJUR.asn1.ASN1Util.oidHexToInt(input.replace(/\s/g, ""));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Object Identifier to Hex operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runObjectIdentifierToHex: function(input, args) {
|
||||
return r.KJUR.asn1.ASN1Util.oidIntToHex(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ASN1_TRUNCATE_LENGTH: 32,
|
||||
|
||||
/**
|
||||
* Parse ASN.1 hex string operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseAsn1HexString: function(input, args) {
|
||||
let truncateLen = args[1],
|
||||
index = args[0];
|
||||
return r.ASN1HEX.dump(input.replace(/\s/g, ""), {
|
||||
"ommitLongOctet": truncateLen
|
||||
}, index);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Formats Distinguished Name (DN) strings.
|
||||
*
|
||||
* @private
|
||||
* @param {string} dnStr
|
||||
* @param {number} indent
|
||||
* @returns {string}
|
||||
*/
|
||||
_formatDnStr: function(dnStr, indent) {
|
||||
let output = "",
|
||||
fields = dnStr.substr(1).replace(/([^\\])\//g, "$1$1/").split(/[^\\]\//),
|
||||
maxKeyLen = 0,
|
||||
key,
|
||||
value,
|
||||
i,
|
||||
str;
|
||||
|
||||
for (i = 0; i < fields.length; i++) {
|
||||
if (!fields[i].length) continue;
|
||||
|
||||
key = fields[i].split("=")[0];
|
||||
|
||||
maxKeyLen = key.length > maxKeyLen ? key.length : maxKeyLen;
|
||||
}
|
||||
|
||||
for (i = 0; i < fields.length; i++) {
|
||||
if (!fields[i].length) continue;
|
||||
|
||||
key = fields[i].split("=")[0];
|
||||
value = fields[i].split("=")[1];
|
||||
str = key.padEnd(maxKeyLen, " ") + " = " + value + "\n";
|
||||
|
||||
output += str.padStart(indent + str.length, " ");
|
||||
}
|
||||
|
||||
return output.slice(0, -1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Formats byte strings by adding line breaks and delimiters.
|
||||
*
|
||||
* @private
|
||||
* @param {string} byteStr
|
||||
* @param {number} length - Line width
|
||||
* @param {number} indent
|
||||
* @returns {string}
|
||||
*/
|
||||
_formatByteStr: function(byteStr, length, indent) {
|
||||
byteStr = toHex(fromHex(byteStr), ":");
|
||||
length = length * 3;
|
||||
let output = "";
|
||||
|
||||
for (let i = 0; i < byteStr.length; i += length) {
|
||||
const str = byteStr.slice(i, i + length) + "\n";
|
||||
if (i === 0) {
|
||||
output += str;
|
||||
} else {
|
||||
output += str.padStart(indent + str.length, " ");
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Formats dates.
|
||||
*
|
||||
* @private
|
||||
* @param {string} dateStr
|
||||
* @returns {string}
|
||||
*/
|
||||
_formatDate: function(dateStr) {
|
||||
return dateStr[4] + dateStr[5] + "/" +
|
||||
dateStr[2] + dateStr[3] + "/" +
|
||||
dateStr[0] + dateStr[1] + " " +
|
||||
dateStr[6] + dateStr[7] + ":" +
|
||||
dateStr[8] + dateStr[9] + ":" +
|
||||
dateStr[10] + dateStr[11];
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default PublicKey;
|
@ -1,58 +0,0 @@
|
||||
import punycode from "punycode";
|
||||
|
||||
|
||||
/**
|
||||
* Punycode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Punycode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IDN: false,
|
||||
|
||||
/**
|
||||
* To Punycode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToAscii: function(input, args) {
|
||||
const idn = args[0];
|
||||
|
||||
if (idn) {
|
||||
return punycode.toASCII(input);
|
||||
} else {
|
||||
return punycode.encode(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Punycode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToUnicode: function(input, args) {
|
||||
const idn = args[0];
|
||||
|
||||
if (idn) {
|
||||
return punycode.toUnicode(input);
|
||||
} else {
|
||||
return punycode.decode(input);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Punycode;
|
@ -1,272 +0,0 @@
|
||||
/** @license
|
||||
========================================================================
|
||||
mimelib: http://github.com/andris9/mimelib
|
||||
Copyright (c) 2011-2012 Andris Reinman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Quoted Printable operations.
|
||||
* Some parts taken from mimelib (http://github.com/andris9/mimelib)
|
||||
*
|
||||
* @author Andris Reinman
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const QuotedPrintable = {
|
||||
|
||||
/**
|
||||
* To Quoted Printable operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function (input, args) {
|
||||
let mimeEncodedStr = QuotedPrintable.mimeEncode(input);
|
||||
|
||||
// fix line breaks
|
||||
mimeEncodedStr = mimeEncodedStr.replace(/\r?\n|\r/g, function() {
|
||||
return "\r\n";
|
||||
}).replace(/[\t ]+$/gm, function(spaces) {
|
||||
return spaces.replace(/ /g, "=20").replace(/\t/g, "=09");
|
||||
});
|
||||
|
||||
return QuotedPrintable._addSoftLinebreaks(mimeEncodedStr, "qp");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Quoted Printable operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function (input, args) {
|
||||
const str = input.replace(/=(?:\r?\n|$)/g, "");
|
||||
return QuotedPrintable.mimeDecode(str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Decodes mime-encoded data.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
mimeDecode: function(str) {
|
||||
let encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length,
|
||||
bufferLength = str.length - encodedBytesCount * 2,
|
||||
chr, hex,
|
||||
buffer = new Array(bufferLength),
|
||||
bufferPos = 0;
|
||||
|
||||
for (let i = 0, len = str.length; i < len; i++) {
|
||||
chr = str.charAt(i);
|
||||
if (chr === "=" && (hex = str.substr(i + 1, 2)) && /[\da-fA-F]{2}/.test(hex)) {
|
||||
buffer[bufferPos++] = parseInt(hex, 16);
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
buffer[bufferPos++] = chr.charCodeAt(0);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Encodes mime data.
|
||||
*
|
||||
* @param {byteArray} buffer
|
||||
* @returns {string}
|
||||
*/
|
||||
mimeEncode: function(buffer) {
|
||||
let ranges = [
|
||||
[0x09],
|
||||
[0x0A],
|
||||
[0x0D],
|
||||
[0x20],
|
||||
[0x21],
|
||||
[0x23, 0x3C],
|
||||
[0x3E],
|
||||
[0x40, 0x5E],
|
||||
[0x60, 0x7E]
|
||||
],
|
||||
result = "";
|
||||
|
||||
for (let i = 0, len = buffer.length; i < len; i++) {
|
||||
if (this._checkRanges(buffer[i], ranges)) {
|
||||
result += String.fromCharCode(buffer[i]);
|
||||
continue;
|
||||
}
|
||||
result += "=" + (buffer[i] < 0x10 ? "0" : "") + buffer[i].toString(16).toUpperCase();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a given number falls within a given set of ranges.
|
||||
*
|
||||
* @private
|
||||
* @param {number} nr
|
||||
* @param {byteArray[]} ranges
|
||||
* @returns {bolean}
|
||||
*/
|
||||
_checkRanges: function(nr, ranges) {
|
||||
for (let i = ranges.length - 1; i >= 0; i--) {
|
||||
if (!ranges[i].length)
|
||||
continue;
|
||||
if (ranges[i].length === 1 && nr === ranges[i][0])
|
||||
return true;
|
||||
if (ranges[i].length === 2 && nr >= ranges[i][0] && nr <= ranges[i][1])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds soft line breaks to a string.
|
||||
* Lines can't be longer that 76 + <CR><LF> = 78 bytes
|
||||
* http://tools.ietf.org/html/rfc2045#section-6.7
|
||||
*
|
||||
* @private
|
||||
* @param {string} str
|
||||
* @param {string} encoding
|
||||
* @returns {string}
|
||||
*/
|
||||
_addSoftLinebreaks: function(str, encoding) {
|
||||
const lineLengthMax = 76;
|
||||
|
||||
encoding = (encoding || "base64").toString().toLowerCase().trim();
|
||||
|
||||
if (encoding === "qp") {
|
||||
return this._addQPSoftLinebreaks(str, lineLengthMax);
|
||||
} else {
|
||||
return this._addBase64SoftLinebreaks(str, lineLengthMax);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds soft line breaks to a base64 string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} base64EncodedStr
|
||||
* @param {number} lineLengthMax
|
||||
* @returns {string}
|
||||
*/
|
||||
_addBase64SoftLinebreaks: function(base64EncodedStr, lineLengthMax) {
|
||||
base64EncodedStr = (base64EncodedStr || "").toString().trim();
|
||||
return base64EncodedStr.replace(new RegExp(".{" + lineLengthMax + "}", "g"), "$&\r\n").trim();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds soft line breaks to a quoted printable string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} mimeEncodedStr
|
||||
* @param {number} lineLengthMax
|
||||
* @returns {string}
|
||||
*/
|
||||
_addQPSoftLinebreaks: function(mimeEncodedStr, lineLengthMax) {
|
||||
let pos = 0,
|
||||
len = mimeEncodedStr.length,
|
||||
match, code, line,
|
||||
lineMargin = Math.floor(lineLengthMax / 3),
|
||||
result = "";
|
||||
|
||||
// insert soft linebreaks where needed
|
||||
while (pos < len) {
|
||||
line = mimeEncodedStr.substr(pos, lineLengthMax);
|
||||
if ((match = line.match(/\r\n/))) {
|
||||
line = line.substr(0, match.index + match[0].length);
|
||||
result += line;
|
||||
pos += line.length;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.substr(-1) === "\n") {
|
||||
// nothing to change here
|
||||
result += line;
|
||||
pos += line.length;
|
||||
continue;
|
||||
} else if ((match = line.substr(-lineMargin).match(/\n.*?$/))) {
|
||||
// truncate to nearest line break
|
||||
line = line.substr(0, line.length - (match[0].length - 1));
|
||||
result += line;
|
||||
pos += line.length;
|
||||
continue;
|
||||
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t.,!?][^ \t.,!?]*$/))) {
|
||||
// truncate to nearest space
|
||||
line = line.substr(0, line.length - (match[0].length - 1));
|
||||
} else if (line.substr(-1) === "\r") {
|
||||
line = line.substr(0, line.length - 1);
|
||||
} else {
|
||||
if (line.match(/=[\da-f]{0,2}$/i)) {
|
||||
|
||||
// push incomplete encoding sequences to the next line
|
||||
if ((match = line.match(/=[\da-f]{0,1}$/i))) {
|
||||
line = line.substr(0, line.length - match[0].length);
|
||||
}
|
||||
|
||||
// ensure that utf-8 sequences are not split
|
||||
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/=[\da-f]{2}$/ig))) {
|
||||
code = parseInt(match[0].substr(1, 2), 16);
|
||||
if (code < 128) {
|
||||
break;
|
||||
}
|
||||
|
||||
line = line.substr(0, line.length - 3);
|
||||
|
||||
if (code >= 0xC0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (pos + line.length < len && line.substr(-1) !== "\n") {
|
||||
if (line.length === 76 && line.match(/=[\da-f]{2}$/i)) {
|
||||
line = line.substr(0, line.length - 3);
|
||||
} else if (line.length === 76) {
|
||||
line = line.substr(0, line.length - 1);
|
||||
}
|
||||
pos += line.length;
|
||||
line += "=\r\n";
|
||||
} else {
|
||||
pos += line.length;
|
||||
}
|
||||
|
||||
result += line;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default QuotedPrintable;
|
@ -1,278 +0,0 @@
|
||||
import XRegExp from "xregexp";
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Regex operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Regex = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_PRE_POPULATE: [
|
||||
{
|
||||
name: "User defined",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "IPv4 address",
|
||||
value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?"
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
|
||||
},
|
||||
{
|
||||
name: "Email address",
|
||||
value: "\\b(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})\\b"
|
||||
},
|
||||
{
|
||||
name: "URL",
|
||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||
},
|
||||
{
|
||||
name: "Domain",
|
||||
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
|
||||
},
|
||||
{
|
||||
name: "Windows file path",
|
||||
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)~]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
|
||||
},
|
||||
{
|
||||
name: "UNIX file path",
|
||||
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
|
||||
},
|
||||
{
|
||||
name: "MAC address",
|
||||
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
|
||||
},
|
||||
{
|
||||
name: "Date (yyyy-mm-dd)",
|
||||
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
|
||||
},
|
||||
{
|
||||
name: "Date (dd/mm/yyyy)",
|
||||
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Date (mm/dd/yyyy)",
|
||||
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Strings",
|
||||
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISPLAY_TOTAL: false,
|
||||
|
||||
/**
|
||||
* Regular expression operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runRegex: function(input, args) {
|
||||
const userRegex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
s = args[4],
|
||||
u = args[5],
|
||||
a = args[6],
|
||||
displayTotal = args[7],
|
||||
outputFormat = args[8];
|
||||
let modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
if (s) modifiers += "s";
|
||||
if (u) modifiers += "u";
|
||||
if (a) modifiers += "A";
|
||||
|
||||
if (userRegex && userRegex !== "^" && userRegex !== "$") {
|
||||
try {
|
||||
const regex = new XRegExp(userRegex, modifiers);
|
||||
|
||||
switch (outputFormat) {
|
||||
case "Highlight matches":
|
||||
return Regex._regexHighlight(input, regex, displayTotal);
|
||||
case "List matches":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
}
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
} else {
|
||||
return Utils.escapeHtml(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_GLOBAL: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_CASE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_MULTILINE: true,
|
||||
|
||||
/**
|
||||
* Find / Replace operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFindReplace: function(input, args) {
|
||||
let find = args[0].string,
|
||||
type = args[0].option,
|
||||
replace = args[1],
|
||||
g = args[2],
|
||||
i = args[3],
|
||||
m = args[4],
|
||||
modifiers = "";
|
||||
|
||||
if (g) modifiers += "g";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (type === "Regex") {
|
||||
find = new RegExp(find, modifiers);
|
||||
return input.replace(find, replace);
|
||||
}
|
||||
|
||||
if (type.indexOf("Extended") === 0) {
|
||||
find = Utils.parseEscapedChars(find);
|
||||
}
|
||||
|
||||
find = new RegExp(Utils.escapeRegex(find), modifiers);
|
||||
|
||||
return input.replace(find, replace);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds HTML highlights to matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexHighlight: function(input, regex, displayTotal) {
|
||||
let output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (m.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
}
|
||||
|
||||
// Add up to match
|
||||
output += Utils.escapeHtml(input.slice(i, m.index));
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
|
||||
// Switch highlight
|
||||
hl = hl === 1 ? 2 : 1;
|
||||
|
||||
i = regex.lastIndex;
|
||||
total++;
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += Utils.escapeHtml(input.slice(i, input.length));
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string listing the matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @param {boolean} matches - Display full match
|
||||
* @param {boolean} captureGroups - Display each of the capture groups separately
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexList: function(input, regex, displayTotal, matches, captureGroups) {
|
||||
let output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = regex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (match.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
}
|
||||
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (captureGroups) {
|
||||
for (let i = 1; i < match.length; i++) {
|
||||
if (matches) {
|
||||
output += " Group " + i + ": ";
|
||||
}
|
||||
output += match[i] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output.slice(0, -1);
|
||||
},
|
||||
};
|
||||
|
||||
export default Regex;
|
@ -1,257 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Sequence utility operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const SeqUtils = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SORT_REVERSE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"],
|
||||
|
||||
/**
|
||||
* Sort operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSort: function (input, args) {
|
||||
let delim = Utils.charRep(args[0]),
|
||||
sortReverse = args[1],
|
||||
order = args[2],
|
||||
sorted = input.split(delim);
|
||||
|
||||
if (order === "Alphabetical (case sensitive)") {
|
||||
sorted = sorted.sort();
|
||||
} else if (order === "Alphabetical (case insensitive)") {
|
||||
sorted = sorted.sort(SeqUtils._caseInsensitiveSort);
|
||||
} else if (order === "IP address") {
|
||||
sorted = sorted.sort(SeqUtils._ipSort);
|
||||
} else if (order === "Numeric") {
|
||||
sorted = sorted.sort(SeqUtils._numericSort);
|
||||
}
|
||||
|
||||
if (sortReverse) sorted.reverse();
|
||||
return sorted.join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Unique operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runUnique: function (input, args) {
|
||||
const delim = Utils.charRep(args[0]);
|
||||
return input.split(delim).unique().join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
|
||||
|
||||
/**
|
||||
* Count occurrences operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runCount: function(input, args) {
|
||||
let search = args[0].string,
|
||||
type = args[0].option;
|
||||
|
||||
if (type === "Regex" && search) {
|
||||
try {
|
||||
let regex = new RegExp(search, "gi"),
|
||||
matches = input.match(regex);
|
||||
return matches.length;
|
||||
} catch (err) {
|
||||
return 0;
|
||||
}
|
||||
} else if (search) {
|
||||
if (type.indexOf("Extended") === 0) {
|
||||
search = Utils.parseEscapedChars(search);
|
||||
}
|
||||
return input.count(search);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REVERSE_BY: ["Character", "Line"],
|
||||
|
||||
/**
|
||||
* Reverse operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runReverse: function (input, args) {
|
||||
let i;
|
||||
if (args[0] === "Line") {
|
||||
let lines = [],
|
||||
line = [],
|
||||
result = [];
|
||||
for (i = 0; i < input.length; i++) {
|
||||
if (input[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(input[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
lines.reverse();
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
result = result.concat(lines[i]);
|
||||
result.push(0x0a);
|
||||
}
|
||||
return result.slice(0, input.length);
|
||||
} else {
|
||||
return input.reverse();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Add line numbers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAddLineNumbers: function(input, args) {
|
||||
let lines = input.split("\n"),
|
||||
output = "",
|
||||
width = lines.length.toString().length;
|
||||
|
||||
for (let n = 0; n < lines.length; n++) {
|
||||
output += (n+1).toString().padStart(width, " ") + " " + lines[n] + "\n";
|
||||
}
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove line numbers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRemoveLineNumbers: function(input, args) {
|
||||
return input.replace(/^[ \t]{0,5}\d+[\s:|\-,.)\]]/gm, "");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Expand alphabet range operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runExpandAlphRange: function(input, args) {
|
||||
return Utils.expandAlphRange(input).join(args[0]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of strings ignoring case.
|
||||
*
|
||||
* @private
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
_caseInsensitiveSort: function(a, b) {
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of IPv4 addresses.
|
||||
*
|
||||
* @private
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
_ipSort: function(a, b) {
|
||||
let a_ = a.split("."),
|
||||
b_ = b.split(".");
|
||||
|
||||
a_ = a_[0] * 0x1000000 + a_[1] * 0x10000 + a_[2] * 0x100 + a_[3] * 1;
|
||||
b_ = b_[0] * 0x1000000 + b_[1] * 0x10000 + b_[2] * 0x100 + b_[3] * 1;
|
||||
|
||||
if (isNaN(a_) && !isNaN(b_)) return 1;
|
||||
if (!isNaN(a_) && isNaN(b_)) return -1;
|
||||
if (isNaN(a_) && isNaN(b_)) return a.localeCompare(b);
|
||||
|
||||
return a_ - b_;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of numeric values.
|
||||
*
|
||||
* @author Chris van Marle
|
||||
* @private
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
_numericSort: function _numericSort(a, b) {
|
||||
let a_ = a.split(/([^\d]+)/),
|
||||
b_ = b.split(/([^\d]+)/);
|
||||
|
||||
for (let i = 0; i < a_.length && i < b.length; ++i) {
|
||||
if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
|
||||
if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
|
||||
if (isNaN(a_[i]) && isNaN(b_[i])) {
|
||||
let ret = a_[i].localeCompare(b_[i]); // Compare strings
|
||||
if (ret !== 0) return ret;
|
||||
}
|
||||
if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
|
||||
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return a.localeCompare(b);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default SeqUtils;
|
@ -1,96 +0,0 @@
|
||||
import disassemble from "../vendor/DisassembleX86-64.js";
|
||||
|
||||
|
||||
/**
|
||||
* Shellcode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Shellcode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MODE: ["64", "32", "16"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
COMPATIBILITY: [
|
||||
"Full x86 architecture",
|
||||
"Knights Corner",
|
||||
"Larrabee",
|
||||
"Cyrix",
|
||||
"Geode",
|
||||
"Centaur",
|
||||
"X86/486"
|
||||
],
|
||||
|
||||
/**
|
||||
* Disassemble x86 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDisassemble: function(input, args) {
|
||||
const mode = args[0],
|
||||
compatibility = args[1],
|
||||
codeSegment = args[2],
|
||||
offset = args[3],
|
||||
showInstructionHex = args[4],
|
||||
showInstructionPos = args[5];
|
||||
|
||||
switch (mode) {
|
||||
case "64":
|
||||
disassemble.setBitMode(2);
|
||||
break;
|
||||
case "32":
|
||||
disassemble.setBitMode(1);
|
||||
break;
|
||||
case "16":
|
||||
disassemble.setBitMode(0);
|
||||
break;
|
||||
default:
|
||||
throw "Invalid mode value";
|
||||
}
|
||||
|
||||
switch (compatibility) {
|
||||
case "Full x86 architecture":
|
||||
disassemble.CompatibilityMode(0);
|
||||
break;
|
||||
case "Knights Corner":
|
||||
disassemble.CompatibilityMode(1);
|
||||
break;
|
||||
case "Larrabee":
|
||||
disassemble.CompatibilityMode(2);
|
||||
break;
|
||||
case "Cyrix":
|
||||
disassemble.CompatibilityMode(3);
|
||||
break;
|
||||
case "Geode":
|
||||
disassemble.CompatibilityMode(4);
|
||||
break;
|
||||
case "Centaur":
|
||||
disassemble.CompatibilityMode(5);
|
||||
break;
|
||||
case "X86/486":
|
||||
disassemble.CompatibilityMode(6);
|
||||
break;
|
||||
}
|
||||
|
||||
disassemble.SetBasePosition(codeSegment + ":" + offset);
|
||||
disassemble.setShowInstructionHex(showInstructionHex);
|
||||
disassemble.setShowInstructionPos(showInstructionPos);
|
||||
disassemble.LoadBinCode(input.replace(/\s/g, ""));
|
||||
return disassemble.LDisassemble();
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Shellcode;
|
@ -1,413 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
import {fromHex} from "../lib/Hex";
|
||||
import jsesc from "jsesc";
|
||||
|
||||
|
||||
/**
|
||||
* String utility operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const StrUtils = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CASE_SCOPE: ["All", "Word", "Sentence", "Paragraph"],
|
||||
|
||||
/**
|
||||
* To Upper case operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runUpper: function (input, args) {
|
||||
const scope = args[0];
|
||||
|
||||
switch (scope) {
|
||||
case "Word":
|
||||
return input.replace(/(\b\w)/gi, function(m) {
|
||||
return m.toUpperCase();
|
||||
});
|
||||
case "Sentence":
|
||||
return input.replace(/(?:\.|^)\s*(\b\w)/gi, function(m) {
|
||||
return m.toUpperCase();
|
||||
});
|
||||
case "Paragraph":
|
||||
return input.replace(/(?:\n|^)\s*(\b\w)/gi, function(m) {
|
||||
return m.toUpperCase();
|
||||
});
|
||||
case "All":
|
||||
/* falls through */
|
||||
default:
|
||||
return input.toUpperCase();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Upper case operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runLower: function (input, args) {
|
||||
return input.toLowerCase();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SPLIT_DELIM_OPTIONS: [
|
||||
{name: "Comma", value: ","},
|
||||
{name: "Space", value: " "},
|
||||
{name: "Line feed", value: "\\n"},
|
||||
{name: "CRLF", value: "\\r\\n"},
|
||||
{name: "Semi-colon", value: ";"},
|
||||
{name: "Colon", value: ":"},
|
||||
{name: "Nothing (separate chars)", value: ""}
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
JOIN_DELIM_OPTIONS: [
|
||||
{name: "Line feed", value: "\\n"},
|
||||
{name: "CRLF", value: "\\r\\n"},
|
||||
{name: "Space", value: " "},
|
||||
{name: "Comma", value: ","},
|
||||
{name: "Semi-colon", value: ";"},
|
||||
{name: "Colon", value: ":"},
|
||||
{name: "Nothing (join chars)", value: ""}
|
||||
],
|
||||
|
||||
/**
|
||||
* Split operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSplit: function(input, args) {
|
||||
let splitDelim = args[0],
|
||||
joinDelim = args[1],
|
||||
sections = input.split(splitDelim);
|
||||
|
||||
return sections.join(joinDelim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
|
||||
/**
|
||||
* Filter operation.
|
||||
*
|
||||
* @author Mikescher (https://github.com/Mikescher | https://mikescher.com)
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFilter: function(input, args) {
|
||||
let delim = Utils.charRep(args[0]),
|
||||
regex,
|
||||
reverse = args[2];
|
||||
|
||||
try {
|
||||
regex = new RegExp(args[1]);
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
|
||||
const regexFilter = function(value) {
|
||||
return reverse ^ regex.test(value);
|
||||
};
|
||||
|
||||
return input.split(delim).filter(regexFilter).join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OFF_CHK_SAMPLE_DELIMITER: "\\n\\n",
|
||||
|
||||
/**
|
||||
* Offset checker operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runOffsetChecker: function(input, args) {
|
||||
let sampleDelim = args[0],
|
||||
samples = input.split(sampleDelim),
|
||||
outputs = new Array(samples.length),
|
||||
i = 0,
|
||||
s = 0,
|
||||
match = false,
|
||||
inMatch = false,
|
||||
chr;
|
||||
|
||||
if (!samples || samples.length < 2) {
|
||||
return "Not enough samples, perhaps you need to modify the sample delimiter or add more data?";
|
||||
}
|
||||
|
||||
// Initialise output strings
|
||||
outputs.fill("", 0, samples.length);
|
||||
|
||||
// Loop through each character in the first sample
|
||||
for (i = 0; i < samples[0].length; i++) {
|
||||
chr = samples[0][i];
|
||||
match = false;
|
||||
|
||||
// Loop through each sample to see if the chars are the same
|
||||
for (s = 1; s < samples.length; s++) {
|
||||
if (samples[s][i] !== chr) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
match = true;
|
||||
}
|
||||
|
||||
// Write output for each sample
|
||||
for (s = 0; s < samples.length; s++) {
|
||||
if (samples[s].length <= i) {
|
||||
if (inMatch) outputs[s] += "</span>";
|
||||
if (s === samples.length - 1) inMatch = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (match && !inMatch) {
|
||||
outputs[s] += "<span class='hl5'>" + Utils.escapeHtml(samples[s][i]);
|
||||
if (samples[s].length === i + 1) outputs[s] += "</span>";
|
||||
if (s === samples.length - 1) inMatch = true;
|
||||
} else if (!match && inMatch) {
|
||||
outputs[s] += "</span>" + Utils.escapeHtml(samples[s][i]);
|
||||
if (s === samples.length - 1) inMatch = false;
|
||||
} else {
|
||||
outputs[s] += Utils.escapeHtml(samples[s][i]);
|
||||
if (inMatch && samples[s].length === i + 1) {
|
||||
outputs[s] += "</span>";
|
||||
if (samples[s].length - 1 !== i) inMatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (samples[0].length - 1 === i) {
|
||||
if (inMatch) outputs[s] += "</span>";
|
||||
outputs[s] += Utils.escapeHtml(samples[s].substring(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputs.join(sampleDelim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
QUOTE_TYPES: ["Single", "Double", "Backtick"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ESCAPE_LEVEL: ["Special chars", "Everything", "Minimal"],
|
||||
|
||||
/**
|
||||
* Escape string operation.
|
||||
*
|
||||
* @author Vel0x [dalemy@microsoft.com]
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* StrUtils.runEscape("Don't do that", [])
|
||||
* > "Don\'t do that"
|
||||
* StrUtils.runEscape(`Hello
|
||||
* World`, [])
|
||||
* > "Hello\nWorld"
|
||||
*/
|
||||
runEscape: function(input, args) {
|
||||
const level = args[0],
|
||||
quotes = args[1],
|
||||
jsonCompat = args[2],
|
||||
es6Compat = args[3],
|
||||
lowercaseHex = !args[4];
|
||||
|
||||
return jsesc(input, {
|
||||
quotes: quotes.toLowerCase(),
|
||||
es6: es6Compat,
|
||||
escapeEverything: level === "Everything",
|
||||
minimal: level === "Minimal",
|
||||
json: jsonCompat,
|
||||
lowercaseHex: lowercaseHex,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Unescape string operation.
|
||||
*
|
||||
* @author Vel0x [dalemy@microsoft.com]
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* StrUtils.runUnescape("Don\'t do that", [])
|
||||
* > "Don't do that"
|
||||
* StrUtils.runUnescape("Hello\nWorld", [])
|
||||
* > `Hello
|
||||
* World`
|
||||
*/
|
||||
runUnescape: function(input, args) {
|
||||
return Utils.parseEscapedChars(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Head lines operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHead: function(input, args) {
|
||||
let delimiter = args[0],
|
||||
number = args[1];
|
||||
|
||||
delimiter = Utils.charRep(delimiter);
|
||||
const splitInput = input.split(delimiter);
|
||||
|
||||
return splitInput
|
||||
.filter((line, lineIndex) => {
|
||||
lineIndex += 1;
|
||||
|
||||
if (number < 0) {
|
||||
return lineIndex <= splitInput.length + number;
|
||||
} else {
|
||||
return lineIndex <= number;
|
||||
}
|
||||
})
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Tail lines operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTail: function(input, args) {
|
||||
let delimiter = args[0],
|
||||
number = args[1];
|
||||
|
||||
delimiter = Utils.charRep(delimiter);
|
||||
const splitInput = input.split(delimiter);
|
||||
|
||||
return splitInput
|
||||
.filter((line, lineIndex) => {
|
||||
lineIndex += 1;
|
||||
|
||||
if (number < 0) {
|
||||
return lineIndex > -number;
|
||||
} else {
|
||||
return lineIndex > splitInput.length - number;
|
||||
}
|
||||
})
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HAMMING_DELIM: "\\n\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HAMMING_INPUT_TYPE: ["Raw string", "Hex"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HAMMING_UNIT: ["Byte", "Bit"],
|
||||
|
||||
/**
|
||||
* Hamming Distance operation.
|
||||
*
|
||||
* @author GCHQ Contributor [2]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHamming: function(input, args) {
|
||||
const delim = args[0],
|
||||
byByte = args[1] === "Byte",
|
||||
inputType = args[2],
|
||||
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.";
|
||||
}
|
||||
|
||||
if (samples[0].length !== samples[1].length) {
|
||||
return "Error: Both inputs must be of the same length.";
|
||||
}
|
||||
|
||||
if (inputType === "Hex") {
|
||||
samples[0] = fromHex(samples[0]);
|
||||
samples[1] = fromHex(samples[1]);
|
||||
} else {
|
||||
samples[0] = Utils.strToByteArray(samples[0]);
|
||||
samples[1] = Utils.strToByteArray(samples[1]);
|
||||
}
|
||||
|
||||
let dist = 0;
|
||||
|
||||
for (let i = 0; i < samples[0].length; i++) {
|
||||
const lhs = samples[0][i],
|
||||
rhs = samples[1][i];
|
||||
|
||||
if (byByte && lhs !== rhs) {
|
||||
dist++;
|
||||
} else if (!byByte) {
|
||||
let xord = lhs ^ rhs;
|
||||
|
||||
while (xord) {
|
||||
dist++;
|
||||
xord &= xord - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist.toString();
|
||||
},
|
||||
};
|
||||
|
||||
export default StrUtils;
|
@ -1,250 +0,0 @@
|
||||
/**
|
||||
* Tidy operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Tidy = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_SPACES: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_CARIAGE_RETURNS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_LINE_FEEDS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_TABS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_FORM_FEEDS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_FULL_STOPS: false,
|
||||
|
||||
/**
|
||||
* Remove whitespace operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRemoveWhitespace: function (input, args) {
|
||||
let removeSpaces = args[0],
|
||||
removeCariageReturns = args[1],
|
||||
removeLineFeeds = args[2],
|
||||
removeTabs = args[3],
|
||||
removeFormFeeds = args[4],
|
||||
removeFullStops = args[5],
|
||||
data = input;
|
||||
|
||||
if (removeSpaces) data = data.replace(/ /g, "");
|
||||
if (removeCariageReturns) data = data.replace(/\r/g, "");
|
||||
if (removeLineFeeds) data = data.replace(/\n/g, "");
|
||||
if (removeTabs) data = data.replace(/\t/g, "");
|
||||
if (removeFormFeeds) data = data.replace(/\f/g, "");
|
||||
if (removeFullStops) data = data.replace(/\./g, "");
|
||||
return data;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove null bytes operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRemoveNulls: function (input, args) {
|
||||
const output = [];
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
if (input[i] !== 0) output.push(input[i]);
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
APPLY_TO_EACH_LINE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DROP_START: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DROP_LENGTH: 5,
|
||||
|
||||
/**
|
||||
* Drop bytes operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runDropBytes: function(input, args) {
|
||||
const start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
|
||||
if (!applyToEachLine) {
|
||||
const left = input.slice(0, start),
|
||||
right = input.slice(start + length, input.byteLength);
|
||||
let result = new Uint8Array(left.byteLength + right.byteLength);
|
||||
result.set(new Uint8Array(left), 0);
|
||||
result.set(new Uint8Array(right), left.byteLength);
|
||||
return result.buffer;
|
||||
}
|
||||
|
||||
// Split input into lines
|
||||
const data = new Uint8Array(input);
|
||||
let lines = [],
|
||||
line = [],
|
||||
i;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
if (data[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(data[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
let output = [];
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length)));
|
||||
output.push(0x0a);
|
||||
}
|
||||
return new Uint8Array(output.slice(0, output.length-1)).buffer;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TAKE_START: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TAKE_LENGTH: 5,
|
||||
|
||||
/**
|
||||
* Take bytes operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runTakeBytes: function(input, args) {
|
||||
const start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
|
||||
if (!applyToEachLine)
|
||||
return input.slice(start, start+length);
|
||||
|
||||
// Split input into lines
|
||||
const data = new Uint8Array(input);
|
||||
let lines = [],
|
||||
line = [],
|
||||
i;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
if (data[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(data[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
let output = [];
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(start, start+length));
|
||||
output.push(0x0a);
|
||||
}
|
||||
return new Uint8Array(output.slice(0, output.length-1)).buffer;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_POSITION: ["Start", "End"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_LENGTH: 5,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_CHAR: " ",
|
||||
|
||||
/**
|
||||
* Pad lines operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runPad: function(input, args) {
|
||||
let position = args[0],
|
||||
len = args[1],
|
||||
chr = args[2],
|
||||
lines = input.split("\n"),
|
||||
output = "",
|
||||
i = 0;
|
||||
|
||||
if (position === "Start") {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output += lines[i].padStart(lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
} else if (position === "End") {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output += lines[i].padEnd(lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Tidy;
|
@ -1,164 +0,0 @@
|
||||
/**
|
||||
* ToTable operations.
|
||||
*
|
||||
* @author Mark Jones [github.com/justanothermark]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
const ToTable = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FORMATS: [
|
||||
"ASCII",
|
||||
"HTML"
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* To Table operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runToTable: function (input, args) {
|
||||
const [cellDelims, rowDelims, firstRowHeader, format] = args;
|
||||
|
||||
// Process the input into a nested array of elements.
|
||||
const tableData = Utils.parseCSV(input, cellDelims.split(""), rowDelims.split(""));
|
||||
|
||||
if (!tableData.length) return "";
|
||||
|
||||
// Render the data in the requested format.
|
||||
switch (format) {
|
||||
case "ASCII":
|
||||
return asciiOutput(tableData);
|
||||
case "HTML":
|
||||
default:
|
||||
return htmlOutput(tableData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs an array of data as an ASCII table.
|
||||
*
|
||||
* @param {string[][]} tableData
|
||||
* @returns {string}
|
||||
*/
|
||||
function asciiOutput(tableData) {
|
||||
const horizontalBorder = "-";
|
||||
const verticalBorder = "|";
|
||||
const crossBorder = "+";
|
||||
|
||||
let output = "";
|
||||
let longestCells = [];
|
||||
|
||||
// Find longestCells value per column to pad cells equally.
|
||||
tableData.forEach(function(row, index) {
|
||||
row.forEach(function(cell, cellIndex) {
|
||||
if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) {
|
||||
longestCells[cellIndex] = cell.length;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add the top border of the table to the output.
|
||||
output += outputHorizontalBorder(longestCells);
|
||||
|
||||
// If the first row is a header, remove the row from the data and
|
||||
// add it to the output with another horizontal border.
|
||||
if (firstRowHeader) {
|
||||
let row = tableData.shift();
|
||||
output += outputRow(row, longestCells);
|
||||
output += outputHorizontalBorder(longestCells);
|
||||
}
|
||||
|
||||
// Add the rest of the table rows.
|
||||
tableData.forEach(function(row, index) {
|
||||
output += outputRow(row, longestCells);
|
||||
});
|
||||
|
||||
// Close the table with a final horizontal border.
|
||||
output += outputHorizontalBorder(longestCells);
|
||||
|
||||
return output;
|
||||
|
||||
/**
|
||||
* Outputs a row of correctly padded cells.
|
||||
*/
|
||||
function outputRow(row, longestCells) {
|
||||
let rowOutput = verticalBorder;
|
||||
row.forEach(function(cell, index) {
|
||||
rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder;
|
||||
});
|
||||
rowOutput += "\n";
|
||||
return rowOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs a horizontal border with a different character where
|
||||
* the horizontal border meets a vertical border.
|
||||
*/
|
||||
function outputHorizontalBorder(longestCells) {
|
||||
let rowOutput = crossBorder;
|
||||
longestCells.forEach(function(cellLength) {
|
||||
rowOutput += horizontalBorder.repeat(cellLength + 2) + crossBorder;
|
||||
});
|
||||
rowOutput += "\n";
|
||||
return rowOutput;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs a table of data as a HTML table.
|
||||
*
|
||||
* @param {string[][]} tableData
|
||||
* @returns {string}
|
||||
*/
|
||||
function htmlOutput(tableData) {
|
||||
// Start the HTML output with suitable classes for styling.
|
||||
let output = "<table class='table table-hover table-condensed table-bordered table-nonfluid'>";
|
||||
|
||||
// If the first row is a header then put it in <thead> with <th> cells.
|
||||
if (firstRowHeader) {
|
||||
let row = tableData.shift();
|
||||
output += "<thead>";
|
||||
output += outputRow(row, "th");
|
||||
output += "</thead>";
|
||||
}
|
||||
|
||||
// Output the rest of the rows in the <tbody>.
|
||||
output += "<tbody>";
|
||||
tableData.forEach(function(row, index) {
|
||||
output += outputRow(row, "td");
|
||||
});
|
||||
|
||||
// Close the body and table elements.
|
||||
output += "</tbody></table>";
|
||||
return output;
|
||||
|
||||
/**
|
||||
* Outputs a table row.
|
||||
*
|
||||
* @param {string[]} row
|
||||
* @param {string} cellType
|
||||
*/
|
||||
function outputRow(row, cellType) {
|
||||
let output = "<tr>";
|
||||
row.forEach(function(cell) {
|
||||
output += "<" + cellType + ">" + cell + "</" + cellType + ">";
|
||||
});
|
||||
output += "</tr>";
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ToTable;
|
@ -1,36 +0,0 @@
|
||||
import crypto from "crypto";
|
||||
|
||||
|
||||
/**
|
||||
* UUID operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const UUID = {
|
||||
|
||||
/**
|
||||
* Generate UUID operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runGenerateV4: function(input, args) {
|
||||
const buf = new Uint32Array(4).map(() => {
|
||||
return crypto.randomBytes(4).readUInt32BE(0, true);
|
||||
});
|
||||
let i = 0;
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
let r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
i++;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default UUID;
|
@ -1,101 +0,0 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Unicode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Unicode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PREFIXES: ["\\u", "%u", "U+"],
|
||||
|
||||
/**
|
||||
* Unescape Unicode Characters operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runUnescape: function(input, args) {
|
||||
let prefix = Unicode._prefixToRegex[args[0]],
|
||||
regex = new RegExp(prefix+"([a-f\\d]{4})", "ig"),
|
||||
output = "",
|
||||
m,
|
||||
i = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Add up to match
|
||||
output += input.slice(i, m.index);
|
||||
i = m.index;
|
||||
|
||||
// Add match
|
||||
output += Utils.chr(parseInt(m[1], 16));
|
||||
|
||||
i = regex.lastIndex;
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += input.slice(i, input.length);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Escape Unicode Characters operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runEscape: function(input, args) {
|
||||
const regexWhitelist = /[ -~]/i,
|
||||
prefix = args[0],
|
||||
encodeAll = args[1],
|
||||
padding = args[2],
|
||||
uppercaseHex = args[3];
|
||||
|
||||
let output = "",
|
||||
character = "";
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
character = input[i];
|
||||
if (!encodeAll && regexWhitelist.test(character)) {
|
||||
// It’s a printable ASCII character so don’t escape it.
|
||||
output += character;
|
||||
continue;
|
||||
}
|
||||
|
||||
let cp = character.codePointAt(0).toString(16);
|
||||
if (uppercaseHex) cp = cp.toUpperCase();
|
||||
output += prefix + cp.padStart(padding, "0");
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Lookup table to add prefixes to unicode delimiters so that they can be used in a regex.
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_prefixToRegex: {
|
||||
"\\u": "\\\\u",
|
||||
"%u": "%u",
|
||||
"U+": "U\\+"
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Unicode;
|
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* XKCD operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const XKCD = {
|
||||
|
||||
/**
|
||||
* XKCD Random Number operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runRandomNumber: function(input, args) {
|
||||
return 4; // chosen by fair dice roll.
|
||||
// guaranteed to be random.
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default XKCD;
|
753
src/web/App.js
753
src/web/App.js
@ -1,753 +0,0 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Utils from "../core/Utils";
|
||||
import {fromBase64} from "../core/lib/Base64";
|
||||
import Manager from "./Manager";
|
||||
import HTMLCategory from "./HTMLCategory";
|
||||
import HTMLOperation from "./HTMLOperation";
|
||||
import Split from "split.js";
|
||||
|
||||
|
||||
/**
|
||||
* HTML view for CyberChef responsible for building the web page and dealing with all user
|
||||
* interactions.
|
||||
*/
|
||||
class App {
|
||||
|
||||
/**
|
||||
* App constructor.
|
||||
*
|
||||
* @param {CatConf[]} categories - The list of categories and operations to be populated.
|
||||
* @param {Object.<string, OpConf>} operations - The list of operation configuration objects.
|
||||
* @param {String[]} defaultFavourites - A list of default favourite operations.
|
||||
* @param {Object} options - Default setting for app options.
|
||||
*/
|
||||
constructor(categories, operations, defaultFavourites, defaultOptions) {
|
||||
this.categories = categories;
|
||||
this.operations = operations;
|
||||
this.dfavourites = defaultFavourites;
|
||||
this.doptions = defaultOptions;
|
||||
this.options = Object.assign({}, defaultOptions);
|
||||
|
||||
this.manager = new Manager(this);
|
||||
|
||||
this.baking = false;
|
||||
this.autoBake_ = false;
|
||||
this.autoBakePause = false;
|
||||
this.progress = 0;
|
||||
this.ingId = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function sets up the stage and creates listeners for all events.
|
||||
*
|
||||
* @fires Manager#appstart
|
||||
*/
|
||||
setup() {
|
||||
document.dispatchEvent(this.manager.appstart);
|
||||
this.initialiseSplitter();
|
||||
this.loadLocalStorage();
|
||||
this.populateOperationsList();
|
||||
this.manager.setup();
|
||||
this.resetLayout();
|
||||
this.setCompileMessage();
|
||||
|
||||
log.debug("App loaded");
|
||||
this.appLoaded = true;
|
||||
|
||||
this.loadURIParams();
|
||||
this.loaded();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fires once all setup activities have completed.
|
||||
*
|
||||
* @fires Manager#apploaded
|
||||
*/
|
||||
loaded() {
|
||||
// Check that both the app and the worker have loaded successfully, and that
|
||||
// we haven't already loaded before attempting to remove the loading screen.
|
||||
if (!this.workerLoaded || !this.appLoaded ||
|
||||
!document.getElementById("loader-wrapper")) return;
|
||||
|
||||
// Trigger CSS animations to remove preloader
|
||||
document.body.classList.add("loaded");
|
||||
|
||||
// Wait for animations to complete then remove the preloader and loaded style
|
||||
// so that the animations for existing elements don't play again.
|
||||
setTimeout(function() {
|
||||
document.getElementById("loader-wrapper").remove();
|
||||
document.body.classList.remove("loaded");
|
||||
}, 1000);
|
||||
|
||||
// Clear the loading message interval
|
||||
clearInterval(window.loadingMsgsInt);
|
||||
|
||||
// Remove the loading error handler
|
||||
window.removeEventListener("error", window.loadingErrorHandler);
|
||||
|
||||
document.dispatchEvent(this.manager.apploaded);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An error handler for displaying the error to the user.
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {boolean} [logToConsole=false]
|
||||
*/
|
||||
handleError(err, logToConsole) {
|
||||
if (logToConsole) log.error(err);
|
||||
const msg = err.displayStr || err.toString();
|
||||
this.alert(msg, "danger", this.options.errorTimeout, !this.options.showErrors);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asks the ChefWorker to bake the current input using the current recipe.
|
||||
*
|
||||
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
|
||||
* whole recipe.
|
||||
*/
|
||||
bake(step) {
|
||||
if (this.baking) return;
|
||||
|
||||
// Reset attemptHighlight flag
|
||||
this.options.attemptHighlight = true;
|
||||
|
||||
this.manager.worker.bake(
|
||||
this.getInput(), // The user's input
|
||||
this.getRecipeConfig(), // The configuration of the recipe
|
||||
this.options, // Options set by the user
|
||||
this.progress, // The current position in the recipe
|
||||
step // Whether or not to take one step or execute the whole recipe
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs Auto Bake if it is set.
|
||||
*/
|
||||
autoBake() {
|
||||
// If autoBakePause is set, we are loading a full recipe (and potentially input), so there is no
|
||||
// need to set the staleness indicator. Just exit and wait until auto bake is called after loading
|
||||
// has completed.
|
||||
if (this.autoBakePause) return false;
|
||||
|
||||
if (this.autoBake_ && !this.baking) {
|
||||
log.debug("Auto-baking");
|
||||
this.bake();
|
||||
} else {
|
||||
this.manager.controls.showStaleIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs a silent bake, forcing the browser to load and cache all the relevant JavaScript code needed
|
||||
* to do a real bake.
|
||||
*
|
||||
* The output will not be modified (hence "silent" bake). This will only actually execute the recipe
|
||||
* if auto-bake is enabled, otherwise it will just wake up the ChefWorker with an empty recipe.
|
||||
*/
|
||||
silentBake() {
|
||||
let recipeConfig = [];
|
||||
|
||||
if (this.autoBake_) {
|
||||
// If auto-bake is not enabled we don't want to actually run the recipe as it may be disabled
|
||||
// for a good reason.
|
||||
recipeConfig = this.getRecipeConfig();
|
||||
}
|
||||
|
||||
this.manager.worker.silentBake(recipeConfig);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's input data.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
getInput() {
|
||||
return this.manager.input.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the user's input data.
|
||||
*
|
||||
* @param {string} input - The string to set the input to
|
||||
*/
|
||||
setInput(input) {
|
||||
this.manager.input.set(input);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Populates the operations accordion list with the categories and operations specified in the
|
||||
* view constructor.
|
||||
*
|
||||
* @fires Manager#oplistcreate
|
||||
*/
|
||||
populateOperationsList() {
|
||||
// Move edit button away before we overwrite it
|
||||
document.body.appendChild(document.getElementById("edit-favourites"));
|
||||
|
||||
let html = "";
|
||||
let i;
|
||||
|
||||
for (i = 0; i < this.categories.length; i++) {
|
||||
const catConf = this.categories[i],
|
||||
selected = i === 0,
|
||||
cat = new HTMLCategory(catConf.name, selected);
|
||||
|
||||
for (let j = 0; j < catConf.ops.length; j++) {
|
||||
const opName = catConf.ops[j];
|
||||
if (!this.operations.hasOwnProperty(opName)) {
|
||||
log.warn(`${opName} could not be found.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const op = new HTMLOperation(opName, this.operations[opName], this, this.manager);
|
||||
cat.addOperation(op);
|
||||
}
|
||||
|
||||
html += cat.toHtml();
|
||||
}
|
||||
|
||||
document.getElementById("categories").innerHTML = html;
|
||||
|
||||
const opLists = document.querySelectorAll("#categories .op-list");
|
||||
|
||||
for (i = 0; i < opLists.length; i++) {
|
||||
opLists[i].dispatchEvent(this.manager.oplistcreate);
|
||||
}
|
||||
|
||||
// Add edit button to first category (Favourites)
|
||||
document.querySelector("#categories a").appendChild(document.getElementById("edit-favourites"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets up the adjustable splitter to allow the user to resize areas of the page.
|
||||
*/
|
||||
initialiseSplitter() {
|
||||
this.columnSplitter = Split(["#operations", "#recipe", "#IO"], {
|
||||
sizes: [20, 30, 50],
|
||||
minSize: [240, 325, 450],
|
||||
gutterSize: 4,
|
||||
onDrag: function() {
|
||||
this.manager.controls.adjustWidth();
|
||||
this.manager.output.adjustWidth();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
this.ioSplitter = Split(["#input", "#output"], {
|
||||
direction: "vertical",
|
||||
gutterSize: 4,
|
||||
});
|
||||
|
||||
this.resetLayout();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads the information previously saved to the HTML5 local storage object so that user options
|
||||
* and favourites can be restored.
|
||||
*/
|
||||
loadLocalStorage() {
|
||||
// Load options
|
||||
let lOptions;
|
||||
if (this.isLocalStorageAvailable() && localStorage.options !== undefined) {
|
||||
lOptions = JSON.parse(localStorage.options);
|
||||
}
|
||||
this.manager.options.load(lOptions);
|
||||
|
||||
// Load favourites
|
||||
this.loadFavourites();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads the user's favourite operations from the HTML5 local storage object and populates the
|
||||
* Favourites category with them.
|
||||
* If the user currently has no saved favourites, the defaults from the view constructor are used.
|
||||
*/
|
||||
loadFavourites() {
|
||||
let favourites;
|
||||
|
||||
if (this.isLocalStorageAvailable()) {
|
||||
favourites = localStorage.favourites && localStorage.favourites.length > 2 ?
|
||||
JSON.parse(localStorage.favourites) :
|
||||
this.dfavourites;
|
||||
favourites = this.validFavourites(favourites);
|
||||
this.saveFavourites(favourites);
|
||||
} else {
|
||||
favourites = this.dfavourites;
|
||||
}
|
||||
|
||||
const favCat = this.categories.filter(function(c) {
|
||||
return c.name === "Favourites";
|
||||
})[0];
|
||||
|
||||
if (favCat) {
|
||||
favCat.ops = favourites;
|
||||
} else {
|
||||
this.categories.unshift({
|
||||
name: "Favourites",
|
||||
ops: favourites
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list of favourite operations that the user had stored and removes any that are no
|
||||
* longer available. The user is notified if this is the case.
|
||||
|
||||
* @param {string[]} favourites - A list of the user's favourite operations
|
||||
* @returns {string[]} A list of the valid favourites
|
||||
*/
|
||||
validFavourites(favourites) {
|
||||
const validFavs = [];
|
||||
for (let i = 0; i < favourites.length; i++) {
|
||||
if (this.operations.hasOwnProperty(favourites[i])) {
|
||||
validFavs.push(favourites[i]);
|
||||
} else {
|
||||
this.alert("The operation \"" + Utils.escapeHtml(favourites[i]) +
|
||||
"\" is no longer available. It has been removed from your favourites.", "info");
|
||||
}
|
||||
}
|
||||
return validFavs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves a list of favourite operations to the HTML5 local storage object.
|
||||
*
|
||||
* @param {string[]} favourites - A list of the user's favourite operations
|
||||
*/
|
||||
saveFavourites(favourites) {
|
||||
if (!this.isLocalStorageAvailable()) {
|
||||
this.alert(
|
||||
"Your security settings do not allow access to local storage so your favourites cannot be saved.",
|
||||
"danger",
|
||||
5000
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
localStorage.setItem("favourites", JSON.stringify(this.validFavourites(favourites)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets favourite operations back to the default as specified in the view constructor and
|
||||
* refreshes the operation list.
|
||||
*/
|
||||
resetFavourites() {
|
||||
this.saveFavourites(this.dfavourites);
|
||||
this.loadFavourites();
|
||||
this.populateOperationsList();
|
||||
this.manager.recipe.initialiseOperationDragNDrop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds an operation to the user's favourites.
|
||||
*
|
||||
* @param {string} name - The name of the operation
|
||||
*/
|
||||
addFavourite(name) {
|
||||
const favourites = JSON.parse(localStorage.favourites);
|
||||
|
||||
if (favourites.indexOf(name) >= 0) {
|
||||
this.alert("'" + name + "' is already in your favourites", "info", 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
favourites.push(name);
|
||||
this.saveFavourites(favourites);
|
||||
this.loadFavourites();
|
||||
this.populateOperationsList();
|
||||
this.manager.recipe.initialiseOperationDragNDrop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for input and recipe in the URI parameters and loads them if present.
|
||||
*/
|
||||
loadURIParams() {
|
||||
// Load query string or hash from URI (depending on which is populated)
|
||||
// We prefer getting the hash by splitting the href rather than referencing
|
||||
// location.hash as some browsers (Firefox) automatically URL decode it,
|
||||
// which cause issues.
|
||||
const params = window.location.search ||
|
||||
window.location.href.split("#")[1] ||
|
||||
window.location.hash;
|
||||
this.uriParams = Utils.parseURIParams(params);
|
||||
this.autoBakePause = true;
|
||||
|
||||
// Read in recipe from URI params
|
||||
if (this.uriParams.recipe) {
|
||||
try {
|
||||
const recipeConfig = Utils.parseRecipeConfig(this.uriParams.recipe);
|
||||
this.setRecipeConfig(recipeConfig);
|
||||
} catch (err) {}
|
||||
} else if (this.uriParams.op) {
|
||||
// If there's no recipe, look for single operations
|
||||
this.manager.recipe.clearRecipe();
|
||||
|
||||
// Search for nearest match and add it
|
||||
const matchedOps = this.manager.ops.filterOperations(this.uriParams.op, false);
|
||||
if (matchedOps.length) {
|
||||
this.manager.recipe.addOperation(matchedOps[0].name);
|
||||
}
|
||||
|
||||
// Populate search with the string
|
||||
const search = document.getElementById("search");
|
||||
|
||||
search.value = this.uriParams.op;
|
||||
search.dispatchEvent(new Event("search"));
|
||||
}
|
||||
|
||||
// Read in input data from URI params
|
||||
if (this.uriParams.input) {
|
||||
try {
|
||||
const inputData = fromBase64(this.uriParams.input);
|
||||
this.setInput(inputData);
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
this.autoBakePause = false;
|
||||
this.autoBake();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next ingredient ID and increments it for next time.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
nextIngId() {
|
||||
return this.ingId++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current recipe configuration.
|
||||
*
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
getRecipeConfig() {
|
||||
return this.manager.recipe.getConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a recipe configuration, sets the recipe to that configuration.
|
||||
*
|
||||
* @fires Manager#statechange
|
||||
* @param {Object[]} recipeConfig - The recipe configuration
|
||||
*/
|
||||
setRecipeConfig(recipeConfig) {
|
||||
document.getElementById("rec-list").innerHTML = null;
|
||||
|
||||
// Pause auto-bake while loading but don't modify `this.autoBake_`
|
||||
// otherwise `manualBake` cannot trigger.
|
||||
this.autoBakePause = true;
|
||||
|
||||
for (let i = 0; i < recipeConfig.length; i++) {
|
||||
const item = this.manager.recipe.addOperation(recipeConfig[i].op);
|
||||
|
||||
// Populate arguments
|
||||
const args = item.querySelectorAll(".arg");
|
||||
for (let j = 0; j < args.length; j++) {
|
||||
if (recipeConfig[i].args[j] === undefined) continue;
|
||||
if (args[j].getAttribute("type") === "checkbox") {
|
||||
// checkbox
|
||||
args[j].checked = recipeConfig[i].args[j];
|
||||
} else if (args[j].classList.contains("toggle-string")) {
|
||||
// toggleString
|
||||
args[j].value = recipeConfig[i].args[j].string;
|
||||
args[j].previousSibling.children[0].innerHTML =
|
||||
Utils.escapeHtml(recipeConfig[i].args[j].option) +
|
||||
" <span class='caret'></span>";
|
||||
} else {
|
||||
// all others
|
||||
args[j].value = recipeConfig[i].args[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Set disabled and breakpoint
|
||||
if (recipeConfig[i].disabled) {
|
||||
item.querySelector(".disable-icon").click();
|
||||
}
|
||||
if (recipeConfig[i].breakpoint) {
|
||||
item.querySelector(".breakpoint").click();
|
||||
}
|
||||
|
||||
this.progress = 0;
|
||||
}
|
||||
|
||||
// Unpause auto bake
|
||||
this.autoBakePause = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets the splitter positions to default.
|
||||
*/
|
||||
resetLayout() {
|
||||
this.columnSplitter.setSizes([20, 30, 50]);
|
||||
this.ioSplitter.setSizes([50, 50]);
|
||||
|
||||
this.manager.controls.adjustWidth();
|
||||
this.manager.output.adjustWidth();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the compile message.
|
||||
*/
|
||||
setCompileMessage() {
|
||||
// Display time since last build and compile message
|
||||
const now = new Date(),
|
||||
timeSinceCompile = Utils.fuzzyTime(now.getTime() - window.compileTime);
|
||||
|
||||
// Calculate previous version to compare to
|
||||
const prev = PKG_VERSION.split(".").map(n => {
|
||||
return parseInt(n, 10);
|
||||
});
|
||||
if (prev[2] > 0) prev[2]--;
|
||||
else if (prev[1] > 0) prev[1]--;
|
||||
else prev[0]--;
|
||||
|
||||
const compareURL = `https://github.com/gchq/CyberChef/compare/v${prev.join(".")}...v${PKG_VERSION}`;
|
||||
|
||||
let compileInfo = `<a href='${compareURL}'>Last build: ${timeSinceCompile.substr(0, 1).toUpperCase() + timeSinceCompile.substr(1)} ago</a>`;
|
||||
|
||||
if (window.compileMessage !== "") {
|
||||
compileInfo += " - " + window.compileMessage;
|
||||
}
|
||||
|
||||
document.getElementById("notice").innerHTML = compileInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether the browser supports Local Storage and if it is accessible.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isLocalStorageAvailable() {
|
||||
try {
|
||||
if (!localStorage) return false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
// Access to LocalStorage is denied
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pops up a message to the user and writes it to the console log.
|
||||
*
|
||||
* @param {string} str - The message to display (HTML supported)
|
||||
* @param {string} style - The colour of the popup
|
||||
* "danger" = red
|
||||
* "warning" = amber
|
||||
* "info" = blue
|
||||
* "success" = green
|
||||
* @param {number} timeout - The number of milliseconds before the popup closes automatically
|
||||
* 0 for never (until the user closes it)
|
||||
* @param {boolean} [silent=false] - Don't show the message in the popup, only print it to the
|
||||
* console
|
||||
*
|
||||
* @example
|
||||
* // Pops up a red box with the message "[current time] Error: Something has gone wrong!"
|
||||
* // that will need to be dismissed by the user.
|
||||
* this.alert("Error: Something has gone wrong!", "danger", 0);
|
||||
*
|
||||
* // Pops up a blue information box with the message "[current time] Happy Christmas!"
|
||||
* // that will disappear after 5 seconds.
|
||||
* this.alert("Happy Christmas!", "info", 5000);
|
||||
*/
|
||||
alert(str, style, timeout, silent) {
|
||||
const time = new Date();
|
||||
|
||||
log.info("[" + time.toLocaleString() + "] " + str);
|
||||
if (silent) return;
|
||||
|
||||
style = style || "danger";
|
||||
timeout = timeout || 0;
|
||||
|
||||
const alertEl = document.getElementById("alert"),
|
||||
alertContent = document.getElementById("alert-content");
|
||||
|
||||
alertEl.classList.remove("alert-danger");
|
||||
alertEl.classList.remove("alert-warning");
|
||||
alertEl.classList.remove("alert-info");
|
||||
alertEl.classList.remove("alert-success");
|
||||
alertEl.classList.add("alert-" + style);
|
||||
|
||||
// If the box hasn't been closed, append to it rather than replacing
|
||||
if (alertEl.style.display === "block") {
|
||||
alertContent.innerHTML +=
|
||||
"<br><br>[" + time.toLocaleTimeString() + "] " + str;
|
||||
} else {
|
||||
alertContent.innerHTML =
|
||||
"[" + time.toLocaleTimeString() + "] " + str;
|
||||
}
|
||||
|
||||
// Stop the animation if it is in progress
|
||||
$("#alert").stop();
|
||||
alertEl.style.display = "block";
|
||||
alertEl.style.opacity = 1;
|
||||
|
||||
if (timeout > 0) {
|
||||
clearTimeout(this.alertTimeout);
|
||||
this.alertTimeout = setTimeout(function(){
|
||||
$("#alert").slideUp(100);
|
||||
}, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pops up a box asking the user a question and sending the answer to a specified callback function.
|
||||
*
|
||||
* @param {string} title - The title of the box
|
||||
* @param {string} body - The question (HTML supported)
|
||||
* @param {function} callback - A function accepting one boolean argument which handles the
|
||||
* response e.g. function(answer) {...}
|
||||
* @param {Object} [scope=this] - The object to bind to the callback function
|
||||
*
|
||||
* @example
|
||||
* // Pops up a box asking if the user would like a cookie. Prints the answer to the console.
|
||||
* this.confirm("Question", "Would you like a cookie?", function(answer) {console.log(answer);});
|
||||
*/
|
||||
confirm(title, body, callback, scope) {
|
||||
scope = scope || this;
|
||||
document.getElementById("confirm-title").innerHTML = title;
|
||||
document.getElementById("confirm-body").innerHTML = body;
|
||||
document.getElementById("confirm-modal").style.display = "block";
|
||||
|
||||
this.confirmClosed = false;
|
||||
$("#confirm-modal").modal()
|
||||
.one("show.bs.modal", function(e) {
|
||||
this.confirmClosed = false;
|
||||
}.bind(this))
|
||||
.one("click", "#confirm-yes", function() {
|
||||
this.confirmClosed = true;
|
||||
callback.bind(scope)(true);
|
||||
$("#confirm-modal").modal("hide");
|
||||
}.bind(this))
|
||||
.one("hide.bs.modal", function(e) {
|
||||
if (!this.confirmClosed)
|
||||
callback.bind(scope)(false);
|
||||
this.confirmClosed = true;
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the alert close button click event.
|
||||
* Closes the alert box.
|
||||
*/
|
||||
alertCloseClick() {
|
||||
document.getElementById("alert").style.display = "none";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for CyerChef statechange events.
|
||||
* Fires whenever the input or recipe changes in any way.
|
||||
*
|
||||
* @listens Manager#statechange
|
||||
* @param {event} e
|
||||
*/
|
||||
stateChange(e) {
|
||||
this.autoBake();
|
||||
|
||||
// Set title
|
||||
const recipeConfig = this.getRecipeConfig();
|
||||
let title = "CyberChef";
|
||||
if (recipeConfig.length === 1) {
|
||||
title = `${recipeConfig[0].op} - ${title}`;
|
||||
} else if (recipeConfig.length > 1) {
|
||||
// See how long the full recipe is
|
||||
const ops = recipeConfig.map(op => op.op).join(", ");
|
||||
if (ops.length < 45) {
|
||||
title = `${ops} - ${title}`;
|
||||
} else {
|
||||
// If it's too long, just use the first one and say how many more there are
|
||||
title = `${recipeConfig[0].op}, ${recipeConfig.length - 1} more - ${title}`;
|
||||
}
|
||||
}
|
||||
document.title = title;
|
||||
|
||||
// Update the current history state (not creating a new one)
|
||||
if (this.options.updateUrl) {
|
||||
this.lastStateUrl = this.manager.controls.generateStateUrl(true, true, recipeConfig);
|
||||
window.history.replaceState({}, title, this.lastStateUrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the history popstate event.
|
||||
* Reloads parameters from the URL.
|
||||
*
|
||||
* @param {event} e
|
||||
*/
|
||||
popState(e) {
|
||||
this.loadURIParams();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to call an external API from this view.
|
||||
*/
|
||||
callApi(url, type, data, dataType, contentType) {
|
||||
type = type || "POST";
|
||||
data = data || {};
|
||||
dataType = dataType || undefined;
|
||||
contentType = contentType || "application/json";
|
||||
|
||||
let response = null,
|
||||
success = false;
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
async: false,
|
||||
type: type,
|
||||
data: data,
|
||||
dataType: dataType,
|
||||
contentType: contentType,
|
||||
success: function(data) {
|
||||
success = true;
|
||||
response = data;
|
||||
},
|
||||
error: function(data) {
|
||||
success = false;
|
||||
response = data;
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
success: success,
|
||||
response: response
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default App;
|
@ -12,10 +12,10 @@ const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
const banner = `/**
|
||||
* CyberChef - The Cyber Swiss Army Knife
|
||||
*
|
||||
* @copyright Crown Copyright 2017
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* Copyright 2017 Crown Copyright
|
||||
* Copyright 2016 Crown Copyright
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
Loading…
Reference in New Issue
Block a user