mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-22 07:46:16 -04:00
Initial commit
This commit is contained in:
commit
b1d73a725d
238 changed files with 105357 additions and 0 deletions
52
src/js/operations/Base.js
Executable file
52
src/js/operations/Base.js
Executable file
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Numerical base operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Base = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DEFAULT_RADIX: 36,
|
||||
|
||||
/**
|
||||
* To Base operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to: 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}
|
||||
*/
|
||||
run_from: 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";
|
||||
}
|
||||
return parseInt(input.replace(/\s/g, ""), radix);
|
||||
},
|
||||
|
||||
};
|
341
src/js/operations/Base64.js
Executable file
341
src/js/operations/Base64.js
Executable file
|
@ -0,0 +1,341 @@
|
|||
/**
|
||||
* Base64 operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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+/="},
|
||||
],
|
||||
|
||||
/**
|
||||
* To Base64 operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET;
|
||||
return Utils.to_base64(input, alphabet);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_NON_ALPH_CHARS: true,
|
||||
|
||||
/**
|
||||
* From Base64 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_from: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET,
|
||||
remove_non_alph_chars = args[1];
|
||||
|
||||
return Utils.from_base64(input, alphabet, "byte_array", remove_non_alph_chars);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BASE32_ALPHABET: "A-Z2-7=",
|
||||
|
||||
/**
|
||||
* To Base32 operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_32: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
var alphabet = args[0] ?
|
||||
Utils.expand_alph_range(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) & 63;
|
||||
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 {byte_array}
|
||||
*/
|
||||
run_from_32: function(input, args) {
|
||||
if (!input) return [];
|
||||
|
||||
var alphabet = args[0] ?
|
||||
Utils.expand_alph_range(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
||||
remove_non_alph_chars = args[0];
|
||||
|
||||
var output = [],
|
||||
chr1, chr2, chr3, chr4, chr5,
|
||||
enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8,
|
||||
i = 0;
|
||||
|
||||
if (remove_non_alph_chars) {
|
||||
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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
run_offsets: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET,
|
||||
show_variable = args[1],
|
||||
offset0 = Utils.to_base64(input, alphabet),
|
||||
offset1 = Utils.to_base64([0].concat(input), alphabet),
|
||||
offset2 = Utils.to_base64([0, 0].concat(input), alphabet),
|
||||
len0 = offset0.indexOf("="),
|
||||
len1 = offset1.indexOf("="),
|
||||
len2 = offset2.indexOf("="),
|
||||
script = "<script type='application/javascript'>$('[data-toggle=\"tooltip\"]').tooltip()</script>",
|
||||
static_section = "",
|
||||
padding = "";
|
||||
|
||||
if (input.length < 1) {
|
||||
return "Please enter a string.";
|
||||
}
|
||||
|
||||
// Highlight offset 0
|
||||
if (len0 % 4 == 2) {
|
||||
static_section = offset0.slice(0, -3);
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64(static_section, alphabet).slice(0, -2) + "'>" +
|
||||
static_section + "</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) {
|
||||
static_section = offset0.slice(0, -2);
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64(static_section, alphabet).slice(0, -1) + "'>" +
|
||||
static_section + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 1) + "</span>";
|
||||
} else {
|
||||
static_section = offset0;
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64(static_section, alphabet) + "'>" +
|
||||
static_section + "</span>";
|
||||
}
|
||||
|
||||
if (!show_variable) {
|
||||
offset0 = static_section;
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
static_section = offset1.slice(0, -3);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64("AA" + static_section, alphabet).slice(1, -2) + "'>" +
|
||||
static_section + "</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) {
|
||||
static_section = offset1.slice(0, -2);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64("AA" + static_section, alphabet).slice(1, -1) + "'>" +
|
||||
static_section + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 1) + "</span>";
|
||||
} else {
|
||||
static_section = offset1;
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64("AA" + static_section, alphabet).slice(1) + "'>" +
|
||||
static_section + "</span>";
|
||||
}
|
||||
|
||||
if (!show_variable) {
|
||||
offset1 = static_section;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
static_section = offset2.slice(0, -3);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64("AAA" + static_section, alphabet).slice(2, -2) + "'>" +
|
||||
static_section + "</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) {
|
||||
static_section = offset2.slice(0, -2);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64("AAA" + static_section, alphabet).slice(2, -2) + "'>" +
|
||||
static_section + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 1) + "</span>";
|
||||
} else {
|
||||
static_section = offset2;
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.from_base64("AAA" + static_section, alphabet).slice(2) + "'>" +
|
||||
static_section + "</span>";
|
||||
}
|
||||
|
||||
if (!show_variable) {
|
||||
offset2 = static_section;
|
||||
}
|
||||
|
||||
return (show_variable ? "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
|
||||
*/
|
||||
highlight_to: 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
|
||||
*/
|
||||
highlight_from: 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;
|
||||
},
|
||||
|
||||
};
|
299
src/js/operations/BitwiseOp.js
Executable file
299
src/js/operations/BitwiseOp.js
Executable file
|
@ -0,0 +1,299 @@
|
|||
/* globals CryptoJS */
|
||||
|
||||
/**
|
||||
* Bitwise operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var BitwiseOp = {
|
||||
|
||||
/**
|
||||
* Runs bitwise operations across the input data.
|
||||
*
|
||||
* @private
|
||||
* @param {byte_array} input
|
||||
* @param {byte_array} key
|
||||
* @param {function} func - The bitwise calculation to carry out
|
||||
* @param {boolean} null_preserving
|
||||
* @param {boolean} differential
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
_bit_op: function (input, key, func, null_preserving, differential) {
|
||||
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 = null_preserving && (o === 0 || o == k) ? o : func(o, k);
|
||||
result.push(x);
|
||||
if (differential && !(null_preserving && (o === 0 || o == k))) {
|
||||
key[i % key.length] = x;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_PRESERVE_NULLS: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_DIFFERENTIAL: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KEY_FORMAT: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
|
||||
|
||||
/**
|
||||
* XOR operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_xor: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || ""),
|
||||
null_preserving = args[1],
|
||||
differential = args[2];
|
||||
|
||||
key = Utils.word_array_to_byte_array(key);
|
||||
|
||||
return BitwiseOp._bit_op(input, key, BitwiseOp._xor, null_preserving, differential);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_xor_brute: function (input, args) {
|
||||
var key_length = parseInt(args[0], 10),
|
||||
sample_length = args[1],
|
||||
sample_offset = args[2],
|
||||
null_preserving = args[3],
|
||||
differential = args[4],
|
||||
crib = args[5],
|
||||
print_key = args[6],
|
||||
output_hex = args[7],
|
||||
regex;
|
||||
|
||||
var output = "",
|
||||
result,
|
||||
result_utf8;
|
||||
|
||||
input = input.slice(sample_offset, sample_offset + sample_length);
|
||||
|
||||
if (crib !== "") {
|
||||
regex = new RegExp(crib, "im");
|
||||
}
|
||||
|
||||
|
||||
for (var key = 1, l = Math.pow(256, key_length); key < l; key++) {
|
||||
result = BitwiseOp._bit_op(input, Utils.hex_to_byte_array(key.toString(16)), BitwiseOp._xor, null_preserving, differential);
|
||||
result_utf8 = Utils.byte_array_to_utf8(result);
|
||||
if (crib !== "" && result_utf8.search(regex) === -1) continue;
|
||||
if (print_key) output += "Key = " + Utils.hex(key, (2*key_length)) + ": ";
|
||||
if (output_hex)
|
||||
output += Utils.byte_array_to_hex(result) + "\n";
|
||||
else
|
||||
output += Utils.printable(result_utf8, false) + "\n";
|
||||
if (print_key) output += "\n";
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* NOT operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_not: function (input, args) {
|
||||
return BitwiseOp._bit_op(input, null, BitwiseOp._not);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AND operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_and: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.word_array_to_byte_array(key);
|
||||
|
||||
return BitwiseOp._bit_op(input, key, BitwiseOp._and);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* OR operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_or: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.word_array_to_byte_array(key);
|
||||
|
||||
return BitwiseOp._bit_op(input, key, BitwiseOp._or);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* ADD operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_add: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.word_array_to_byte_array(key);
|
||||
|
||||
return BitwiseOp._bit_op(input, key, BitwiseOp._add);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SUB operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_sub: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.word_array_to_byte_array(key);
|
||||
|
||||
return BitwiseOp._bit_op(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;
|
||||
},
|
||||
|
||||
};
|
394
src/js/operations/ByteRepr.js
Executable file
394
src/js/operations/ByteRepr.js
Executable file
|
@ -0,0 +1,394 @@
|
|||
/* globals app */
|
||||
|
||||
/**
|
||||
* Byte representation operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_hex: function(input, args) {
|
||||
var delim = Utils.char_rep[args[0] || "Space"];
|
||||
return Utils.to_hex(input, delim, 2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Hex operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_from_hex: function(input, args) {
|
||||
var delim = args[0] || "Space";
|
||||
return Utils.from_hex(input, delim, 2);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CHARCODE_BASE: 16,
|
||||
|
||||
/**
|
||||
* To Charcode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_charcode: function(input, args) {
|
||||
var delim = Utils.char_rep[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.options.attempt_highlight = false;
|
||||
|
||||
output += Utils.hex(ordinal, padding) + delim;
|
||||
} else {
|
||||
app.options.attempt_highlight = false;
|
||||
output += ordinal.toString(base) + delim;
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, -delim.length);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Charcode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_from_charcode: function(input, args) {
|
||||
var delim = Utils.char_rep[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.options.attempt_highlight = 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.str_to_byte_array(latin1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to hex
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlight_to: function(pos, args) {
|
||||
var delim = Utils.char_rep[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
|
||||
*/
|
||||
highlight_from: function(pos, args) {
|
||||
var delim = Utils.char_rep[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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_decimal: function(input, args) {
|
||||
var delim = Utils.char_rep[args[0]];
|
||||
return input.join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Decimal operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_from_decimal: function(input, args) {
|
||||
var delim = Utils.char_rep[args[0]];
|
||||
var byte_str = input.split(delim), output = [];
|
||||
if (byte_str[byte_str.length-1] === "")
|
||||
byte_str = byte_str.slice(0, byte_str.length-1);
|
||||
|
||||
for (var i = 0; i < byte_str.length; i++) {
|
||||
output[i] = parseInt(byte_str[i]);
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* To Binary operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_binary: function(input, args) {
|
||||
var delim = Utils.char_rep[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 {byte_array}
|
||||
*/
|
||||
run_from_binary: function(input, args) {
|
||||
if (args[0] != "None") {
|
||||
var delim_regex = Utils.regex_rep[args[0] || "Space"];
|
||||
input = input.replace(delim_regex, '');
|
||||
}
|
||||
|
||||
var output = [];
|
||||
var byte_len = 8;
|
||||
for (var i = 0; i < input.length; i += byte_len) {
|
||||
output.push(parseInt(input.substr(i, byte_len), 2));
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to binary
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlight_to_binary: function(pos, args) {
|
||||
var delim = Utils.char_rep[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
|
||||
*/
|
||||
highlight_from_binary: function(pos, args) {
|
||||
var delim = Utils.char_rep[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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_hex_content: function(input, args) {
|
||||
var convert = args[0];
|
||||
var spaces = args[1];
|
||||
if (convert == "All chars") {
|
||||
var result = "|" + Utils.to_hex(input) + "|";
|
||||
if (!spaces) result = result.replace(/ /g, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
var output = "",
|
||||
in_hex = false,
|
||||
convert_spaces = convert == "Only special chars including spaces",
|
||||
b;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
b = input[i];
|
||||
if ((b == 32 && convert_spaces) || (b < 48 && b != 32) || (b > 57 && b < 65) || (b > 90 && b < 97) || b > 122) {
|
||||
if (!in_hex) {
|
||||
output += "|";
|
||||
in_hex = true;
|
||||
} else if (spaces) output += " ";
|
||||
output += Utils.to_hex([b]);
|
||||
} else {
|
||||
if (in_hex) {
|
||||
output += "|";
|
||||
in_hex = false;
|
||||
}
|
||||
output += Utils.chr(input[i]);
|
||||
}
|
||||
}
|
||||
if (in_hex) output += "|";
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Hex Content operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_from_hex_content: 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.from_hex(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;
|
||||
},
|
||||
|
||||
};
|
46
src/js/operations/CharEnc.js
Executable file
46
src/js/operations/CharEnc.js
Executable file
|
@ -0,0 +1,46 @@
|
|||
/* globals CryptoJS */
|
||||
|
||||
/**
|
||||
* Character encoding operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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 input_format = args[0],
|
||||
output_format = args[1];
|
||||
|
||||
if (input_format == "Windows-1251") {
|
||||
input = Utils.win1251_to_unicode(input);
|
||||
input = CryptoJS.enc.Utf8.parse(input);
|
||||
} else {
|
||||
input = Utils.format[input_format].parse(input);
|
||||
}
|
||||
|
||||
if (output_format == "Windows-1251") {
|
||||
input = CryptoJS.enc.Utf8.stringify(input);
|
||||
return Utils.unicode_to_win1251(input);
|
||||
} else {
|
||||
return Utils.format[output_format].stringify(input);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
130
src/js/operations/Checksum.js
Executable file
130
src/js/operations/Checksum.js
Executable file
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* Checksum operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Checksum = {
|
||||
|
||||
/**
|
||||
* Fletcher-16 Checksum operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_fletcher16: 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);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adler-32 Checksum operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_adler32: 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_crc32: function(input, args) {
|
||||
var crc_table = window.crc_table || (window.crc_table = Checksum._gen_crc_table()),
|
||||
crc = 0 ^ (-1);
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
crc = (crc >>> 8) ^ crc_table[(crc ^ input[i]) & 0xff];
|
||||
}
|
||||
|
||||
return Utils.hex((crc ^ (-1)) >>> 0);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* TCP/IP Checksum operation.
|
||||
*
|
||||
* @author GCHQ Contributor [1]
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns '3f2c'
|
||||
* Checksum.run_tcp_ip([0x45,0x00,0x00,0x87,0xa3,0x1b,0x40,0x00,0x40,0x06,
|
||||
* 0x00,0x00,0xac,0x11,0x00,0x04,0xac,0x11,0x00,0x03])
|
||||
*
|
||||
* // returns 'a249'
|
||||
* Checksum.run_tcp_ip([0x45,0x00,0x01,0x11,0x3f,0x74,0x40,0x00,0x40,0x06,
|
||||
* 0x00,0x00,0xac,0x11,0x00,0x03,0xac,0x11,0x00,0x04])
|
||||
*/
|
||||
run_tcp_ip: 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}
|
||||
*/
|
||||
_gen_crc_table: function() {
|
||||
var c,
|
||||
crc_table = [];
|
||||
|
||||
for (var n = 0; n < 256; n++) {
|
||||
c = n;
|
||||
for (var k = 0; k < 8; k++) {
|
||||
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
|
||||
}
|
||||
crc_table[n] = c;
|
||||
}
|
||||
|
||||
return crc_table;
|
||||
},
|
||||
|
||||
};
|
429
src/js/operations/Cipher.js
Executable file
429
src/js/operations/Cipher.js
Executable file
|
@ -0,0 +1,429 @@
|
|||
/* globals CryptoJS, blowfish */
|
||||
|
||||
/**
|
||||
* Cipher operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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 {byte_array} 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]],
|
||||
result_option = args[5].toLowerCase(),
|
||||
output_format = 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 (result_option == "show all") {
|
||||
result += "Key: " + encrypted.key.toString(Utils.format[output_format]);
|
||||
result += "\nIV: " + encrypted.iv.toString(Utils.format[output_format]);
|
||||
if (encrypted.salt) result += "\nSalt: " + encrypted.salt.toString(Utils.format[output_format]);
|
||||
result += "\n\nCiphertext: " + encrypted.ciphertext.toString(Utils.format[output_format]);
|
||||
} else {
|
||||
result = encrypted[result_option].toString(Utils.format[output_format]);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Runs decryption operations using the CryptoJS framework.
|
||||
*
|
||||
* @private
|
||||
* @param {function} algo - The CryptoJS algorithm to use
|
||||
* @param {byte_array} 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]],
|
||||
input_format = args[5],
|
||||
output_format = args[6];
|
||||
|
||||
// The ZeroPadding option causes a crash when the input length is 0
|
||||
if (!input.length) {
|
||||
return "No input";
|
||||
}
|
||||
|
||||
var ciphertext = Utils.format[input_format].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[output_format]);
|
||||
} catch (err) {
|
||||
result = "Decrypt error: " + err.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AES Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_aes_enc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.AES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AES Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_aes_dec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.AES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* DES Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_des_enc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.DES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* DES Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_des_dec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.DES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Triple DES Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_triple_des_enc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.TripleDES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Triple DES Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_triple_des_dec: function (input, args) {
|
||||
return Cipher._dec(CryptoJS.TripleDES, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rabbit Encrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_rabbit_enc: function (input, args) {
|
||||
return Cipher._enc(CryptoJS.Rabbit, input, args);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rabbit Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_rabbit_dec: 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}
|
||||
*/
|
||||
run_blowfish_enc: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
|
||||
mode = args[1],
|
||||
output_format = args[2];
|
||||
|
||||
if (key.length === 0) return "Enter a key";
|
||||
|
||||
var enc_hex = blowfish.encrypt(input, key, {
|
||||
outputType: 1,
|
||||
cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
|
||||
}),
|
||||
enc = CryptoJS.enc.Hex.parse(enc_hex);
|
||||
|
||||
return enc.toString(Utils.format[output_format]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Blowfish Decrypt operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_blowfish_dec: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
|
||||
mode = args[1],
|
||||
input_format = args[2];
|
||||
|
||||
if (key.length === 0) return "Enter a key";
|
||||
|
||||
input = Utils.format[input_format].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}
|
||||
*/
|
||||
run_pbkdf2: function (input, args) {
|
||||
var key_size = args[0] / 32,
|
||||
iterations = args[1],
|
||||
salt = CryptoJS.enc.Hex.parse(args[2] || ""),
|
||||
input_format = args[3],
|
||||
output_format = args[4],
|
||||
passphrase = Utils.format[input_format].parse(input),
|
||||
key = CryptoJS.PBKDF2(passphrase, salt, { keySize: key_size, iterations: iterations });
|
||||
|
||||
return key.toString(Utils.format[output_format]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Derive EVP key operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_evpkdf: function (input, args) {
|
||||
var key_size = args[0] / 32,
|
||||
iterations = args[1],
|
||||
salt = CryptoJS.enc.Hex.parse(args[2] || ""),
|
||||
input_format = args[3],
|
||||
output_format = args[4],
|
||||
passphrase = Utils.format[input_format].parse(input),
|
||||
key = CryptoJS.EvpKDF(passphrase, salt, { keySize: key_size, iterations: iterations });
|
||||
|
||||
return key.toString(Utils.format[output_format]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* RC4 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_rc4: 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}
|
||||
*/
|
||||
run_rc4drop: 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]]);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 });
|
||||
};
|
305
src/js/operations/Code.js
Executable file
305
src/js/operations/Code.js
Executable file
|
@ -0,0 +1,305 @@
|
|||
/* globals prettyPrintOne, vkbeautify */
|
||||
|
||||
/**
|
||||
* Code operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_syntax_highlight: function(input, args) {
|
||||
var language = args[0],
|
||||
line_nums = args[1];
|
||||
return "<code class='prettyprint'>" + prettyPrintOne(Utils.escape_html(input), language, line_nums) + "</code>";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
BEAUTIFY_INDENT: "\\t",
|
||||
|
||||
/**
|
||||
* XML Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_xml_beautify: function(input, args) {
|
||||
var indent_str = args[0];
|
||||
return vkbeautify.xml(input, indent_str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* JSON Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_json_beautify: function(input, args) {
|
||||
var indent_str = args[0];
|
||||
return vkbeautify.json(input, indent_str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CSS Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_css_beautify: function(input, args) {
|
||||
var indent_str = args[0];
|
||||
return vkbeautify.css(input, indent_str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SQL Beautify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_sql_beautify: function(input, args) {
|
||||
var indent_str = args[0];
|
||||
return vkbeautify.sql(input, indent_str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PRESERVE_COMMENTS: false,
|
||||
|
||||
/**
|
||||
* XML Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_xml_minify: function(input, args) {
|
||||
var preserve_comments = args[0];
|
||||
return vkbeautify.xmlmin(input, preserve_comments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* JSON Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_json_minify: function(input, args) {
|
||||
return vkbeautify.jsonmin(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CSS Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_css_minify: function(input, args) {
|
||||
var preserve_comments = args[0];
|
||||
return vkbeautify.cssmin(input, preserve_comments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SQL Minify operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_sql_minify: 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}
|
||||
*/
|
||||
run_generic_beautify: function(input, args) {
|
||||
var code = input,
|
||||
t = 0,
|
||||
preserved_tokens = [],
|
||||
m;
|
||||
|
||||
// Remove strings
|
||||
var sstrings = /'([^'\\]|\\.)*'/g;
|
||||
while (!!(m = sstrings.exec(code))) {
|
||||
code = preserve_token(code, m, t++);
|
||||
sstrings.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var dstrings = /"([^"\\]|\\.)*"/g;
|
||||
while (!!(m = dstrings.exec(code))) {
|
||||
code = preserve_token(code, m, t++);
|
||||
dstrings.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Remove comments
|
||||
var scomments = /\/\/[^\n\r]*/g;
|
||||
while (!!(m = scomments.exec(code))) {
|
||||
code = preserve_token(code, m, t++);
|
||||
scomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var mcomments = /\/\*[\s\S]*?\*\//gm;
|
||||
while (!!(m = mcomments.exec(code))) {
|
||||
code = preserve_token(code, m, t++);
|
||||
mcomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var hcomments = /(^|\n)#[^\n\r#]+/g;
|
||||
while (!!(m = hcomments.exec(code))) {
|
||||
code = preserve_token(code, m, t++);
|
||||
hcomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Remove regexes
|
||||
var regexes = /\/.*?[^\\]\/[gim]{0,3}/gi;
|
||||
while (!!(m = regexes.exec(code))) {
|
||||
code = preserve_token(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 = /###preserved_token(\d+)###/g;
|
||||
while (!!(m = ptokens.exec(code))) {
|
||||
var ti = parseInt(m[1]);
|
||||
code = code.substring(0, m.index) + preserved_tokens[ti] + code.substring(m.index + m[0].length);
|
||||
ptokens.lastIndex = m.index;
|
||||
}
|
||||
|
||||
return code;
|
||||
|
||||
function preserve_token(str, match, t) {
|
||||
preserved_tokens[t] = match[0];
|
||||
return str.substring(0, match.index) +
|
||||
"###preserved_token" + t + "###" +
|
||||
str.substring(match.index + match[0].length);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
349
src/js/operations/Compress.js
Executable file
349
src/js/operations/Compress.js
Executable file
|
@ -0,0 +1,349 @@
|
|||
/* globals Zlib, bzip2 */
|
||||
|
||||
/**
|
||||
* Compression operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_raw_deflate: 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_raw_inflate: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.str_to_byte_array(Utils.byte_array_to_utf8(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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_zlib_deflate: 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_zlib_inflate: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.str_to_byte_array(Utils.byte_array_to_utf8(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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_gzip: 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_gunzip: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.str_to_byte_array(Utils.byte_array_to_utf8(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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_pkzip: function(input, args) {
|
||||
var password = Utils.str_to_byte_array(args[2]),
|
||||
options = {
|
||||
filename: Utils.str_to_byte_array(args[0]),
|
||||
comment: Utils.str_to_byte_array(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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_pkunzip: function(input, args) {
|
||||
var options = {
|
||||
password: Utils.str_to_byte_array(args[0]),
|
||||
verify: args[1]
|
||||
},
|
||||
file = "",
|
||||
unzip = new Zlib.Unzip(input, options),
|
||||
filenames = unzip.getFilenames(),
|
||||
output = "<div style='padding: 5px;'>" + filenames.length + " file(s) found</div>\n";
|
||||
|
||||
output += "<div class='panel-group' id='zip-accordion' role='tablist' aria-multiselectable='true'>";
|
||||
|
||||
window.uzip = unzip;
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
file = Utils.byte_array_to_utf8(unzip.decompress(filenames[i]));
|
||||
output += "<div class='panel panel-default'>" +
|
||||
"<div class='panel-heading' role='tab' id='heading" + i + "'>" +
|
||||
"<h4 class='panel-title'>" +
|
||||
"<a class='collapsed' role='button' data-toggle='collapse' data-parent='#zip-accordion' href='#collapse" + i +
|
||||
"' aria-expanded='true' aria-controls='collapse" + i + "'>" +
|
||||
filenames[i] + "<span class='pull-right'>" + file.length.toLocaleString() + " bytes</span></a></h4></div>" +
|
||||
"<div id='collapse" + i + "' class='panel-collapse collapse' role='tabpanel' aria-labelledby='heading" + i + "'>" +
|
||||
"<div class='panel-body'>" +
|
||||
Utils.escape_html(file) + "</div></div></div>";
|
||||
}
|
||||
|
||||
return output + "</div>";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Bzip2 Decompress operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_bzip2_decompress: function(input, args) {
|
||||
var compressed = new Uint8Array(input),
|
||||
bzip2_reader,
|
||||
plain = "";
|
||||
|
||||
bzip2_reader = bzip2.array(compressed);
|
||||
plain = bzip2.simple(bzip2_reader);
|
||||
return plain;
|
||||
},
|
||||
|
||||
};
|
412
src/js/operations/Convert.js
Executable file
412
src/js/operations/Convert.js
Executable file
|
@ -0,0 +1,412 @@
|
|||
/**
|
||||
* Unit conversion operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_distance: function (input, args) {
|
||||
var input_units = args[0],
|
||||
output_units = args[1];
|
||||
|
||||
input = input * Convert.DISTANCE_FACTOR[input_units];
|
||||
return input / Convert.DISTANCE_FACTOR[output_units];
|
||||
// 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}
|
||||
*/
|
||||
run_data_size: function (input, args) {
|
||||
var input_units = args[0],
|
||||
output_units = args[1];
|
||||
|
||||
input = input * Convert.DATA_FACTOR[input_units];
|
||||
return input / Convert.DATA_FACTOR[output_units];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
run_area: function (input, args) {
|
||||
var input_units = args[0],
|
||||
output_units = args[1];
|
||||
|
||||
input = input * Convert.AREA_FACTOR[input_units];
|
||||
return input / Convert.AREA_FACTOR[output_units];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
run_mass: function (input, args) {
|
||||
var input_units = args[0],
|
||||
output_units = args[1];
|
||||
|
||||
input = input * Convert.MASS_FACTOR[input_units];
|
||||
return input / Convert.MASS_FACTOR[output_units];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
run_speed: function (input, args) {
|
||||
var input_units = args[0],
|
||||
output_units = args[1];
|
||||
|
||||
input = input * Convert.SPEED_FACTOR[input_units];
|
||||
return input / Convert.SPEED_FACTOR[output_units];
|
||||
},
|
||||
|
||||
};
|
454
src/js/operations/DateTime.js
Executable file
454
src/js/operations/DateTime.js
Executable file
|
@ -0,0 +1,454 @@
|
|||
/* globals moment */
|
||||
|
||||
/**
|
||||
* Date and time operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var DateTime = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
|
||||
|
||||
/**
|
||||
* From UNIX Timestamp operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_from_unix_timestamp: 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}
|
||||
*/
|
||||
run_to_unix_timestamp: 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}
|
||||
*/
|
||||
run_translate_format: function(input, args) {
|
||||
var input_format = args[1],
|
||||
input_timezone = args[2],
|
||||
output_format = args[3],
|
||||
output_timezone = args[4],
|
||||
date;
|
||||
|
||||
try {
|
||||
date = moment.tz(input, input_format, input_timezone);
|
||||
if (!date || date.format() == "Invalid date") throw Error;
|
||||
} catch(err) {
|
||||
return "Invalid format.\n\n" + DateTime.FORMAT_EXAMPLES;
|
||||
}
|
||||
|
||||
return date.tz(output_timezone).format(output_format);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse DateTime operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
run_parse: function(input, args) {
|
||||
var input_format = args[1],
|
||||
input_timezone = args[2],
|
||||
date,
|
||||
output = "";
|
||||
|
||||
try {
|
||||
date = moment.tz(input, input_format, input_timezone);
|
||||
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>",
|
||||
|
||||
|
||||
};
|
94
src/js/operations/Endian.js
Executable file
94
src/js/operations/Endian.js
Executable file
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Endian operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_swap_endianness: function(input, args) {
|
||||
var data_format = args[0],
|
||||
word_length = args[1],
|
||||
pad_incomplete_words = args[2],
|
||||
data = [],
|
||||
result = [],
|
||||
words = [],
|
||||
i = 0,
|
||||
j = 0;
|
||||
|
||||
if (word_length <= 0) {
|
||||
return "Word length must be greater than 0";
|
||||
}
|
||||
|
||||
// Convert input to raw data based on specified data format
|
||||
switch (data_format) {
|
||||
case "Hex":
|
||||
data = Utils.from_hex(input);
|
||||
break;
|
||||
case "Raw":
|
||||
data = Utils.str_to_byte_array(input);
|
||||
break;
|
||||
default:
|
||||
data = input;
|
||||
}
|
||||
|
||||
// Split up into words
|
||||
for (i = 0; i < data.length; i += word_length) {
|
||||
var word = data.slice(i, i + word_length);
|
||||
|
||||
// Pad word if too short
|
||||
if (pad_incomplete_words && word.length < word_length){
|
||||
for (j = word.length; j < word_length; 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 (data_format) {
|
||||
case "Hex":
|
||||
return Utils.to_hex(result);
|
||||
case "Raw":
|
||||
return Utils.byte_array_to_utf8(result);
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
};
|
166
src/js/operations/Entropy.js
Executable file
166
src/js/operations/Entropy.js
Executable file
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* Entropy operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Entropy = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CHUNK_SIZE: 1000,
|
||||
|
||||
/**
|
||||
* Entropy operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
run_entropy: function(input, args) {
|
||||
var chunk_size = args[0],
|
||||
output = "",
|
||||
entropy = Entropy._calc_entropy(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'),\
|
||||
parent_rect = canvas.parentNode.getBoundingClientRect(),\
|
||||
entropy = " + entropy + ",\
|
||||
height = parent_rect.height * 0.25;\
|
||||
\
|
||||
canvas.width = parent_rect.width * 0.95;\
|
||||
canvas.height = height > 150 ? 150 : height;\
|
||||
\
|
||||
CanvasComponents.draw_scale_bar(canvas, entropy, 8, [\
|
||||
{\
|
||||
label: 'English text',\
|
||||
min: 3.5,\
|
||||
max: 5\
|
||||
},{\
|
||||
label: 'Encrypted/compressed',\
|
||||
min: 7.5,\
|
||||
max: 8\
|
||||
}\
|
||||
]);\
|
||||
</script>";
|
||||
|
||||
var chunk_entropy = 0;
|
||||
if (chunk_size !== 0) {
|
||||
for (var i = 0; i < input.length; i += chunk_size) {
|
||||
chunk_entropy = Entropy._calc_entropy(input.slice(i, i+chunk_size));
|
||||
output += "Bytes " + i + " to " + (i+chunk_size) + ": " + chunk_entropy + "\n";
|
||||
}
|
||||
} else {
|
||||
output += "Chunk size cannot be 0.";
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FREQ_ZEROS: false,
|
||||
|
||||
/**
|
||||
* Frequency distribution operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
run_freq_distrib: function (input, args) {
|
||||
if (!input.length) return "No data";
|
||||
|
||||
var distrib = new Array(256),
|
||||
percentages = new Array(256),
|
||||
len = input.length,
|
||||
show_zeroes = 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'),\
|
||||
parent_rect = canvas.parentNode.getBoundingClientRect(),\
|
||||
scores = " + JSON.stringify(percentages) + ";\
|
||||
\
|
||||
canvas.width = parent_rect.width * 0.95;\
|
||||
canvas.height = parent_rect.height * 0.9;\
|
||||
\
|
||||
CanvasComponents.draw_bar_chart(canvas, scores, 'Byte', 'Frequency %', 16, 6);\
|
||||
</script>";
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (distrib[i] || show_zeroes) {
|
||||
output += " " + Utils.hex(i, 2) + " (" +
|
||||
Utils.pad_right(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 {byte_array} data
|
||||
* @returns {number}
|
||||
*/
|
||||
_calc_entropy: function(data) {
|
||||
var prob = [],
|
||||
uniques = data.unique(),
|
||||
str = Utils.byte_array_to_chars(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;
|
||||
},
|
||||
|
||||
};
|
297
src/js/operations/Extract.js
Executable file
297
src/js/operations/Extract.js
Executable file
|
@ -0,0 +1,297 @@
|
|||
/**
|
||||
* Identifier extraction operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Extract = {
|
||||
|
||||
/**
|
||||
* Runs search operations across the input data using refular expressions.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} search_regex
|
||||
* @param {RegExp} remove_regex - A regular expression defining results to remove from the
|
||||
* final list
|
||||
* @param {boolean} include_total - Whether or not to include the total number of results
|
||||
* @returns {string}
|
||||
*/
|
||||
_search: function(input, search_regex, remove_regex, include_total) {
|
||||
var output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while (!!(match = search_regex.exec(input))) {
|
||||
if (remove_regex && remove_regex.test(match[0]))
|
||||
continue;
|
||||
total++;
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
|
||||
if (include_total)
|
||||
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}
|
||||
*/
|
||||
run_strings: function(input, args) {
|
||||
var min_len = args[0] || Extract.MIN_STRING_LEN,
|
||||
display_total = args[1],
|
||||
strings = "[A-Z\\d/\\-:.,_$%'\"()<>= !\\[\\]{}@]",
|
||||
regex = new RegExp(strings + "{" + min_len + ",}", "ig");
|
||||
|
||||
return Extract._search(input, regex, null, display_total);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
run_ip: function(input, args) {
|
||||
var include_ipv4 = args[0],
|
||||
include_ipv6 = args[1],
|
||||
remove_local = args[2],
|
||||
display_total = 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 (include_ipv4 && include_ipv6) {
|
||||
ips = ipv4 + "|" + ipv6;
|
||||
} else if (include_ipv4) {
|
||||
ips = ipv4;
|
||||
} else if (include_ipv6) {
|
||||
ips = ipv6;
|
||||
}
|
||||
|
||||
if (ips) {
|
||||
var regex = new RegExp(ips, "ig");
|
||||
|
||||
if (remove_local) {
|
||||
var ten = "10\\..+",
|
||||
oneninetwo = "192\\.168\\..+",
|
||||
oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
|
||||
onetwoseven = "127\\..+",
|
||||
remove_regex = new RegExp("^(?:" + ten + "|" + oneninetwo +
|
||||
"|" + oneseventwo + "|" + onetwoseven + ")");
|
||||
|
||||
return Extract._search(input, regex, remove_regex, display_total);
|
||||
} else {
|
||||
return Extract._search(input, regex, null, display_total);
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract email addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_email: function(input, args) {
|
||||
var display_total = args[0],
|
||||
regex = /\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}/ig;
|
||||
|
||||
return Extract._search(input, regex, null, display_total);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract MAC addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_mac: function(input, args) {
|
||||
var display_total = args[0],
|
||||
regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig;
|
||||
|
||||
return Extract._search(input, regex, null, display_total);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract URLs operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_urls: function(input, args) {
|
||||
var display_total = 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, display_total);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract domains operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_domains: function(input, args) {
|
||||
var display_total = 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, display_total);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_WIN_PATH: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_UNIX_PATH: true,
|
||||
|
||||
/**
|
||||
* Extract file paths operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_file_paths: function(input, args) {
|
||||
var include_win_path = args[0],
|
||||
include_unix_path = args[1],
|
||||
display_total = args[2],
|
||||
win_drive = "[A-Z]:\\\\",
|
||||
win_name = "[A-Z\\d][A-Z\\d\\- '_\\(\\)]{0,61}",
|
||||
win_ext = "[A-Z\\d]{1,6}",
|
||||
win_path = win_drive + "(?:" + win_name + "\\\\?)*" + win_name +
|
||||
"(?:\\." + win_ext + ")?",
|
||||
unix_path = "(?:/[A-Z\\d.][A-Z\\d\\-.]{0,61})+",
|
||||
file_paths = "";
|
||||
|
||||
if (include_win_path && include_unix_path) {
|
||||
file_paths = win_path + "|" + unix_path;
|
||||
} else if (include_win_path) {
|
||||
file_paths = win_path;
|
||||
} else if (include_unix_path) {
|
||||
file_paths = unix_path;
|
||||
}
|
||||
|
||||
if (file_paths) {
|
||||
var regex = new RegExp(file_paths, "ig");
|
||||
return Extract._search(input, regex, null, display_total);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract dates operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_dates: function(input, args) {
|
||||
var display_total = 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, display_total);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract all identifiers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_all_idents: function(input, args) {
|
||||
var output = "";
|
||||
output += "IP addresses\n";
|
||||
output += Extract.run_ip(input, [true, true, false]);
|
||||
|
||||
output += "\nEmail addresses\n";
|
||||
output += Extract.run_email(input, []);
|
||||
|
||||
output += "\nMAC addresses\n";
|
||||
output += Extract.run_mac(input, []);
|
||||
|
||||
output += "\nURLs\n";
|
||||
output += Extract.run_urls(input, []);
|
||||
|
||||
output += "\nDomain names\n";
|
||||
output += Extract.run_domains(input, []);
|
||||
|
||||
output += "\nFile paths\n";
|
||||
output += Extract.run_file_paths(input, [true, true]);
|
||||
|
||||
output += "\nDates\n";
|
||||
output += Extract.run_dates(input, []);
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
526
src/js/operations/FileType.js
Executable file
526
src/js/operations/FileType.js
Executable file
|
@ -0,0 +1,526 @@
|
|||
/**
|
||||
* File type operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var FileType = {
|
||||
|
||||
/**
|
||||
* Detect File Type operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_detect: function(input, args) {
|
||||
var type = FileType._magic_type(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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_scan_for_embedded_files: 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,
|
||||
ignore_common = args[0],
|
||||
common_exts = ["ico", "ttf", ""],
|
||||
num_found = 0,
|
||||
num_common_found = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
type = FileType._magic_type(input.slice(i));
|
||||
if (type) {
|
||||
if (ignore_common && common_exts.indexOf(type.ext) > -1) {
|
||||
num_common_found++;
|
||||
continue;
|
||||
}
|
||||
num_found++;
|
||||
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 (num_found === 0) {
|
||||
output += "\nNo embedded files were found.";
|
||||
}
|
||||
|
||||
if (num_common_found > 0) {
|
||||
output += "\n\n" + num_common_found;
|
||||
output += num_common_found == 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 {byte_array} buf
|
||||
* @returns {Object} type
|
||||
* @returns {string} type.ext - File extension
|
||||
* @returns {string} type.mime - Mime type
|
||||
* @returns {string} [type.desc] - Description
|
||||
*/
|
||||
_magic_type: 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;
|
||||
},
|
||||
|
||||
};
|
851
src/js/operations/HTML.js
Executable file
851
src/js/operations/HTML.js
Executable file
|
@ -0,0 +1,851 @@
|
|||
/**
|
||||
* HTML operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_to_entity: function(input, args) {
|
||||
var convert_all = args[0],
|
||||
numeric = args[1] == "Numeric entities",
|
||||
hexa = args[1] == "Hex entities";
|
||||
|
||||
var charcodes = Utils.str_to_charcode(input);
|
||||
var output = "";
|
||||
|
||||
for (var i = 0; i < charcodes.length; i++) {
|
||||
if (convert_all && numeric) {
|
||||
output += "&#" + charcodes[i] + ";";
|
||||
} else if (convert_all && hexa) {
|
||||
output += "&#x" + Utils.hex(charcodes[i]) + ";";
|
||||
} else if (convert_all) {
|
||||
output += HTML._byte_to_entity[charcodes[i]] || "&#" + charcodes[i] + ";";
|
||||
} else if (numeric) {
|
||||
if (charcodes[i] > 255 || HTML._byte_to_entity.hasOwnProperty(charcodes[i])) {
|
||||
output += "&#" + charcodes[i] + ";";
|
||||
} else {
|
||||
output += Utils.chr(charcodes[i]);
|
||||
}
|
||||
} else if (hexa) {
|
||||
if (charcodes[i] > 255 || HTML._byte_to_entity.hasOwnProperty(charcodes[i])) {
|
||||
output += "&#x" + Utils.hex(charcodes[i]) + ";";
|
||||
} else {
|
||||
output += Utils.chr(charcodes[i]);
|
||||
}
|
||||
} else {
|
||||
output += HTML._byte_to_entity[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}
|
||||
*/
|
||||
run_from_entity: 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._entity_to_byte[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}
|
||||
*/
|
||||
run_strip_tags: function(input, args) {
|
||||
var remove_indentation = args[0],
|
||||
remove_line_breaks = args[1];
|
||||
|
||||
input = Utils.strip_html_tags(input);
|
||||
|
||||
if (remove_indentation) {
|
||||
input = input.replace(/\n[ \f\t]+/g, "\n");
|
||||
}
|
||||
|
||||
if (remove_line_breaks) {
|
||||
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}
|
||||
*/
|
||||
run_parse_colour_code: 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._hsl_to_rgb(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._rgb_to_hsl(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), // jshint ignore:line
|
||||
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.pad_left(Math.round(r).toString(16), 2) +
|
||||
Utils.pad_left(Math.round(g).toString(16), 2) +
|
||||
Utils.pad_left(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.auto_bake();\
|
||||
});\
|
||||
</script>";
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts an HSL color value to RGB. Conversion formula
|
||||
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
|
||||
* 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
|
||||
*/
|
||||
_hsl_to_rgb: 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_color_space.
|
||||
* 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
|
||||
*/
|
||||
_rgb_to_hsl: 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
|
||||
*/
|
||||
_byte_to_entity: {
|
||||
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
|
||||
*/
|
||||
_entity_to_byte : {
|
||||
"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,
|
||||
},
|
||||
|
||||
};
|
53
src/js/operations/HTTP.js
Executable file
53
src/js/operations/HTTP.js
Executable file
|
@ -0,0 +1,53 @@
|
|||
/* globals UAS_parser */
|
||||
|
||||
/**
|
||||
* HTTP operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var HTTP = {
|
||||
|
||||
/**
|
||||
* Strip HTTP headers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_strip_headers: function(input, args) {
|
||||
var header_end = input.indexOf("\r\n\r\n") +
|
||||
(header_end < 0) ? input.indexOf("\n\n") + 2 : header_end + 4;
|
||||
|
||||
return (header_end < 2) ? input : input.slice(header_end, input.length);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse User Agent operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_parse_user_agent: function(input, args) {
|
||||
var ua = UAS_parser.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";
|
||||
},
|
||||
|
||||
};
|
341
src/js/operations/Hash.js
Executable file
341
src/js/operations/Hash.js
Executable file
|
@ -0,0 +1,341 @@
|
|||
/* globals CryptoJS, Checksum */
|
||||
|
||||
/**
|
||||
* Hashing operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Hash = {
|
||||
|
||||
/**
|
||||
* MD5 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_md5: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray
|
||||
return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA1 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_sha1: 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}
|
||||
*/
|
||||
run_sha224: 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}
|
||||
*/
|
||||
run_sha256: 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}
|
||||
*/
|
||||
run_sha384: 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}
|
||||
*/
|
||||
run_sha512: 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}
|
||||
*/
|
||||
run_sha3: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
var sha3_length = args[0],
|
||||
options = {
|
||||
outputLength: parseInt(sha3_length, 10)
|
||||
};
|
||||
return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* RIPEMD-160 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_ripemd160: 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}
|
||||
*/
|
||||
run_hmac: function (input, args) {
|
||||
var hash_func = 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[hash_func].toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generate all hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_all: function (input, args) {
|
||||
var byte_array = Utils.str_to_byte_array(input),
|
||||
output = "MD5: " + Hash.run_md5(input, []) +
|
||||
"\nSHA1: " + Hash.run_sha1(input, []) +
|
||||
"\nSHA2 224: " + Hash.run_sha224(input, []) +
|
||||
"\nSHA2 256: " + Hash.run_sha256(input, []) +
|
||||
"\nSHA2 384: " + Hash.run_sha384(input, []) +
|
||||
"\nSHA2 512: " + Hash.run_sha512(input, []) +
|
||||
"\nSHA3 224: " + Hash.run_sha3(input, ["224"]) +
|
||||
"\nSHA3 256: " + Hash.run_sha3(input, ["256"]) +
|
||||
"\nSHA3 384: " + Hash.run_sha3(input, ["384"]) +
|
||||
"\nSHA3 512: " + Hash.run_sha3(input, ["512"]) +
|
||||
"\nRIPEMD-160: " + Hash.run_ripemd160(input, []) +
|
||||
"\n\nChecksums:" +
|
||||
"\nFletcher-16: " + Checksum.run_fletcher16(byte_array, []) +
|
||||
"\nAdler-32: " + Checksum.run_adler32(byte_array, []) +
|
||||
"\nCRC-32: " + Checksum.run_crc32(byte_array, []);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Analyse hash operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_analyse: function(input, args) {
|
||||
input = input.replace(/\s/g, "");
|
||||
|
||||
var output = "",
|
||||
byte_length = input.length / 2,
|
||||
bit_length = byte_length * 8,
|
||||
possible_hash_functions = [];
|
||||
|
||||
if (!/^[a-f0-9]+$/i.test(input)) {
|
||||
return "Invalid hash";
|
||||
}
|
||||
|
||||
output += "Hash length: " + input.length + "\n" +
|
||||
"Byte length: " + byte_length + "\n" +
|
||||
"Bit length: " + bit_length + "\n\n" +
|
||||
"Based on the length, this hash could have been generated by one of the following hashing functions:\n";
|
||||
|
||||
switch (bit_length) {
|
||||
case 4:
|
||||
possible_hash_functions = [
|
||||
"Fletcher-4",
|
||||
"Luhn algorithm",
|
||||
"Verhoeff algorithm",
|
||||
];
|
||||
break;
|
||||
case 8:
|
||||
possible_hash_functions = [
|
||||
"Fletcher-8",
|
||||
];
|
||||
break;
|
||||
case 16:
|
||||
possible_hash_functions = [
|
||||
"BSD checksum",
|
||||
"CRC-16",
|
||||
"SYSV checksum",
|
||||
"Fletcher-16"
|
||||
];
|
||||
break;
|
||||
case 32:
|
||||
possible_hash_functions = [
|
||||
"CRC-32",
|
||||
"Fletcher-32",
|
||||
"Adler-32",
|
||||
];
|
||||
break;
|
||||
case 64:
|
||||
possible_hash_functions = [
|
||||
"CRC-64",
|
||||
"RIPEMD-64",
|
||||
"SipHash",
|
||||
];
|
||||
break;
|
||||
case 128:
|
||||
possible_hash_functions = [
|
||||
"MD5",
|
||||
"MD4",
|
||||
"MD2",
|
||||
"HAVAL-128",
|
||||
"RIPEMD-128",
|
||||
"Snefru",
|
||||
"Tiger-128",
|
||||
];
|
||||
break;
|
||||
case 160:
|
||||
possible_hash_functions = [
|
||||
"SHA-1",
|
||||
"SHA-0",
|
||||
"FSB-160",
|
||||
"HAS-160",
|
||||
"HAVAL-160",
|
||||
"RIPEMD-160",
|
||||
"Tiger-160",
|
||||
];
|
||||
break;
|
||||
case 192:
|
||||
possible_hash_functions = [
|
||||
"Tiger",
|
||||
"HAVAL-192",
|
||||
];
|
||||
break;
|
||||
case 224:
|
||||
possible_hash_functions = [
|
||||
"SHA-224",
|
||||
"SHA3-224",
|
||||
"ECOH-224",
|
||||
"FSB-224",
|
||||
"HAVAL-224",
|
||||
];
|
||||
break;
|
||||
case 256:
|
||||
possible_hash_functions = [
|
||||
"SHA-256",
|
||||
"SHA3-256",
|
||||
"BLAKE-256",
|
||||
"ECOH-256",
|
||||
"FSB-256",
|
||||
"GOST",
|
||||
"Grøstl-256",
|
||||
"HAVAL-256",
|
||||
"PANAMA",
|
||||
"RIPEMD-256",
|
||||
"Snefru",
|
||||
];
|
||||
break;
|
||||
case 320:
|
||||
possible_hash_functions = [
|
||||
"RIPEMD-320",
|
||||
];
|
||||
break;
|
||||
case 384:
|
||||
possible_hash_functions = [
|
||||
"SHA-384",
|
||||
"SHA3-384",
|
||||
"ECOH-384",
|
||||
"FSB-384",
|
||||
];
|
||||
break;
|
||||
case 512:
|
||||
possible_hash_functions = [
|
||||
"SHA-512",
|
||||
"SHA3-512",
|
||||
"BLAKE-512",
|
||||
"ECOH-512",
|
||||
"FSB-512",
|
||||
"Grøstl-512",
|
||||
"JH",
|
||||
"MD6",
|
||||
"Spectral Hash",
|
||||
"SWIFFT",
|
||||
"Whirlpool",
|
||||
];
|
||||
break;
|
||||
case 1024:
|
||||
possible_hash_functions = [
|
||||
"Fowler-Noll-Vo",
|
||||
];
|
||||
break;
|
||||
default:
|
||||
possible_hash_functions = [
|
||||
"Unknown"
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
return output + possible_hash_functions.join("\n");
|
||||
},
|
||||
|
||||
};
|
195
src/js/operations/Hexdump.js
Executable file
195
src/js/operations/Hexdump.js
Executable file
|
@ -0,0 +1,195 @@
|
|||
/* globals app */
|
||||
|
||||
/**
|
||||
* Hexdump operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Hexdump = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WIDTH: 16,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
UPPER_CASE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_FINAL_LENGTH: false,
|
||||
|
||||
/**
|
||||
* To Hexdump operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to: function(input, args) {
|
||||
var length = args[0] || Hexdump.WIDTH;
|
||||
var upper_case = args[1];
|
||||
var include_final_length = 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 line_no = Utils.hex(i, 8);
|
||||
|
||||
if (upper_case) {
|
||||
hexa = hexa.toUpperCase();
|
||||
line_no = line_no.toUpperCase();
|
||||
}
|
||||
|
||||
output += line_no + " " +
|
||||
Utils.pad_right(hexa, (length*(padding+1))) +
|
||||
" |" + Utils.pad_right(Utils.printable(Utils.byte_array_to_chars(buff)), buff.length) + "|\n";
|
||||
|
||||
if (include_final_length && 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 {byte_array}
|
||||
*/
|
||||
run_from: 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.from_hex(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) {
|
||||
app.options.attempt_highlight = false;
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to hexdump
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlight_to: 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 start_line_num = Math.floor(pos[0].start / width);
|
||||
var end_line_num = Math.floor(pos[0].end / width);
|
||||
|
||||
if (start_line_num == end_line_num) {
|
||||
pos.push(pos[0]);
|
||||
} else {
|
||||
start = pos[0].start;
|
||||
end = (start_line_num+1) * width - w - 5;
|
||||
pos.push({ start: start, end: end });
|
||||
while (end < pos[0].end) {
|
||||
start_line_num++;
|
||||
start = start_line_num * width + 10;
|
||||
end = (start_line_num+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, line_num = 0;
|
||||
start = 0;
|
||||
end = 0;
|
||||
for (var i = 1; i < len; i++) {
|
||||
line_num = Math.floor(pos[i].start / width);
|
||||
start = (((pos[i].start - (line_num * width)) - 10) / 3) + (width - w -2) + (line_num * width);
|
||||
end = (((pos[i].end + 1 - (line_num * width)) - 10) / 3) + (width - w -2) + (line_num * 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
|
||||
*/
|
||||
highlight_from: 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;
|
||||
},
|
||||
|
||||
};
|
802
src/js/operations/IP.js
Executable file
802
src/js/operations/IP.js
Executable file
|
@ -0,0 +1,802 @@
|
|||
/* globals BigInteger */
|
||||
|
||||
/**
|
||||
* Internet Protocol address operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var IP = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_NETWORK_INFO: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENUMERATE_ADDRESSES: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ALLOW_LARGE_LIST: false,
|
||||
|
||||
/**
|
||||
* Parse IP range operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_parse_ip_range: function (input, args) {
|
||||
var include_network_info = args[0],
|
||||
enumerate_addresses = args[1],
|
||||
allow_large_list = args[2];
|
||||
|
||||
// Check what type of input we are looking at
|
||||
var ipv4_cidr_regex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
|
||||
ipv4_range_regex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
|
||||
ipv6_cidr_regex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i,
|
||||
ipv6_range_regex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
|
||||
match;
|
||||
|
||||
if (!!(match = ipv4_cidr_regex.exec(input))) {
|
||||
return IP._ipv4_cidr_range(match, include_network_info, enumerate_addresses, allow_large_list);
|
||||
} else if (!!(match = ipv4_range_regex.exec(input))) {
|
||||
return IP._ipv4_hyphenated_range(match, include_network_info, enumerate_addresses, allow_large_list);
|
||||
} else if (!!(match = ipv6_cidr_regex.exec(input))) {
|
||||
return IP._ipv6_cidr_range(match, include_network_info);
|
||||
} else if (!!(match = ipv6_range_regex.exec(input))) {
|
||||
return IP._ipv6_hyphenated_range(match, include_network_info);
|
||||
} else {
|
||||
return "Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IPv4_REGEX: /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IPv6_REGEX: /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
|
||||
|
||||
/**
|
||||
* Parse IPv6 address operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_parse_ipv6: function (input, args) {
|
||||
var match,
|
||||
output = "";
|
||||
|
||||
if (!!(match = IP.IPv6_REGEX.exec(input))) {
|
||||
var ipv6 = IP._str_to_ipv6(match[1]),
|
||||
longhand = IP._ipv6_to_str(ipv6),
|
||||
shorthand = IP._ipv6_to_str(ipv6, true);
|
||||
|
||||
output += "Longhand: " + longhand + "\nShorthand: " + shorthand + "\n";
|
||||
|
||||
// Detect reserved addresses
|
||||
if (shorthand == "::") {
|
||||
// Unspecified address
|
||||
output += "\nUnspecified address corresponding to 0.0.0.0/32 in IPv4.";
|
||||
output += "\nUnspecified address range: ::/128";
|
||||
} else if (shorthand == "::1") {
|
||||
// Loopback address
|
||||
output += "\nLoopback address to the local host corresponding to 127.0.0.1/8 in IPv4.";
|
||||
output += "\nLoopback addresses range: ::1/128";
|
||||
} else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 &&
|
||||
ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0xffff) {
|
||||
// IPv4-mapped IPv6 address
|
||||
output += "\nIPv4-mapped IPv6 address detected. IPv6 clients will be handled natively by default, and IPv4 clients appear as IPv6 clients at their IPv4-mapped IPv6 address.";
|
||||
output += "\nMapped IPv4 address: " + IP._ipv4_to_str((ipv6[6] << 16) + ipv6[7]);
|
||||
output += "\nIPv4-mapped IPv6 addresses range: ::ffff:0:0/96";
|
||||
} else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 &&
|
||||
ipv6[3] === 0 && ipv6[4] === 0xffff && ipv6[5] === 0) {
|
||||
// IPv4-translated address
|
||||
output += "\nIPv4-translated address detected. Used by Stateless IP/ICMP Translation (SIIT). See RFCs 6145 and 6052 for more details.";
|
||||
output += "\nTranslated IPv4 address: " + IP._ipv4_to_str((ipv6[6] << 16) + ipv6[7]);
|
||||
output += "\nIPv4-translated addresses range: ::ffff:0:0:0/96";
|
||||
} else if (ipv6[0] === 0x100) {
|
||||
// Discard prefix per RFC 6666
|
||||
output += "\nDiscard prefix detected. This is used when forwarding traffic to a sinkhole router to mitigate the effects of a denial-of-service attack. See RFC 6666 for more details.";
|
||||
output += "\nDiscard range: 100::/64";
|
||||
} else if (ipv6[0] === 0x64 && ipv6[1] === 0xff9b && ipv6[2] === 0 &&
|
||||
ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0) {
|
||||
// IPv4/IPv6 translation per RFC 6052
|
||||
output += "\n'Well-Known' prefix for IPv4/IPv6 translation detected. See RFC 6052 for more details.";
|
||||
output += "\nTranslated IPv4 address: " + IP._ipv4_to_str((ipv6[6] << 16) + ipv6[7]);
|
||||
output += "\n'Well-Known prefix range: 64:ff9b::/96";
|
||||
} else if (ipv6[0] === 0x2001 && ipv6[1] === 0) {
|
||||
// Teredo tunneling
|
||||
output += "\nTeredo tunneling IPv6 address detected\n";
|
||||
var server_ipv4 = (ipv6[2] << 16) + ipv6[3],
|
||||
udp_port = (~ipv6[5]) & 0xffff,
|
||||
client_ipv4 = ~((ipv6[6] << 16) + ipv6[7]),
|
||||
flag_cone = (ipv6[4] >>> 15) & 1,
|
||||
flag_r = (ipv6[4] >>> 14) & 1,
|
||||
flag_random1 = (ipv6[4] >>> 10) & 15,
|
||||
flag_ug = (ipv6[4] >>> 8) & 3,
|
||||
flag_random2 = ipv6[4] & 255;
|
||||
|
||||
output += "\nServer IPv4 address: " + IP._ipv4_to_str(server_ipv4) +
|
||||
"\nClient IPv4 address: " + IP._ipv4_to_str(client_ipv4) +
|
||||
"\nClient UDP port: " + udp_port +
|
||||
"\nFlags:" +
|
||||
"\n\tCone: " + flag_cone;
|
||||
|
||||
if (flag_cone) {
|
||||
output += " (Client is behind a cone NAT)";
|
||||
} else {
|
||||
output += " (Client is not behind a cone NAT)";
|
||||
}
|
||||
|
||||
output += "\n\tR: " + flag_r;
|
||||
|
||||
if (flag_r) {
|
||||
output += " Error: This flag should be set to 0. See RFC 5991 and RFC 4380.";
|
||||
}
|
||||
|
||||
output += "\n\tRandom1: " + Utils.bin(flag_random1, 4) +
|
||||
"\n\tUG: " + Utils.bin(flag_ug, 2);
|
||||
|
||||
if (flag_ug) {
|
||||
output += " Error: This flag should be set to 00. See RFC 4380.";
|
||||
}
|
||||
|
||||
output += "\n\tRandom2: " + Utils.bin(flag_random2, 8);
|
||||
|
||||
if (!flag_r && !flag_ug && flag_random1 && flag_random2) {
|
||||
output += "\n\nThis is a valid Teredo address which complies with RFC 4380 and RFC 5991.";
|
||||
} else if (!flag_r && !flag_ug) {
|
||||
output += "\n\nThis is a valid Teredo address which complies with RFC 4380, however it does not comply with RFC 5991 (Teredo Security Updates) as there are no randomised bits in the flag field.";
|
||||
} else {
|
||||
output += "\n\nThis is an invalid Teredo address.";
|
||||
}
|
||||
output += "\n\nTeredo prefix range: 2001::/32";
|
||||
} else if (ipv6[0] === 0x2001 && ipv6[1] === 0x2 && ipv6[2] === 0) {
|
||||
// Benchmarking
|
||||
output += "\nAssigned to the Benchmarking Methodology Working Group (BMWG) for benchmarking IPv6. Corresponds to 198.18.0.0/15 for benchmarking IPv4. See RFC 5180 for more details.";
|
||||
output += "\nBMWG range: 2001:2::/48";
|
||||
} else if (ipv6[0] == 0x2001 && ipv6[1] >= 0x10 && ipv6[1] <= 0x1f) {
|
||||
// ORCHIDv1
|
||||
output += "\nDeprecated, previously ORCHIDv1 (Overlay Routable Cryptographic Hash Identifiers).\nORCHIDv1 range: 2001:10::/28\nORCHIDv2 now uses 2001:20::/28.";
|
||||
} else if (ipv6[0] == 0x2001 && ipv6[1] >= 0x20 && ipv6[1] <= 0x2f) {
|
||||
// ORCHIDv2
|
||||
output += "\nORCHIDv2 (Overlay Routable Cryptographic Hash Identifiers).\nThese are non-routed IPv6 addresses used for Cryptographic Hash Identifiers.";
|
||||
output += "\nORCHIDv2 range: 2001:20::/28";
|
||||
} else if (ipv6[0] == 0x2001 && ipv6[1] == 0xdb8) {
|
||||
// Documentation
|
||||
output += "\nThis is a documentation IPv6 address. This range should be used whenever an example IPv6 address is given or to model networking scenarios. Corresponds to 192.0.2.0/24, 198.51.100.0/24, and 203.0.113.0/24 in IPv4.";
|
||||
output += "\nDocumentation range: 2001:db8::/32";
|
||||
} else if (ipv6[0] == 0x2002) {
|
||||
// 6to4
|
||||
output += "\n6to4 transition IPv6 address detected. See RFC 3056 for more details." +
|
||||
"\n6to4 prefix range: 2002::/16";
|
||||
|
||||
var v4_addr = IP._ipv4_to_str((ipv6[1] << 16) + ipv6[2]),
|
||||
sla_id = ipv6[3],
|
||||
interface_id_str = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16),
|
||||
interface_id = new BigInteger(interface_id_str, 16);
|
||||
|
||||
output += "\n\nEncapsulated IPv4 address: " + v4_addr +
|
||||
"\nSLA ID: " + sla_id +
|
||||
"\nInterface ID (base 16): " + interface_id_str +
|
||||
"\nInterface ID (base 10): " + interface_id.toString();
|
||||
} else if (ipv6[0] >= 0xfc00 && ipv6[0] <= 0xfdff) {
|
||||
// Unique local address
|
||||
output += "\nThis is a unique local address comparable to the IPv4 private addresses 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. See RFC 4193 for more details.";
|
||||
output += "\nUnique local addresses range: fc00::/7";
|
||||
} else if (ipv6[0] >= 0xfe80 && ipv6[0] <= 0xfebf) {
|
||||
// Link-local address
|
||||
output += "\nThis is a link-local address comparable to the auto-configuration addresses 169.254.0.0/16 in IPv4.";
|
||||
output += "\nLink-local addresses range: fe80::/10";
|
||||
} else if (ipv6[0] >= 0xff00) {
|
||||
// Multicast
|
||||
output += "\nThis is a reserved multicast address.";
|
||||
output += "\nMulticast addresses range: ff00::/8";
|
||||
}
|
||||
} else {
|
||||
return "Invalid IPv6 address";
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IP_FORMAT_LIST: ["Dotted Decimal", "Decimal", "Hex"],
|
||||
|
||||
/**
|
||||
* Change IP format operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_change_ip_format: function(input, args) {
|
||||
var in_format = args[0],
|
||||
out_format = args[1],
|
||||
lines = input.split("\n"),
|
||||
output = "",
|
||||
j = 0;
|
||||
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
if (lines[i] === "") continue;
|
||||
var ba_ip = [];
|
||||
|
||||
if (in_format == out_format) {
|
||||
output += lines[i] + "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert to byte array IP from input format
|
||||
switch (in_format) {
|
||||
case "Dotted Decimal":
|
||||
var octets = lines[i].split(".");
|
||||
for (j = 0; j < octets.length; j++) {
|
||||
ba_ip.push(parseInt(octets[j], 10));
|
||||
}
|
||||
break;
|
||||
case "Decimal":
|
||||
var decimal = lines[i].toString();
|
||||
ba_ip.push(decimal >> 24 & 255);
|
||||
ba_ip.push(decimal >> 16 & 255);
|
||||
ba_ip.push(decimal >> 8 & 255);
|
||||
ba_ip.push(decimal & 255);
|
||||
break;
|
||||
case "Hex":
|
||||
ba_ip = Utils.hex_to_byte_array(lines[i]);
|
||||
break;
|
||||
default:
|
||||
throw "Unsupported input IP format";
|
||||
}
|
||||
|
||||
// Convert byte array IP to output format
|
||||
switch (out_format) {
|
||||
case "Dotted Decimal":
|
||||
var dd_ip = "";
|
||||
for (j = 0; j < ba_ip.length; j++) {
|
||||
dd_ip += ba_ip[j] + ".";
|
||||
}
|
||||
output += dd_ip.slice(0, dd_ip.length-1) + "\n";
|
||||
break;
|
||||
case "Decimal":
|
||||
var dec_ip = ((ba_ip[0] << 24) | (ba_ip[1] << 16) | (ba_ip[2] << 8) | ba_ip[3]) >>> 0;
|
||||
output += dec_ip.toString() + "\n";
|
||||
break;
|
||||
case "Hex":
|
||||
var hex_ip = "";
|
||||
for (j = 0; j < ba_ip.length; j++) {
|
||||
hex_ip += Utils.hex(ba_ip[j]);
|
||||
}
|
||||
output += hex_ip + "\n";
|
||||
break;
|
||||
default:
|
||||
throw "Unsupported output IP format";
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIM_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
GROUP_CIDR: 24,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
GROUP_ONLY_SUBNET: false,
|
||||
|
||||
/**
|
||||
* Group IP addresses operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_group_ips: function(input, args) {
|
||||
var delim = Utils.char_rep[args[0]],
|
||||
cidr = args[1],
|
||||
only_subnets = args[2],
|
||||
ipv4_mask = cidr < 32 ? ~(0xFFFFFFFF >>> cidr) : 0xFFFFFFFF,
|
||||
ipv6_mask = IP._gen_ipv6_mask(cidr),
|
||||
ips = input.split(delim),
|
||||
ipv4_networks = {},
|
||||
ipv6_networks = {},
|
||||
match = null,
|
||||
output = "",
|
||||
ip = null,
|
||||
network = null,
|
||||
network_str = "";
|
||||
|
||||
if (cidr < 0 || cidr > 127) {
|
||||
return "CIDR must be less than 32 for IPv4 or 128 for IPv6";
|
||||
}
|
||||
|
||||
// Parse all IPs and add to network dictionary
|
||||
for (var i = 0; i < ips.length; i++) {
|
||||
if (!!(match = IP.IPv4_REGEX.exec(ips[i]))) {
|
||||
ip = IP._str_to_ipv4(match[1]) >>> 0;
|
||||
network = ip & ipv4_mask;
|
||||
|
||||
if (ipv4_networks.hasOwnProperty(network)) {
|
||||
ipv4_networks[network].push(ip);
|
||||
} else {
|
||||
ipv4_networks[network] = [ip];
|
||||
}
|
||||
} else if (!!(match = IP.IPv6_REGEX.exec(ips[i]))) {
|
||||
ip = IP._str_to_ipv6(match[1]);
|
||||
network = [];
|
||||
network_str = "";
|
||||
|
||||
for (var j = 0; j < 8; j++) {
|
||||
network.push(ip[j] & ipv6_mask[j]);
|
||||
}
|
||||
|
||||
network_str = IP._ipv6_to_str(network, true);
|
||||
|
||||
if (ipv6_networks.hasOwnProperty(network_str)) {
|
||||
ipv6_networks[network_str].push(ip);
|
||||
} else {
|
||||
ipv6_networks[network_str] = [ip];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort IPv4 network dictionaries and print
|
||||
for (network in ipv4_networks) {
|
||||
ipv4_networks[network] = ipv4_networks[network].sort();
|
||||
|
||||
output += IP._ipv4_to_str(network) + "/" + cidr + "\n";
|
||||
|
||||
if (!only_subnets) {
|
||||
for (i = 0; i < ipv4_networks[network].length; i++) {
|
||||
output += " " + IP._ipv4_to_str(ipv4_networks[network][i]) + "\n";
|
||||
}
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Sort IPv6 network dictionaries and print
|
||||
for (network_str in ipv6_networks) {
|
||||
//ipv6_networks[network_str] = ipv6_networks[network_str].sort(); TODO
|
||||
|
||||
output += network_str + "/" + cidr + "\n";
|
||||
|
||||
if (!only_subnets) {
|
||||
for (i = 0; i < ipv6_networks[network_str].length; i++) {
|
||||
output += " " + IP._ipv6_to_str(ipv6_networks[network_str][i], true) + "\n";
|
||||
}
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
* @private
|
||||
*/
|
||||
_LARGE_RANGE_ERROR: "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges.",
|
||||
|
||||
/**
|
||||
* Parses an IPv4 CIDR range (e.g. 192.168.0.0/24) and displays information about it.
|
||||
*
|
||||
* @private
|
||||
* @param {RegExp} cidr
|
||||
* @param {boolean} include_network_info
|
||||
* @param {boolean} enumerate_addresses
|
||||
* @param {boolean} allow_large_list
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv4_cidr_range: function(cidr, include_network_info, enumerate_addresses, allow_large_list) {
|
||||
var output = "",
|
||||
network = IP._str_to_ipv4(cidr[1]),
|
||||
cidr_range = parseInt(cidr[2], 10);
|
||||
|
||||
if (cidr_range < 0 || cidr_range > 31) {
|
||||
return "IPv4 CIDR must be less than 32";
|
||||
}
|
||||
|
||||
var mask = ~(0xFFFFFFFF >>> cidr_range),
|
||||
ip1 = network & mask,
|
||||
ip2 = ip1 | ~mask;
|
||||
|
||||
if (include_network_info) {
|
||||
output += "Network: " + IP._ipv4_to_str(network) + "\n";
|
||||
output += "CIDR: " + cidr_range + "\n";
|
||||
output += "Mask: " + IP._ipv4_to_str(mask) + "\n";
|
||||
output += "Range: " + IP._ipv4_to_str(ip1) + " - " + IP._ipv4_to_str(ip2) + "\n";
|
||||
output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
|
||||
}
|
||||
|
||||
if (enumerate_addresses) {
|
||||
if (cidr_range >= 16 || allow_large_list) {
|
||||
output += IP._generate_ipv4_range(ip1, ip2).join("\n");
|
||||
} else {
|
||||
output += IP._LARGE_RANGE_ERROR;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parses an IPv6 CIDR range (e.g. ff00::/48) and displays information about it.
|
||||
*
|
||||
* @private
|
||||
* @param {RegExp} cidr
|
||||
* @param {boolean} include_network_info
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv6_cidr_range: function(cidr, include_network_info) {
|
||||
var output = "",
|
||||
network = IP._str_to_ipv6(cidr[1]),
|
||||
cidr_range = parseInt(cidr[cidr.length-1], 10);
|
||||
|
||||
if (cidr_range < 0 || cidr_range > 127) {
|
||||
return "IPv6 CIDR must be less than 128";
|
||||
}
|
||||
|
||||
var mask = IP._gen_ipv6_mask(cidr_range),
|
||||
ip1 = new Array(8),
|
||||
ip2 = new Array(8),
|
||||
total_diff = "",
|
||||
total = new Array(128);
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
ip1[i] = network[i] & mask[i];
|
||||
ip2[i] = ip1[i] | (~mask[i] & 0x0000FFFF);
|
||||
total_diff = (ip2[i] - ip1[i]).toString(2);
|
||||
|
||||
if (total_diff != "0") {
|
||||
for (var n = 0; n < total_diff.length; n++) {
|
||||
total[i*16 + 16-(total_diff.length-n)] = total_diff[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (include_network_info) {
|
||||
output += "Network: " + IP._ipv6_to_str(network) + "\n";
|
||||
output += "Shorthand: " + IP._ipv6_to_str(network, true) + "\n";
|
||||
output += "CIDR: " + cidr_range + "\n";
|
||||
output += "Mask: " + IP._ipv6_to_str(mask) + "\n";
|
||||
output += "Range: " + IP._ipv6_to_str(ip1) + " - " + IP._ipv6_to_str(ip2) + "\n";
|
||||
output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n";
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generates an IPv6 subnet mask given a CIDR value.
|
||||
*
|
||||
* @private
|
||||
* @param {number} cidr
|
||||
* @returns {number[]}
|
||||
*/
|
||||
_gen_ipv6_mask: function(cidr) {
|
||||
var mask = new Array(8),
|
||||
shift;
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
if (cidr > ((i+1)*16)) {
|
||||
mask[i] = 0x0000FFFF;
|
||||
} else {
|
||||
shift = cidr-(i*16);
|
||||
if (shift < 0) shift = 0;
|
||||
mask[i] = ~((0x0000FFFF >>> shift) | 0xFFFF0000);
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parses an IPv4 hyphenated range (e.g. 192.168.0.0 - 192.168.0.255) and displays information
|
||||
* about it.
|
||||
*
|
||||
* @private
|
||||
* @param {RegExp} range
|
||||
* @param {boolean} include_network_info
|
||||
* @param {boolean} enumerate_addresses
|
||||
* @param {boolean} allow_large_list
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv4_hyphenated_range: function(range, include_network_info, enumerate_addresses, allow_large_list) {
|
||||
var output = "",
|
||||
ip1 = IP._str_to_ipv4(range[1]),
|
||||
ip2 = IP._str_to_ipv4(range[2]);
|
||||
|
||||
// Calculate mask
|
||||
var diff = ip1 ^ ip2,
|
||||
cidr = 32,
|
||||
mask = 0;
|
||||
|
||||
while (diff !== 0) {
|
||||
diff >>= 1;
|
||||
cidr--;
|
||||
mask = (mask << 1) | 1;
|
||||
}
|
||||
|
||||
mask = ~mask >>> 0;
|
||||
var network = ip1 & mask,
|
||||
sub_ip1 = network & mask,
|
||||
sub_ip2 = sub_ip1 | ~mask;
|
||||
|
||||
if (include_network_info) {
|
||||
output += "Minimum subnet required to hold this range:\n";
|
||||
output += "\tNetwork: " + IP._ipv4_to_str(network) + "\n";
|
||||
output += "\tCIDR: " + cidr + "\n";
|
||||
output += "\tMask: " + IP._ipv4_to_str(mask) + "\n";
|
||||
output += "\tSubnet range: " + IP._ipv4_to_str(sub_ip1) + " - " + IP._ipv4_to_str(sub_ip2) + "\n";
|
||||
output += "\tTotal addresses in subnet: " + (((sub_ip2 - sub_ip1) >>> 0) + 1) + "\n\n";
|
||||
output += "Range: " + IP._ipv4_to_str(ip1) + " - " + IP._ipv4_to_str(ip2) + "\n";
|
||||
output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
|
||||
}
|
||||
|
||||
if (enumerate_addresses) {
|
||||
if (((ip2 - ip1) >>> 0) <= 65536 || allow_large_list) {
|
||||
output += IP._generate_ipv4_range(ip1, ip2).join("\n");
|
||||
} else {
|
||||
output += IP._LARGE_RANGE_ERROR;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parses an IPv6 hyphenated range (e.g. ff00:: - ffff::) and displays information about it.
|
||||
*
|
||||
* @private
|
||||
* @param {RegExp} range
|
||||
* @param {boolean} include_network_info
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv6_hyphenated_range: function(range, include_network_info) {
|
||||
var output = "",
|
||||
ip1 = IP._str_to_ipv6(range[1]),
|
||||
ip2 = IP._str_to_ipv6(range[14]);
|
||||
|
||||
var t = "",
|
||||
total = new Array(128);
|
||||
|
||||
// Initialise total array to "0"
|
||||
for (var i = 0; i < 128; i++)
|
||||
total[i] = "0";
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
t = (ip2[i] - ip1[i]).toString(2);
|
||||
if (t != "0") {
|
||||
for (var n = 0; n < t.length; n++) {
|
||||
total[i*16 + 16-(t.length-n)] = t[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (include_network_info) {
|
||||
output += "Range: " + IP._ipv6_to_str(ip1) + " - " + IP._ipv6_to_str(ip2) + "\n";
|
||||
output += "Shorthand range: " + IP._ipv6_to_str(ip1, true) + " - " + IP._ipv6_to_str(ip2, true) + "\n";
|
||||
output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n";
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts an IPv4 address from string format to numerical format.
|
||||
*
|
||||
* @private
|
||||
* @param {string} ip_str
|
||||
* @returns {number}
|
||||
*
|
||||
* @example
|
||||
* // returns 168427520
|
||||
* IP._str_to_ipv4("10.10.0.0");
|
||||
*/
|
||||
_str_to_ipv4: function (ip_str) {
|
||||
var blocks = ip_str.split("."),
|
||||
num_blocks = parse_blocks(blocks),
|
||||
result = 0;
|
||||
|
||||
result += num_blocks[0] << 24;
|
||||
result += num_blocks[1] << 16;
|
||||
result += num_blocks[2] << 8;
|
||||
result += num_blocks[3];
|
||||
|
||||
return result;
|
||||
|
||||
function parse_blocks(blocks) {
|
||||
if (blocks.length != 4)
|
||||
throw "More than 4 blocks.";
|
||||
|
||||
var num_blocks = [];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
num_blocks[i] = parseInt(blocks[i], 10);
|
||||
if (num_blocks[i] < 0 || num_blocks[i] > 255)
|
||||
throw "Block out of range.";
|
||||
}
|
||||
return num_blocks;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts an IPv4 address from numerical format to string format.
|
||||
*
|
||||
* @private
|
||||
* @param {number} ip_int
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns "10.10.0.0"
|
||||
* IP._ipv4_to_str(168427520);
|
||||
*/
|
||||
_ipv4_to_str: function(ip_int) {
|
||||
var blockA = (ip_int >> 24) & 255,
|
||||
blockB = (ip_int >> 16) & 255,
|
||||
blockC = (ip_int >> 8) & 255,
|
||||
blockD = ip_int & 255;
|
||||
|
||||
return blockA + "." + blockB + "." + blockC + "." + blockD;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts an IPv6 address from string format to numerical array format.
|
||||
*
|
||||
* @private
|
||||
* @param {string} ip_str
|
||||
* @returns {number[]}
|
||||
*
|
||||
* @example
|
||||
* // returns [65280, 0, 0, 0, 0, 0, 4369, 8738]
|
||||
* IP._str_to_ipv6("ff00::1111:2222");
|
||||
*/
|
||||
_str_to_ipv6: function(ip_str) {
|
||||
var blocks = ip_str.split(":"),
|
||||
num_blocks = parse_blocks(blocks),
|
||||
j = 0,
|
||||
ipv6 = new Array(8);
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
if (isNaN(num_blocks[j])) {
|
||||
ipv6[i] = 0;
|
||||
if (i == (8-num_blocks.slice(j).length)) j++;
|
||||
} else {
|
||||
ipv6[i] = num_blocks[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return ipv6;
|
||||
|
||||
function parse_blocks(blocks) {
|
||||
if (blocks.length < 3 || blocks.length > 8)
|
||||
throw "Badly formatted IPv6 address.";
|
||||
var num_blocks = [];
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
num_blocks[i] = parseInt(blocks[i], 16);
|
||||
if (num_blocks[i] < 0 || num_blocks[i] > 65535)
|
||||
throw "Block out of range.";
|
||||
}
|
||||
return num_blocks;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts an IPv6 address from numerical array format to string format.
|
||||
*
|
||||
* @private
|
||||
* @param {number[]} ipv6
|
||||
* @param {boolean} compact - Whether or not to return the address in shorthand or not
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns "ff00::1111:2222"
|
||||
* IP._ipv6_to_str([65280, 0, 0, 0, 0, 0, 4369, 8738], true);
|
||||
*
|
||||
* // returns "ff00:0000:0000:0000:0000:0000:1111:2222"
|
||||
* IP._ipv6_to_str([65280, 0, 0, 0, 0, 0, 4369, 8738], false);
|
||||
*/
|
||||
_ipv6_to_str: function(ipv6, compact) {
|
||||
var output = "",
|
||||
skips = 0,
|
||||
i = 0;
|
||||
|
||||
if (compact) {
|
||||
var start = -1,
|
||||
end = -1,
|
||||
s = 0,
|
||||
e = -1;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (ipv6[i] === 0 && e === (i-1)) {
|
||||
e = i;
|
||||
} else if (ipv6[i] === 0) {
|
||||
s = i; e = i;
|
||||
}
|
||||
if (e >= 0 && (e-s) > (end - start)) {
|
||||
start = s;
|
||||
end = e;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i != start) {
|
||||
output += Utils.hex(ipv6[i],1) + ":";
|
||||
} else {
|
||||
output += ":";
|
||||
i = end;
|
||||
if (end === 7) output += ":";
|
||||
}
|
||||
}
|
||||
if (output[0] === ":")
|
||||
output = ":" + output;
|
||||
} else {
|
||||
for (i = 0; i < 8; i++) {
|
||||
output += Utils.hex(ipv6[i],4) + ":";
|
||||
}
|
||||
}
|
||||
return output.slice(0,output.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generates a list of IPv4 addresses in string format between two given numerical values.
|
||||
*
|
||||
* @private
|
||||
* @param {number} ip
|
||||
* @param {number} end_ip
|
||||
* @returns {string[]}
|
||||
*
|
||||
* @example
|
||||
* // returns ["0.0.0.1", "0.0.0.2", "0.0.0.3"]
|
||||
* IP._generate_ipv4_range(1, 3);
|
||||
*/
|
||||
_generate_ipv4_range: function(ip, end_ip) {
|
||||
var range = [];
|
||||
if (end_ip >= ip) {
|
||||
for (; ip <= end_ip; ip++) {
|
||||
range.push(IP._ipv4_to_str(ip));
|
||||
}
|
||||
} else {
|
||||
range[0] = "Second IP address smaller than first.";
|
||||
}
|
||||
return range;
|
||||
},
|
||||
|
||||
};
|
159
src/js/operations/JS.js
Executable file
159
src/js/operations/JS.js
Executable file
|
@ -0,0 +1,159 @@
|
|||
/* globals esprima, escodegen, esmangle */
|
||||
|
||||
/**
|
||||
* JavaScript operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_parse: function (input, args) {
|
||||
var parse_loc = args[0],
|
||||
parse_range = args[1],
|
||||
parse_tokens = args[2],
|
||||
parse_comment = args[3],
|
||||
parse_tolerant = args[4],
|
||||
result = {},
|
||||
options = {
|
||||
loc: parse_loc,
|
||||
range: parse_range,
|
||||
tokens: parse_tokens,
|
||||
comment: parse_comment,
|
||||
tolerant: parse_tolerant
|
||||
};
|
||||
|
||||
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}
|
||||
*/
|
||||
run_beautify: function(input, args) {
|
||||
var beautify_indent = args[0] || JS.BEAUTIFY_INDENT,
|
||||
quotes = args[1].toLowerCase(),
|
||||
beautify_semicolons = args[2],
|
||||
beautify_comment = args[3],
|
||||
result = "",
|
||||
AST;
|
||||
|
||||
try {
|
||||
AST = esprima.parse(input, {
|
||||
range: true,
|
||||
tokens: true,
|
||||
comment: true
|
||||
});
|
||||
|
||||
var options = {
|
||||
format: {
|
||||
indent: {
|
||||
style: beautify_indent
|
||||
},
|
||||
quotes: quotes,
|
||||
semicolons: beautify_semicolons,
|
||||
},
|
||||
comment: beautify_comment
|
||||
};
|
||||
|
||||
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}
|
||||
*/
|
||||
run_minify: function(input, args) {
|
||||
var result = "",
|
||||
AST = esprima.parse(input),
|
||||
optimised_AST = esmangle.optimize(AST, null),
|
||||
mangled_AST = esmangle.mangle(optimised_AST);
|
||||
|
||||
result = escodegen.generate(mangled_AST, {
|
||||
format: {
|
||||
renumber: true,
|
||||
hexadecimal: true,
|
||||
escapeless: true,
|
||||
compact: true,
|
||||
semicolons: false,
|
||||
parentheses: false
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
88
src/js/operations/MAC.js
Executable file
88
src/js/operations/MAC.js
Executable file
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* MAC address operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_format: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
var output_case = args[0],
|
||||
no_delim = args[1],
|
||||
dash_delim = args[2],
|
||||
colon_delim = args[3],
|
||||
cisco_style = args[4],
|
||||
output_list = [],
|
||||
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 (output_case == "Lower only") {
|
||||
if (no_delim) output_list.push(cleanMac);
|
||||
if (dash_delim) output_list.push(macHyphen);
|
||||
if (colon_delim) output_list.push(macColon);
|
||||
if (cisco_style) output_list.push(macCisco);
|
||||
} else if (output_case == "Upper only") {
|
||||
if (no_delim) output_list.push(cleanMac.toUpperCase());
|
||||
if (dash_delim) output_list.push(macHyphen.toUpperCase());
|
||||
if (colon_delim) output_list.push(macColon.toUpperCase());
|
||||
if (cisco_style) output_list.push(macCisco.toUpperCase());
|
||||
} else {
|
||||
if (no_delim) output_list.push(cleanMac, cleanMac.toUpperCase());
|
||||
if (dash_delim) output_list.push(macHyphen, macHyphen.toUpperCase());
|
||||
if (colon_delim) output_list.push(macColon, macColon.toUpperCase());
|
||||
if (cisco_style) output_list.push(macCisco, macCisco.toUpperCase());
|
||||
}
|
||||
|
||||
output_list.push(
|
||||
"" // Empty line to delimit groups
|
||||
);
|
||||
});
|
||||
|
||||
// Return the data as a string
|
||||
return output_list.join('\n');
|
||||
},
|
||||
|
||||
};
|
27
src/js/operations/Numberwang.js
Executable file
27
src/js/operations/Numberwang.js
Executable file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Numberwang operations.
|
||||
*
|
||||
* @author Unknown Male 282
|
||||
* @namespace
|
||||
*/
|
||||
var 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!";
|
||||
}
|
||||
},
|
||||
|
||||
};
|
309
src/js/operations/OS.js
Executable file
309
src/js/operations/OS.js
Executable file
|
@ -0,0 +1,309 @@
|
|||
/**
|
||||
* Operating system operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var OS = {
|
||||
|
||||
/**
|
||||
* Parse UNIX file permissions operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_parse_unix_perms: 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._perms_to_str(perms);
|
||||
output += "\nOctal representation: " + OS._perms_to_octal(perms);
|
||||
|
||||
// File type
|
||||
if (textual) {
|
||||
output += "\nFile type: " + OS._ft_from_perms(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}
|
||||
*/
|
||||
_perms_to_str: 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}
|
||||
*/
|
||||
_perms_to_octal: 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}
|
||||
*/
|
||||
_ft_from_perms: 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";
|
||||
},
|
||||
|
||||
};
|
1053
src/js/operations/PublicKey.js
Executable file
1053
src/js/operations/PublicKey.js
Executable file
File diff suppressed because it is too large
Load diff
55
src/js/operations/Punycode.js
Executable file
55
src/js/operations/Punycode.js
Executable file
|
@ -0,0 +1,55 @@
|
|||
/* globals punycode */
|
||||
|
||||
/**
|
||||
* Punycode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Punycode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IDN: false,
|
||||
|
||||
/**
|
||||
* To Punycode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to_ascii: 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}
|
||||
*/
|
||||
run_to_unicode: function(input, args) {
|
||||
var idn = args[0];
|
||||
|
||||
if (idn) {
|
||||
return punycode.ToUnicode(input);
|
||||
} else {
|
||||
return punycode.decode(input);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
270
src/js/operations/QuotedPrintable.js
Executable file
270
src/js/operations/QuotedPrintable.js
Executable file
|
@ -0,0 +1,270 @@
|
|||
/** @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
|
||||
*/
|
||||
var QuotedPrintable = {
|
||||
|
||||
/**
|
||||
* To Quoted Printable operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to: 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 {byte_array}
|
||||
*/
|
||||
run_from: function (input, args) {
|
||||
var str = input.replace(/\=(?:\r?\n|$)/g, "");
|
||||
return QuotedPrintable.mimeDecode(str);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Decodes mime-encoded data.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
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 {byte_array} 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 {byte_array[]} 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;
|
||||
},
|
||||
|
||||
};
|
206
src/js/operations/Rotate.js
Executable file
206
src/js/operations/Rotate.js
Executable file
|
@ -0,0 +1,206 @@
|
|||
/**
|
||||
* Bit rotation operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*
|
||||
* @todo Support for UTF16
|
||||
*/
|
||||
var Rotate = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROTATE_AMOUNT: 1,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROTATE_WHOLE: false,
|
||||
|
||||
/**
|
||||
* Runs rotation operations across the input data.
|
||||
*
|
||||
* @private
|
||||
* @param {byte_array} data
|
||||
* @param {number} amount
|
||||
* @param {function} algo - The rotation operation to carry out
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
_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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_rotr: function(input, args) {
|
||||
if (args[1]) {
|
||||
return Rotate._rotr_whole(input, args[0]);
|
||||
} else {
|
||||
return Rotate._rot(input, args[0], Rotate._rotr);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Rotate left operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_rotl: function(input, args) {
|
||||
if (args[1]) {
|
||||
return Rotate._rotl_whole(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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_rot13: function(input, args) {
|
||||
var amount = args[2],
|
||||
output = input,
|
||||
chr,
|
||||
rot13_lowercase = args[0],
|
||||
rot13_upperacse = 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 (rot13_upperacse && chr >= 65 && chr <= 90) { // Upper case
|
||||
chr = (chr - 65 + amount) % 26;
|
||||
output[i] = chr + 65;
|
||||
} else if (rot13_lowercase && chr >= 97 && chr <= 122) { // Lower case
|
||||
chr = (chr - 97 + amount) % 26;
|
||||
output[i] = chr + 97;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {byte_array} data
|
||||
* @param {number} amount
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
_rotr_whole: function(data, amount) {
|
||||
var carry_bits = 0,
|
||||
new_byte,
|
||||
result = [];
|
||||
|
||||
amount = amount % 8;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var old_byte = data[i] >>> 0;
|
||||
new_byte = (old_byte >> amount) | carry_bits;
|
||||
carry_bits = (old_byte & (Math.pow(2, amount)-1)) << (8-amount);
|
||||
result.push(new_byte);
|
||||
}
|
||||
result[0] |= carry_bits;
|
||||
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 {byte_array} data
|
||||
* @param {number} amount
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
_rotl_whole: function(data, amount) {
|
||||
var carry_bits = 0,
|
||||
new_byte,
|
||||
result = [];
|
||||
|
||||
amount = amount % 8;
|
||||
for (var i = data.length-1; i >= 0; i--) {
|
||||
var old_byte = data[i];
|
||||
new_byte = ((old_byte << amount) | carry_bits) & 0xFF;
|
||||
carry_bits = (old_byte >> (8-amount)) & (Math.pow(2, amount)-1);
|
||||
result[i] = (new_byte);
|
||||
}
|
||||
result[data.length-1] = result[data.length-1] | carry_bits;
|
||||
return result;
|
||||
},
|
||||
|
||||
};
|
220
src/js/operations/SeqUtils.js
Executable file
220
src/js/operations/SeqUtils.js
Executable file
|
@ -0,0 +1,220 @@
|
|||
/**
|
||||
* Sequence utility operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_sort: function (input, args) {
|
||||
var delim = Utils.char_rep[args[0]],
|
||||
sort_reverse = 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._case_insensitive_sort);
|
||||
} else if (order == "IP address") {
|
||||
sorted = sorted.sort(SeqUtils._ip_sort);
|
||||
}
|
||||
|
||||
if (sort_reverse) sorted.reverse();
|
||||
return sorted.join(delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Unique operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_unique: function (input, args) {
|
||||
var delim = Utils.char_rep[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}
|
||||
*/
|
||||
run_count: 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.parse_escaped_chars(search);
|
||||
}
|
||||
return input.count(search);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REVERSE_BY: ["Character", "Line"],
|
||||
|
||||
/**
|
||||
* Reverse operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_reverse: 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}
|
||||
*/
|
||||
run_add_line_numbers: 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}
|
||||
*/
|
||||
run_remove_line_numbers: function(input, args) {
|
||||
return input.replace(/^[ \t]{0,5}\d+[\s:|\-,.)\]]/gm, "");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Expand alphabet range operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_expand_alph_range: function(input, args) {
|
||||
return Utils.expand_alph_range(input).join(args[0]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of strings ignoring case.
|
||||
*
|
||||
* @private
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
_case_insensitive_sort: 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}
|
||||
*/
|
||||
_ip_sort: 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_;
|
||||
},
|
||||
|
||||
};
|
512
src/js/operations/StrUtils.js
Executable file
512
src/js/operations/StrUtils.js
Executable file
|
@ -0,0 +1,512 @@
|
|||
/* globals JsDiff */
|
||||
|
||||
/**
|
||||
* String utility operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_regex: function(input, args) {
|
||||
var user_regex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
display_total = args[4],
|
||||
output_format = args[5],
|
||||
modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (user_regex && user_regex != "^" && user_regex != "$") {
|
||||
try {
|
||||
var regex = new RegExp(user_regex, modifiers);
|
||||
|
||||
switch (output_format) {
|
||||
case "Highlight matches":
|
||||
return StrUtils._regex_highlight(input, regex, display_total);
|
||||
case "List matches":
|
||||
return Utils.escape_html(StrUtils._regex_list(input, regex, display_total, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escape_html(StrUtils._regex_list(input, regex, display_total, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escape_html(StrUtils._regex_list(input, regex, display_total, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
}
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
} else {
|
||||
return Utils.escape_html(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
CASE_SCOPE: ["All", "Word", "Sentence", "Paragraph"],
|
||||
|
||||
/**
|
||||
* To Upper case operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_upper: 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}
|
||||
*/
|
||||
run_lower: 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}
|
||||
*/
|
||||
run_find_replace: 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.parse_escaped_chars(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}
|
||||
*/
|
||||
run_split: function(input, args) {
|
||||
var split_delim = args[0] || StrUtils.SPLIT_DELIM,
|
||||
join_delim = Utils.char_rep[args[1]],
|
||||
sections = input.split(split_delim);
|
||||
|
||||
return sections.join(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}
|
||||
*/
|
||||
run_diff: function(input, args) {
|
||||
var sample_delim = args[0],
|
||||
diff_by = args[1],
|
||||
show_added = args[2],
|
||||
show_removed = args[3],
|
||||
ignore_whitespace = args[4],
|
||||
samples = input.split(sample_delim),
|
||||
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 (diff_by) {
|
||||
case "Character":
|
||||
diff = JsDiff.diffChars(samples[0], samples[1]);
|
||||
break;
|
||||
case "Word":
|
||||
if (ignore_whitespace) {
|
||||
diff = JsDiff.diffWords(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Line":
|
||||
if (ignore_whitespace) {
|
||||
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 (show_added) output += "<span class='hlgreen'>" + Utils.escape_html(diff[i].value) + "</span>";
|
||||
} else if (diff[i].removed) {
|
||||
if (show_removed) output += "<span class='hlred'>" + Utils.escape_html(diff[i].value) + "</span>";
|
||||
} else {
|
||||
output += Utils.escape_html(diff[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OFF_CHK_SAMPLE_DELIMITER: "\\n\\n",
|
||||
|
||||
/**
|
||||
* Offset checker operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
run_offset_checker: function(input, args) {
|
||||
var sample_delim = args[0],
|
||||
samples = input.split(sample_delim),
|
||||
outputs = [],
|
||||
i = 0,
|
||||
s = 0,
|
||||
match = false,
|
||||
in_match = 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 (in_match) outputs[s] += "</span>";
|
||||
if (s == samples.length - 1) in_match = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (match && !in_match) {
|
||||
outputs[s] += "<span class='hlgreen'>" + Utils.escape_html(samples[s][i]);
|
||||
if (samples[s].length == i + 1) outputs[s] += "</span>";
|
||||
if (s == samples.length - 1) in_match = true;
|
||||
} else if (!match && in_match) {
|
||||
outputs[s] += "</span>" + Utils.escape_html(samples[s][i]);
|
||||
if (s == samples.length - 1) in_match = false;
|
||||
} else {
|
||||
outputs[s] += Utils.escape_html(samples[s][i]);
|
||||
if (in_match && samples[s].length == i + 1) {
|
||||
outputs[s] += "</span>";
|
||||
if (samples[s].length - 1 != i) in_match = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (samples[0].length - 1 == i) {
|
||||
if (in_match) outputs[s] += "</span>";
|
||||
outputs[s] += Utils.escape_html(samples[s].substring(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputs.join(sample_delim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Parse escaped string operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_parse_escaped_string: function(input, args) {
|
||||
return Utils.parse_escaped_chars(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds HTML highlights to matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} display_total
|
||||
* @returns {string}
|
||||
*/
|
||||
_regex_highlight: function(input, regex, display_total) {
|
||||
var output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
|
||||
while (!!(m = regex.exec(input))) {
|
||||
// Add up to match
|
||||
output += Utils.escape_html(input.slice(i, m.index));
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escape_html(m[0]) + "</span>";
|
||||
|
||||
// Switch highlight
|
||||
hl = hl == 1 ? 2 : 1;
|
||||
|
||||
i = regex.lastIndex;
|
||||
total++;
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += Utils.escape_html(input.slice(i, input.length));
|
||||
|
||||
if (display_total)
|
||||
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} display_total
|
||||
* @param {boolean} matches - Display full match
|
||||
* @param {boolean} capture_groups - Display each of the capture groups separately
|
||||
* @returns {string}
|
||||
*/
|
||||
_regex_list: function(input, regex, display_total, matches, capture_groups) {
|
||||
var output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while (!!(match = regex.exec(input))) {
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (capture_groups) {
|
||||
for (var i = 1; i < match.length; i++) {
|
||||
if (matches) {
|
||||
output += " Group " + i + ": ";
|
||||
}
|
||||
output += match[i] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (display_total)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
238
src/js/operations/Tidy.js
Executable file
238
src/js/operations/Tidy.js
Executable file
|
@ -0,0 +1,238 @@
|
|||
/**
|
||||
* Tidy operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var 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}
|
||||
*/
|
||||
run_remove_whitespace: function (input, args) {
|
||||
var remove_spaces = args[0],
|
||||
remove_cariage_returns = args[1],
|
||||
remove_line_feeds = args[2],
|
||||
remove_tabs = args[3],
|
||||
remove_form_feeds = args[4],
|
||||
remove_full_stops = args[5],
|
||||
data = input;
|
||||
|
||||
if (remove_spaces) data = data.replace(/ /g, "");
|
||||
if (remove_cariage_returns) data = data.replace(/\r/g, "");
|
||||
if (remove_line_feeds) data = data.replace(/\n/g, "");
|
||||
if (remove_tabs) data = data.replace(/\t/g, "");
|
||||
if (remove_form_feeds) data = data.replace(/\f/g, "");
|
||||
if (remove_full_stops) data = data.replace(/\./g, "");
|
||||
return data;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove null bytes operation.
|
||||
*
|
||||
* @param {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_remove_nulls: 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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_drop_bytes: function(input, args) {
|
||||
var start = args[0],
|
||||
length = args[1],
|
||||
apply_to_each_line = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
|
||||
if (!apply_to_each_line)
|
||||
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 {byte_array} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byte_array}
|
||||
*/
|
||||
run_take_bytes: function(input, args) {
|
||||
var start = args[0],
|
||||
length = args[1],
|
||||
apply_to_each_line = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
|
||||
if (!apply_to_each_line)
|
||||
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}
|
||||
*/
|
||||
run_pad: 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.pad_left(lines[i], lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
} else if (position == "End") {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output += Utils.pad_right(lines[i], lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
|
||||
};
|
130
src/js/operations/URL.js
Executable file
130
src/js/operations/URL.js
Executable file
|
@ -0,0 +1,130 @@
|
|||
/* globals unescape */
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
var URL_ = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENCODE_ALL: false,
|
||||
|
||||
/**
|
||||
* URL Encode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_to: function(input, args) {
|
||||
var encode_all = args[0];
|
||||
return encode_all ? URL_._encode_all_chars(input) : encodeURI(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* URL Decode operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_from: 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}
|
||||
*/
|
||||
run_parse: function(input, args) {
|
||||
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) {
|
||||
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) {
|
||||
output += "Hash:\t\t" + a.hash + "\n";
|
||||
}
|
||||
|
||||
if (a.search) {
|
||||
output += "Arguments:\n";
|
||||
var args_ = (a.search.slice(1, a.search.length)).split("&");
|
||||
var split_args = [], padding = 0;
|
||||
for (var i = 0; i < args_.length; i++) {
|
||||
split_args.push(args_[i].split("="));
|
||||
padding = (split_args[i][0].length > padding) ? split_args[i][0].length : padding;
|
||||
}
|
||||
for (i = 0; i < split_args.length; i++) {
|
||||
output += "\t" + Utils.pad_right(split_args[i][0], padding);
|
||||
if (split_args[i].length > 1 && split_args[i][1].length)
|
||||
output += " = " + split_args[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}
|
||||
*/
|
||||
_encode_all_chars: 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");
|
||||
},
|
||||
|
||||
};
|
39
src/js/operations/UUID.js
Executable file
39
src/js/operations/UUID.js
Executable file
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* UUID operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var UUID = {
|
||||
|
||||
/**
|
||||
* Generate UUID operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_generate_v4: function(input, args) {
|
||||
if (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);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
};
|
62
src/js/operations/Unicode.js
Executable file
62
src/js/operations/Unicode.js
Executable file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Unicode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Unicode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PREFIXES: ["\\u", "%u", "U+"],
|
||||
|
||||
/**
|
||||
* Unescape Unicode Characters operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run_unescape: function(input, args) {
|
||||
var prefix = Unicode._prefix_to_regex[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
|
||||
*/
|
||||
_prefix_to_regex: {
|
||||
"\\u": "\\\\u",
|
||||
"%u": "%u",
|
||||
"U+": "U\\+"
|
||||
},
|
||||
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue