mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-22 07:46:16 -04:00
Merge remote-tracking branch 'upstream/master' into feature-octal
This commit is contained in:
commit
a36c9ca339
266 changed files with 1139 additions and 70336 deletions
66
src/core/operations/Base.js
Executable file
66
src/core/operations/Base.js
Executable file
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* 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 {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
if (!input) {
|
||||
throw ("Error: Input must be a number");
|
||||
}
|
||||
var 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 {number}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var radix = args[0] || Base.DEFAULT_RADIX;
|
||||
if (radix < 2 || radix > 36) {
|
||||
throw "Error: Radix argument must be between 2 and 36";
|
||||
}
|
||||
|
||||
var number = input.replace(/\s/g, "").split("."),
|
||||
result = parseInt(number[0], radix) || 0;
|
||||
|
||||
if (number.length === 1) return result;
|
||||
|
||||
// Fractional part
|
||||
for (var i = 0; i < number[1].length; i++) {
|
||||
var digit = parseInt(number[1][i], radix);
|
||||
result += digit / Math.pow(radix, i+1);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Base;
|
137
src/core/operations/Base58.js
Executable file
137
src/core/operations/Base58.js
Executable file
|
@ -0,0 +1,137 @@
|
|||
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) {
|
||||
var 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) {
|
||||
var carry = (result[0] << 8) + b;
|
||||
result[0] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
|
||||
for (var 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) {
|
||||
var 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) {
|
||||
var index = alphabet.indexOf(c);
|
||||
|
||||
if (index === -1) {
|
||||
if (removeNonAlphaChars) {
|
||||
return;
|
||||
} else {
|
||||
throw ("Char '" + c + "' at position " + charIndex + " not in alphabet");
|
||||
}
|
||||
}
|
||||
|
||||
var carry = result[0] * 58 + index;
|
||||
result[0] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
|
||||
for (var 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;
|
347
src/core/operations/Base64.js
Executable file
347
src/core/operations/Base64.js
Executable file
|
@ -0,0 +1,347 @@
|
|||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Base64 operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Base64 = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ALPHABET: "A-Za-z0-9+/=",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ALPHABET_OPTIONS: [
|
||||
{name: "Standard: A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
|
||||
{name: "URL safe: A-Za-z0-9-_", value: "A-Za-z0-9-_"},
|
||||
{name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-="},
|
||||
{name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z="},
|
||||
{name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_."},
|
||||
{name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-"},
|
||||
{name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/="},
|
||||
{name: "Radix-64: 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
|
||||
{name: "Uuencoding: [space]-_", value: " -_"},
|
||||
{name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z"},
|
||||
{name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r", value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r"},
|
||||
{name: "ROT13: N-ZA-Mn-za-m0-9+/=", value: "N-ZA-Mn-za-m0-9+/="},
|
||||
{name: "UNIX crypt: ./0-9A-Za-z", value: "./0-9A-Za-z"},
|
||||
],
|
||||
|
||||
/**
|
||||
* To Base64 operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET;
|
||||
return Utils.toBase64(input, alphabet);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_NON_ALPH_CHARS: true,
|
||||
|
||||
/**
|
||||
* From Base64 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET,
|
||||
removeNonAlphChars = args[1];
|
||||
|
||||
return Utils.fromBase64(input, alphabet, "byteArray", removeNonAlphChars);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BASE32_ALPHABET: "A-Z2-7=",
|
||||
|
||||
/**
|
||||
* To Base32 operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo32: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
var alphabet = args[0] ?
|
||||
Utils.expandAlphRange(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
||||
output = "",
|
||||
chr1, chr2, chr3, chr4, chr5,
|
||||
enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8,
|
||||
i = 0;
|
||||
|
||||
while (i < input.length) {
|
||||
chr1 = input[i++];
|
||||
chr2 = input[i++];
|
||||
chr3 = input[i++];
|
||||
chr4 = input[i++];
|
||||
chr5 = input[i++];
|
||||
|
||||
enc1 = chr1 >> 3;
|
||||
enc2 = ((chr1 & 7) << 2) | (chr2 >> 6);
|
||||
enc3 = (chr2 >> 1) & 31;
|
||||
enc4 = ((chr2 & 1) << 4) | (chr3 >> 4);
|
||||
enc5 = ((chr3 & 15) << 1) | (chr4 >> 7);
|
||||
enc6 = (chr4 >> 2) & 31;
|
||||
enc7 = ((chr4 & 3) << 3) | (chr5 >> 5);
|
||||
enc8 = chr5 & 31;
|
||||
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = enc5 = enc6 = enc7 = enc8 = 32;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc5 = enc6 = enc7 = enc8 = 32;
|
||||
} else if (isNaN(chr4)) {
|
||||
enc6 = enc7 = enc8 = 32;
|
||||
} else if (isNaN(chr5)) {
|
||||
enc8 = 32;
|
||||
}
|
||||
|
||||
output += alphabet.charAt(enc1) + alphabet.charAt(enc2) + alphabet.charAt(enc3) +
|
||||
alphabet.charAt(enc4) + alphabet.charAt(enc5) + alphabet.charAt(enc6) +
|
||||
alphabet.charAt(enc7) + alphabet.charAt(enc8);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Base32 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom32: function(input, args) {
|
||||
if (!input) return [];
|
||||
|
||||
var alphabet = args[0] ?
|
||||
Utils.expandAlphRange(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
||||
removeNonAlphChars = args[0];
|
||||
|
||||
var output = [],
|
||||
chr1, chr2, chr3, chr4, chr5,
|
||||
enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8,
|
||||
i = 0;
|
||||
|
||||
if (removeNonAlphChars) {
|
||||
var re = new RegExp("[^" + alphabet.replace(/[\]\\\-^]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
}
|
||||
|
||||
while (i < input.length) {
|
||||
enc1 = alphabet.indexOf(input.charAt(i++));
|
||||
enc2 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
enc3 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
enc4 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
enc5 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
enc6 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
enc7 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
enc8 = alphabet.indexOf(input.charAt(i++) || "=");
|
||||
|
||||
chr1 = (enc1 << 3) | (enc2 >> 2);
|
||||
chr2 = ((enc2 & 3) << 6) | (enc3 << 1) | (enc4 >> 4);
|
||||
chr3 = ((enc4 & 15) << 4) | (enc5 >> 1);
|
||||
chr4 = ((enc5 & 1) << 7) | (enc6 << 2) | (enc7 >> 3);
|
||||
chr5 = ((enc7 & 7) << 5) | enc8;
|
||||
|
||||
output.push(chr1);
|
||||
if (enc2 & 3 !== 0 || enc3 !== 32) output.push(chr2);
|
||||
if (enc4 & 15 !== 0 || enc5 !== 32) output.push(chr3);
|
||||
if (enc5 & 1 !== 0 || enc6 !== 32) output.push(chr4);
|
||||
if (enc7 & 7 !== 0 || enc8 !== 32) output.push(chr5);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHOW_IN_BINARY: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OFFSETS_SHOW_VARIABLE: true,
|
||||
|
||||
/**
|
||||
* Show Base64 offsets operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runOffsets: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET,
|
||||
showVariable = args[1],
|
||||
offset0 = Utils.toBase64(input, alphabet),
|
||||
offset1 = Utils.toBase64([0].concat(input), alphabet),
|
||||
offset2 = Utils.toBase64([0, 0].concat(input), alphabet),
|
||||
len0 = offset0.indexOf("="),
|
||||
len1 = offset1.indexOf("="),
|
||||
len2 = offset2.indexOf("="),
|
||||
script = "<script type='application/javascript'>$('[data-toggle=\"tooltip\"]').tooltip()</script>",
|
||||
staticSection = "",
|
||||
padding = "";
|
||||
|
||||
if (input.length < 1) {
|
||||
return "Please enter a string.";
|
||||
}
|
||||
|
||||
// Highlight offset 0
|
||||
if (len0 % 4 === 2) {
|
||||
staticSection = offset0.slice(0, -3);
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 2) + "</span>";
|
||||
} else if (len0 % 4 === 3) {
|
||||
staticSection = offset0.slice(0, -2);
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset0;
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet)) + "'>" +
|
||||
staticSection + "</span>";
|
||||
}
|
||||
|
||||
if (!showVariable) {
|
||||
offset0 = staticSection;
|
||||
}
|
||||
|
||||
|
||||
// Highlight offset 1
|
||||
padding = "<span class='hlred'>" + offset1.substr(0, 1) + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(1, 1) + "</span>";
|
||||
offset1 = offset1.substr(2);
|
||||
if (len1 % 4 === 2) {
|
||||
staticSection = offset1.slice(0, -3);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 2) + "</span>";
|
||||
} else if (len1 % 4 === 3) {
|
||||
staticSection = offset1.slice(0, -2);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset1;
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1)) + "'>" +
|
||||
staticSection + "</span>";
|
||||
}
|
||||
|
||||
if (!showVariable) {
|
||||
offset1 = staticSection;
|
||||
}
|
||||
|
||||
// Highlight offset 2
|
||||
padding = "<span class='hlred'>" + offset2.substr(0, 2) + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(2, 1) + "</span>";
|
||||
offset2 = offset2.substr(3);
|
||||
if (len2 % 4 === 2) {
|
||||
staticSection = offset2.slice(0, -3);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 2) + "</span>";
|
||||
} else if (len2 % 4 === 3) {
|
||||
staticSection = offset2.slice(0, -2);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset2;
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2)) + "'>" +
|
||||
staticSection + "</span>";
|
||||
}
|
||||
|
||||
if (!showVariable) {
|
||||
offset2 = staticSection;
|
||||
}
|
||||
|
||||
return (showVariable ? "Characters highlighted in <span class='hlgreen'>green</span> could change if the input is surrounded by more data." +
|
||||
"\nCharacters highlighted in <span class='hlred'>red</span> are for padding purposes only." +
|
||||
"\nUnhighlighted characters are <span data-toggle='tooltip' data-placement='top' title='Tooltip on left'>static</span>." +
|
||||
"\nHover over the static sections to see what they decode to on their own.\n" +
|
||||
"\nOffset 0: " + offset0 +
|
||||
"\nOffset 1: " + offset1 +
|
||||
"\nOffset 2: " + offset2 +
|
||||
script :
|
||||
offset0 + "\n" + offset1 + "\n" + offset2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to Base64
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightTo: function(pos, args) {
|
||||
pos[0].start = Math.floor(pos[0].start / 3 * 4);
|
||||
pos[0].end = Math.ceil(pos[0].end / 3 * 4);
|
||||
return pos;
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight from Base64
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFrom: function(pos, args) {
|
||||
pos[0].start = Math.ceil(pos[0].start / 4 * 3);
|
||||
pos[0].end = Math.floor(pos[0].end / 4 * 3);
|
||||
return pos;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Base64;
|
310
src/core/operations/BitwiseOp.js
Executable file
310
src/core/operations/BitwiseOp.js
Executable file
|
@ -0,0 +1,310 @@
|
|||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
|
||||
/**
|
||||
* Bitwise operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const BitwiseOp = {
|
||||
|
||||
/**
|
||||
* Runs bitwise operations across the input data.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} input
|
||||
* @param {byteArray} key
|
||||
* @param {function} func - The bitwise calculation to carry out
|
||||
* @param {boolean} nullPreserving
|
||||
* @param {string} scheme
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_bitOp: function (input, key, func, nullPreserving, scheme) {
|
||||
if (!key || !key.length) key = [0];
|
||||
var result = [],
|
||||
x = null,
|
||||
k = null,
|
||||
o = null;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
k = key[i % key.length];
|
||||
o = input[i];
|
||||
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
|
||||
result.push(x);
|
||||
if (scheme !== "Standard" && !(nullPreserving && (o === 0 || o === k))) {
|
||||
switch (scheme) {
|
||||
case "Input differential":
|
||||
key[i % key.length] = x;
|
||||
break;
|
||||
case "Output differential":
|
||||
key[i % key.length] = o;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_PRESERVE_NULLS: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_SCHEME: ["Standard", "Input differential", "Output differential"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KEY_FORMAT: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
|
||||
|
||||
/**
|
||||
* XOR operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runXor: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || ""),
|
||||
scheme = args[1],
|
||||
nullPreserving = args[2];
|
||||
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._xor, nullPreserving, scheme);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_BRUTE_KEY_LENGTH: ["1", "2"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_BRUTE_SAMPLE_LENGTH: 100,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_BRUTE_SAMPLE_OFFSET: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_BRUTE_PRINT_KEY: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_BRUTE_OUTPUT_HEX: false,
|
||||
|
||||
/**
|
||||
* XOR Brute Force operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runXorBrute: function (input, args) {
|
||||
var keyLength = parseInt(args[0], 10),
|
||||
sampleLength = args[1],
|
||||
sampleOffset = args[2],
|
||||
nullPreserving = args[3],
|
||||
differential = args[4],
|
||||
crib = args[5],
|
||||
printKey = args[6],
|
||||
outputHex = args[7],
|
||||
regex;
|
||||
|
||||
var output = "",
|
||||
result,
|
||||
resultUtf8;
|
||||
|
||||
input = input.slice(sampleOffset, sampleOffset + sampleLength);
|
||||
|
||||
if (crib !== "") {
|
||||
regex = new RegExp(crib, "im");
|
||||
}
|
||||
|
||||
|
||||
for (var key = 1, l = Math.pow(256, keyLength); key < l; key++) {
|
||||
result = BitwiseOp._bitOp(input, Utils.hexToByteArray(key.toString(16)), BitwiseOp._xor, nullPreserving, differential);
|
||||
resultUtf8 = Utils.byteArrayToUtf8(result);
|
||||
if (crib !== "" && resultUtf8.search(regex) === -1) continue;
|
||||
if (printKey) output += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
|
||||
if (outputHex)
|
||||
output += Utils.byteArrayToHex(result) + "\n";
|
||||
else
|
||||
output += Utils.printable(resultUtf8, false) + "\n";
|
||||
if (printKey) output += "\n";
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* NOT operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runNot: function (input, args) {
|
||||
return BitwiseOp._bitOp(input, null, BitwiseOp._not);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AND operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runAnd: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._and);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* OR operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runOr: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._or);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* ADD operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runAdd: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._add);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SUB operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runSub: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._sub);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* XOR bitwise calculation.
|
||||
*
|
||||
* @private
|
||||
* @param {number} operand
|
||||
* @param {number} key
|
||||
* @returns {number}
|
||||
*/
|
||||
_xor: function (operand, key) {
|
||||
return operand ^ key;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* NOT bitwise calculation.
|
||||
*
|
||||
* @private
|
||||
* @param {number} operand
|
||||
* @returns {number}
|
||||
*/
|
||||
_not: function (operand, _) {
|
||||
return ~operand & 0xff;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AND bitwise calculation.
|
||||
*
|
||||
* @private
|
||||
* @param {number} operand
|
||||
* @param {number} key
|
||||
* @returns {number}
|
||||
*/
|
||||
_and: function (operand, key) {
|
||||
return operand & key;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* OR bitwise calculation.
|
||||
*
|
||||
* @private
|
||||
* @param {number} operand
|
||||
* @param {number} key
|
||||
* @returns {number}
|
||||
*/
|
||||
_or: function (operand, key) {
|
||||
return operand | key;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* ADD bitwise calculation.
|
||||
*
|
||||
* @private
|
||||
* @param {number} operand
|
||||
* @param {number} key
|
||||
* @returns {number}
|
||||
*/
|
||||
_add: function (operand, key) {
|
||||
return (operand + key) % 256;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SUB bitwise calculation.
|
||||
*
|
||||
* @private
|
||||
* @param {number} operand
|
||||
* @param {number} key
|
||||
* @returns {number}
|
||||
*/
|
||||
_sub: function (operand, key) {
|
||||
var result = operand - key;
|
||||
return (result < 0) ? 256 + result : result;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default BitwiseOp;
|
425
src/core/operations/ByteRepr.js
Executable file
425
src/core/operations/ByteRepr.js
Executable file
|
@ -0,0 +1,425 @@
|
|||
/* globals app */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
HEX_DELIM_OPTIONS: ["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 Hex operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToHex: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
return Utils.toHex(input, delim, 2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Hex operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromHex: function(input, args) {
|
||||
var delim = args[0] || "Space";
|
||||
return Utils.fromHex(input, delim, 2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Oct operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToOct: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
return input.map(val => parseInt(Utils.bin(val), 2).toString(8)).join(delim);
|
||||
},
|
||||
|
||||
/**
|
||||
* From Oct operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromOct: function(input, args) {
|
||||
var 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) {
|
||||
var 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";
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
ordinal = Utils.ord(input[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 && app) app.options.attemptHighlight = false;
|
||||
|
||||
output += Utils.hex(ordinal, padding) + delim;
|
||||
} else {
|
||||
if (app) app.options.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) {
|
||||
var 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 (base !== 16 && app) {
|
||||
app.options.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));
|
||||
}
|
||||
}
|
||||
|
||||
var latin1 = "";
|
||||
for (i = 0; i < bites.length; i++) {
|
||||
latin1 += Utils.chr(parseInt(bites[i], base));
|
||||
}
|
||||
return Utils.strToByteArray(latin1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to hex
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightTo: function(pos, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
len = delim === "\r\n" ? 1 : delim.length;
|
||||
|
||||
pos[0].start = pos[0].start * (2 + len);
|
||||
pos[0].end = pos[0].end * (2 + len) - len;
|
||||
|
||||
// 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
|
||||
if (delim === "0x" || delim === "\\x") {
|
||||
pos[0].start += 2;
|
||||
pos[0].end += 2;
|
||||
}
|
||||
return pos;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to hex
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFrom: function(pos, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
len = delim === "\r\n" ? 1 : delim.length,
|
||||
width = len + 2;
|
||||
|
||||
// 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
|
||||
if (delim === "0x" || delim === "\\x") {
|
||||
if (pos[0].start > 1) pos[0].start -= 2;
|
||||
else pos[0].start = 0;
|
||||
if (pos[0].end > 1) pos[0].end -= 2;
|
||||
else pos[0].end = 0;
|
||||
}
|
||||
|
||||
pos[0].start = pos[0].start === 0 ? 0 : Math.round(pos[0].start / width);
|
||||
pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / width);
|
||||
return pos;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Decimal operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToDecimal: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]];
|
||||
return input.join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Decimal operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromDecimal: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]];
|
||||
var byteStr = input.split(delim), output = [];
|
||||
if (byteStr[byteStr.length-1] === "")
|
||||
byteStr = byteStr.slice(0, byteStr.length-1);
|
||||
|
||||
for (var 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) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
output = "",
|
||||
padding = 8;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
output += Utils.pad(input[i].toString(2), padding) + 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) {
|
||||
if (args[0] !== "None") {
|
||||
var delimRegex = Utils.regexRep[args[0] || "Space"];
|
||||
input = input.replace(delimRegex, "");
|
||||
}
|
||||
|
||||
var output = [];
|
||||
var byteLen = 8;
|
||||
for (var 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) {
|
||||
var 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) {
|
||||
var 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) {
|
||||
var convert = args[0];
|
||||
var spaces = args[1];
|
||||
if (convert === "All chars") {
|
||||
var result = "|" + Utils.toHex(input) + "|";
|
||||
if (!spaces) result = result.replace(/ /g, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
var output = "",
|
||||
inHex = false,
|
||||
convertSpaces = convert === "Only special chars including spaces",
|
||||
b;
|
||||
for (var 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 += Utils.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) {
|
||||
var regex = /\|([a-f\d ]{2,})\|/gi;
|
||||
var 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
|
||||
var bytes = Utils.fromHex(m[1]);
|
||||
if (bytes) {
|
||||
for (var 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;
|
50
src/core/operations/CharEnc.js
Executable file
50
src/core/operations/CharEnc.js
Executable file
|
@ -0,0 +1,50 @@
|
|||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
|
||||
/**
|
||||
* Character encoding operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const CharEnc = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IO_FORMAT: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Windows-1251", "Hex", "Base64"],
|
||||
|
||||
/**
|
||||
* Text encoding operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run: function(input, args) {
|
||||
var inputFormat = args[0],
|
||||
outputFormat = args[1];
|
||||
|
||||
if (inputFormat === "Windows-1251") {
|
||||
input = Utils.win1251ToUnicode(input);
|
||||
input = CryptoJS.enc.Utf8.parse(input);
|
||||
} else {
|
||||
input = Utils.format[inputFormat].parse(input);
|
||||
}
|
||||
|
||||
if (outputFormat === "Windows-1251") {
|
||||
input = CryptoJS.enc.Utf8.stringify(input);
|
||||
return Utils.unicodeToWin1251(input);
|
||||
} else {
|
||||
return Utils.format[outputFormat].stringify(input);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default CharEnc;
|
195
src/core/operations/Checksum.js
Executable file
195
src/core/operations/Checksum.js
Executable file
|
@ -0,0 +1,195 @@
|
|||
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) {
|
||||
var a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var 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) {
|
||||
var a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var 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) {
|
||||
var a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var 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) {
|
||||
var a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var 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) {
|
||||
var MOD_ADLER = 65521,
|
||||
a = 1,
|
||||
b = 0;
|
||||
|
||||
for (var 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 {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCRC32: function(input, args) {
|
||||
var crcTable = global.crcTable || (global.crcTable = Checksum._genCRCTable()),
|
||||
crc = 0 ^ (-1);
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
crc = (crc >>> 8) ^ crcTable[(crc ^ input[i]) & 0xff];
|
||||
}
|
||||
|
||||
return Utils.hex((crc ^ (-1)) >>> 0);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var csum = 0;
|
||||
|
||||
for (var 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);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generates a CRC table for use with CRC checksums.
|
||||
*
|
||||
* @private
|
||||
* @returns {array}
|
||||
*/
|
||||
_genCRCTable: function() {
|
||||
var c,
|
||||
crcTable = [];
|
||||
|
||||
for (var n = 0; n < 256; n++) {
|
||||
c = n;
|
||||
for (var k = 0; k < 8; k++) {
|
||||
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
|
||||
}
|
||||
crcTable[n] = c;
|
||||
}
|
||||
|
||||
return crcTable;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Checksum;
|
661
src/core/operations/Cipher.js
Executable file
661
src/core/operations/Cipher.js
Executable file
|
@ -0,0 +1,661 @@
|
|||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
import {blowfish as Blowfish} from "sladex-blowfish";
|
||||
|
||||
|
||||
/**
|
||||
* Cipher operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Cipher = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IO_FORMAT1: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IO_FORMAT2: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Hex", "Base64"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IO_FORMAT3: ["Hex", "Base64", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IO_FORMAT4: ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Hex", "Base64"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MODES: ["CBC", "CFB", "CTR", "OFB", "ECB"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PADDING: ["Pkcs7", "Iso97971", "AnsiX923", "Iso10126", "ZeroPadding", "NoPadding"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
RESULT_TYPE: ["Show all", "Ciphertext", "Key", "IV", "Salt"],
|
||||
|
||||
|
||||
/**
|
||||
* Runs encryption operations using the CryptoJS framework.
|
||||
*
|
||||
* @private
|
||||
* @param {function} algo - The CryptoJS algorithm to use
|
||||
* @param {byteArray} input
|
||||
* @param {function} args
|
||||
* @returns {string}
|
||||
*/
|
||||
_enc: function (algo, input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || ""),
|
||||
iv = Utils.format[args[1].option].parse(args[1].string || ""),
|
||||
salt = Utils.format[args[2].option].parse(args[2].string || ""),
|
||||
mode = CryptoJS.mode[args[3]],
|
||||
padding = CryptoJS.pad[args[4]],
|
||||
resultOption = args[5].toLowerCase(),
|
||||
outputFormat = args[6];
|
||||
|
||||
if (iv.sigBytes === 0) {
|
||||
// Use passphrase rather than key. Need to convert it to a string.
|
||||
key = key.toString(CryptoJS.enc.Latin1);
|
||||
}
|
||||
|
||||
var encrypted = algo.encrypt(input, key, {
|
||||
salt: salt.sigBytes > 0 ? salt : false,
|
||||
iv: iv.sigBytes > 0 ? iv : null,
|
||||
mode: mode,
|
||||
padding: padding
|
||||
});
|
||||
|
||||
var result = "";
|
||||
if (resultOption === "show all") {
|
||||
result += "Key: " + encrypted.key.toString(Utils.format[outputFormat]);
|
||||
result += "\nIV: " + encrypted.iv.toString(Utils.format[outputFormat]);
|
||||
if (encrypted.salt) result += "\nSalt: " + encrypted.salt.toString(Utils.format[outputFormat]);
|
||||
result += "\n\nCiphertext: " + encrypted.ciphertext.toString(Utils.format[outputFormat]);
|
||||
} else {
|
||||
result = encrypted[resultOption].toString(Utils.format[outputFormat]);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Runs decryption operations using the CryptoJS framework.
|
||||
*
|
||||
* @private
|
||||
* @param {function} algo - The CryptoJS algorithm to use
|
||||
* @param {byteArray} input
|
||||
* @param {function} args
|
||||
* @returns {string}
|
||||
*/
|
||||
_dec: function (algo, input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || ""),
|
||||
iv = Utils.format[args[1].option].parse(args[1].string || ""),
|
||||
salt = Utils.format[args[2].option].parse(args[2].string || ""),
|
||||
mode = CryptoJS.mode[args[3]],
|
||||
padding = CryptoJS.pad[args[4]],
|
||||
inputFormat = args[5],
|
||||
outputFormat = args[6];
|
||||
|
||||
// The ZeroPadding option causes a crash when the input length is 0
|
||||
if (!input.length) {
|
||||
return "No input";
|
||||
}
|
||||
|
||||
var ciphertext = Utils.format[inputFormat].parse(input);
|
||||
|
||||
if (iv.sigBytes === 0) {
|
||||
// Use passphrase rather than key. Need to convert it to a string.
|
||||
key = key.toString(CryptoJS.enc.Latin1);
|
||||
}
|
||||
|
||||
var decrypted = algo.decrypt({
|
||||
ciphertext: ciphertext,
|
||||
salt: salt.sigBytes > 0 ? salt : false
|
||||
}, key, {
|
||||
iv: iv.sigBytes > 0 ? iv : null,
|
||||
mode: mode,
|
||||
padding: padding
|
||||
});
|
||||
|
||||
var result;
|
||||
try {
|
||||
result = decrypted.toString(Utils.format[outputFormat]);
|
||||
} catch (err) {
|
||||
result = "Decrypt error: " + err.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AES Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAesEnc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.AES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AES Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAesDec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.AES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* DES Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDesEnc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.DES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* DES Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDesDec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.DES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Triple DES Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTripleDesEnc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.TripleDES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Triple DES Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTripleDesDec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.TripleDES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rabbit Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRabbitEnc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.Rabbit, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rabbit Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRabbitDec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.Rabbit, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BLOWFISH_MODES: ["ECB", "CBC", "PCBC", "CFB", "OFB", "CTR"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BLOWFISH_OUTPUT_TYPES: ["Base64", "Hex", "String", "Raw"],
|
||||
|
||||
/**
|
||||
* Blowfish Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBlowfishEnc: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
|
||||
mode = args[1],
|
||||
outputFormat = args[2];
|
||||
|
||||
if (key.length === 0) return "Enter a key";
|
||||
|
||||
var encHex = Blowfish.encrypt(input, key, {
|
||||
outputType: 1,
|
||||
cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
|
||||
}),
|
||||
enc = CryptoJS.enc.Hex.parse(encHex);
|
||||
|
||||
return enc.toString(Utils.format[outputFormat]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Blowfish Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBlowfishDec: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
|
||||
mode = args[1],
|
||||
inputFormat = args[2];
|
||||
|
||||
if (key.length === 0) return "Enter a key";
|
||||
|
||||
input = Utils.format[inputFormat].parse(input);
|
||||
|
||||
return Blowfish.decrypt(input.toString(CryptoJS.enc.Base64), key, {
|
||||
outputType: 0, // This actually means inputType. The library is weird.
|
||||
cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KDF_KEY_SIZE: 256,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KDF_ITERATIONS: 1,
|
||||
|
||||
/**
|
||||
* Derive PBKDF2 key operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runPbkdf2: function (input, args) {
|
||||
var keySize = args[0] / 32,
|
||||
iterations = args[1],
|
||||
salt = CryptoJS.enc.Hex.parse(args[2] || ""),
|
||||
inputFormat = args[3],
|
||||
outputFormat = args[4],
|
||||
passphrase = Utils.format[inputFormat].parse(input),
|
||||
key = CryptoJS.PBKDF2(passphrase, salt, { keySize: keySize, iterations: iterations });
|
||||
|
||||
return key.toString(Utils.format[outputFormat]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Derive EVP key operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runEvpkdf: function (input, args) {
|
||||
var keySize = args[0] / 32,
|
||||
iterations = args[1],
|
||||
salt = CryptoJS.enc.Hex.parse(args[2] || ""),
|
||||
inputFormat = args[3],
|
||||
outputFormat = args[4],
|
||||
passphrase = Utils.format[inputFormat].parse(input),
|
||||
key = CryptoJS.EvpKDF(passphrase, salt, { keySize: keySize, iterations: iterations });
|
||||
|
||||
return key.toString(Utils.format[outputFormat]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* RC4 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRc4: function (input, args) {
|
||||
var message = Utils.format[args[1]].parse(input),
|
||||
passphrase = Utils.format[args[0].option].parse(args[0].string),
|
||||
encrypted = CryptoJS.RC4.encrypt(message, passphrase);
|
||||
|
||||
return encrypted.ciphertext.toString(Utils.format[args[2]]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
RC4DROP_BYTES: 768,
|
||||
|
||||
/**
|
||||
* RC4 Drop operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRc4drop: function (input, args) {
|
||||
var message = Utils.format[args[1]].parse(input),
|
||||
passphrase = Utils.format[args[0].option].parse(args[0].string),
|
||||
drop = args[3],
|
||||
encrypted = CryptoJS.RC4Drop.encrypt(message, passphrase, { drop: drop });
|
||||
|
||||
return encrypted.ciphertext.toString(Utils.format[args[2]]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Vigenère Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runVigenereEnc: function (input, args) {
|
||||
var alphabet = "abcdefghijklmnopqrstuvwxyz",
|
||||
key = args[0].toLowerCase(),
|
||||
output = "",
|
||||
fail = 0,
|
||||
keyIndex,
|
||||
msgIndex,
|
||||
chr;
|
||||
|
||||
if (!key) return "No key entered";
|
||||
if (!/^[a-zA-Z]+$/.test(key)) return "The key must consist only of letters";
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (alphabet.indexOf(input[i]) >= 0) {
|
||||
// Get the corresponding character of key for the current letter, accounting
|
||||
// for chars not in alphabet
|
||||
chr = key[(i - fail) % key.length];
|
||||
// Get the location in the vigenere square of the key char
|
||||
keyIndex = alphabet.indexOf(chr);
|
||||
// Get the location in the vigenere square of the message char
|
||||
msgIndex = alphabet.indexOf(input[i]);
|
||||
// Get the encoded letter by finding the sum of indexes modulo 26 and finding
|
||||
// the letter corresponding to that
|
||||
output += alphabet[(keyIndex + msgIndex) % 26];
|
||||
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
||||
chr = key[(i - fail) % key.length].toLowerCase();
|
||||
keyIndex = alphabet.indexOf(chr);
|
||||
msgIndex = alphabet.indexOf(input[i].toLowerCase());
|
||||
output += alphabet[(keyIndex + msgIndex) % 26].toUpperCase();
|
||||
} else {
|
||||
output += input[i];
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Vigenère Decode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runVigenereDec: function (input, args) {
|
||||
var alphabet = "abcdefghijklmnopqrstuvwxyz",
|
||||
key = args[0].toLowerCase(),
|
||||
output = "",
|
||||
fail = 0,
|
||||
keyIndex,
|
||||
msgIndex,
|
||||
chr;
|
||||
|
||||
if (!key) return "No key entered";
|
||||
if (!/^[a-zA-Z]+$/.test(key)) return "The key must consist only of letters";
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (alphabet.indexOf(input[i]) >= 0) {
|
||||
chr = key[(i - fail) % key.length];
|
||||
keyIndex = alphabet.indexOf(chr);
|
||||
msgIndex = alphabet.indexOf(input[i]);
|
||||
// Subtract indexes from each other, add 26 just in case the value is negative,
|
||||
// modulo to remove if neccessary
|
||||
output += alphabet[(msgIndex - keyIndex + alphabet.length) % 26];
|
||||
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
||||
chr = key[(i - fail) % key.length].toLowerCase();
|
||||
keyIndex = alphabet.indexOf(chr);
|
||||
msgIndex = alphabet.indexOf(input[i].toLowerCase());
|
||||
output += alphabet[(msgIndex + alphabet.length - keyIndex) % 26].toUpperCase();
|
||||
} else {
|
||||
output += input[i];
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
AFFINE_A: 1,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
AFFINE_B: 0,
|
||||
|
||||
/**
|
||||
* Affine Cipher Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAffineEnc: function (input, args) {
|
||||
var alphabet = "abcdefghijklmnopqrstuvwxyz",
|
||||
a = args[0],
|
||||
b = args[1],
|
||||
output = "";
|
||||
|
||||
if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
|
||||
return "The values of a and b can only be integers.";
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (alphabet.indexOf(input[i]) >= 0) {
|
||||
// Uses the affine function ax+b % m = y (where m is length of the alphabet)
|
||||
output += alphabet[((a * alphabet.indexOf(input[i])) + b) % 26];
|
||||
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
||||
// Same as above, accounting for uppercase
|
||||
output += alphabet[((a * alphabet.indexOf(input[i].toLowerCase())) + b) % 26].toUpperCase();
|
||||
} else {
|
||||
// Non-alphabetic characters
|
||||
output += input[i];
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Affine Cipher Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAffineDec: function (input, args) {
|
||||
var alphabet = "abcdefghijklmnopqrstuvwxyz",
|
||||
a = args[0],
|
||||
b = args[1],
|
||||
output = "",
|
||||
aModInv;
|
||||
|
||||
if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
|
||||
return "The values of a and b can only be integers.";
|
||||
}
|
||||
|
||||
if (Utils.gcd(a, 26) !== 1) {
|
||||
return "The value of a must be coprime to 26.";
|
||||
}
|
||||
|
||||
// Calculates modular inverse of a
|
||||
aModInv = Utils.modInv(a, 26);
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (alphabet.indexOf(input[i]) >= 0) {
|
||||
// Uses the affine decode function (y-b * A') % m = x (where m is length of the alphabet and A' is modular inverse)
|
||||
output += alphabet[Utils.mod((alphabet.indexOf(input[i]) - b) * aModInv, 26)];
|
||||
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
||||
// Same as above, accounting for uppercase
|
||||
output += alphabet[Utils.mod((alphabet.indexOf(input[i].toLowerCase()) - b) * aModInv, 26)].toUpperCase();
|
||||
} else {
|
||||
// Non-alphabetic characters
|
||||
output += input[i];
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Atbash Cipher Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAtbash: function (input, args) {
|
||||
return Cipher.runAffineEnc(input, [25, 25]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SUBS_PLAINTEXT: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SUBS_CIPHERTEXT: "XYZABCDEFGHIJKLMNOPQRSTUVW",
|
||||
|
||||
/**
|
||||
* Substitute operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runSubstitute: function (input, args) {
|
||||
var plaintext = Utils.strToByteArray(Utils.expandAlphRange(args[0]).join()),
|
||||
ciphertext = Utils.strToByteArray(Utils.expandAlphRange(args[1]).join()),
|
||||
output = [],
|
||||
index = -1;
|
||||
|
||||
if (plaintext.length !== ciphertext.length) {
|
||||
output = Utils.strToByteArray("Warning: Plaintext and Ciphertext lengths differ\n\n");
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
index = plaintext.indexOf(input[i]);
|
||||
output.push(index > -1 && index < ciphertext.length ? ciphertext[index] : input[i]);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Cipher;
|
||||
|
||||
|
||||
/**
|
||||
* Overwriting the CryptoJS OpenSSL key derivation function so that it is possible to not pass a
|
||||
* salt in.
|
||||
|
||||
* @param {string} password - The password to derive from.
|
||||
* @param {number} keySize - The size in words of the key to generate.
|
||||
* @param {number} ivSize - The size in words of the IV to generate.
|
||||
* @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be
|
||||
* generated randomly. If set to false, no salt will be added.
|
||||
*
|
||||
* @returns {CipherParams} A cipher params object with the key, IV, and salt.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
* // Randomly generates a salt
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
|
||||
* // Uses the salt 'saltsalt'
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
|
||||
* // Does not use a salt
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, false);
|
||||
*/
|
||||
CryptoJS.kdf.OpenSSL.execute = function (password, keySize, ivSize, salt) {
|
||||
// Generate random salt if no salt specified and not set to false
|
||||
// This line changed from `if (!salt) {` to the following
|
||||
if (salt === undefined || salt === null) {
|
||||
salt = CryptoJS.lib.WordArray.random(64/8);
|
||||
}
|
||||
|
||||
// Derive key and IV
|
||||
var key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
|
||||
|
||||
// Separate key and IV
|
||||
var iv = CryptoJS.lib.WordArray.create(key.words.slice(keySize), ivSize * 4);
|
||||
key.sigBytes = keySize * 4;
|
||||
|
||||
// Return params
|
||||
return CryptoJS.lib.CipherParams.create({ key: key, iv: iv, salt: salt });
|
||||
};
|
427
src/core/operations/Code.js
Executable file
427
src/core/operations/Code.js
Executable file
|
@ -0,0 +1,427 @@
|
|||
import Utils from "../Utils.js";
|
||||
import vkbeautify from "vkbeautify";
|
||||
import {DOMParser as dom} from "xmldom";
|
||||
import xpath from "xpath";
|
||||
import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js";
|
||||
|
||||
|
||||
/**
|
||||
* Code operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Code = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LANGUAGES: ["default-code", "default-markup", "bash", "bsh", "c", "cc", "coffee", "cpp", "cs", "csh", "cv", "cxx", "cyc", "htm", "html", "in.tag", "java", "javascript", "js", "json", "m", "mxml", "perl", "pl", "pm", "py", "python", "rb", "rc", "rs", "ruby", "rust", "sh", "uq.val", "xhtml", "xml", "xsl"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LINE_NUMS: false,
|
||||
|
||||
/**
|
||||
* Syntax highlighter operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runSyntaxHighlight: function(input, args) {
|
||||
var language = args[0],
|
||||
lineNums = args[1];
|
||||
return "<code class='prettyprint'>" + prettyPrintOne(Utils.escapeHtml(input), language, lineNums) + "</code>";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BEAUTIFY_INDENT: "\\t",
|
||||
|
||||
/**
|
||||
* XML Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runXmlBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
return vkbeautify.xml(input, indentStr);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* JSON Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runJsonBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
if (!input) return "";
|
||||
return vkbeautify.json(input, indentStr);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CSS Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCssBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
return vkbeautify.css(input, indentStr);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SQL Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSqlBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
return vkbeautify.sql(input, indentStr);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PRESERVE_COMMENTS: false,
|
||||
|
||||
/**
|
||||
* XML Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runXmlMinify: function(input, args) {
|
||||
var preserveComments = args[0];
|
||||
return vkbeautify.xmlmin(input, preserveComments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* JSON Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runJsonMinify: function(input, args) {
|
||||
if (!input) return "";
|
||||
return vkbeautify.jsonmin(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CSS Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCssMinify: function(input, args) {
|
||||
var preserveComments = args[0];
|
||||
return vkbeautify.cssmin(input, preserveComments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SQL Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSqlMinify: function(input, args) {
|
||||
return vkbeautify.sqlmin(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generic Code Beautify operation.
|
||||
*
|
||||
* Yeeeaaah...
|
||||
*
|
||||
* I'm not proud of this code, but seriously, try writing a generic lexer and parser that
|
||||
* correctly generates an AST for multiple different languages. I have tried, and I can tell
|
||||
* you it's pretty much impossible.
|
||||
*
|
||||
* This basically works. That'll have to be good enough. It's not meant to produce working code,
|
||||
* just slightly more readable code.
|
||||
*
|
||||
* Things that don't work:
|
||||
* - For loop formatting
|
||||
* - Do-While loop formatting
|
||||
* - Switch/Case indentation
|
||||
* - Bit shift operators
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runGenericBeautify: function(input, args) {
|
||||
var code = input,
|
||||
t = 0,
|
||||
preservedTokens = [],
|
||||
m;
|
||||
|
||||
// Remove strings
|
||||
var sstrings = /'([^'\\]|\\.)*'/g;
|
||||
while ((m = sstrings.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
sstrings.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var dstrings = /"([^"\\]|\\.)*"/g;
|
||||
while ((m = dstrings.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
dstrings.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Remove comments
|
||||
var scomments = /\/\/[^\n\r]*/g;
|
||||
while ((m = scomments.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
scomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var mcomments = /\/\*[\s\S]*?\*\//gm;
|
||||
while ((m = mcomments.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
mcomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var hcomments = /(^|\n)#[^\n\r#]+/g;
|
||||
while ((m = hcomments.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
hcomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Remove regexes
|
||||
var regexes = /\/.*?[^\\]\/[gim]{0,3}/gi;
|
||||
while ((m = regexes.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
regexes.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Create newlines after ;
|
||||
code = code.replace(/;/g, ";\n");
|
||||
|
||||
// Create newlines after { and around }
|
||||
code = code.replace(/{/g, "{\n");
|
||||
code = code.replace(/}/g, "\n}\n");
|
||||
|
||||
// Remove carriage returns
|
||||
code = code.replace(/\r/g, "");
|
||||
|
||||
// Remove all indentation
|
||||
code = code.replace(/^\s+/g, "");
|
||||
code = code.replace(/\n\s+/g, "\n");
|
||||
|
||||
// Remove trailing spaces
|
||||
code = code.replace(/\s*$/g, "");
|
||||
|
||||
// Remove newlines before {
|
||||
code = code.replace(/\n{/g, "{");
|
||||
|
||||
// Indent
|
||||
var i = 0,
|
||||
level = 0;
|
||||
while (i < code.length) {
|
||||
switch (code[i]) {
|
||||
case "{":
|
||||
level++;
|
||||
break;
|
||||
case "\n":
|
||||
if (i+1 >= code.length) break;
|
||||
|
||||
if (code[i+1] === "}") level--;
|
||||
var indent = (level >= 0) ? Array(level*4+1).join(" ") : "";
|
||||
|
||||
code = code.substring(0, i+1) + indent + code.substring(i+1);
|
||||
if (level > 0) i += level*4;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Add strategic spaces
|
||||
code = code.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ");
|
||||
code = code.replace(/\s*<([=]?)\s*/g, " <$1 ");
|
||||
code = code.replace(/\s*>([=]?)\s*/g, " >$1 ");
|
||||
code = code.replace(/([^+])\+([^+=])/g, "$1 + $2");
|
||||
code = code.replace(/([^-])-([^-=])/g, "$1 - $2");
|
||||
code = code.replace(/([^*])\*([^*=])/g, "$1 * $2");
|
||||
code = code.replace(/([^/])\/([^/=])/g, "$1 / $2");
|
||||
code = code.replace(/\s*,\s*/g, ", ");
|
||||
code = code.replace(/\s*{/g, " {");
|
||||
code = code.replace(/}\n/g, "}\n\n");
|
||||
|
||||
// Just... don't look at this
|
||||
code = code.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3");
|
||||
code = code.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3");
|
||||
code = code.replace(/else\s*\n([^{])/gim, "else\n $1");
|
||||
code = code.replace(/else\s+([^{])/gim, "else $1");
|
||||
|
||||
// Remove strategic spaces
|
||||
code = code.replace(/\s+;/g, ";");
|
||||
code = code.replace(/\{\s+\}/g, "{}");
|
||||
code = code.replace(/\[\s+\]/g, "[]");
|
||||
code = code.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
|
||||
|
||||
|
||||
// Replace preserved tokens
|
||||
var ptokens = /###preservedToken(\d+)###/g;
|
||||
while ((m = ptokens.exec(code))) {
|
||||
var ti = parseInt(m[1], 10);
|
||||
code = code.substring(0, m.index) + preservedTokens[ti] + code.substring(m.index + m[0].length);
|
||||
ptokens.lastIndex = m.index;
|
||||
}
|
||||
|
||||
return code;
|
||||
|
||||
/**
|
||||
* Replaces a matched token with a placeholder value.
|
||||
*/
|
||||
function preserveToken(str, match, t) {
|
||||
preservedTokens[t] = match[0];
|
||||
return str.substring(0, match.index) +
|
||||
"###preservedToken" + t + "###" +
|
||||
str.substring(match.index + match[0].length);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XPATH_INITIAL: "",
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XPATH_DELIMITER: "\\n",
|
||||
|
||||
/**
|
||||
* XPath expression operation.
|
||||
*
|
||||
* @author Mikescher (https://github.com/Mikescher | https://mikescher.com)
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runXpath:function(input, args) {
|
||||
var query = args[0],
|
||||
delimiter = args[1];
|
||||
|
||||
var doc;
|
||||
try {
|
||||
doc = new dom().parseFromString(input);
|
||||
} catch (err) {
|
||||
return "Invalid input XML.";
|
||||
}
|
||||
|
||||
var nodes;
|
||||
try {
|
||||
nodes = xpath.select(query, doc);
|
||||
} catch (err) {
|
||||
return "Invalid XPath. Details:\n" + err.message;
|
||||
}
|
||||
|
||||
var nodeToString = function(node) {
|
||||
return node.toString();
|
||||
};
|
||||
|
||||
return nodes.map(nodeToString).join(delimiter);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CSS_SELECTOR_INITIAL: "",
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CSS_QUERY_DELIMITER: "\\n",
|
||||
|
||||
/**
|
||||
* CSS selector operation.
|
||||
*
|
||||
* @author Mikescher (https://github.com/Mikescher | https://mikescher.com)
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCSSQuery: function(input, args) {
|
||||
var query = args[0],
|
||||
delimiter = args[1],
|
||||
parser = new DOMParser(),
|
||||
html,
|
||||
result;
|
||||
|
||||
if (!query.length || !input.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
html = parser.parseFromString(input, "text/html");
|
||||
} catch (err) {
|
||||
return "Invalid input HTML.";
|
||||
}
|
||||
|
||||
try {
|
||||
result = html.querySelectorAll(query);
|
||||
} catch (err) {
|
||||
return "Invalid CSS Selector. Details:\n" + err.message;
|
||||
}
|
||||
|
||||
var nodeToString = function(node) {
|
||||
switch (node.nodeType) {
|
||||
case Node.ELEMENT_NODE: return node.outerHTML;
|
||||
case Node.ATTRIBUTE_NODE: return node.value;
|
||||
case Node.COMMENT_NODE: return node.data;
|
||||
case Node.TEXT_NODE: return node.wholeText;
|
||||
case Node.DOCUMENT_NODE: return node.outerHTML;
|
||||
default: throw new Error("Unknown Node Type: " + node.nodeType);
|
||||
}
|
||||
};
|
||||
|
||||
return Array.apply(null, Array(result.length))
|
||||
.map(function(_, i) {
|
||||
return result[i];
|
||||
})
|
||||
.map(nodeToString)
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Code;
|
578
src/core/operations/Compress.js
Executable file
578
src/core/operations/Compress.js
Executable file
|
@ -0,0 +1,578 @@
|
|||
import Utils from "../Utils.js";
|
||||
import rawdeflate from "zlibjs/bin/rawdeflate.min";
|
||||
import rawinflate from "zlibjs/bin/rawinflate.min";
|
||||
import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min";
|
||||
import zip from "zlibjs/bin/zip.min";
|
||||
import unzip from "zlibjs/bin/unzip.min";
|
||||
import bzip2 from "exports-loader?bzip2!../lib/bzip2.js";
|
||||
|
||||
var Zlib = {
|
||||
RawDeflate: rawdeflate.Zlib.RawDeflate,
|
||||
RawInflate: rawinflate.Zlib.RawInflate,
|
||||
Deflate: zlibAndGzip.Zlib.Deflate,
|
||||
Inflate: zlibAndGzip.Zlib.Inflate,
|
||||
Gzip: zlibAndGzip.Zlib.Gzip,
|
||||
Gunzip: zlibAndGzip.Zlib.Gunzip,
|
||||
Zip: zip.Zlib.Zip,
|
||||
Unzip: unzip.Zlib.Unzip,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compression operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Compress = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
COMPRESSION_TYPE: ["Dynamic Huffman Coding", "Fixed Huffman Coding", "None (Store)"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INFLATE_BUFFER_TYPE: ["Adaptive", "Block"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
COMPRESSION_METHOD: ["Deflate", "None (Store)"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OS: ["MSDOS", "Unix", "Macintosh"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
RAW_COMPRESSION_TYPE_LOOKUP: {
|
||||
"Fixed Huffman Coding" : Zlib.RawDeflate.CompressionType.FIXED,
|
||||
"Dynamic Huffman Coding" : Zlib.RawDeflate.CompressionType.DYNAMIC,
|
||||
"None (Store)" : Zlib.RawDeflate.CompressionType.NONE,
|
||||
},
|
||||
|
||||
/**
|
||||
* Raw Deflate operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRawDeflate: function(input, args) {
|
||||
var deflate = new Zlib.RawDeflate(input, {
|
||||
compressionType: Compress.RAW_COMPRESSION_TYPE_LOOKUP[args[0]]
|
||||
});
|
||||
return Array.prototype.slice.call(deflate.compress());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INFLATE_INDEX: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INFLATE_BUFFER_SIZE: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INFLATE_RESIZE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INFLATE_VERIFY: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
RAW_BUFFER_TYPE_LOOKUP: {
|
||||
"Adaptive" : Zlib.RawInflate.BufferType.ADAPTIVE,
|
||||
"Block" : Zlib.RawInflate.BufferType.BLOCK,
|
||||
},
|
||||
|
||||
/**
|
||||
* Raw Inflate operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRawInflate: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.strToByteArray(Utils.byteArrayToUtf8(input));
|
||||
var inflate = new Zlib.RawInflate(input, {
|
||||
index: args[0],
|
||||
bufferSize: args[1],
|
||||
bufferType: Compress.RAW_BUFFER_TYPE_LOOKUP[args[2]],
|
||||
resize: args[3],
|
||||
verify: args[4]
|
||||
}),
|
||||
result = Array.prototype.slice.call(inflate.decompress());
|
||||
|
||||
// Raw Inflate somethimes messes up and returns nonsense like this:
|
||||
// ]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]...
|
||||
// e.g. Input data of [8b, 1d, dc, 44]
|
||||
// Look for the first two square brackets:
|
||||
if (result.length > 158 && result[0] === 93 && result[5] === 93) {
|
||||
// If the first two square brackets are there, check that the others
|
||||
// are also there. If they are, throw an error. If not, continue.
|
||||
var valid = false;
|
||||
for (var i = 0; i < 155; i += 5) {
|
||||
if (result[i] !== 93) {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
throw "Error: Unable to inflate data";
|
||||
}
|
||||
}
|
||||
// Trust me, this is the easiest way...
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ZLIB_COMPRESSION_TYPE_LOOKUP: {
|
||||
"Fixed Huffman Coding" : Zlib.Deflate.CompressionType.FIXED,
|
||||
"Dynamic Huffman Coding" : Zlib.Deflate.CompressionType.DYNAMIC,
|
||||
"None (Store)" : Zlib.Deflate.CompressionType.NONE,
|
||||
},
|
||||
|
||||
/**
|
||||
* Zlib Deflate operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runZlibDeflate: function(input, args) {
|
||||
var deflate = new Zlib.Deflate(input, {
|
||||
compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]]
|
||||
});
|
||||
return Array.prototype.slice.call(deflate.compress());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ZLIB_BUFFER_TYPE_LOOKUP: {
|
||||
"Adaptive" : Zlib.Inflate.BufferType.ADAPTIVE,
|
||||
"Block" : Zlib.Inflate.BufferType.BLOCK,
|
||||
},
|
||||
|
||||
/**
|
||||
* Zlib Inflate operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runZlibInflate: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.strToByteArray(Utils.byteArrayToUtf8(input));
|
||||
var inflate = new Zlib.Inflate(input, {
|
||||
index: args[0],
|
||||
bufferSize: args[1],
|
||||
bufferType: Compress.ZLIB_BUFFER_TYPE_LOOKUP[args[2]],
|
||||
resize: args[3],
|
||||
verify: args[4]
|
||||
});
|
||||
return Array.prototype.slice.call(inflate.decompress());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
GZIP_CHECKSUM: false,
|
||||
|
||||
/**
|
||||
* Gzip operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runGzip: function(input, args) {
|
||||
var filename = args[1],
|
||||
comment = args[2],
|
||||
options = {
|
||||
deflateOptions: {
|
||||
compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]]
|
||||
},
|
||||
flags: {
|
||||
fhcrc: args[3]
|
||||
}
|
||||
};
|
||||
|
||||
if (filename.length) {
|
||||
options.flags.fname = true;
|
||||
options.filename = filename;
|
||||
}
|
||||
if (comment.length) {
|
||||
options.flags.fcommenct = true;
|
||||
options.comment = comment;
|
||||
}
|
||||
|
||||
var gzip = new Zlib.Gzip(input, options);
|
||||
return Array.prototype.slice.call(gzip.compress());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Gunzip operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runGunzip: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.strToByteArray(Utils.byteArrayToUtf8(input));
|
||||
var gunzip = new Zlib.Gunzip(input);
|
||||
return Array.prototype.slice.call(gunzip.decompress());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PKZIP_FILENAME: "file.txt",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ZIP_COMPRESSION_METHOD_LOOKUP: {
|
||||
"Deflate" : Zlib.Zip.CompressionMethod.DEFLATE,
|
||||
"None (Store)" : Zlib.Zip.CompressionMethod.STORE
|
||||
},
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ZIP_OS_LOOKUP: {
|
||||
"MSDOS" : Zlib.Zip.OperatingSystem.MSDOS,
|
||||
"Unix" : Zlib.Zip.OperatingSystem.UNIX,
|
||||
"Macintosh" : Zlib.Zip.OperatingSystem.MACINTOSH
|
||||
},
|
||||
|
||||
/**
|
||||
* Zip operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runPkzip: function(input, args) {
|
||||
var password = Utils.strToByteArray(args[2]),
|
||||
options = {
|
||||
filename: Utils.strToByteArray(args[0]),
|
||||
comment: Utils.strToByteArray(args[1]),
|
||||
compressionMethod: Compress.ZIP_COMPRESSION_METHOD_LOOKUP[args[3]],
|
||||
os: Compress.ZIP_OS_LOOKUP[args[4]],
|
||||
deflateOption: {
|
||||
compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[5]]
|
||||
},
|
||||
},
|
||||
zip = new Zlib.Zip();
|
||||
|
||||
if (password.length)
|
||||
zip.setPassword(password);
|
||||
zip.addFile(input, options);
|
||||
return Array.prototype.slice.call(zip.compress());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PKUNZIP_VERIFY: false,
|
||||
|
||||
/**
|
||||
* Unzip operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runPkunzip: function(input, args) {
|
||||
var options = {
|
||||
password: Utils.strToByteArray(args[0]),
|
||||
verify: args[1]
|
||||
},
|
||||
unzip = new Zlib.Unzip(input, options),
|
||||
filenames = unzip.getFilenames(),
|
||||
files = [];
|
||||
|
||||
filenames.forEach(function(fileName) {
|
||||
var bytes = unzip.decompress(fileName);
|
||||
var contents = Utils.byteArrayToUtf8(bytes);
|
||||
|
||||
var file = {
|
||||
fileName: fileName,
|
||||
size: contents.length,
|
||||
};
|
||||
|
||||
var isDir = contents.length === 0 && fileName.endsWith("/");
|
||||
if (!isDir) {
|
||||
file.bytes = bytes;
|
||||
file.contents = contents;
|
||||
}
|
||||
|
||||
files.push(file);
|
||||
});
|
||||
|
||||
return Utils.displayFilesAsHTML(files);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Bzip2 Decompress operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBzip2Decompress: function(input, args) {
|
||||
var 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) {
|
||||
var Tarball = function() {
|
||||
this.bytes = new Array(512);
|
||||
this.position = 0;
|
||||
};
|
||||
|
||||
Tarball.prototype.addEmptyBlock = function() {
|
||||
var filler = new Array(512);
|
||||
filler.fill(0);
|
||||
this.bytes = this.bytes.concat(filler);
|
||||
};
|
||||
|
||||
Tarball.prototype.writeBytes = function(bytes) {
|
||||
var 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() {
|
||||
var numEmptyBlocks = 2;
|
||||
for (var i = 0; i < numEmptyBlocks; i++) {
|
||||
this.addEmptyBlock();
|
||||
}
|
||||
};
|
||||
|
||||
var fileSize = Utils.padLeft(input.length.toString(8), 11, "0");
|
||||
var currentUnixTimestamp = Math.floor(Date.now() / 1000);
|
||||
var lastModTime = Utils.padLeft(currentUnixTimestamp.toString(8), 11, "0");
|
||||
|
||||
var 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),
|
||||
};
|
||||
|
||||
var checksum = 0;
|
||||
for (var key in file) {
|
||||
var bytes = file[key];
|
||||
Array.prototype.forEach.call(bytes, function(b) {
|
||||
if (typeof b.charCodeAt !== "undefined") {
|
||||
checksum += b.charCodeAt();
|
||||
} else {
|
||||
checksum += b;
|
||||
}
|
||||
});
|
||||
}
|
||||
checksum = Utils.padBytesRight(Utils.padLeft(checksum.toString(8), 7, "0"), 8);
|
||||
file.checksum = checksum;
|
||||
|
||||
var 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) {
|
||||
var Stream = function(input) {
|
||||
this.bytes = input;
|
||||
this.position = 0;
|
||||
};
|
||||
|
||||
Stream.prototype.getBytes = function(bytesToGet) {
|
||||
var newPosition = this.position + bytesToGet;
|
||||
var bytes = this.bytes.slice(this.position, newPosition);
|
||||
this.position = newPosition;
|
||||
return bytes;
|
||||
};
|
||||
|
||||
Stream.prototype.readString = function(numBytes) {
|
||||
var result = "";
|
||||
for (var i = this.position; i < this.position + numBytes; i++) {
|
||||
var currentByte = this.bytes[i];
|
||||
if (currentByte === 0) break;
|
||||
result += String.fromCharCode(currentByte);
|
||||
}
|
||||
this.position += numBytes;
|
||||
return result;
|
||||
};
|
||||
|
||||
Stream.prototype.readInt = function(numBytes, base) {
|
||||
var string = this.readString(numBytes);
|
||||
return parseInt(string, base);
|
||||
};
|
||||
|
||||
Stream.prototype.hasMore = function() {
|
||||
return this.position < this.bytes.length;
|
||||
};
|
||||
|
||||
var stream = new Stream(input),
|
||||
files = [];
|
||||
|
||||
while (stream.hasMore()) {
|
||||
var dataPosition = stream.position + 512;
|
||||
|
||||
var 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);
|
||||
var 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;
|
414
src/core/operations/Convert.js
Executable file
414
src/core/operations/Convert.js
Executable file
|
@ -0,0 +1,414 @@
|
|||
/**
|
||||
* 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 {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runDistance: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.DISTANCE_FACTOR[inputUnits];
|
||||
return input / Convert.DISTANCE_FACTOR[outputUnits];
|
||||
// TODO Remove rounding errors (e.g. 1.000000000001)
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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 {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runDataSize: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.DATA_FACTOR[inputUnits];
|
||||
return input / 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 {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runArea: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.AREA_FACTOR[inputUnits];
|
||||
return input / 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 {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runMass: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.MASS_FACTOR[inputUnits];
|
||||
return input / 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 {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runSpeed: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.SPEED_FACTOR[inputUnits];
|
||||
return input / Convert.SPEED_FACTOR[outputUnits];
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Convert;
|
453
src/core/operations/DateTime.js
Executable file
453
src/core/operations/DateTime.js
Executable file
|
@ -0,0 +1,453 @@
|
|||
/**
|
||||
* 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) {
|
||||
var 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";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To UNIX Timestamp operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runToUnixTimestamp: function(input, args) {
|
||||
var units = args[0],
|
||||
d = moment(input);
|
||||
|
||||
if (units === "Seconds (s)") {
|
||||
return d.unix();
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
return d.valueOf();
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
return d.valueOf() * 1000;
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
return d.valueOf() * 1000000;
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
var 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) {
|
||||
var 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;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
*/
|
||||
FORMAT_EXAMPLES: "Format string tokens:\n\n\
|
||||
<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;
|
99
src/core/operations/Endian.js
Executable file
99
src/core/operations/Endian.js
Executable file
|
@ -0,0 +1,99 @@
|
|||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var 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 = Utils.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) {
|
||||
var 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 Utils.toHex(result);
|
||||
case "Raw":
|
||||
return Utils.byteArrayToUtf8(result);
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Endian;
|
171
src/core/operations/Entropy.js
Executable file
171
src/core/operations/Entropy.js
Executable file
|
@ -0,0 +1,171 @@
|
|||
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) {
|
||||
var 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>";
|
||||
|
||||
var chunkEntropy = 0;
|
||||
if (chunkSize !== 0) {
|
||||
for (var 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 {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runFreqDistrib: function (input, args) {
|
||||
if (!input.length) return "No data";
|
||||
|
||||
var distrib = new Array(256),
|
||||
percentages = new Array(256),
|
||||
len = input.length,
|
||||
showZeroes = args[0];
|
||||
|
||||
// Initialise distrib to 0
|
||||
for (var i = 0; i < 256; i++) {
|
||||
distrib[i] = 0;
|
||||
}
|
||||
|
||||
// Count bytes
|
||||
for (i = 0; i < len; i++) {
|
||||
distrib[input[i]]++;
|
||||
}
|
||||
|
||||
// Calculate percentages
|
||||
var repr = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (distrib[i] > 0) repr++;
|
||||
percentages[i] = distrib[i] / len * 100;
|
||||
}
|
||||
|
||||
// Print
|
||||
var 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) + " (" +
|
||||
Utils.padRight(percentages[i].toFixed(2).replace(".00", "") + "%)", 8) +
|
||||
Array(Math.ceil(percentages[i])+1).join("|") + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Shannon entropy for a given chunk of data.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} data
|
||||
* @returns {number}
|
||||
*/
|
||||
_calcEntropy: function(data) {
|
||||
var prob = [],
|
||||
uniques = data.unique(),
|
||||
str = Utils.byteArrayToChars(data);
|
||||
|
||||
for (var i = 0; i < uniques.length; i++) {
|
||||
prob.push(str.count(Utils.chr(uniques[i])) / data.length);
|
||||
}
|
||||
|
||||
var 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;
|
299
src/core/operations/Extract.js
Executable file
299
src/core/operations/Extract.js
Executable file
|
@ -0,0 +1,299 @@
|
|||
/**
|
||||
* Identifier extraction operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Extract = {
|
||||
|
||||
/**
|
||||
* Runs search operations across the input data using regular expressions.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} searchRegex
|
||||
* @param {RegExp} removeRegex - A regular expression defining results to remove from the
|
||||
* final list
|
||||
* @param {boolean} includeTotal - Whether or not to include the total number of results
|
||||
* @returns {string}
|
||||
*/
|
||||
_search: function(input, searchRegex, removeRegex, includeTotal) {
|
||||
var output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = searchRegex.exec(input))) {
|
||||
if (removeRegex && removeRegex.test(match[0]))
|
||||
continue;
|
||||
total++;
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
|
||||
if (includeTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MIN_STRING_LEN: 3,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISPLAY_TOTAL: false,
|
||||
|
||||
/**
|
||||
* Strings operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runStrings: function(input, args) {
|
||||
var minLen = args[0] || Extract.MIN_STRING_LEN,
|
||||
displayTotal = args[1],
|
||||
strings = "[A-Z\\d/\\-:.,_$%'\"()<>= !\\[\\]{}@]",
|
||||
regex = new RegExp(strings + "{" + minLen + ",}", "ig");
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_IPV4: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_IPV6: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_LOCAL: false,
|
||||
|
||||
/**
|
||||
* Extract IP addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runIp: function(input, args) {
|
||||
var includeIpv4 = args[0],
|
||||
includeIpv6 = args[1],
|
||||
removeLocal = args[2],
|
||||
displayTotal = args[3],
|
||||
ipv4 = "(?:(?:\\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})?",
|
||||
ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})((([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})",
|
||||
ips = "";
|
||||
|
||||
if (includeIpv4 && includeIpv6) {
|
||||
ips = ipv4 + "|" + ipv6;
|
||||
} else if (includeIpv4) {
|
||||
ips = ipv4;
|
||||
} else if (includeIpv6) {
|
||||
ips = ipv6;
|
||||
}
|
||||
|
||||
if (ips) {
|
||||
var regex = new RegExp(ips, "ig");
|
||||
|
||||
if (removeLocal) {
|
||||
var ten = "10\\..+",
|
||||
oneninetwo = "192\\.168\\..+",
|
||||
oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
|
||||
onetwoseven = "127\\..+",
|
||||
removeRegex = new RegExp("^(?:" + ten + "|" + oneninetwo +
|
||||
"|" + oneseventwo + "|" + onetwoseven + ")");
|
||||
|
||||
return Extract._search(input, regex, removeRegex, displayTotal);
|
||||
} else {
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract email addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runEmail: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
regex = /\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}/ig;
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract MAC addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMac: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig;
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract URLs operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runUrls: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
protocol = "[A-Z]+://",
|
||||
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
||||
port = ":\\d+",
|
||||
path = "/[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]*";
|
||||
|
||||
path += "(?:[.!,?]+[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||
var regex = new RegExp(protocol + hostname + "(?:" + port +
|
||||
")?(?:" + path + ")?", "ig");
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract domains operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDomains: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
protocol = "https?://",
|
||||
hostname = "[-\\w\\.]+",
|
||||
tld = "\\.(?:com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+",
|
||||
regex = new RegExp("(?:" + protocol + ")?" + hostname + tld, "ig");
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_WIN_PATH: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_UNIX_PATH: true,
|
||||
|
||||
/**
|
||||
* Extract file paths operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFilePaths: function(input, args) {
|
||||
var includeWinPath = args[0],
|
||||
includeUnixPath = args[1],
|
||||
displayTotal = args[2],
|
||||
winDrive = "[A-Z]:\\\\",
|
||||
winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)]{0,61}",
|
||||
winExt = "[A-Z\\d]{1,6}",
|
||||
winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName +
|
||||
"(?:\\." + winExt + ")?",
|
||||
unixPath = "(?:/[A-Z\\d.][A-Z\\d\\-.]{0,61})+",
|
||||
filePaths = "";
|
||||
|
||||
if (includeWinPath && includeUnixPath) {
|
||||
filePaths = winPath + "|" + unixPath;
|
||||
} else if (includeWinPath) {
|
||||
filePaths = winPath;
|
||||
} else if (includeUnixPath) {
|
||||
filePaths = unixPath;
|
||||
}
|
||||
|
||||
if (filePaths) {
|
||||
var regex = new RegExp(filePaths, "ig");
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract dates operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDates: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
date1 = "(?:19|20)\\d\\d[- /.](?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])", // yyyy-mm-dd
|
||||
date2 = "(?:0[1-9]|[12][0-9]|3[01])[- /.](?:0[1-9]|1[012])[- /.](?:19|20)\\d\\d", // dd/mm/yyyy
|
||||
date3 = "(?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])[- /.](?:19|20)\\d\\d", // mm/dd/yyyy
|
||||
regex = new RegExp(date1 + "|" + date2 + "|" + date3, "ig");
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract all identifiers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAllIdents: function(input, args) {
|
||||
var output = "";
|
||||
output += "IP addresses\n";
|
||||
output += Extract.runIp(input, [true, true, false]);
|
||||
|
||||
output += "\nEmail addresses\n";
|
||||
output += Extract.runEmail(input, []);
|
||||
|
||||
output += "\nMAC addresses\n";
|
||||
output += Extract.runMac(input, []);
|
||||
|
||||
output += "\nURLs\n";
|
||||
output += Extract.runUrls(input, []);
|
||||
|
||||
output += "\nDomain names\n";
|
||||
output += Extract.runDomains(input, []);
|
||||
|
||||
output += "\nFile paths\n";
|
||||
output += Extract.runFilePaths(input, [true, true]);
|
||||
|
||||
output += "\nDates\n";
|
||||
output += Extract.runDates(input, []);
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Extract;
|
531
src/core/operations/FileType.js
Executable file
531
src/core/operations/FileType.js
Executable file
|
@ -0,0 +1,531 @@
|
|||
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 {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDetect: function(input, args) {
|
||||
var type = FileType._magicType(input);
|
||||
|
||||
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 {
|
||||
var 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 {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runScanForEmbeddedFiles: function(input, args) {
|
||||
var 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,
|
||||
ignoreCommon = args[0],
|
||||
commonExts = ["ico", "ttf", ""],
|
||||
numFound = 0,
|
||||
numCommonFound = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
type = FileType._magicType(input.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.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} 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",
|
||||
mime: "application/x-apple-diskimage"
|
||||
};
|
||||
}
|
||||
|
||||
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: "",
|
||||
mime: "",
|
||||
desc: "Little-endian UTF-32 encoded Unicode byte order mark detected."
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xFF && buf[1] === 0xFE) {
|
||||
return {
|
||||
ext: "",
|
||||
mime: "",
|
||||
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"
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default FileType;
|
855
src/core/operations/HTML.js
Executable file
855
src/core/operations/HTML.js
Executable file
|
@ -0,0 +1,855 @@
|
|||
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) {
|
||||
var convertAll = args[0],
|
||||
numeric = args[1] === "Numeric entities",
|
||||
hexa = args[1] === "Hex entities";
|
||||
|
||||
var charcodes = Utils.strToCharcode(input);
|
||||
var output = "";
|
||||
|
||||
for (var 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) {
|
||||
var 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
|
||||
var bite = HTML._entityToByte[m[1]];
|
||||
if (bite) {
|
||||
output += Utils.chr(bite);
|
||||
} else if (!bite && m[1][0] === "#" && m[1].length > 1 && /^#\d{1,5}$/.test(m[1])) {
|
||||
// Numeric entity (e.g. )
|
||||
var 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. :)
|
||||
var 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) {
|
||||
var 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) {
|
||||
var 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)
|
||||
var 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)
|
||||
var 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_));
|
||||
}
|
||||
|
||||
var 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),
|
||||
m = (1 - g/255 - k) / (1 - k), // eslint-disable-line no-redeclare
|
||||
y = (1 - b/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);
|
||||
|
||||
var hex = "#" +
|
||||
Utils.padLeft(Math.round(r).toString(16), 2) +
|
||||
Utils.padLeft(Math.round(g).toString(16), 2) +
|
||||
Utils.padLeft(Math.round(b).toString(16), 2),
|
||||
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 + "\n" +
|
||||
"RGB: " + rgb + "\n" +
|
||||
"RGBA: " + rgba + "\n" +
|
||||
"HSL: " + hsl + "\n" +
|
||||
"HSLA: " + hsla + "\n" +
|
||||
"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){
|
||||
var r, g, b;
|
||||
|
||||
if (s === 0){
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
var 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;
|
||||
};
|
||||
|
||||
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
var 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;
|
||||
var 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 {
|
||||
var 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;
|
56
src/core/operations/HTTP.js
Executable file
56
src/core/operations/HTTP.js
Executable file
|
@ -0,0 +1,56 @@
|
|||
import {UAS_parser as UAParser} from "../lib/uas_parser.js";
|
||||
|
||||
|
||||
/**
|
||||
* HTTP operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const HTTP = {
|
||||
|
||||
/**
|
||||
* Strip HTTP headers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runStripHeaders: function(input, args) {
|
||||
var 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) {
|
||||
var ua = UAParser.parse(input);
|
||||
|
||||
return "Type: " + ua.type + "\n" +
|
||||
"Family: " + ua.uaFamily + "\n" +
|
||||
"Name: " + ua.uaName + "\n" +
|
||||
"URL: " + ua.uaUrl + "\n" +
|
||||
"Company: " + ua.uaCompany + "\n" +
|
||||
"Company URL: " + ua.uaCompanyUrl + "\n\n" +
|
||||
"OS Family: " + ua.osFamily + "\n" +
|
||||
"OS Name: " + ua.osName + "\n" +
|
||||
"OS URL: " + ua.osUrl + "\n" +
|
||||
"OS Company: " + ua.osCompany + "\n" +
|
||||
"OS Company URL: " + ua.osCompanyUrl + "\n" +
|
||||
"Device Type: " + ua.deviceType + "\n";
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default HTTP;
|
389
src/core/operations/Hash.js
Executable file
389
src/core/operations/Hash.js
Executable file
|
@ -0,0 +1,389 @@
|
|||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
import CryptoApi from "crypto-api";
|
||||
import Checksum from "./Checksum.js";
|
||||
|
||||
|
||||
/**
|
||||
* Hashing operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Hash = {
|
||||
|
||||
/**
|
||||
* MD2 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD2: function (input, args) {
|
||||
return Utils.toHexFast(CryptoApi.hash("md2", input, {}));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD4 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD4: function (input, args) {
|
||||
return Utils.toHexFast(CryptoApi.hash("md4", input, {}));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD5 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD5: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray
|
||||
return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA0 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA0: function (input, args) {
|
||||
return Utils.toHexFast(CryptoApi.hash("sha0", input, {}));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA1 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA1: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA1(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA224 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA224: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA224(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA256 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA256: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA256(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA384 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA384: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA384(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA512 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA512: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA512(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHA3_LENGTH: ["512", "384", "256", "224"],
|
||||
|
||||
/**
|
||||
* SHA3 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA3: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
var sha3Length = args[0],
|
||||
options = {
|
||||
outputLength: parseInt(sha3Length, 10)
|
||||
};
|
||||
return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* RIPEMD-160 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRIPEMD160: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.RIPEMD160(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HMAC_FUNCTIONS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD-160"],
|
||||
|
||||
/**
|
||||
* HMAC operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHMAC: function (input, args) {
|
||||
var hashFunc = args[1];
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
var execute = {
|
||||
"MD5": CryptoJS.HmacMD5(input, args[0]),
|
||||
"SHA1": CryptoJS.HmacSHA1(input, args[0]),
|
||||
"SHA224": CryptoJS.HmacSHA224(input, args[0]),
|
||||
"SHA256": CryptoJS.HmacSHA256(input, args[0]),
|
||||
"SHA384": CryptoJS.HmacSHA384(input, args[0]),
|
||||
"SHA512": CryptoJS.HmacSHA512(input, args[0]),
|
||||
"SHA3": CryptoJS.HmacSHA3(input, args[0]),
|
||||
"RIPEMD-160": CryptoJS.HmacRIPEMD160(input, args[0]),
|
||||
};
|
||||
return execute[hashFunc].toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generate all hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAll: function (input, args) {
|
||||
var byteArray = Utils.strToByteArray(input),
|
||||
output = "MD2: " + Hash.runMD2(input, []) +
|
||||
"\nMD4: " + Hash.runMD4(input, []) +
|
||||
"\nMD5: " + Hash.runMD5(input, []) +
|
||||
"\nSHA0: " + Hash.runSHA0(input, []) +
|
||||
"\nSHA1: " + Hash.runSHA1(input, []) +
|
||||
"\nSHA2 224: " + Hash.runSHA224(input, []) +
|
||||
"\nSHA2 256: " + Hash.runSHA256(input, []) +
|
||||
"\nSHA2 384: " + Hash.runSHA384(input, []) +
|
||||
"\nSHA2 512: " + Hash.runSHA512(input, []) +
|
||||
"\nSHA3 224: " + Hash.runSHA3(input, ["224"]) +
|
||||
"\nSHA3 256: " + Hash.runSHA3(input, ["256"]) +
|
||||
"\nSHA3 384: " + Hash.runSHA3(input, ["384"]) +
|
||||
"\nSHA3 512: " + Hash.runSHA3(input, ["512"]) +
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD160(input, []) +
|
||||
"\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-32: " + Checksum.runCRC32(byteArray, []);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Analyse hash operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAnalyse: function(input, args) {
|
||||
input = input.replace(/\s/g, "");
|
||||
|
||||
var 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;
|
202
src/core/operations/Hexdump.js
Executable file
202
src/core/operations/Hexdump.js
Executable file
|
@ -0,0 +1,202 @@
|
|||
/* globals app */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* 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 {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var length = args[0] || Hexdump.WIDTH;
|
||||
var upperCase = args[1];
|
||||
var includeFinalLength = args[2];
|
||||
|
||||
var output = "", padding = 2;
|
||||
for (var i = 0; i < input.length; i += length) {
|
||||
var buff = input.slice(i, i+length);
|
||||
var hexa = "";
|
||||
for (var j = 0; j < buff.length; j++) {
|
||||
hexa += Utils.hex(buff[j], padding) + " ";
|
||||
}
|
||||
|
||||
var lineNo = Utils.hex(i, 8);
|
||||
|
||||
if (upperCase) {
|
||||
hexa = hexa.toUpperCase();
|
||||
lineNo = lineNo.toUpperCase();
|
||||
}
|
||||
|
||||
output += lineNo + " " +
|
||||
Utils.padRight(hexa, (length*(padding+1))) +
|
||||
" |" + Utils.padRight(Utils.printable(Utils.byteArrayToChars(buff)), buff.length) + "|\n";
|
||||
|
||||
if (includeFinalLength && i+buff.length === input.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) {
|
||||
var output = [],
|
||||
regex = /^\s*(?:[\dA-F]{4,16}:?)?\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 = Utils.fromHex(block[1].replace(/-/g, " "));
|
||||
for (var i = 0; i < line.length; i++) {
|
||||
output.push(line[i]);
|
||||
}
|
||||
}
|
||||
// Is this a CyberChef hexdump or is it from a different tool?
|
||||
var width = input.indexOf("\n");
|
||||
var 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 (app) app.options.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
|
||||
var 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
|
||||
var startLineNum = Math.floor(pos[0].start / width);
|
||||
var 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
|
||||
var len = pos.length, lineNum = 0;
|
||||
start = 0;
|
||||
end = 0;
|
||||
for (var 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) {
|
||||
var w = args[0] || 16;
|
||||
var width = 14 + (w*4);
|
||||
|
||||
var line = Math.floor(pos[0].start / width);
|
||||
var 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;
|
1081
src/core/operations/IP.js
Executable file
1081
src/core/operations/IP.js
Executable file
File diff suppressed because it is too large
Load diff
164
src/core/operations/JS.js
Executable file
164
src/core/operations/JS.js
Executable file
|
@ -0,0 +1,164 @@
|
|||
import esprima from "esprima";
|
||||
import escodegen from "escodegen";
|
||||
import esmangle from "esmangle";
|
||||
|
||||
|
||||
/**
|
||||
* JavaScript operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const JS = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PARSE_LOC: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PARSE_RANGE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PARSE_TOKENS: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PARSE_COMMENT: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PARSE_TOLERANT: false,
|
||||
|
||||
/**
|
||||
* JavaScript Parser operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParse: function (input, args) {
|
||||
var parseLoc = args[0],
|
||||
parseRange = args[1],
|
||||
parseTokens = args[2],
|
||||
parseComment = args[3],
|
||||
parseTolerant = args[4],
|
||||
result = {},
|
||||
options = {
|
||||
loc: parseLoc,
|
||||
range: parseRange,
|
||||
tokens: parseTokens,
|
||||
comment: parseComment,
|
||||
tolerant: parseTolerant
|
||||
};
|
||||
|
||||
result = esprima.parse(input, options);
|
||||
return JSON.stringify(result, null, 2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BEAUTIFY_INDENT: "\\t",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BEAUTIFY_QUOTES: ["Auto", "Single", "Double"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BEAUTIFY_SEMICOLONS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BEAUTIFY_COMMENT: true,
|
||||
|
||||
/**
|
||||
* JavaScript Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBeautify: function(input, args) {
|
||||
var beautifyIndent = args[0] || JS.BEAUTIFY_INDENT,
|
||||
quotes = args[1].toLowerCase(),
|
||||
beautifySemicolons = args[2],
|
||||
beautifyComment = args[3],
|
||||
result = "",
|
||||
AST;
|
||||
|
||||
try {
|
||||
AST = esprima.parse(input, {
|
||||
range: true,
|
||||
tokens: true,
|
||||
comment: true
|
||||
});
|
||||
|
||||
var options = {
|
||||
format: {
|
||||
indent: {
|
||||
style: beautifyIndent
|
||||
},
|
||||
quotes: quotes,
|
||||
semicolons: beautifySemicolons,
|
||||
},
|
||||
comment: beautifyComment
|
||||
};
|
||||
|
||||
if (options.comment)
|
||||
AST = escodegen.attachComments(AST, AST.comments, AST.tokens);
|
||||
|
||||
result = escodegen.generate(AST, options);
|
||||
} catch (e) {
|
||||
// Leave original error so the user can see the detail
|
||||
throw "Unable to parse JavaScript.<br>" + e.message;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* JavaScript Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMinify: function(input, args) {
|
||||
var result = "",
|
||||
AST = esprima.parse(input),
|
||||
optimisedAST = esmangle.optimize(AST, null),
|
||||
mangledAST = esmangle.mangle(optimisedAST);
|
||||
|
||||
result = escodegen.generate(mangledAST, {
|
||||
format: {
|
||||
renumber: true,
|
||||
hexadecimal: true,
|
||||
escapeless: true,
|
||||
compact: true,
|
||||
semicolons: false,
|
||||
parentheses: false
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default JS;
|
90
src/core/operations/MAC.js
Executable file
90
src/core/operations/MAC.js
Executable file
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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,
|
||||
|
||||
/**
|
||||
* Format MAC addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFormat: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
var outputCase = args[0],
|
||||
noDelim = args[1],
|
||||
dashDelim = args[2],
|
||||
colonDelim = args[3],
|
||||
ciscoStyle = args[4],
|
||||
outputList = [],
|
||||
macs = input.toLowerCase().split(/[,\s\r\n]+/);
|
||||
|
||||
macs.forEach(function(mac) {
|
||||
var cleanMac = mac.replace(/[:.-]+/g, ""),
|
||||
macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"),
|
||||
macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"),
|
||||
macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1.");
|
||||
|
||||
if (outputCase === "Lower only") {
|
||||
if (noDelim) outputList.push(cleanMac);
|
||||
if (dashDelim) outputList.push(macHyphen);
|
||||
if (colonDelim) outputList.push(macColon);
|
||||
if (ciscoStyle) outputList.push(macCisco);
|
||||
} 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());
|
||||
} 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());
|
||||
}
|
||||
|
||||
outputList.push(
|
||||
"" // Empty line to delimit groups
|
||||
);
|
||||
});
|
||||
|
||||
// Return the data as a string
|
||||
return outputList.join("\n");
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default MAC;
|
190
src/core/operations/MorseCode.js
Normal file
190
src/core/operations/MorseCode.js
Normal file
|
@ -0,0 +1,190 @@
|
|||
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) {
|
||||
var format = args[0].split("/");
|
||||
var dash = format[0];
|
||||
var dot = format[1];
|
||||
|
||||
var letterDelim = Utils.charRep[args[1]];
|
||||
var wordDelim = Utils.charRep[args[2]];
|
||||
|
||||
input = input.split(/\r?\n/);
|
||||
input = Array.prototype.map.call(input, function(line) {
|
||||
var words = line.split(/ +/);
|
||||
words = Array.prototype.map.call(words, function(word) {
|
||||
var letters = Array.prototype.map.call(word, function(character) {
|
||||
var 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() {
|
||||
var reversedTable = null;
|
||||
var reverseTable = function() {
|
||||
reversedTable = {};
|
||||
|
||||
for (var letter in MorseCode.MORSE_TABLE) {
|
||||
var signal = MorseCode.MORSE_TABLE[letter];
|
||||
reversedTable[signal] = letter;
|
||||
}
|
||||
};
|
||||
|
||||
return function(input, args) {
|
||||
if (reversedTable === null) {
|
||||
reverseTable();
|
||||
}
|
||||
|
||||
var letterDelim = Utils.charRep[args[0]];
|
||||
var 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>");
|
||||
|
||||
var words = input.split(wordDelim);
|
||||
words = Array.prototype.map.call(words, function(word) {
|
||||
var signals = word.split(letterDelim);
|
||||
|
||||
var letters = signals.map(function(signal) {
|
||||
return reversedTable[signal];
|
||||
});
|
||||
|
||||
return letters.join("");
|
||||
});
|
||||
words = words.join(" ");
|
||||
|
||||
return words;
|
||||
};
|
||||
})(),
|
||||
|
||||
};
|
||||
|
||||
export default MorseCode;
|
59
src/core/operations/NetBIOS.js
Normal file
59
src/core/operations/NetBIOS.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* 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) {
|
||||
var output = [],
|
||||
offset = args[0];
|
||||
|
||||
for (var 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) {
|
||||
var output = [],
|
||||
offset = args[0];
|
||||
|
||||
for (var i = 0; i < input.length; i += 2) {
|
||||
output.push(((input[i] - offset) << 4) |
|
||||
((input[i + 1] - offset) & 0xf));
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default NetBIOS;
|
29
src/core/operations/Numberwang.js
Executable file
29
src/core/operations/Numberwang.js
Executable file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 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) {
|
||||
if (!input) return "Let's play Wangernumb!";
|
||||
var match = input.match(/\d+/);
|
||||
if (match) {
|
||||
return match[0] + "! That's Numberwang!";
|
||||
} else {
|
||||
// That's a bad miss!
|
||||
return "Sorry, that's not Numberwang. Let's rotate the board!";
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Numberwang;
|
311
src/core/operations/OS.js
Executable file
311
src/core/operations/OS.js
Executable file
|
@ -0,0 +1,311 @@
|
|||
/**
|
||||
* 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) {
|
||||
var 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) {
|
||||
var 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) {
|
||||
var 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;
|
1056
src/core/operations/PublicKey.js
Executable file
1056
src/core/operations/PublicKey.js
Executable file
File diff suppressed because it is too large
Load diff
58
src/core/operations/Punycode.js
Executable file
58
src/core/operations/Punycode.js
Executable file
|
@ -0,0 +1,58 @@
|
|||
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) {
|
||||
var 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) {
|
||||
var idn = args[0];
|
||||
|
||||
if (idn) {
|
||||
return punycode.toUnicode(input);
|
||||
} else {
|
||||
return punycode.decode(input);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Punycode;
|
272
src/core/operations/QuotedPrintable.js
Executable file
272
src/core/operations/QuotedPrintable.js
Executable file
|
@ -0,0 +1,272 @@
|
|||
/** @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) {
|
||||
var 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) {
|
||||
var str = input.replace(/\=(?:\r?\n|$)/g, "");
|
||||
return QuotedPrintable.mimeDecode(str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Decodes mime-encoded data.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
mimeDecode: function(str) {
|
||||
var encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length,
|
||||
bufferLength = str.length - encodedBytesCount * 2,
|
||||
chr, hex,
|
||||
buffer = new Array(bufferLength),
|
||||
bufferPos = 0;
|
||||
|
||||
for (var 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) {
|
||||
var ranges = [
|
||||
[0x09],
|
||||
[0x0A],
|
||||
[0x0D],
|
||||
[0x20],
|
||||
[0x21],
|
||||
[0x23, 0x3C],
|
||||
[0x3E],
|
||||
[0x40, 0x5E],
|
||||
[0x60, 0x7E]
|
||||
],
|
||||
result = "";
|
||||
|
||||
for (var 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 (var 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) {
|
||||
var 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) {
|
||||
var 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;
|
244
src/core/operations/Rotate.js
Executable file
244
src/core/operations/Rotate.js
Executable file
|
@ -0,0 +1,244 @@
|
|||
/**
|
||||
* Bit rotation operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*
|
||||
* @todo Support for UTF16
|
||||
*/
|
||||
const Rotate = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROTATE_AMOUNT: 1,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROTATE_WHOLE: false,
|
||||
|
||||
/**
|
||||
* Runs rotation operations across the input data.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} data
|
||||
* @param {number} amount
|
||||
* @param {function} algo - The rotation operation to carry out
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_rot: function(data, amount, algo) {
|
||||
var result = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var b = data[i];
|
||||
for (var j = 0; j < amount; j++) {
|
||||
b = algo(b);
|
||||
}
|
||||
result.push(b);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotate right operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRotr: function(input, args) {
|
||||
if (args[1]) {
|
||||
return Rotate._rotrWhole(input, args[0]);
|
||||
} else {
|
||||
return Rotate._rot(input, args[0], Rotate._rotr);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotate left operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRotl: function(input, args) {
|
||||
if (args[1]) {
|
||||
return Rotate._rotlWhole(input, args[0]);
|
||||
} else {
|
||||
return Rotate._rot(input, args[0], Rotate._rotl);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROT13_AMOUNT: 13,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROT13_LOWERCASE: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROT13_UPPERCASE: true,
|
||||
|
||||
/**
|
||||
* ROT13 operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRot13: function(input, args) {
|
||||
var amount = args[2],
|
||||
output = input,
|
||||
chr,
|
||||
rot13Lowercase = args[0],
|
||||
rot13Upperacse = args[1];
|
||||
|
||||
if (amount) {
|
||||
if (amount < 0) {
|
||||
amount = 26 - (Math.abs(amount) % 26);
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
chr = input[i];
|
||||
if (rot13Upperacse && chr >= 65 && chr <= 90) { // Upper case
|
||||
chr = (chr - 65 + amount) % 26;
|
||||
output[i] = chr + 65;
|
||||
} else if (rot13Lowercase && chr >= 97 && chr <= 122) { // Lower case
|
||||
chr = (chr - 97 + amount) % 26;
|
||||
output[i] = chr + 97;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROT47_AMOUNT: 47,
|
||||
|
||||
/**
|
||||
* ROT47 operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRot47: function(input, args) {
|
||||
var amount = args[0],
|
||||
output = input,
|
||||
chr;
|
||||
|
||||
if (amount) {
|
||||
if (amount < 0) {
|
||||
amount = 94 - (Math.abs(amount) % 94);
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
chr = input[i];
|
||||
if (chr >= 33 && chr <= 126) {
|
||||
chr = (chr - 33 + amount) % 94;
|
||||
output[i] = chr + 33;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotate right bitwise op.
|
||||
*
|
||||
* @private
|
||||
* @param {byte} b
|
||||
* @returns {byte}
|
||||
*/
|
||||
_rotr: function(b) {
|
||||
var bit = (b & 1) << 7;
|
||||
return (b >> 1) | bit;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotate left bitwise op.
|
||||
*
|
||||
* @private
|
||||
* @param {byte} b
|
||||
* @returns {byte}
|
||||
*/
|
||||
_rotl: function(b) {
|
||||
var bit = (b >> 7) & 1;
|
||||
return ((b << 1) | bit) & 0xFF;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotates a byte array to the right by a specific amount as a whole, so that bits are wrapped
|
||||
* from the end of the array to the beginning.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} data
|
||||
* @param {number} amount
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_rotrWhole: function(data, amount) {
|
||||
var carryBits = 0,
|
||||
newByte,
|
||||
result = [];
|
||||
|
||||
amount = amount % 8;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var oldByte = data[i] >>> 0;
|
||||
newByte = (oldByte >> amount) | carryBits;
|
||||
carryBits = (oldByte & (Math.pow(2, amount)-1)) << (8-amount);
|
||||
result.push(newByte);
|
||||
}
|
||||
result[0] |= carryBits;
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotates a byte array to the left by a specific amount as a whole, so that bits are wrapped
|
||||
* from the beginning of the array to the end.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} data
|
||||
* @param {number} amount
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_rotlWhole: function(data, amount) {
|
||||
var carryBits = 0,
|
||||
newByte,
|
||||
result = [];
|
||||
|
||||
amount = amount % 8;
|
||||
for (var i = data.length-1; i >= 0; i--) {
|
||||
var oldByte = data[i];
|
||||
newByte = ((oldByte << amount) | carryBits) & 0xFF;
|
||||
carryBits = (oldByte >> (8-amount)) & (Math.pow(2, amount)-1);
|
||||
result[i] = (newByte);
|
||||
}
|
||||
result[data.length-1] = result[data.length-1] | carryBits;
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Rotate;
|
225
src/core/operations/SeqUtils.js
Executable file
225
src/core/operations/SeqUtils.js
Executable file
|
@ -0,0 +1,225 @@
|
|||
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"],
|
||||
|
||||
/**
|
||||
* Sort operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSort: function (input, args) {
|
||||
var 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);
|
||||
}
|
||||
|
||||
if (sortReverse) sorted.reverse();
|
||||
return sorted.join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Unique operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runUnique: function (input, args) {
|
||||
var 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) {
|
||||
var search = args[0].string,
|
||||
type = args[0].option;
|
||||
|
||||
if (type === "Regex" && search) {
|
||||
try {
|
||||
var 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) {
|
||||
if (args[0] === "Line") {
|
||||
var lines = [],
|
||||
line = [],
|
||||
result = [];
|
||||
for (var 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) {
|
||||
var lines = input.split("\n"),
|
||||
output = "",
|
||||
width = lines.length.toString().length;
|
||||
|
||||
for (var n = 0; n < lines.length; n++) {
|
||||
output += Utils.pad((n+1).toString(), 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) {
|
||||
var 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_;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default SeqUtils;
|
542
src/core/operations/StrUtils.js
Executable file
542
src/core/operations/StrUtils.js
Executable file
|
@ -0,0 +1,542 @@
|
|||
import Utils from "../Utils.js";
|
||||
import * as JsDiff from "diff";
|
||||
|
||||
|
||||
/**
|
||||
* String utility operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const StrUtils = {
|
||||
|
||||
/**
|
||||
* @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: "(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})"
|
||||
},
|
||||
{
|
||||
name: "URL",
|
||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||
},
|
||||
{
|
||||
name: "Domain",
|
||||
value: "(?:(https?):\\/\\/)?([-\\w.]+)\\.(com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+"
|
||||
},
|
||||
{
|
||||
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
|
||||
*/
|
||||
REGEX_CASE_INSENSITIVE: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_MULTILINE_MATCHING: true,
|
||||
/**
|
||||
* @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) {
|
||||
var userRegex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
displayTotal = args[4],
|
||||
outputFormat = args[5],
|
||||
modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (userRegex && userRegex !== "^" && userRegex !== "$") {
|
||||
try {
|
||||
var regex = new RegExp(userRegex, modifiers);
|
||||
|
||||
switch (outputFormat) {
|
||||
case "Highlight matches":
|
||||
return StrUtils._regexHighlight(input, regex, displayTotal);
|
||||
case "List matches":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(StrUtils._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
|
||||
*/
|
||||
CASE_SCOPE: ["All", "Word", "Sentence", "Paragraph"],
|
||||
|
||||
/**
|
||||
* To Upper case operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runUpper: function (input, args) {
|
||||
var 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
|
||||
*/
|
||||
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) {
|
||||
var 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);
|
||||
} else if (type.indexOf("Extended") === 0) {
|
||||
find = Utils.parseEscapedChars(find);
|
||||
}
|
||||
|
||||
return input.replace(find, replace, modifiers);
|
||||
// Non-standard addition of flags in the third argument. This will work in Firefox but
|
||||
// probably nowhere else. The purpose is to allow global matching when the `find` parameter
|
||||
// is just a string.
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SPLIT_DELIM: ",",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
|
||||
/**
|
||||
* Split operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSplit: function(input, args) {
|
||||
var splitDelim = args[0] || StrUtils.SPLIT_DELIM,
|
||||
joinDelim = Utils.charRep[args[1]],
|
||||
sections = input.split(splitDelim);
|
||||
|
||||
return sections.join(joinDelim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Filter operation.
|
||||
*
|
||||
* @author Mikescher (https://github.com/Mikescher | https://mikescher.com)
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFilter: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]],
|
||||
reverse = args[2];
|
||||
|
||||
try {
|
||||
var regex = new RegExp(args[1]);
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
|
||||
var regexFilter = function(value) {
|
||||
return reverse ^ regex.test(value);
|
||||
};
|
||||
|
||||
return input.split(delim).filter(regexFilter).join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
var 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 (var i = 0; i < diff.length; i++) {
|
||||
if (diff[i].added) {
|
||||
if (showAdded) output += "<span class='hlgreen'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else if (diff[i].removed) {
|
||||
if (showRemoved) output += "<span class='hlred'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else {
|
||||
output += Utils.escapeHtml(diff[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OFF_CHK_SAMPLE_DELIMITER: "\\n\\n",
|
||||
|
||||
/**
|
||||
* Offset checker operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runOffsetChecker: function(input, args) {
|
||||
var sampleDelim = args[0],
|
||||
samples = input.split(sampleDelim),
|
||||
outputs = [],
|
||||
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
|
||||
for (s = 0; s < samples.length; s++) {
|
||||
outputs[s] = "";
|
||||
}
|
||||
|
||||
// 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='hlgreen'>" + 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);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse escaped string operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseEscapedString: function(input, args) {
|
||||
return Utils.parseEscapedChars(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// 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) {
|
||||
var output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = regex.exec(input))) {
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (captureGroups) {
|
||||
for (var 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;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default StrUtils;
|
243
src/core/operations/Tidy.js
Executable file
243
src/core/operations/Tidy.js
Executable file
|
@ -0,0 +1,243 @@
|
|||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var 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) {
|
||||
var output = [];
|
||||
for (var 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 {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runDropBytes: function(input, args) {
|
||||
var start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
|
||||
if (!applyToEachLine)
|
||||
return input.slice(0, start).concat(input.slice(start+length, input.length));
|
||||
|
||||
// Split input into lines
|
||||
var lines = [],
|
||||
line = [];
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (input[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(input[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
var 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 output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TAKE_START: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TAKE_LENGTH: 5,
|
||||
|
||||
/**
|
||||
* Take bytes operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runTakeBytes: function(input, args) {
|
||||
var 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
|
||||
var lines = [],
|
||||
line = [];
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (input[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(input[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
var output = [];
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(start, start+length));
|
||||
output.push(0x0a);
|
||||
}
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
var 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 += Utils.padLeft(lines[i], lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
} else if (position === "End") {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output += Utils.padRight(lines[i], lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Tidy;
|
138
src/core/operations/URL.js
Executable file
138
src/core/operations/URL.js
Executable file
|
@ -0,0 +1,138 @@
|
|||
/* globals unescape */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* URL operations.
|
||||
* Namespace is appended with an underscore to prevent overwriting the global URL object.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const URL_ = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENCODE_ALL: false,
|
||||
|
||||
/**
|
||||
* URL Encode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var encodeAll = args[0];
|
||||
return encodeAll ? URL_._encodeAllChars(input) : encodeURI(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* URL Decode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var data = input.replace(/\+/g, "%20");
|
||||
try {
|
||||
return decodeURIComponent(data);
|
||||
} catch (err) {
|
||||
return unescape(data);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse URI operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParse: function(input, args) {
|
||||
if (!document) {
|
||||
throw "This operation only works in a browser.";
|
||||
}
|
||||
|
||||
var a = document.createElement("a");
|
||||
|
||||
// Overwrite base href which will be the current CyberChef URL to reduce confusion.
|
||||
a.href = "http://example.com/";
|
||||
a.href = input;
|
||||
|
||||
if (a.protocol) {
|
||||
var output = "";
|
||||
if (a.hostname !== window.location.hostname) {
|
||||
output = "Protocol:\t" + a.protocol + "\n";
|
||||
if (a.hostname) output += "Hostname:\t" + a.hostname + "\n";
|
||||
if (a.port) output += "Port:\t\t" + a.port + "\n";
|
||||
}
|
||||
|
||||
if (a.pathname && a.pathname !== window.location.pathname) {
|
||||
var pathname = a.pathname;
|
||||
if (pathname.indexOf(window.location.pathname) === 0)
|
||||
pathname = pathname.replace(window.location.pathname, "");
|
||||
if (pathname)
|
||||
output += "Path name:\t" + pathname + "\n";
|
||||
}
|
||||
|
||||
if (a.hash && a.hash !== window.location.hash) {
|
||||
output += "Hash:\t\t" + a.hash + "\n";
|
||||
}
|
||||
|
||||
if (a.search && a.search !== window.location.search) {
|
||||
output += "Arguments:\n";
|
||||
var args_ = (a.search.slice(1, a.search.length)).split("&");
|
||||
var splitArgs = [], padding = 0;
|
||||
for (var i = 0; i < args_.length; i++) {
|
||||
splitArgs.push(args_[i].split("="));
|
||||
padding = (splitArgs[i][0].length > padding) ? splitArgs[i][0].length : padding;
|
||||
}
|
||||
for (i = 0; i < splitArgs.length; i++) {
|
||||
output += "\t" + Utils.padRight(splitArgs[i][0], padding);
|
||||
if (splitArgs[i].length > 1 && splitArgs[i][1].length)
|
||||
output += " = " + splitArgs[i][1] + "\n";
|
||||
else output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
return "Invalid URI";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* URL encodes additional special characters beyond the standard set.
|
||||
*
|
||||
* @private
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
_encodeAllChars: function(str) {
|
||||
//TODO Do this programatically
|
||||
return encodeURIComponent(str)
|
||||
.replace(/!/g, "%21")
|
||||
.replace(/#/g, "%23")
|
||||
.replace(/'/g, "%27")
|
||||
.replace(/\(/g, "%28")
|
||||
.replace(/\)/g, "%29")
|
||||
.replace(/\*/g, "%2A")
|
||||
.replace(/\-/g, "%2D")
|
||||
.replace(/\./g, "%2E")
|
||||
.replace(/_/g, "%5F")
|
||||
.replace(/~/g, "%7E");
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default URL_;
|
41
src/core/operations/UUID.js
Executable file
41
src/core/operations/UUID.js
Executable file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* 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) {
|
||||
if (window && typeof(window.crypto) !== "undefined" && typeof(window.crypto.getRandomValues) !== "undefined") {
|
||||
var buf = new Uint32Array(4),
|
||||
i = 0;
|
||||
window.crypto.getRandomValues(buf);
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
var r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
i++;
|
||||
return v.toString(16);
|
||||
});
|
||||
} else {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
var r = Math.random() * 16 | 0,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default UUID;
|
67
src/core/operations/Unicode.js
Executable file
67
src/core/operations/Unicode.js
Executable file
|
@ -0,0 +1,67 @@
|
|||
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) {
|
||||
var prefix = Unicode._prefixToRegex[args[0]],
|
||||
regex = new RegExp(prefix+"([a-f\\d]{4,6})", "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;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
Loading…
Add table
Add a link
Reference in a new issue