mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
209a5b7274 | ||
|
|
e962c9594b | ||
|
|
242bad09ea | ||
|
|
8dd223f1cb | ||
|
|
d15662dea4 | ||
|
|
f47a408755 | ||
|
|
8360c9e9f9 | ||
|
|
328142dac7 | ||
|
|
372b2378a8 | ||
|
|
574207c626 | ||
|
|
ead64dcb47 | ||
|
|
da473de9f0 | ||
|
|
a177e2ab7e | ||
|
|
8cef6db482 | ||
|
|
79a3128491 | ||
|
|
cb1fe80214 | ||
|
|
19f2e6dae0 | ||
|
|
74394a773d | ||
|
|
d491e95d1c | ||
|
|
881523ce54 | ||
|
|
502a9fbb92 | ||
|
|
cc44fe6557 | ||
|
|
5b1ac3de18 | ||
|
|
5a2a649d8e | ||
|
|
1aef193b40 | ||
|
|
750fa45c04 | ||
|
|
50f2819699 | ||
|
|
ab55b91da1 | ||
|
|
59f7774964 | ||
|
|
b5eb44af9f | ||
|
|
8518fa67f2 | ||
|
|
f6b68f9880 | ||
|
|
f6b2783f8b | ||
|
|
078849041f | ||
|
|
1c711f5e03 | ||
|
|
614af0602a | ||
|
|
e55cfe0bc1 | ||
|
|
2b703b2b9b | ||
|
|
170feaaff2 | ||
|
|
870c2b6d8b | ||
|
|
eee8b7db56 | ||
|
|
3c669a075e | ||
|
|
f528930ad2 | ||
|
|
231322eddf | ||
|
|
8e6763c165 | ||
|
|
f091918575 | ||
|
|
bb077c87b3 | ||
|
|
fe8f8bc712 | ||
|
|
abe87830cd | ||
|
|
7490651a06 | ||
|
|
6220128a74 | ||
|
|
ec205f4f7d | ||
|
|
512487328d | ||
|
|
6fbb2f26d1 | ||
|
|
c91bfeaa81 | ||
|
|
aa2b3b2843 | ||
|
|
90d8be48d4 | ||
|
|
aa6890432c | ||
|
|
192d0ed8a6 | ||
|
|
fff188eb30 | ||
|
|
71067939e3 | ||
|
|
b07c014b48 | ||
|
|
f2c073798b | ||
|
|
4cc38db895 | ||
|
|
ec02b7deda | ||
|
|
56551712d6 |
@@ -51,6 +51,7 @@
|
||||
"mode": "minimum"
|
||||
}],
|
||||
"indent": ["error", 4, {
|
||||
"ignoreComments": true,
|
||||
"ArrayExpression": "first",
|
||||
"SwitchCase": 1
|
||||
}],
|
||||
|
||||
@@ -11,6 +11,7 @@ script:
|
||||
- grunt node
|
||||
- grunt prod --msg="$COMPILE_MSG"
|
||||
before_deploy:
|
||||
- grunt exec:sitemap
|
||||
- grunt copy:ghPages
|
||||
deploy:
|
||||
- provider: pages
|
||||
|
||||
50
Gruntfile.js
50
Gruntfile.js
@@ -185,8 +185,12 @@ module.exports = function (grunt) {
|
||||
webpack: {
|
||||
options: webpackConfig,
|
||||
metaConf: {
|
||||
mode: "production",
|
||||
target: "node",
|
||||
entry: "./src/core/config/OperationConfig.js",
|
||||
entry: [
|
||||
"babel-polyfill",
|
||||
"./src/core/config/OperationConfig.js"
|
||||
],
|
||||
output: {
|
||||
filename: "MetaConfig.js",
|
||||
path: __dirname + "/src/core/config/",
|
||||
@@ -197,8 +201,12 @@ module.exports = function (grunt) {
|
||||
externals: [NodeExternals()],
|
||||
},
|
||||
metaConfDev: {
|
||||
mode: "development",
|
||||
target: "node",
|
||||
entry: "./src/core/config/OperationConfig.js",
|
||||
entry: [
|
||||
"babel-polyfill",
|
||||
"./src/core/config/OperationConfig.js"
|
||||
],
|
||||
output: {
|
||||
filename: "MetaConfig.js",
|
||||
path: __dirname + "/src/core/config/",
|
||||
@@ -210,9 +218,11 @@ module.exports = function (grunt) {
|
||||
watch: true
|
||||
},
|
||||
web: {
|
||||
mode: "production",
|
||||
target: "web",
|
||||
entry: Object.assign({
|
||||
main: "./src/web/index.js"
|
||||
main: "./src/web/index.js",
|
||||
sitemap: "./src/web/static/sitemap.js"
|
||||
}, moduleEntryPoints),
|
||||
output: {
|
||||
path: __dirname + "/build/prod"
|
||||
@@ -224,15 +234,6 @@ module.exports = function (grunt) {
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
"screw_ie8": true,
|
||||
"dead_code": true,
|
||||
"unused": true,
|
||||
"warnings": false
|
||||
},
|
||||
comments: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
@@ -249,6 +250,7 @@ module.exports = function (grunt) {
|
||||
]
|
||||
},
|
||||
webInline: {
|
||||
mode: "production",
|
||||
target: "web",
|
||||
entry: "./src/web/index.js",
|
||||
output: {
|
||||
@@ -256,21 +258,14 @@ module.exports = function (grunt) {
|
||||
path: __dirname + "/build/prod"
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
"screw_ie8": true,
|
||||
"dead_code": true,
|
||||
"unused": true,
|
||||
"warnings": false
|
||||
},
|
||||
comments: false,
|
||||
}),
|
||||
new webpack.DefinePlugin(Object.assign({}, BUILD_CONSTANTS, {
|
||||
INLINE: "true"
|
||||
})),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "cyberchef.htm",
|
||||
template: "./src/web/html/index.html",
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
version: pkg.version + "s",
|
||||
inline: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
@@ -282,6 +277,7 @@ module.exports = function (grunt) {
|
||||
]
|
||||
},
|
||||
tests: {
|
||||
mode: "development",
|
||||
target: "node",
|
||||
entry: "./test/index.js",
|
||||
externals: [NodeExternals()],
|
||||
@@ -294,6 +290,7 @@ module.exports = function (grunt) {
|
||||
]
|
||||
},
|
||||
node: {
|
||||
mode: "production",
|
||||
target: "node",
|
||||
entry: "./src/node/index.js",
|
||||
externals: [NodeExternals()],
|
||||
@@ -320,11 +317,13 @@ module.exports = function (grunt) {
|
||||
children: false,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
entrypoints: false,
|
||||
warningsFilter: /source-map/,
|
||||
}
|
||||
},
|
||||
start: {
|
||||
webpack: {
|
||||
mode: "development",
|
||||
target: "web",
|
||||
entry: Object.assign({
|
||||
main: "./src/web/index.js"
|
||||
@@ -371,7 +370,7 @@ module.exports = function (grunt) {
|
||||
expand: true,
|
||||
src: "docs/**",
|
||||
dest: "build/prod/"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -400,6 +399,9 @@ module.exports = function (grunt) {
|
||||
cleanGit: {
|
||||
command: "git gc --prune=now --aggressive"
|
||||
},
|
||||
sitemap: {
|
||||
command: "node build/prod/sitemap.js > build/prod/sitemap.xml"
|
||||
}
|
||||
},
|
||||
execute: {
|
||||
test: "build/test/index.js"
|
||||
|
||||
@@ -103,4 +103,4 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
|
||||
[8]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
||||
[9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ
|
||||
[10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D)&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg
|
||||
[11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||
[11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'Standard',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||
|
||||
5386
package-lock.json
generated
5386
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
64
package.json
64
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "7.5.0",
|
||||
"version": "7.8.0",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -31,14 +31,15 @@
|
||||
"bugs": "https://github.com/gchq/CyberChef/issues",
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-loader": "^7.1.3",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"exports-loader": "^0.6.4",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.6",
|
||||
"grunt": ">=1.0.1",
|
||||
"grunt-accessibility": "~5.0.0",
|
||||
"css-loader": "^0.28.10",
|
||||
"eslint": "^4.18.1",
|
||||
"exports-loader": "^0.7.0",
|
||||
"extract-text-webpack-plugin": "^4.0.0-alpha0",
|
||||
"file-loader": "^1.1.10",
|
||||
"grunt": ">=1.0.2",
|
||||
"grunt-accessibility": "~6.0.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-concurrent": "^2.3.1",
|
||||
"grunt-contrib-clean": "~1.1.0",
|
||||
@@ -46,63 +47,68 @@
|
||||
"grunt-eslint": "^20.1.0",
|
||||
"grunt-exec": "~3.0.0",
|
||||
"grunt-execute": "^0.2.2",
|
||||
"grunt-jsdoc": "^2.2.0",
|
||||
"grunt-jsdoc": "^2.2.1",
|
||||
"grunt-webpack": "^3.0.2",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"imports-loader": "^0.7.1",
|
||||
"html-webpack-plugin": "^3.0.4",
|
||||
"imports-loader": "^0.8.0",
|
||||
"ink-docstrap": "^1.3.2",
|
||||
"jsdoc-babel": "^0.3.0",
|
||||
"less": "^2.7.3",
|
||||
"less-loader": "^4.0.5",
|
||||
"less": "^3.0.1",
|
||||
"less-loader": "^4.0.6",
|
||||
"postcss-css-variables": "^0.8.0",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.9",
|
||||
"style-loader": "^0.19.1",
|
||||
"postcss-import": "^11.1.0",
|
||||
"postcss-loader": "^2.1.1",
|
||||
"sitemap": "^1.13.0",
|
||||
"style-loader": "^0.20.2",
|
||||
"url-loader": "^0.6.2",
|
||||
"val-loader": "^1.1.0",
|
||||
"web-resource-inliner": "^4.2.0",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-dev-server": "^2.9.7",
|
||||
"web-resource-inliner": "^4.2.1",
|
||||
"webpack": "^4.0.1",
|
||||
"webpack-dev-server": "^3.1.0",
|
||||
"webpack-node-externals": "^1.6.0",
|
||||
"worker-loader": "^1.1.0"
|
||||
"worker-loader": "^1.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bignumber.js": "^5.0.0",
|
||||
"bignumber.js": "^6.0.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"bootstrap-colorpicker": "^2.5.2",
|
||||
"bootstrap-switch": "^3.3.4",
|
||||
"crypto-api": "^0.7.5",
|
||||
"crypto-api": "^0.8.0",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"ctph.js": "0.0.5",
|
||||
"diff": "^3.4.0",
|
||||
"escodegen": "^1.9.0",
|
||||
"escodegen": "^1.9.1",
|
||||
"esmangle": "^1.0.1",
|
||||
"esprima": "^4.0.0",
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^1.3.3",
|
||||
"google-code-prettify": "^1.0.5",
|
||||
"jquery": "^3.2.1",
|
||||
"highlight.js": "^9.12.0",
|
||||
"jquery": "^3.3.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.7.0",
|
||||
"jsbn": "^1.1.0",
|
||||
"jsonpath": "^1.0.0",
|
||||
"jsrsasign": "8.0.4",
|
||||
"lodash": "^4.17.4",
|
||||
"loglevel": "^1.6.0",
|
||||
"jsrsasign": "8.0.6",
|
||||
"lodash": "^4.17.5",
|
||||
"loglevel": "^1.6.1",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"moment": "^2.20.1",
|
||||
"moment-timezone": "^0.5.14",
|
||||
"node-forge": "^0.7.1",
|
||||
"node-forge": "^0.7.2",
|
||||
"node-md6": "^0.1.0",
|
||||
"nwmatcher": "^1.4.3",
|
||||
"otp": "^0.1.3",
|
||||
"sladex-blowfish": "^0.8.1",
|
||||
"sortablejs": "^1.7.0",
|
||||
"split.js": "^1.3.5",
|
||||
"ssdeep.js": "0.0.2",
|
||||
"ua-parser-js": "^0.7.17",
|
||||
"utf8": "^3.0.0",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.1.27",
|
||||
"xpath": "0.0.27",
|
||||
"xregexp": "^4.1.1",
|
||||
"zlibjs": "^0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -138,6 +138,7 @@ function loadRequiredModules(recipeConfig) {
|
||||
log.info("Loading module " + module);
|
||||
self.sendStatusMessage("Loading module " + module);
|
||||
self.importScripts(self.docURL + "/" + module + ".js");
|
||||
self.sendStatusMessage("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,14 +52,25 @@ const FlowControl = {
|
||||
output = "",
|
||||
progress = 0;
|
||||
|
||||
state.forkOffset += state.progress + 1;
|
||||
|
||||
recipe.addOperations(subOpList);
|
||||
|
||||
// Take a deep(ish) copy of the ingredient values
|
||||
const ingValues = subOpList.map(op => JSON.parse(JSON.stringify(op.getIngValues())));
|
||||
|
||||
// Run recipe over each tranche
|
||||
for (i = 0; i < inputs.length; i++) {
|
||||
log.debug(`Entering tranche ${i + 1} of ${inputs.length}`);
|
||||
|
||||
// Baseline ing values for each tranche so that registers are reset
|
||||
subOpList.forEach((op, i) => {
|
||||
op.setIngValues(JSON.parse(JSON.stringify(ingValues[i])));
|
||||
});
|
||||
|
||||
const dish = new Dish(inputs[i], inputType);
|
||||
try {
|
||||
progress = await recipe.execute(dish, 0);
|
||||
progress = await recipe.execute(dish, 0, state);
|
||||
} catch (err) {
|
||||
if (!ignoreErrors) {
|
||||
throw err;
|
||||
@@ -117,7 +128,7 @@ const FlowControl = {
|
||||
if (!registers) return state;
|
||||
|
||||
if (ENVIRONMENT_IS_WORKER()) {
|
||||
self.setRegisters(state.progress, state.numRegisters, registers.slice(1));
|
||||
self.setRegisters(state.forkOffset + state.progress, state.numRegisters, registers.slice(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -141,11 +141,14 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
|
||||
*
|
||||
* @param {Dish} dish
|
||||
* @param {number} [startFrom=0] - The index of the Operation to start executing from
|
||||
* @param {number} [forkState={}] - If this is a forked recipe, the state of the recipe up to this point
|
||||
* @returns {number} - The final progress through the recipe
|
||||
*/
|
||||
Recipe.prototype.execute = async function(dish, startFrom) {
|
||||
startFrom = startFrom || 0;
|
||||
let op, input, output, numJumps = 0, numRegisters = 0;
|
||||
Recipe.prototype.execute = async function(dish, startFrom = 0, forkState = {}) {
|
||||
let op, input, output,
|
||||
numJumps = 0,
|
||||
numRegisters = forkState.numRegisters || 0;
|
||||
|
||||
log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`);
|
||||
|
||||
for (let i = startFrom; i < this.opList.length; i++) {
|
||||
@@ -171,7 +174,8 @@ Recipe.prototype.execute = async function(dish, startFrom) {
|
||||
"dish": dish,
|
||||
"opList": this.opList,
|
||||
"numJumps": numJumps,
|
||||
"numRegisters": numRegisters
|
||||
"numRegisters": numRegisters,
|
||||
"forkOffset": forkState.forkOffset || 0
|
||||
};
|
||||
|
||||
state = await op.run(state);
|
||||
@@ -256,4 +260,5 @@ Recipe.prototype.generateHighlightList = function() {
|
||||
return highlights;
|
||||
};
|
||||
|
||||
|
||||
export default Recipe;
|
||||
|
||||
@@ -495,15 +495,16 @@ const Utils = {
|
||||
* Converts an ArrayBuffer to a string.
|
||||
*
|
||||
* @param {ArrayBuffer} arrayBuffer
|
||||
* @param {boolean} [utf8=true] - Whether to attempt to decode the buffer as UTF-8
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns "hello"
|
||||
* Utils.arrayBufferToStr(Uint8Array.from([104,101,108,108,111]).buffer);
|
||||
*/
|
||||
arrayBufferToStr: function(arrayBuffer) {
|
||||
arrayBufferToStr: function(arrayBuffer, utf8=true) {
|
||||
const byteArray = Array.prototype.slice.call(new Uint8Array(arrayBuffer));
|
||||
return Utils.byteArrayToUtf8(byteArray);
|
||||
return utf8 ? Utils.byteArrayToUtf8(byteArray) : Utils.byteArrayToChars(byteArray);
|
||||
},
|
||||
|
||||
|
||||
@@ -903,9 +904,9 @@ const Utils = {
|
||||
* "Pretty" CyberChef recipe formats are designed to be included in the fragment (#) or query (?)
|
||||
* parts of the URL. They can also be loaded into CyberChef through the 'Load' interface. In order
|
||||
* to make this format as readable as possible, various special characters are used unescaped. This
|
||||
* reduces the amount of percent-encoding included in the URL which is typically difficult to read,
|
||||
* as well as substantially increasing the overall length. These characteristics can be quite
|
||||
* offputting for users.
|
||||
* reduces the amount of percent-encoding included in the URL which is typically difficult to read
|
||||
* and substantially increases the overall length. These characteristics can be quite off-putting
|
||||
* for users.
|
||||
*
|
||||
* @param {Object[]} recipeConfig
|
||||
* @param {boolean} newline - whether to add a newline after each operation
|
||||
@@ -922,12 +923,11 @@ const Utils = {
|
||||
name = op.op.replace(/ /g, "_");
|
||||
args = JSON.stringify(op.args)
|
||||
.slice(1, -1) // Remove [ and ] as they are implied
|
||||
// We now need to switch double-quoted (") strings to single-quotes (') as these do not
|
||||
// need to be percent-encoded.
|
||||
// We now need to switch double-quoted (") strings to single quotes (') as single quotes
|
||||
// do not need to be percent-encoded.
|
||||
.replace(/'/g, "\\'") // Escape single quotes
|
||||
.replace(/\\"/g, '"') // Unescape double quotes
|
||||
.replace(/(^|,|{|:)"/g, "$1'") // Replace opening " with '
|
||||
.replace(/"(,|:|}|$)/g, "'$1"); // Replace closing " with '
|
||||
.replace(/"((?:[^"\\]|\\.)*)"/g, "'$1'") // Replace opening and closing " with '
|
||||
.replace(/\\"/g, '"'); // Unescape double quotes
|
||||
|
||||
disabled = op.disabled ? "/disabled": "";
|
||||
bp = op.breakpoint ? "/breakpoint" : "";
|
||||
@@ -953,7 +953,7 @@ const Utils = {
|
||||
// Parse bespoke recipe format
|
||||
recipe = recipe.replace(/\n/g, "");
|
||||
let m,
|
||||
recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/])*)(\/[^)]+)?\)/g,
|
||||
recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/'])*)(\/[^)]+)?\)/g,
|
||||
recipeConfig = [],
|
||||
args;
|
||||
|
||||
|
||||
@@ -201,6 +201,7 @@ const Categories = [
|
||||
"Escape string",
|
||||
"Unescape string",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Sleep",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -213,6 +214,7 @@ const Categories = [
|
||||
"Windows Filetime to UNIX Timestamp",
|
||||
"UNIX Timestamp to Windows Filetime",
|
||||
"Extract dates",
|
||||
"Sleep",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -268,6 +270,10 @@ const Categories = [
|
||||
"HAS-160",
|
||||
"Whirlpool",
|
||||
"Snefru",
|
||||
"SSDEEP",
|
||||
"CTPH",
|
||||
"Compare SSDEEP hashes",
|
||||
"Compare CTPH hashes",
|
||||
"HMAC",
|
||||
"Fletcher-8 Checksum",
|
||||
"Fletcher-16 Checksum",
|
||||
@@ -324,6 +330,7 @@ const Categories = [
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
"Numberwang",
|
||||
"XKCD Random Number",
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ import NetBIOS from "../operations/NetBIOS.js";
|
||||
import PHP from "../operations/PHP.js";
|
||||
import PublicKey from "../operations/PublicKey.js";
|
||||
import Punycode from "../operations/Punycode.js";
|
||||
import Regex from "../operations/Regex.js";
|
||||
import Rotate from "../operations/Rotate.js";
|
||||
import SeqUtils from "../operations/SeqUtils.js";
|
||||
import Shellcode from "../operations/Shellcode.js";
|
||||
@@ -1824,6 +1825,11 @@ const OperationConfig = {
|
||||
name: "Cisco style",
|
||||
type: "boolean",
|
||||
value: MAC.CISCO_STYLE
|
||||
},
|
||||
{
|
||||
name: "IPv6 interface ID",
|
||||
type: "boolean",
|
||||
value: MAC.IPV6_INTERFACE_ID
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2058,9 +2064,8 @@ const OperationConfig = {
|
||||
args: []
|
||||
},
|
||||
"Find / Replace": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Replaces all occurrences of the first string with the second.<br><br> Includes support for regular expressions (regex), simple strings and extended strings (which support \\n, \\r, \\t, \\b, \\f and escaped hex bytes using \\x notation, e.g. \\x00 for a null byte).",
|
||||
manualBake: true,
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
@@ -2068,7 +2073,7 @@ const OperationConfig = {
|
||||
name: "Find",
|
||||
type: "toggleString",
|
||||
value: "",
|
||||
toggleValues: StrUtils.SEARCH_TYPE
|
||||
toggleValues: Regex.SEARCH_TYPE
|
||||
},
|
||||
{
|
||||
name: "Replace",
|
||||
@@ -2078,17 +2083,17 @@ const OperationConfig = {
|
||||
{
|
||||
name: "Global match",
|
||||
type: "boolean",
|
||||
value: StrUtils.FIND_REPLACE_GLOBAL,
|
||||
value: Regex.FIND_REPLACE_GLOBAL,
|
||||
},
|
||||
{
|
||||
name: "Case insensitive",
|
||||
type: "boolean",
|
||||
value: StrUtils.FIND_REPLACE_CASE,
|
||||
value: Regex.FIND_REPLACE_CASE,
|
||||
},
|
||||
{
|
||||
name: "Multiline matching",
|
||||
type: "boolean",
|
||||
value: StrUtils.FIND_REPLACE_MULTILINE,
|
||||
value: Regex.FIND_REPLACE_MULTILINE,
|
||||
},
|
||||
|
||||
]
|
||||
@@ -2125,20 +2130,19 @@ const OperationConfig = {
|
||||
args: [
|
||||
{
|
||||
name: "Split delimiter",
|
||||
type: "binaryShortString",
|
||||
value: StrUtils.SPLIT_DELIM
|
||||
type: "editableOption",
|
||||
value: StrUtils.SPLIT_DELIM_OPTIONS
|
||||
},
|
||||
{
|
||||
name: "Join delimiter",
|
||||
type: "option",
|
||||
value: StrUtils.DELIMITER_OPTIONS
|
||||
type: "editableOption",
|
||||
value: StrUtils.JOIN_DELIM_OPTIONS
|
||||
}
|
||||
]
|
||||
},
|
||||
"Filter": {
|
||||
module: "Default",
|
||||
description: "Splits up the input using the specified delimiter and then filters each branch based on a regular expression.",
|
||||
manualBake: true,
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
@@ -2155,21 +2159,31 @@ const OperationConfig = {
|
||||
{
|
||||
name: "Invert condition",
|
||||
type: "boolean",
|
||||
value: SeqUtils.SORT_REVERSE
|
||||
value: false
|
||||
},
|
||||
]
|
||||
},
|
||||
"Strings": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts all strings from the input.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Encoding",
|
||||
type: "option",
|
||||
value: Extract.ENCODING_LIST
|
||||
},
|
||||
{
|
||||
name: "Minimum length",
|
||||
type: "number",
|
||||
value: Extract.MIN_STRING_LEN
|
||||
},
|
||||
{
|
||||
name: "Match",
|
||||
type: "option",
|
||||
value: Extract.STRING_MATCH_TYPE
|
||||
},
|
||||
{
|
||||
name: "Display total",
|
||||
type: "boolean",
|
||||
@@ -2178,7 +2192,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract IP addresses": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>710.65.0.456</code>, this will match <code>10.65.0.45</code> so always check the original input!",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2206,7 +2220,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract email addresses": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts all email addresses from the input.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2219,7 +2233,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract MAC addresses": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts all Media Access Control (MAC) addresses from the input.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2232,7 +2246,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract URLs": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts Uniform Resource Locators (URLs) from the input. The protocol (http, ftp etc.) is required otherwise there will be far too many false positives.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2245,7 +2259,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract domains": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts domain names.<br>Note that this will not include paths. Use <strong>Extract URLs</strong> to find entire URLs.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2258,7 +2272,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract file paths": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts anything that looks like a Windows or UNIX file path.<br><br>Note that if UNIX is selected, there will likely be a lot of false positives.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2281,7 +2295,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Extract dates": {
|
||||
module: "Default",
|
||||
module: "Regex",
|
||||
description: "Extracts dates in the following formats<ul><li><code>yyyy-mm-dd</code></li><li><code>dd/mm/yyyy</code></li><li><code>mm/dd/yyyy</code></li></ul>Dividers can be any of /, -, . or space",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2294,16 +2308,15 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Regular expression": {
|
||||
module: "Default",
|
||||
description: "Define your own regular expression (regex) to search the input data with, optionally choosing from a list of pre-defined patterns.",
|
||||
manualBake: true,
|
||||
module: "Regex",
|
||||
description: "Define your own regular expression (regex) to search the input data with, optionally choosing from a list of pre-defined patterns.<br><br>Supports extended regex syntax including the 'dot matches all' flag, named capture groups, full unicode coverage (including <code>\\p{}</code> categories and scripts as well as astral codes) and recursive matching.",
|
||||
inputType: "string",
|
||||
outputType: "html",
|
||||
args: [
|
||||
{
|
||||
name: "Built in regexes",
|
||||
type: "populateOption",
|
||||
value: StrUtils.REGEX_PRE_POPULATE,
|
||||
value: Regex.REGEX_PRE_POPULATE,
|
||||
target: 1,
|
||||
},
|
||||
{
|
||||
@@ -2314,22 +2327,37 @@ const OperationConfig = {
|
||||
{
|
||||
name: "Case insensitive",
|
||||
type: "boolean",
|
||||
value: StrUtils.REGEX_CASE_INSENSITIVE
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Multiline matching",
|
||||
name: "^ and $ match at newlines",
|
||||
type: "boolean",
|
||||
value: StrUtils.REGEX_MULTILINE_MATCHING
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Dot matches all",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Unicode support",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Astral support",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Display total",
|
||||
type: "boolean",
|
||||
value: StrUtils.DISPLAY_TOTAL
|
||||
value: Regex.DISPLAY_TOTAL
|
||||
},
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: StrUtils.OUTPUT_FORMAT
|
||||
value: Regex.OUTPUT_FORMAT
|
||||
},
|
||||
]
|
||||
},
|
||||
@@ -2418,8 +2446,21 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"Sleep": {
|
||||
module: "Default",
|
||||
description: "Sleep causes the recipe to wait for a specified number of milliseconds before continuing execution.",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "ArrayBuffer",
|
||||
args: [
|
||||
{
|
||||
name: "Time (ms)",
|
||||
type: "number",
|
||||
value: 1000
|
||||
}
|
||||
]
|
||||
},
|
||||
"Windows Filetime to UNIX Timestamp": {
|
||||
module: "JSBN",
|
||||
module: "Default",
|
||||
description: "Converts a Windows Filetime value to a UNIX timestamp.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2437,7 +2478,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"UNIX Timestamp to Windows Filetime": {
|
||||
module: "JSBN",
|
||||
module: "Default",
|
||||
description: "Converts a UNIX timestamp to a Windows Filetime value.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2969,21 +3010,21 @@ const OperationConfig = {
|
||||
"MD2": {
|
||||
module: "Hashing",
|
||||
description: "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.<br><br>Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"MD4": {
|
||||
module: "Hashing",
|
||||
description: "The MD4 (Message-Digest 4) algorithm is a cryptographic hash function developed by Ronald Rivest in 1990. The digest length is 128 bits. The algorithm has influenced later designs, such as the MD5, SHA-1 and RIPEMD algorithms.<br><br>The security of MD4 has been severely compromised.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"MD5": {
|
||||
module: "Hashing",
|
||||
description: "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.<br><br>However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
@@ -3013,21 +3054,21 @@ const OperationConfig = {
|
||||
"SHA0": {
|
||||
module: "Hashing",
|
||||
description: "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"SHA1": {
|
||||
module: "Hashing",
|
||||
description: "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.<br><br>However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"SHA2": {
|
||||
module: "Hashing",
|
||||
description: "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul>",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3040,7 +3081,7 @@ const OperationConfig = {
|
||||
"SHA3": {
|
||||
module: "Hashing",
|
||||
description: "The SHA-3 (Secure Hash Algorithm 3) hash functions were released by NIST on August 5, 2015. Although part of the same series of standards, SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.<br><br>SHA-3 is a subset of the broader cryptographic primitive family Keccak designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3053,7 +3094,7 @@ const OperationConfig = {
|
||||
"Keccak": {
|
||||
module: "Hashing",
|
||||
description: "The Keccak hash algorithm was designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún. It was selected as the winner of the SHA-3 design competition.<br><br>This version of the algorithm is Keccak[c=2d] and differs from the SHA-3 specification.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3066,7 +3107,7 @@ const OperationConfig = {
|
||||
"Shake": {
|
||||
module: "Hashing",
|
||||
description: "Shake is an Extendable Output Function (XOF) of the SHA-3 hash algorithm, part of the Keccak family, allowing for variable output length/size.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3085,7 +3126,7 @@ const OperationConfig = {
|
||||
"RIPEMD": {
|
||||
module: "Hashing",
|
||||
description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.<br><br>RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.<br><br>",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3098,14 +3139,14 @@ const OperationConfig = {
|
||||
"HAS-160": {
|
||||
module: "Hashing",
|
||||
description: "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists of 80 rounds.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"Whirlpool": {
|
||||
module: "Hashing",
|
||||
description: "Whirlpool is a cryptographic hash function designed by Vincent Rijmen (co-creator of AES) and Paulo S. L. M. Barreto, who first described it in 2000.<br><br>Several variants exist:<ul><li>Whirlpool-0 is the original version released in 2000.</li><li>Whirlpool-T is the first revision, released in 2001, improving the generation of the s-box.</li><li>Wirlpool is the latest revision, released in 2003, fixing a flaw in the difusion matrix.</li></ul>",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3118,7 +3159,7 @@ const OperationConfig = {
|
||||
"Snefru": {
|
||||
module: "Hashing",
|
||||
description: "Snefru is a cryptographic hash function invented by Ralph Merkle in 1990 while working at Xerox PARC. The function supports 128-bit and 256-bit output. It was named after the Egyptian Pharaoh Sneferu, continuing the tradition of the Khufu and Khafre block ciphers.<br><br>The original design of Snefru was shown to be insecure by Eli Biham and Adi Shamir who were able to use differential cryptanalysis to find hash collisions. The design was then modified by increasing the number of iterations of the main pass of the algorithm from two to eight.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3133,14 +3174,54 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"SSDEEP": {
|
||||
module: "Hashing",
|
||||
description: "SSDEEP is a program for computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.<br><br>SSDEEP hashes are now widely used for simple identification purposes (e.g. the 'Basic Properties' section in VirusTotal). Although 'better' fuzzy hashes are available, SSDEEP is still one of the primary choices because of its speed and being a de facto standard.<br><br>This operation is fundamentally the same as the CTPH operation, however their outputs differ in format.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"CTPH": {
|
||||
module: "Hashing",
|
||||
description: "Context Triggered Piecewise Hashing, also called Fuzzy Hashing, can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.<br><br>CTPH was originally based on the work of Dr. Andrew Tridgell and a spam email detector called SpamSum. This method was adapted by Jesse Kornblum and published at the DFRWS conference in 2006 in a paper 'Identifying Almost Identical Files Using Context Triggered Piecewise Hashing'.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"Compare SSDEEP hashes": {
|
||||
module: "Hashing",
|
||||
description: "Compares two SSDEEP fuzzy hashes to determine the similarity between them on a scale of 0 to 100.",
|
||||
inputType: "string",
|
||||
outputType: "Number",
|
||||
args: [
|
||||
{
|
||||
name: "Delimiter",
|
||||
type: "option",
|
||||
value: Hash.DELIM_OPTIONS
|
||||
}
|
||||
]
|
||||
},
|
||||
"Compare CTPH hashes": {
|
||||
module: "Hashing",
|
||||
description: "Compares two Context Triggered Piecewise Hashing (CTPH) fuzzy hashes to determine the similarity between them on a scale of 0 to 100.",
|
||||
inputType: "string",
|
||||
outputType: "Number",
|
||||
args: [
|
||||
{
|
||||
name: "Delimiter",
|
||||
type: "option",
|
||||
value: Hash.DELIM_OPTIONS
|
||||
}
|
||||
]
|
||||
},
|
||||
"HMAC": {
|
||||
module: "Hashing",
|
||||
description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Password",
|
||||
name: "Key",
|
||||
type: "binaryString",
|
||||
value: ""
|
||||
},
|
||||
@@ -3203,7 +3284,7 @@ const OperationConfig = {
|
||||
"Generate all hashes": {
|
||||
module: "Hashing",
|
||||
description: "Generates all available hashes and checksums for the input.",
|
||||
inputType: "string",
|
||||
inputType: "ArrayBuffer",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
@@ -3426,15 +3507,10 @@ const OperationConfig = {
|
||||
outputType: "html",
|
||||
args: [
|
||||
{
|
||||
name: "Language/File extension",
|
||||
name: "Language",
|
||||
type: "option",
|
||||
value: Code.LANGUAGES
|
||||
},
|
||||
{
|
||||
name: "Display line numbers",
|
||||
type: "boolean",
|
||||
value: Code.LINE_NUMS
|
||||
}
|
||||
]
|
||||
},
|
||||
"TCP/IP Checksum": {
|
||||
@@ -3935,6 +4011,13 @@ const OperationConfig = {
|
||||
value: StrUtils.HAMMING_INPUT_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
"XKCD Random Number": {
|
||||
module: "Default",
|
||||
description: "RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.<br><br><a href='https://xkcd.com/221/'>XKCD #221</a>",
|
||||
inputType: "string",
|
||||
outputType: "number",
|
||||
args: []
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import Code from "../../operations/Code.js";
|
||||
* - xmldom
|
||||
* - xpath
|
||||
* - jpath
|
||||
* - googlecodeprettify
|
||||
* - highlight.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
|
||||
@@ -10,7 +10,7 @@ import Convert from "../../operations/Convert.js";
|
||||
import DateTime from "../../operations/DateTime.js";
|
||||
import Endian from "../../operations/Endian.js";
|
||||
import Entropy from "../../operations/Entropy.js";
|
||||
import Extract from "../../operations/Extract.js";
|
||||
import Filetime from "../../operations/Filetime.js";
|
||||
import FileType from "../../operations/FileType.js";
|
||||
import Hexdump from "../../operations/Hexdump.js";
|
||||
import HTML from "../../operations/HTML.js";
|
||||
@@ -29,6 +29,8 @@ import StrUtils from "../../operations/StrUtils.js";
|
||||
import Tidy from "../../operations/Tidy.js";
|
||||
import Unicode from "../../operations/Unicode.js";
|
||||
import UUID from "../../operations/UUID.js";
|
||||
import XKCD from "../../operations/XKCD.js";
|
||||
|
||||
|
||||
/**
|
||||
* Default module.
|
||||
@@ -40,6 +42,7 @@ import UUID from "../../operations/UUID.js";
|
||||
* - Utils.js
|
||||
* - otp
|
||||
* - crypto
|
||||
* - bignumber.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
@@ -89,7 +92,7 @@ OpModules.Default = {
|
||||
"Bit shift right": BitwiseOp.runBitShiftRight,
|
||||
"XOR": BitwiseOp.runXor,
|
||||
"XOR Brute Force": BitwiseOp.runXorBrute,
|
||||
"OR": BitwiseOp.runXor,
|
||||
"OR": BitwiseOp.runOr,
|
||||
"NOT": BitwiseOp.runNot,
|
||||
"AND": BitwiseOp.runAnd,
|
||||
"ADD": BitwiseOp.runAdd,
|
||||
@@ -99,11 +102,9 @@ OpModules.Default = {
|
||||
"Format MAC addresses": MAC.runFormat,
|
||||
"Encode NetBIOS Name": NetBIOS.runEncodeName,
|
||||
"Decode NetBIOS Name": NetBIOS.runDecodeName,
|
||||
"Regular expression": StrUtils.runRegex,
|
||||
"Offset checker": StrUtils.runOffsetChecker,
|
||||
"To Upper case": StrUtils.runUpper,
|
||||
"To Lower case": StrUtils.runLower,
|
||||
"Find / Replace": StrUtils.runFindReplace,
|
||||
"Split": StrUtils.runSplit,
|
||||
"Filter": StrUtils.runFilter,
|
||||
"Escape string": StrUtils.runEscape,
|
||||
@@ -133,14 +134,7 @@ OpModules.Default = {
|
||||
"Translate DateTime Format": DateTime.runTranslateFormat,
|
||||
"From UNIX Timestamp": DateTime.runFromUnixTimestamp,
|
||||
"To UNIX Timestamp": DateTime.runToUnixTimestamp,
|
||||
"Strings": Extract.runStrings,
|
||||
"Extract IP addresses": Extract.runIp,
|
||||
"Extract email addresses": Extract.runEmail,
|
||||
"Extract MAC addresses": Extract.runMac,
|
||||
"Extract URLs": Extract.runUrls,
|
||||
"Extract domains": Extract.runDomains,
|
||||
"Extract file paths": Extract.runFilePaths,
|
||||
"Extract dates": Extract.runDates,
|
||||
"Sleep": DateTime.runSleep,
|
||||
"Microsoft Script Decoder": MS.runDecodeScript,
|
||||
"Entropy": Entropy.runEntropy,
|
||||
"Frequency distribution": Entropy.runFreqDistrib,
|
||||
@@ -167,6 +161,9 @@ OpModules.Default = {
|
||||
"Mean": Arithmetic.runMean,
|
||||
"Median": Arithmetic.runMedian,
|
||||
"Standard Deviation": Arithmetic.runStdDev,
|
||||
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
|
||||
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
|
||||
"XKCD Random Number": XKCD.runRandomNumber,
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,31 +18,35 @@ import Hash from "../../operations/Hash.js";
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Hashing = {
|
||||
"Analyse hash": Hash.runAnalyse,
|
||||
"Generate all hashes": Hash.runAll,
|
||||
"MD2": Hash.runMD2,
|
||||
"MD4": Hash.runMD4,
|
||||
"MD5": Hash.runMD5,
|
||||
"MD6": Hash.runMD6,
|
||||
"SHA0": Hash.runSHA0,
|
||||
"SHA1": Hash.runSHA1,
|
||||
"SHA2": Hash.runSHA2,
|
||||
"SHA3": Hash.runSHA3,
|
||||
"Keccak": Hash.runKeccak,
|
||||
"Shake": Hash.runShake,
|
||||
"RIPEMD": Hash.runRIPEMD,
|
||||
"HAS-160": Hash.runHAS,
|
||||
"Whirlpool": Hash.runWhirlpool,
|
||||
"Snefru": Hash.runSnefru,
|
||||
"HMAC": Hash.runHMAC,
|
||||
"Fletcher-8 Checksum": Checksum.runFletcher8,
|
||||
"Fletcher-16 Checksum": Checksum.runFletcher16,
|
||||
"Fletcher-32 Checksum": Checksum.runFletcher32,
|
||||
"Fletcher-64 Checksum": Checksum.runFletcher64,
|
||||
"Adler-32 Checksum": Checksum.runAdler32,
|
||||
"CRC-16 Checksum": Checksum.runCRC16,
|
||||
"CRC-32 Checksum": Checksum.runCRC32,
|
||||
"TCP/IP Checksum": Checksum.runTCPIP,
|
||||
"Analyse hash": Hash.runAnalyse,
|
||||
"Generate all hashes": Hash.runAll,
|
||||
"MD2": Hash.runMD2,
|
||||
"MD4": Hash.runMD4,
|
||||
"MD5": Hash.runMD5,
|
||||
"MD6": Hash.runMD6,
|
||||
"SHA0": Hash.runSHA0,
|
||||
"SHA1": Hash.runSHA1,
|
||||
"SHA2": Hash.runSHA2,
|
||||
"SHA3": Hash.runSHA3,
|
||||
"Keccak": Hash.runKeccak,
|
||||
"Shake": Hash.runShake,
|
||||
"RIPEMD": Hash.runRIPEMD,
|
||||
"HAS-160": Hash.runHAS,
|
||||
"Whirlpool": Hash.runWhirlpool,
|
||||
"Snefru": Hash.runSnefru,
|
||||
"CTPH": Hash.runCTPH,
|
||||
"SSDEEP": Hash.runSSDEEP,
|
||||
"Compare CTPH hashes": Hash.runCompareCTPH,
|
||||
"Compare SSDEEP hashes": Hash.runCompareSSDEEP,
|
||||
"HMAC": Hash.runHMAC,
|
||||
"Fletcher-8 Checksum": Checksum.runFletcher8,
|
||||
"Fletcher-16 Checksum": Checksum.runFletcher16,
|
||||
"Fletcher-32 Checksum": Checksum.runFletcher32,
|
||||
"Fletcher-64 Checksum": Checksum.runFletcher64,
|
||||
"Adler-32 Checksum": Checksum.runAdler32,
|
||||
"CRC-16 Checksum": Checksum.runCRC16,
|
||||
"CRC-32 Checksum": Checksum.runCRC32,
|
||||
"TCP/IP Checksum": Checksum.runTCPIP,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import IP from "../../operations/IP.js";
|
||||
import Filetime from "../../operations/Filetime.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -21,8 +20,6 @@ OpModules.JSBN = {
|
||||
"Parse IPv4 header": IP.runParseIPv4Header,
|
||||
"Change IP format": IP.runChangeIpFormat,
|
||||
"Group IP addresses": IP.runGroupIps,
|
||||
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
|
||||
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
|
||||
@@ -18,6 +18,7 @@ import HTTPModule from "./HTTP.js";
|
||||
import ImageModule from "./Image.js";
|
||||
import JSBNModule from "./JSBN.js";
|
||||
import PublicKeyModule from "./PublicKey.js";
|
||||
import RegexModule from "./Regex.js";
|
||||
import ShellcodeModule from "./Shellcode.js";
|
||||
import URLModule from "./URL.js";
|
||||
|
||||
@@ -34,6 +35,7 @@ Object.assign(
|
||||
ImageModule,
|
||||
JSBNModule,
|
||||
PublicKeyModule,
|
||||
RegexModule,
|
||||
ShellcodeModule,
|
||||
URLModule
|
||||
);
|
||||
|
||||
30
src/core/config/modules/Regex.js
Normal file
30
src/core/config/modules/Regex.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import Extract from "../../operations/Extract.js";
|
||||
import Regex from "../../operations/Regex.js";
|
||||
|
||||
|
||||
/**
|
||||
* Regex module.
|
||||
*
|
||||
* Libraries:
|
||||
* - XRegExp
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Regex = {
|
||||
"Regular expression": Regex.runRegex,
|
||||
"Find / Replace": Regex.runFindReplace,
|
||||
"Strings": Extract.runStrings,
|
||||
"Extract IP addresses": Extract.runIp,
|
||||
"Extract email addresses": Extract.runEmail,
|
||||
"Extract MAC addresses": Extract.runMac,
|
||||
"Extract URLs": Extract.runUrls,
|
||||
"Extract domains": Extract.runDomains,
|
||||
"Extract file paths": Extract.runFilePaths,
|
||||
"Extract dates": Extract.runDates,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ const BCD = {
|
||||
runToBCD: function(input, args) {
|
||||
if (input.isNaN())
|
||||
return "Invalid input";
|
||||
if (!input.floor().equals(input))
|
||||
if (!input.integerValue(BigNumber.ROUND_DOWN).isEqualTo(input))
|
||||
return "Fractional values are not supported by BCD";
|
||||
|
||||
const encoding = BCD.ENCODING_LOOKUP[args[0]],
|
||||
|
||||
@@ -521,6 +521,10 @@ DES uses a key length of 8 bytes (64 bits).`;
|
||||
* @default
|
||||
*/
|
||||
PRNG_BYTES: 32,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PRNG_OUTPUT: ["Hex", "Integer", "Byte array", "Raw"],
|
||||
|
||||
/**
|
||||
@@ -551,7 +555,7 @@ DES uses a key length of 8 bytes (64 bits).`;
|
||||
return forge.util.bytesToHex(bytes);
|
||||
case "Integer":
|
||||
for (i = bytes.length - 1; i >= 0; i--) {
|
||||
value = value.mul(256).plus(bytes.charCodeAt(i));
|
||||
value = value.times(256).plus(bytes.charCodeAt(i));
|
||||
}
|
||||
return value.toFixed();
|
||||
case "Byte array":
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import {camelCase, kebabCase, snakeCase} from "lodash";
|
||||
|
||||
import Utils from "../Utils.js";
|
||||
import vkbeautify from "vkbeautify";
|
||||
import {DOMParser} from "xmldom";
|
||||
import xpath from "xpath";
|
||||
import jpath from "jsonpath";
|
||||
import nwmatcher from "nwmatcher";
|
||||
import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js";
|
||||
import hljs from "highlight.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -24,12 +22,7 @@ const Code = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LANGUAGES: ["default-code", "default-markup", "bash", "bsh", "c", "cc", "coffee", "cpp", "cs", "csh", "cv", "cxx", "cyc", "htm", "html", "in.tag", "java", "javascript", "js", "json", "m", "mxml", "perl", "pl", "pm", "py", "python", "rb", "rc", "rs", "ruby", "rust", "sh", "uq.val", "xhtml", "xml", "xsl"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LINE_NUMS: false,
|
||||
LANGUAGES: ["auto detect"].concat(hljs.listLanguages()),
|
||||
|
||||
/**
|
||||
* Syntax highlighter operation.
|
||||
@@ -39,9 +32,13 @@ const Code = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runSyntaxHighlight: function(input, args) {
|
||||
let language = args[0],
|
||||
lineNums = args[1];
|
||||
return "<code class='prettyprint'>" + prettyPrintOne(Utils.escapeHtml(input), language, lineNums) + "</code>";
|
||||
const language = args[0];
|
||||
|
||||
if (language === "auto detect") {
|
||||
return hljs.highlightAuto(input).value;
|
||||
}
|
||||
|
||||
return hljs.highlight(language, input, true).value;
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ const Convert = {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.mul(Convert.DISTANCE_FACTOR[inputUnits]);
|
||||
input = input.times(Convert.DISTANCE_FACTOR[inputUnits]);
|
||||
return input.div(Convert.DISTANCE_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
@@ -148,7 +148,7 @@ const Convert = {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.mul(Convert.DATA_FACTOR[inputUnits]);
|
||||
input = input.times(Convert.DATA_FACTOR[inputUnits]);
|
||||
return input.div(Convert.DATA_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
@@ -228,7 +228,7 @@ const Convert = {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.mul(Convert.AREA_FACTOR[inputUnits]);
|
||||
input = input.times(Convert.AREA_FACTOR[inputUnits]);
|
||||
return input.div(Convert.AREA_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
@@ -339,7 +339,7 @@ const Convert = {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.mul(Convert.MASS_FACTOR[inputUnits]);
|
||||
input = input.times(Convert.MASS_FACTOR[inputUnits]);
|
||||
return input.div(Convert.MASS_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
@@ -404,7 +404,7 @@ const Convert = {
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input.mul(Convert.SPEED_FACTOR[inputUnits]);
|
||||
input = input.times(Convert.SPEED_FACTOR[inputUnits]);
|
||||
return input.div(Convert.SPEED_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
@@ -189,6 +189,20 @@ const DateTime = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sleep operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runSleep: async function(input, args) {
|
||||
const ms = args[0];
|
||||
await new Promise(r => setTimeout(r, ms));
|
||||
return input;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import XRegExp from "xregexp";
|
||||
|
||||
|
||||
/**
|
||||
* Identifier extraction operations.
|
||||
*
|
||||
@@ -26,6 +29,11 @@ const Extract = {
|
||||
match;
|
||||
|
||||
while ((match = searchRegex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (match.index === searchRegex.lastIndex) {
|
||||
searchRegex.lastIndex++;
|
||||
}
|
||||
|
||||
if (removeRegex && removeRegex.test(match[0]))
|
||||
continue;
|
||||
total++;
|
||||
@@ -43,7 +51,20 @@ const Extract = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MIN_STRING_LEN: 3,
|
||||
MIN_STRING_LEN: 4,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
STRING_MATCH_TYPE: [
|
||||
"[ASCII]", "Alphanumeric + punctuation (A)", "All printable chars (A)", "Null-terminated strings (A)",
|
||||
"[Unicode]", "Alphanumeric + punctuation (U)", "All printable chars (U)", "Null-terminated strings (U)"
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENCODING_LIST: ["Single byte", "16-bit littleendian", "16-bit bigendian", "All"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -58,10 +79,59 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runStrings: function(input, args) {
|
||||
let minLen = args[0] || Extract.MIN_STRING_LEN,
|
||||
displayTotal = args[1],
|
||||
strings = "[A-Z\\d/\\-:.,_$%'\"()<>= !\\[\\]{}@]",
|
||||
regex = new RegExp(strings + "{" + minLen + ",}", "ig");
|
||||
const encoding = args[0],
|
||||
minLen = args[1],
|
||||
matchType = args[2],
|
||||
displayTotal = args[3],
|
||||
alphanumeric = "A-Z\\d",
|
||||
punctuation = "/\\-:.,_$%'\"()<>= !\\[\\]{}@",
|
||||
printable = "\x20-\x7e",
|
||||
uniAlphanumeric = "\\pL\\pN",
|
||||
uniPunctuation = "\\pP\\pZ",
|
||||
uniPrintable = "\\pL\\pM\\pZ\\pS\\pN\\pP";
|
||||
|
||||
let strings = "";
|
||||
|
||||
switch (matchType) {
|
||||
case "Alphanumeric + punctuation (A)":
|
||||
strings = `[${alphanumeric + punctuation}]`;
|
||||
break;
|
||||
case "All printable chars (A)":
|
||||
case "Null-terminated strings (A)":
|
||||
strings = `[${printable}]`;
|
||||
break;
|
||||
case "Alphanumeric + punctuation (U)":
|
||||
strings = `[${uniAlphanumeric + uniPunctuation}]`;
|
||||
break;
|
||||
case "All printable chars (U)":
|
||||
case "Null-terminated strings (U)":
|
||||
strings = `[${uniPrintable}]`;
|
||||
break;
|
||||
}
|
||||
|
||||
// UTF-16 support is hacked in by allowing null bytes on either side of the matched chars
|
||||
switch (encoding) {
|
||||
case "All":
|
||||
strings = `(\x00?${strings}\x00?)`;
|
||||
break;
|
||||
case "16-bit littleendian":
|
||||
strings = `(${strings}\x00)`;
|
||||
break;
|
||||
case "16-bit bigendian":
|
||||
strings = `(\x00${strings})`;
|
||||
break;
|
||||
case "Single byte":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
strings = `${strings}{${minLen},}`;
|
||||
|
||||
if (matchType.includes("Null-terminated")) {
|
||||
strings += "\x00";
|
||||
}
|
||||
|
||||
const regex = new XRegExp(strings, "ig");
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
@@ -137,7 +207,7 @@ const Extract = {
|
||||
*/
|
||||
runEmail: function(input, args) {
|
||||
let displayTotal = args[0],
|
||||
regex = /\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}/ig;
|
||||
regex = /\b\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}\b/ig;
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
@@ -217,7 +287,7 @@ const Extract = {
|
||||
includeUnixPath = args[1],
|
||||
displayTotal = args[2],
|
||||
winDrive = "[A-Z]:\\\\",
|
||||
winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)]{0,61}",
|
||||
winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)~]{0,61}",
|
||||
winExt = "[A-Z\\d]{1,6}",
|
||||
winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName +
|
||||
"(?:\\." + winExt + ")?",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {BigInteger} from "jsbn";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* Windows Filetime operations.
|
||||
@@ -35,27 +35,29 @@ const Filetime = {
|
||||
let units = args[0],
|
||||
format = args[1];
|
||||
|
||||
if (!input) return "";
|
||||
|
||||
if (format === "Hex") {
|
||||
input = new BigInteger(input, 16);
|
||||
input = new BigNumber(input, 16);
|
||||
} else {
|
||||
input = new BigInteger(input);
|
||||
input = new BigNumber(input);
|
||||
}
|
||||
|
||||
input = input.subtract(new BigInteger("116444736000000000"));
|
||||
input = input.minus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.divide(new BigInteger("10000000"));
|
||||
input = input.dividedBy(new BigNumber("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
input = input.divide(new BigInteger("10000"));
|
||||
input = input.dividedBy(new BigNumber("10000"));
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
input = input.divide(new BigInteger("10"));
|
||||
input = input.dividedBy(new BigNumber("10"));
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
input = input.multiply(new BigInteger("100"));
|
||||
input = input.multipliedBy(new BigNumber("100"));
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
return input.toString();
|
||||
return input.toFixed();
|
||||
},
|
||||
|
||||
|
||||
@@ -71,26 +73,28 @@ const Filetime = {
|
||||
let units = args[0],
|
||||
format = args[1];
|
||||
|
||||
input = new BigInteger(input);
|
||||
if (!input) return "";
|
||||
|
||||
input = new BigNumber(input);
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.multiply(new BigInteger("10000000"));
|
||||
input = input.multipliedBy(new BigNumber("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
input = input.multiply(new BigInteger("10000"));
|
||||
input = input.multipliedBy(new BigNumber("10000"));
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
input = input.multiply(new BigInteger("10"));
|
||||
input = input.multiplyiedBy(new BigNumber("10"));
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
input = input.divide(new BigInteger("100"));
|
||||
input = input.dividedBy(new BigNumber("100"));
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
input = input.add(new BigInteger("116444736000000000"));
|
||||
input = input.plus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (format === "Hex"){
|
||||
return input.toString(16);
|
||||
} else {
|
||||
return input.toString();
|
||||
return input.toFixed();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {UAS_parser as UAParser} from "../lib/uas_parser.js";
|
||||
import UAParser from "ua-parser-js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -46,20 +46,22 @@ const HTTP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseUserAgent: function(input, args) {
|
||||
const ua = UAParser.parse(input);
|
||||
|
||||
return "Type: " + ua.type + "\n" +
|
||||
"Family: " + ua.uaFamily + "\n" +
|
||||
"Name: " + ua.uaName + "\n" +
|
||||
"URL: " + ua.uaUrl + "\n" +
|
||||
"Company: " + ua.uaCompany + "\n" +
|
||||
"Company URL: " + ua.uaCompanyUrl + "\n\n" +
|
||||
"OS Family: " + ua.osFamily + "\n" +
|
||||
"OS Name: " + ua.osName + "\n" +
|
||||
"OS URL: " + ua.osUrl + "\n" +
|
||||
"OS Company: " + ua.osCompany + "\n" +
|
||||
"OS Company URL: " + ua.osCompanyUrl + "\n" +
|
||||
"Device Type: " + ua.deviceType + "\n";
|
||||
const ua = UAParser(input);
|
||||
return `Browser
|
||||
Name: ${ua.browser.name || "unknown"}
|
||||
Version: ${ua.browser.version || "unknown"}
|
||||
Device
|
||||
Model: ${ua.device.model || "unknown"}
|
||||
Type: ${ua.device.type || "unknown"}
|
||||
Vendor: ${ua.device.vendor || "unknown"}
|
||||
Engine
|
||||
Name: ${ua.engine.name || "unknown"}
|
||||
Version: ${ua.engine.version || "unknown"}
|
||||
OS
|
||||
Name: ${ua.os.name || "unknown"}
|
||||
Version: ${ua.os.version || "unknown"}
|
||||
CPU
|
||||
Architecture: ${ua.cpu.architecture || "unknown"}`;
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import Utils from "../Utils.js";
|
||||
import CryptoApi from "crypto-api";
|
||||
import CryptoApi from "babel-loader!crypto-api";
|
||||
import MD6 from "node-md6";
|
||||
import * as SHA3 from "js-sha3";
|
||||
import Checksum from "./Checksum.js";
|
||||
import ctph from "ctph.js";
|
||||
import ssdeep from "ssdeep.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -20,22 +22,22 @@ const Hash = {
|
||||
* Generic hash function.
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object} [options={}]
|
||||
* @returns {string}
|
||||
*/
|
||||
runHash: function(name, input) {
|
||||
const hasher = CryptoApi.hasher(name);
|
||||
hasher.state.message = input;
|
||||
hasher.state.length += input.length;
|
||||
hasher.process();
|
||||
return hasher.finalize().stringify("hex");
|
||||
runHash: function(name, input, options={}) {
|
||||
const msg = Utils.arrayBufferToStr(input, false),
|
||||
hasher = CryptoApi.getHasher(name, options);
|
||||
hasher.update(msg);
|
||||
return CryptoApi.encoder.toHex(hasher.finalize());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD2 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -47,7 +49,7 @@ const Hash = {
|
||||
/**
|
||||
* MD4 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -59,7 +61,7 @@ const Hash = {
|
||||
/**
|
||||
* MD5 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -103,7 +105,7 @@ const Hash = {
|
||||
/**
|
||||
* SHA0 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -115,7 +117,7 @@ const Hash = {
|
||||
/**
|
||||
* SHA1 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -133,7 +135,7 @@ const Hash = {
|
||||
/**
|
||||
* SHA2 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -152,7 +154,7 @@ const Hash = {
|
||||
/**
|
||||
* SHA3 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -190,7 +192,7 @@ const Hash = {
|
||||
/**
|
||||
* Keccak operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -233,7 +235,7 @@ const Hash = {
|
||||
/**
|
||||
* Shake operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -269,7 +271,7 @@ const Hash = {
|
||||
/**
|
||||
* RIPEMD operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -282,7 +284,7 @@ const Hash = {
|
||||
/**
|
||||
* HAS-160 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -300,7 +302,7 @@ const Hash = {
|
||||
/**
|
||||
* Whirlpool operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -324,14 +326,73 @@ const Hash = {
|
||||
/**
|
||||
* Snefru operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSnefru: function (input, args) {
|
||||
const rounds = args[0],
|
||||
size = args[1];
|
||||
return Hash.runHash(`snefru-${rounds}-${size}`, input);
|
||||
return Hash.runHash("snefru", input, {
|
||||
rounds: args[0],
|
||||
length: args[1]
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* CTPH operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCTPH: function (input, args) {
|
||||
return ctph.digest(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SSDEEP operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSSDEEP: function (input, args) {
|
||||
return ssdeep.digest(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIM_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon"],
|
||||
|
||||
/**
|
||||
* Compare CTPH hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {Number}
|
||||
*/
|
||||
runCompareCTPH: function (input, args) {
|
||||
const samples = input.split(Utils.charRep[args[0]]);
|
||||
if (samples.length !== 2) throw "Incorrect number of samples.";
|
||||
return ctph.similarity(samples[0], samples[1]);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Compare SSDEEP hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {Number}
|
||||
*/
|
||||
runCompareSSDEEP: function (input, args) {
|
||||
const samples = input.split(Utils.charRep[args[0]]);
|
||||
if (samples.length !== 2) throw "Incorrect number of samples.";
|
||||
return ssdeep.similarity(samples[0], samples[1]);
|
||||
},
|
||||
|
||||
|
||||
@@ -358,71 +419,85 @@ const Hash = {
|
||||
"HAS160",
|
||||
"Whirlpool",
|
||||
"Whirlpool-0",
|
||||
"Whirlpool-T"
|
||||
"Whirlpool-T",
|
||||
"Snefru"
|
||||
],
|
||||
|
||||
/**
|
||||
* HMAC operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHMAC: function (input, args) {
|
||||
const password = args[0],
|
||||
const key = args[0],
|
||||
hashFunc = args[1].toLowerCase(),
|
||||
hmac = CryptoApi.mac("hmac", password, hashFunc, {});
|
||||
msg = Utils.arrayBufferToStr(input, false),
|
||||
hasher = CryptoApi.getHasher(hashFunc);
|
||||
|
||||
hmac.update(input);
|
||||
return hmac.finalize().stringify("hex");
|
||||
// Horrible shim to fix constructor bug. Reported in nf404/crypto-api#8
|
||||
hasher.reset = () => {
|
||||
hasher.state = {};
|
||||
const tmp = new hasher.constructor();
|
||||
hasher.state = tmp.state;
|
||||
};
|
||||
|
||||
const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
|
||||
mac.update(msg);
|
||||
return CryptoApi.encoder.toHex(mac.finalize());
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generate all hashes operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAll: function (input, args) {
|
||||
let byteArray = Utils.strToByteArray(input),
|
||||
output = "MD2: " + Hash.runMD2(input, []) +
|
||||
"\nMD4: " + Hash.runMD4(input, []) +
|
||||
"\nMD5: " + Hash.runMD5(input, []) +
|
||||
"\nMD6: " + Hash.runMD6(input, []) +
|
||||
"\nSHA0: " + Hash.runSHA0(input, []) +
|
||||
"\nSHA1: " + Hash.runSHA1(input, []) +
|
||||
"\nSHA2 224: " + Hash.runSHA2(input, ["224"]) +
|
||||
"\nSHA2 256: " + Hash.runSHA2(input, ["256"]) +
|
||||
"\nSHA2 384: " + Hash.runSHA2(input, ["384"]) +
|
||||
"\nSHA2 512: " + Hash.runSHA2(input, ["512"]) +
|
||||
"\nSHA3 224: " + Hash.runSHA3(input, ["224"]) +
|
||||
"\nSHA3 256: " + Hash.runSHA3(input, ["256"]) +
|
||||
"\nSHA3 384: " + Hash.runSHA3(input, ["384"]) +
|
||||
"\nSHA3 512: " + Hash.runSHA3(input, ["512"]) +
|
||||
"\nKeccak 224: " + Hash.runKeccak(input, ["224"]) +
|
||||
"\nKeccak 256: " + Hash.runKeccak(input, ["256"]) +
|
||||
"\nKeccak 384: " + Hash.runKeccak(input, ["384"]) +
|
||||
"\nKeccak 512: " + Hash.runKeccak(input, ["512"]) +
|
||||
"\nShake 128: " + Hash.runShake(input, ["128", 256]) +
|
||||
"\nShake 256: " + Hash.runShake(input, ["256", 512]) +
|
||||
"\nRIPEMD-128: " + Hash.runRIPEMD(input, ["128"]) +
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD(input, ["160"]) +
|
||||
"\nRIPEMD-256: " + Hash.runRIPEMD(input, ["256"]) +
|
||||
"\nRIPEMD-320: " + Hash.runRIPEMD(input, ["320"]) +
|
||||
"\nHAS-160: " + Hash.runHAS(input, []) +
|
||||
"\nWhirlpool-0: " + Hash.runWhirlpool(input, ["Whirlpool-0"]) +
|
||||
"\nWhirlpool-T: " + Hash.runWhirlpool(input, ["Whirlpool-T"]) +
|
||||
"\nWhirlpool: " + Hash.runWhirlpool(input, ["Whirlpool"]) +
|
||||
const arrayBuffer = input,
|
||||
str = Utils.arrayBufferToStr(arrayBuffer, false),
|
||||
byteArray = new Uint8Array(arrayBuffer),
|
||||
output = "MD2: " + Hash.runMD2(arrayBuffer, []) +
|
||||
"\nMD4: " + Hash.runMD4(arrayBuffer, []) +
|
||||
"\nMD5: " + Hash.runMD5(arrayBuffer, []) +
|
||||
"\nMD6: " + Hash.runMD6(str, []) +
|
||||
"\nSHA0: " + Hash.runSHA0(arrayBuffer, []) +
|
||||
"\nSHA1: " + Hash.runSHA1(arrayBuffer, []) +
|
||||
"\nSHA2 224: " + Hash.runSHA2(arrayBuffer, ["224"]) +
|
||||
"\nSHA2 256: " + Hash.runSHA2(arrayBuffer, ["256"]) +
|
||||
"\nSHA2 384: " + Hash.runSHA2(arrayBuffer, ["384"]) +
|
||||
"\nSHA2 512: " + Hash.runSHA2(arrayBuffer, ["512"]) +
|
||||
"\nSHA3 224: " + Hash.runSHA3(arrayBuffer, ["224"]) +
|
||||
"\nSHA3 256: " + Hash.runSHA3(arrayBuffer, ["256"]) +
|
||||
"\nSHA3 384: " + Hash.runSHA3(arrayBuffer, ["384"]) +
|
||||
"\nSHA3 512: " + Hash.runSHA3(arrayBuffer, ["512"]) +
|
||||
"\nKeccak 224: " + Hash.runKeccak(arrayBuffer, ["224"]) +
|
||||
"\nKeccak 256: " + Hash.runKeccak(arrayBuffer, ["256"]) +
|
||||
"\nKeccak 384: " + Hash.runKeccak(arrayBuffer, ["384"]) +
|
||||
"\nKeccak 512: " + Hash.runKeccak(arrayBuffer, ["512"]) +
|
||||
"\nShake 128: " + Hash.runShake(arrayBuffer, ["128", 256]) +
|
||||
"\nShake 256: " + Hash.runShake(arrayBuffer, ["256", 512]) +
|
||||
"\nRIPEMD-128: " + Hash.runRIPEMD(arrayBuffer, ["128"]) +
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD(arrayBuffer, ["160"]) +
|
||||
"\nRIPEMD-256: " + Hash.runRIPEMD(arrayBuffer, ["256"]) +
|
||||
"\nRIPEMD-320: " + Hash.runRIPEMD(arrayBuffer, ["320"]) +
|
||||
"\nHAS-160: " + Hash.runHAS(arrayBuffer, []) +
|
||||
"\nWhirlpool-0: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-0"]) +
|
||||
"\nWhirlpool-T: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-T"]) +
|
||||
"\nWhirlpool: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool"]) +
|
||||
"\nSSDEEP: " + Hash.runSSDEEP(str) +
|
||||
"\nCTPH: " + Hash.runCTPH(str) +
|
||||
"\n\nChecksums:" +
|
||||
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
|
||||
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
|
||||
"\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
|
||||
"\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
|
||||
"\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
|
||||
"\nCRC-16: " + Checksum.runCRC16(input, []) +
|
||||
"\nCRC-32: " + Checksum.runCRC32(input, []);
|
||||
"\nCRC-16: " + Checksum.runCRC16(str, []) +
|
||||
"\nCRC-32: " + Checksum.runCRC32(str, []);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
@@ -34,6 +34,11 @@ const MAC = {
|
||||
* @default
|
||||
*/
|
||||
CISCO_STYLE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
IPV6_INTERFACE_ID: false,
|
||||
|
||||
/**
|
||||
* Format MAC addresses operation.
|
||||
@@ -50,6 +55,7 @@ const MAC = {
|
||||
dashDelim = args[2],
|
||||
colonDelim = args[3],
|
||||
ciscoStyle = args[4],
|
||||
ipv6IntID = args[5],
|
||||
outputList = [],
|
||||
macs = input.toLowerCase().split(/[,\s\r\n]+/);
|
||||
|
||||
@@ -57,23 +63,32 @@ const MAC = {
|
||||
let cleanMac = mac.replace(/[:.-]+/g, ""),
|
||||
macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"),
|
||||
macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"),
|
||||
macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1.");
|
||||
macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1."),
|
||||
macIPv6 = cleanMac.slice(0, 6) + "fffe" + cleanMac.slice(6);
|
||||
|
||||
macIPv6 = macIPv6.replace(/(.{4}(?=.))/g, "$1:");
|
||||
let bite = parseInt(macIPv6.slice(0, 2), 16) ^ 2;
|
||||
bite = bite.toString(16).padStart(2, "0");
|
||||
macIPv6 = bite + macIPv6.slice(2);
|
||||
|
||||
if (outputCase === "Lower only") {
|
||||
if (noDelim) outputList.push(cleanMac);
|
||||
if (dashDelim) outputList.push(macHyphen);
|
||||
if (colonDelim) outputList.push(macColon);
|
||||
if (ciscoStyle) outputList.push(macCisco);
|
||||
if (ipv6IntID) outputList.push(macIPv6);
|
||||
} else if (outputCase === "Upper only") {
|
||||
if (noDelim) outputList.push(cleanMac.toUpperCase());
|
||||
if (dashDelim) outputList.push(macHyphen.toUpperCase());
|
||||
if (colonDelim) outputList.push(macColon.toUpperCase());
|
||||
if (ciscoStyle) outputList.push(macCisco.toUpperCase());
|
||||
if (ipv6IntID) outputList.push(macIPv6.toUpperCase());
|
||||
} else {
|
||||
if (noDelim) outputList.push(cleanMac, cleanMac.toUpperCase());
|
||||
if (dashDelim) outputList.push(macHyphen, macHyphen.toUpperCase());
|
||||
if (colonDelim) outputList.push(macColon, macColon.toUpperCase());
|
||||
if (ciscoStyle) outputList.push(macCisco, macCisco.toUpperCase());
|
||||
if (ipv6IntID) outputList.push(macIPv6, macIPv6.toUpperCase());
|
||||
}
|
||||
|
||||
outputList.push(
|
||||
|
||||
278
src/core/operations/Regex.js
Normal file
278
src/core/operations/Regex.js
Normal file
@@ -0,0 +1,278 @@
|
||||
import XRegExp from "xregexp";
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Regex operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Regex = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_PRE_POPULATE: [
|
||||
{
|
||||
name: "User defined",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "IPv4 address",
|
||||
value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?"
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
|
||||
},
|
||||
{
|
||||
name: "Email address",
|
||||
value: "\\b(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})\\b"
|
||||
},
|
||||
{
|
||||
name: "URL",
|
||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||
},
|
||||
{
|
||||
name: "Domain",
|
||||
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
|
||||
},
|
||||
{
|
||||
name: "Windows file path",
|
||||
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)~]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
|
||||
},
|
||||
{
|
||||
name: "UNIX file path",
|
||||
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
|
||||
},
|
||||
{
|
||||
name: "MAC address",
|
||||
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
|
||||
},
|
||||
{
|
||||
name: "Date (yyyy-mm-dd)",
|
||||
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
|
||||
},
|
||||
{
|
||||
name: "Date (dd/mm/yyyy)",
|
||||
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Date (mm/dd/yyyy)",
|
||||
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Strings",
|
||||
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISPLAY_TOTAL: false,
|
||||
|
||||
/**
|
||||
* Regular expression operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runRegex: function(input, args) {
|
||||
const userRegex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
s = args[4],
|
||||
u = args[5],
|
||||
a = args[6],
|
||||
displayTotal = args[7],
|
||||
outputFormat = args[8];
|
||||
let modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
if (s) modifiers += "s";
|
||||
if (u) modifiers += "u";
|
||||
if (a) modifiers += "A";
|
||||
|
||||
if (userRegex && userRegex !== "^" && userRegex !== "$") {
|
||||
try {
|
||||
const regex = new XRegExp(userRegex, modifiers);
|
||||
|
||||
switch (outputFormat) {
|
||||
case "Highlight matches":
|
||||
return Regex._regexHighlight(input, regex, displayTotal);
|
||||
case "List matches":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
}
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
} else {
|
||||
return Utils.escapeHtml(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_GLOBAL: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_CASE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_MULTILINE: true,
|
||||
|
||||
/**
|
||||
* Find / Replace operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFindReplace: function(input, args) {
|
||||
let find = args[0].string,
|
||||
type = args[0].option,
|
||||
replace = args[1],
|
||||
g = args[2],
|
||||
i = args[3],
|
||||
m = args[4],
|
||||
modifiers = "";
|
||||
|
||||
if (g) modifiers += "g";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (type === "Regex") {
|
||||
find = new RegExp(find, modifiers);
|
||||
return input.replace(find, replace);
|
||||
}
|
||||
|
||||
if (type.indexOf("Extended") === 0) {
|
||||
find = Utils.parseEscapedChars(find);
|
||||
}
|
||||
|
||||
find = new RegExp(Utils.escapeRegex(find), modifiers);
|
||||
|
||||
return input.replace(find, replace);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds HTML highlights to matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexHighlight: function(input, regex, displayTotal) {
|
||||
let output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (m.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
}
|
||||
|
||||
// Add up to match
|
||||
output += Utils.escapeHtml(input.slice(i, m.index));
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
|
||||
// Switch highlight
|
||||
hl = hl === 1 ? 2 : 1;
|
||||
|
||||
i = regex.lastIndex;
|
||||
total++;
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += Utils.escapeHtml(input.slice(i, input.length));
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string listing the matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @param {boolean} matches - Display full match
|
||||
* @param {boolean} captureGroups - Display each of the capture groups separately
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexList: function(input, regex, displayTotal, matches, captureGroups) {
|
||||
let output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = regex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (match.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
}
|
||||
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (captureGroups) {
|
||||
for (let i = 1; i < match.length; i++) {
|
||||
if (matches) {
|
||||
output += " Group " + i + ": ";
|
||||
}
|
||||
output += match[i] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output.slice(0, -1);
|
||||
},
|
||||
};
|
||||
|
||||
export default Regex;
|
||||
@@ -12,128 +12,6 @@ import Utils from "../Utils.js";
|
||||
*/
|
||||
const StrUtils = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_PRE_POPULATE: [
|
||||
{
|
||||
name: "User defined",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "IPv4 address",
|
||||
value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?"
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
|
||||
},
|
||||
{
|
||||
name: "Email address",
|
||||
value: "(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})"
|
||||
},
|
||||
{
|
||||
name: "URL",
|
||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||
},
|
||||
{
|
||||
name: "Domain",
|
||||
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
|
||||
},
|
||||
{
|
||||
name: "Windows file path",
|
||||
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
|
||||
},
|
||||
{
|
||||
name: "UNIX file path",
|
||||
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
|
||||
},
|
||||
{
|
||||
name: "MAC address",
|
||||
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
|
||||
},
|
||||
{
|
||||
name: "Date (yyyy-mm-dd)",
|
||||
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
|
||||
},
|
||||
{
|
||||
name: "Date (dd/mm/yyyy)",
|
||||
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Date (mm/dd/yyyy)",
|
||||
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Strings",
|
||||
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_CASE_INSENSITIVE: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_MULTILINE_MATCHING: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISPLAY_TOTAL: false,
|
||||
|
||||
/**
|
||||
* Regular expression operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runRegex: function(input, args) {
|
||||
let userRegex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
displayTotal = args[4],
|
||||
outputFormat = args[5],
|
||||
modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (userRegex && userRegex !== "^" && userRegex !== "$") {
|
||||
try {
|
||||
const regex = new RegExp(userRegex, modifiers);
|
||||
|
||||
switch (outputFormat) {
|
||||
case "Highlight matches":
|
||||
return StrUtils._regexHighlight(input, regex, displayTotal);
|
||||
case "List matches":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
}
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
} else {
|
||||
return Utils.escapeHtml(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -187,68 +65,28 @@ const StrUtils = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
|
||||
SPLIT_DELIM_OPTIONS: [
|
||||
{name: "Comma", value: ","},
|
||||
{name: "Space", value: " "},
|
||||
{name: "Line feed", value: "\\n"},
|
||||
{name: "CRLF", value: "\\r\\n"},
|
||||
{name: "Semi-colon", value: ";"},
|
||||
{name: "Colon", value: ":"},
|
||||
{name: "Nothing (separate chars)", value: ""}
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_GLOBAL: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_CASE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_MULTILINE: true,
|
||||
|
||||
/**
|
||||
* Find / Replace operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFindReplace: function(input, args) {
|
||||
let find = args[0].string,
|
||||
type = args[0].option,
|
||||
replace = args[1],
|
||||
g = args[2],
|
||||
i = args[3],
|
||||
m = args[4],
|
||||
modifiers = "";
|
||||
|
||||
if (g) modifiers += "g";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (type === "Regex") {
|
||||
find = new RegExp(find, modifiers);
|
||||
return input.replace(find, replace);
|
||||
}
|
||||
|
||||
if (type.indexOf("Extended") === 0) {
|
||||
find = Utils.parseEscapedChars(find);
|
||||
}
|
||||
|
||||
find = new RegExp(Utils.escapeRegex(find), modifiers);
|
||||
|
||||
return input.replace(find, replace);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SPLIT_DELIM: ",",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
JOIN_DELIM_OPTIONS: [
|
||||
{name: "Line feed", value: "\\n"},
|
||||
{name: "CRLF", value: "\\r\\n"},
|
||||
{name: "Space", value: " "},
|
||||
{name: "Comma", value: ","},
|
||||
{name: "Semi-colon", value: ";"},
|
||||
{name: "Colon", value: ":"},
|
||||
{name: "Nothing (join chars)", value: ""}
|
||||
],
|
||||
|
||||
/**
|
||||
* Split operation.
|
||||
@@ -258,14 +96,20 @@ const StrUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSplit: function(input, args) {
|
||||
let splitDelim = args[0] || StrUtils.SPLIT_DELIM,
|
||||
joinDelim = Utils.charRep[args[1]],
|
||||
let splitDelim = args[0],
|
||||
joinDelim = args[1],
|
||||
sections = input.split(splitDelim);
|
||||
|
||||
return sections.join(joinDelim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
|
||||
/**
|
||||
* Filter operation.
|
||||
*
|
||||
@@ -576,84 +420,6 @@ const StrUtils = {
|
||||
|
||||
return dist.toString();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds HTML highlights to matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexHighlight: function(input, regex, displayTotal) {
|
||||
let output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Add up to match
|
||||
output += Utils.escapeHtml(input.slice(i, m.index));
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
|
||||
// Switch highlight
|
||||
hl = hl === 1 ? 2 : 1;
|
||||
|
||||
i = regex.lastIndex;
|
||||
total++;
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += Utils.escapeHtml(input.slice(i, input.length));
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string listing the matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @param {boolean} matches - Display full match
|
||||
* @param {boolean} captureGroups - Display each of the capture groups separately
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexList: function(input, regex, displayTotal, matches, captureGroups) {
|
||||
let output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = regex.exec(input))) {
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (captureGroups) {
|
||||
for (let i = 1; i < match.length; i++) {
|
||||
if (matches) {
|
||||
output += " Group " + i + ": ";
|
||||
}
|
||||
output += match[i] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
};
|
||||
|
||||
export default StrUtils;
|
||||
|
||||
@@ -27,7 +27,7 @@ const Unicode = {
|
||||
*/
|
||||
runUnescape: function(input, args) {
|
||||
let prefix = Unicode._prefixToRegex[args[0]],
|
||||
regex = new RegExp(prefix+"([a-f\\d]{4,6})", "ig"),
|
||||
regex = new RegExp(prefix+"([a-f\\d]{4})", "ig"),
|
||||
output = "",
|
||||
m,
|
||||
i = 0;
|
||||
|
||||
26
src/core/operations/XKCD.js
Executable file
26
src/core/operations/XKCD.js
Executable file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* XKCD operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const XKCD = {
|
||||
|
||||
/**
|
||||
* XKCD Random Number operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runRandomNumber: function(input, args) {
|
||||
return 4; // chosen by fair dice roll.
|
||||
// guaranteed to be random.
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default XKCD;
|
||||
@@ -377,6 +377,7 @@ App.prototype.loadURIParams = function() {
|
||||
window.location.href.split("#")[1] ||
|
||||
window.location.hash;
|
||||
this.uriParams = Utils.parseURIParams(params);
|
||||
this.autoBakePause = true;
|
||||
|
||||
// Read in recipe from URI params
|
||||
if (this.uriParams.recipe) {
|
||||
@@ -387,35 +388,29 @@ App.prototype.loadURIParams = function() {
|
||||
} else if (this.uriParams.op) {
|
||||
// If there's no recipe, look for single operations
|
||||
this.manager.recipe.clearRecipe();
|
||||
try {
|
||||
this.manager.recipe.addOperation(this.uriParams.op);
|
||||
} catch (err) {
|
||||
// If no exact match, search for nearest match and add that
|
||||
const matchedOps = this.manager.ops.filterOperations(this.uriParams.op, false);
|
||||
if (matchedOps.length) {
|
||||
this.manager.recipe.addOperation(matchedOps[0].name);
|
||||
}
|
||||
|
||||
// Populate search with the string
|
||||
const search = document.getElementById("search");
|
||||
|
||||
search.value = this.uriParams.op;
|
||||
search.dispatchEvent(new Event("search"));
|
||||
// Search for nearest match and add it
|
||||
const matchedOps = this.manager.ops.filterOperations(this.uriParams.op, false);
|
||||
if (matchedOps.length) {
|
||||
this.manager.recipe.addOperation(matchedOps[0].name);
|
||||
}
|
||||
|
||||
// Populate search with the string
|
||||
const search = document.getElementById("search");
|
||||
|
||||
search.value = this.uriParams.op;
|
||||
search.dispatchEvent(new Event("search"));
|
||||
}
|
||||
|
||||
// Read in input data from URI params
|
||||
if (this.uriParams.input) {
|
||||
this.autoBakePause = true;
|
||||
try {
|
||||
const inputData = Utils.fromBase64(this.uriParams.input);
|
||||
this.setInput(inputData);
|
||||
} catch (err) {
|
||||
} finally {
|
||||
this.autoBakePause = false;
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
this.autoBakePause = false;
|
||||
this.autoBake();
|
||||
};
|
||||
|
||||
@@ -443,6 +438,7 @@ App.prototype.getRecipeConfig = function() {
|
||||
/**
|
||||
* Given a recipe configuration, sets the recipe to that configuration.
|
||||
*
|
||||
* @fires Manager#statechange
|
||||
* @param {Object[]} recipeConfig - The recipe configuration
|
||||
*/
|
||||
App.prototype.setRecipeConfig = function(recipeConfig) {
|
||||
|
||||
@@ -382,10 +382,13 @@ ControlsWaiter.prototype.supportButtonClick = function(e) {
|
||||
const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
|
||||
|
||||
if (reportBugInfo) {
|
||||
reportBugInfo.innerHTML = "* Version: " + PKG_VERSION + "\n" +
|
||||
"* Compile time: " + COMPILE_TIME + "\n" +
|
||||
"* User-Agent: \n" + navigator.userAgent + "\n" +
|
||||
"* [Link to reproduce](" + saveLink + ")\n\n";
|
||||
reportBugInfo.innerHTML = `* Version: ${PKG_VERSION + (typeof INLINE === "undefined" ? "" : "s")}
|
||||
* Compile time: ${COMPILE_TIME}
|
||||
* User-Agent:
|
||||
${navigator.userAgent}
|
||||
* [Link to reproduce](${saveLink})
|
||||
|
||||
`;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -110,6 +110,15 @@ HTMLOperation.prototype.highlightSearchString = function(searchStr, namePos, des
|
||||
}
|
||||
|
||||
if (this.description && descPos >= 0) {
|
||||
// Find HTML tag offsets
|
||||
const re = /<[^>]+>/g;
|
||||
let match;
|
||||
while ((match = re.exec(this.description))) {
|
||||
// If the search string occurs within an HTML tag, return without highlighting it.
|
||||
if (descPos >= match.index && descPos <= (match.index + match[0].length))
|
||||
return;
|
||||
}
|
||||
|
||||
this.description = this.description.slice(0, descPos) + "<b><u>" +
|
||||
this.description.slice(descPos, descPos + searchStr.length) + "</u></b>" +
|
||||
this.description.slice(descPos + searchStr.length);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import LoaderWorker from "worker-loader?inline&fallback=false!./LoaderWorker.js";
|
||||
import Utils from "../core/Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -64,6 +65,7 @@ InputWaiter.prototype.set = function(input) {
|
||||
this.setInputInfo(input.size, null);
|
||||
} else {
|
||||
inputText.value = input;
|
||||
this.closeFile();
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
const lines = input.length < (this.app.options.ioDisplayThreshold * 1024) ?
|
||||
input.count("\n") + 1 : null;
|
||||
@@ -262,11 +264,28 @@ InputWaiter.prototype.handleLoaderMessage = function(e) {
|
||||
if (r.hasOwnProperty("fileBuffer")) {
|
||||
log.debug("Input file loaded");
|
||||
this.fileBuffer = r.fileBuffer;
|
||||
this.displayFilePreview();
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows a chunk of the file in the input behind the file overlay.
|
||||
*/
|
||||
InputWaiter.prototype.displayFilePreview = function() {
|
||||
const inputText = document.getElementById("input-text"),
|
||||
fileSlice = this.fileBuffer.slice(0, 4096);
|
||||
|
||||
inputText.style.overflow = "hidden";
|
||||
inputText.classList.add("blur");
|
||||
inputText.value = Utils.printable(Utils.arrayBufferToStr(fileSlice));
|
||||
if (this.fileBuffer.byteLength > 4096) {
|
||||
inputText.value += "[truncated]...";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for file close events.
|
||||
*/
|
||||
@@ -274,6 +293,9 @@ InputWaiter.prototype.closeFile = function() {
|
||||
if (this.loaderWorker) this.loaderWorker.terminate();
|
||||
this.fileBuffer = null;
|
||||
document.getElementById("input-file").style.display = "none";
|
||||
const inputText = document.getElementById("input-text");
|
||||
inputText.style.overflow = "auto";
|
||||
inputText.classList.remove("blur");
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ self.loadFile = function(file) {
|
||||
};
|
||||
|
||||
reader.onerror = function(e) {
|
||||
self.postMessage({"error": file.error.message});
|
||||
self.postMessage({"error": reader.error.message});
|
||||
};
|
||||
|
||||
seek();
|
||||
|
||||
@@ -167,7 +167,8 @@ OperationsWaiter.prototype.opListCreate = function(e) {
|
||||
OperationsWaiter.prototype.enableOpsListPopovers = function(el) {
|
||||
$(el).find("[data-toggle=popover]").addBack("[data-toggle=popover]")
|
||||
.popover({trigger: "manual"})
|
||||
.on("mouseenter", function() {
|
||||
.on("mouseenter", function(e) {
|
||||
if (e.buttons > 0) return; // Mouse button held down - likely dragging an opertion
|
||||
const _this = this;
|
||||
$(this).popover("show");
|
||||
$(".popover").on("mouseleave", function () {
|
||||
@@ -178,7 +179,7 @@ OperationsWaiter.prototype.enableOpsListPopovers = function(el) {
|
||||
setTimeout(function() {
|
||||
// Determine if the popover associated with this element is being hovered over
|
||||
if ($(_this).data("bs.popover") &&
|
||||
!$(_this).data("bs.popover").$tip.is(":hover")) {
|
||||
($(_this).data("bs.popover").$tip && !$(_this).data("bs.popover").$tip.is(":hover"))) {
|
||||
$(_this).popover("hide");
|
||||
}
|
||||
}, 50);
|
||||
|
||||
@@ -64,7 +64,7 @@ OutputWaiter.prototype.set = function(data, type, duration, preserveBuffer) {
|
||||
|
||||
outputText.value = "";
|
||||
outputHtml.innerHTML = data;
|
||||
this.dishStr = Utils.stripHtmlTags(data, true);
|
||||
this.dishStr = Utils.unescapeHtml(Utils.stripHtmlTags(data, true));
|
||||
length = data.length;
|
||||
lines = this.dishStr.count("\n") + 1;
|
||||
|
||||
@@ -128,6 +128,13 @@ OutputWaiter.prototype.setFile = function(buf) {
|
||||
|
||||
fileOverlay.style.display = "block";
|
||||
fileSize.textContent = file.size.toLocaleString() + " bytes";
|
||||
|
||||
// Display preview slice in the background
|
||||
const outputText = document.getElementById("output-text"),
|
||||
fileSlice = this.dishBuffer.slice(0, 4096);
|
||||
|
||||
outputText.classList.add("blur");
|
||||
outputText.value = Utils.printable(Utils.arrayBufferToStr(fileSlice));
|
||||
};
|
||||
|
||||
|
||||
@@ -137,6 +144,7 @@ OutputWaiter.prototype.setFile = function(buf) {
|
||||
OutputWaiter.prototype.closeFile = function() {
|
||||
this.dishBuffer = null;
|
||||
document.getElementById("output-file").style.display = "none";
|
||||
document.getElementById("output-text").classList.remove("blur");
|
||||
};
|
||||
|
||||
|
||||
@@ -163,6 +171,7 @@ OutputWaiter.prototype.displayFileSlice = function() {
|
||||
sliceTo = parseInt(sliceToEl.value, 10),
|
||||
str = Utils.arrayBufferToStr(this.dishBuffer.slice(sliceFrom, sliceTo));
|
||||
|
||||
document.getElementById("output-text").classList.remove("blur");
|
||||
showFileOverlay.style.display = "block";
|
||||
this.set(str, "string", new Date().getTime() - startTime, true);
|
||||
};
|
||||
@@ -177,6 +186,7 @@ OutputWaiter.prototype.showFileOverlayClick = function(e) {
|
||||
const outputFile = document.getElementById("output-file"),
|
||||
showFileOverlay = e.target;
|
||||
|
||||
document.getElementById("output-text").classList.add("blur");
|
||||
outputFile.style.display = "block";
|
||||
showFileOverlay.style.display = "none";
|
||||
this.setOutputInfo(this.dishBuffer.byteLength, null, 0);
|
||||
|
||||
@@ -87,7 +87,9 @@
|
||||
changeLoadingMsg();
|
||||
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 2000) + 1500);
|
||||
</script>
|
||||
<% if (!htmlWebpackPlugin.options.inline) { %>
|
||||
<% if (htmlWebpackPlugin.options.inline) { %>
|
||||
<meta name="robots" content="noindex" />
|
||||
<% } else { %>
|
||||
<script type="application/ld+json">
|
||||
<% print(JSON.stringify(require("../static/structuredData.json"))); %>
|
||||
</script>
|
||||
@@ -183,8 +185,9 @@
|
||||
</div>
|
||||
<div class="textarea-wrapper no-select">
|
||||
<div id="input-highlighter" class="no-select"></div>
|
||||
<textarea id="input-text"></textarea>
|
||||
<textarea id="input-text" spellcheck="false"></textarea>
|
||||
<div id="input-file">
|
||||
<div class="file-overlay"></div>
|
||||
<div style="position: relative; height: 100%;">
|
||||
<div class="card">
|
||||
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
|
||||
@@ -218,9 +221,10 @@
|
||||
<div class="textarea-wrapper">
|
||||
<div id="output-highlighter" class="no-select"></div>
|
||||
<div id="output-html"></div>
|
||||
<textarea id="output-text" readonly="readonly"></textarea>
|
||||
<textarea id="output-text" readonly="readonly" spellcheck="false"></textarea>
|
||||
<img id="show-file-overlay" aria-hidden="true" src="<%- require('../static/images/file-32x32.png') %>" alt="Show file overlay" title="Show file overlay"/>
|
||||
<div id="output-file">
|
||||
<div class="file-overlay"></div>
|
||||
<div style="position: relative; height: 100%;">
|
||||
<div class="card">
|
||||
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
|
||||
@@ -233,7 +237,7 @@
|
||||
</span>
|
||||
<input type="number" class="form-control" id="output-file-slice-from" placeholder="From" value="0" step="1024" min="0">
|
||||
<div class="input-group-addon">to</div>
|
||||
<input type="number" class="form-control" id="output-file-slice-to" placeholder="To" value="1024" step="1024" min="0">
|
||||
<input type="number" class="form-control" id="output-file-slice-to" placeholder="To" value="2048" step="1024" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
33
src/web/static/sitemap.js
Normal file
33
src/web/static/sitemap.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import sm from "sitemap";
|
||||
import OperationConfig from "../../core/config/MetaConfig.js";
|
||||
|
||||
|
||||
/**
|
||||
* Generates an XML sitemap for all CyberChef operations and a number of recipes.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
const sitemap = sm.createSitemap({
|
||||
hostname: "https://gchq.github.io/CyberChef",
|
||||
});
|
||||
|
||||
sitemap.add({
|
||||
url: "/",
|
||||
changefreq: "weekly",
|
||||
priority: 1.0
|
||||
});
|
||||
|
||||
for (let op in OperationConfig) {
|
||||
sitemap.add({
|
||||
url: `/?op=${encodeURIComponent(op)}`,
|
||||
changeFreq: "yearly",
|
||||
priority: 0.5
|
||||
});
|
||||
}
|
||||
|
||||
const xml = sitemap.toString();
|
||||
|
||||
console.log(xml); // eslint-disable-line no-console
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/* Libraries */
|
||||
import "google-code-prettify/src/prettify.css";
|
||||
import "highlight.js/styles/vs.css";
|
||||
|
||||
/* Frameworks */
|
||||
import "./vendors/bootstrap.less";
|
||||
|
||||
@@ -84,10 +84,17 @@
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--title-background-colour);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file-overlay {
|
||||
position: absolute;
|
||||
opacity: 0.8;
|
||||
background-color: var(--title-background-colour);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#show-file-overlay {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
|
||||
@@ -30,6 +30,7 @@ import "./tests/operations/MS.js";
|
||||
import "./tests/operations/PHP.js";
|
||||
import "./tests/operations/NetBIOS.js";
|
||||
import "./tests/operations/OTP.js";
|
||||
import "./tests/operations/Regex.js";
|
||||
import "./tests/operations/StrUtils.js";
|
||||
import "./tests/operations/SeqUtils.js";
|
||||
|
||||
|
||||
@@ -415,4 +415,264 @@ TestRegister.addTests([
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "MD5: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "4f4f02e2646545aa8fc42f613c9aa068",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "MD5",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA1: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "2c5400aaee7e8ad4cad29bfbdf8d566924e5442c",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA1",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 224: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "66c166eba2529ecc44a7b7b218a64a8e3892f873c8d231e8e3c1ef3d",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 256: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "186ffd22c3af83995afa4a0316023f81a7f8834fd16bd2ed358c7b1b8182ba41",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 384: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "2a6369ffec550ea0bfb810b3b8246b7d6b7f060edfae88441f0f242b98b91549aa4ff407de38c6d03b5f377434ad2f36",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 512: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "544ae686522c05b70d12b460b5b39ea0a758eb4027333edbded7e2b3f467aa605804f71f54db61a7bbe50e6e7898510635efd6721fd418a9ea4d05b286d12806",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 224: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "e2c07562ee8c2d73e3dd309efea257159abd0948ebc14619bab9ffb3",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 256: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "55a55275387586afd1ed64757c9ee7ad1d96ca81a5b7b742c40127856ee78a2d",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 384: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "39f8796dd697dc39e5a943817833793f2c29dc0d1adc7037854c0fb51e135c6bd26b113240c4fb1e3fcc16ff8690c91a",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 512: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
expectedOutput: "ee9061bed83b1ad1e2fc4a4bac72a5a65a23a0fa55193b808af0a3e2013b718a5a3e40474765b4f93d1b2747401058a5b58099cc890a159db92b2ea816287add",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "MD5: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "2e93ee2b5b2a337ccb678c7db12eff1b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MD5",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA1: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "87f483b1515dce672be044bf183ae8103e3b2d4b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA1",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 224: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "563ca57b500157717961a5fa87ce42c6db76a488c98ea9c28d620770",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 256: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "36abbb4622ffff06aa3e3cea266765601b21457bb3755a0a2cf0a206422863c1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 384: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "140b929391a66c9a943bcd60e6964f0d19526d3bc9ba020fbb29aae51cddb8e63a78784d8770f1d36335bf4efff8c131",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA2 512: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "04a7887c400bf647b7c67b9a0f1ada70d176348b5afdfebea184f7e62748849828669c7b5160be99455fdbf625589bd1689c003bc06ef60c39607d825a2f8838",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA2",
|
||||
"args": ["512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 224: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "b3ffc9620949f879cb561fb240452494e2566cb4e4f701a85715e14f",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 256: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "b5f247d725b46546c832502cd07bccb5d4de0c41a6665d3944ed2cc55cd9d156",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 384: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "93e87b9aa8c9c47eba146adac357c525b418b71677f6db01d1c760d87b058682e639c8d43a8bfe91529cecd9800700e3",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SHA3 512: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "1fbc484b5184982561795162757717474eebc846ca9f10029a75a54cdd897a7b48d1db42f2478fa1d5d213a0dd7de71c809cb19c60581ba57e7289d29408fb36",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SHA3",
|
||||
"args": ["512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
]);
|
||||
|
||||
59
test/tests/operations/Regex.js
Normal file
59
test/tests/operations/Regex.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* StrUtils tests.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Regex: non-HTML op",
|
||||
input: "/<>",
|
||||
expectedOutput: "/<>",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Regular expression",
|
||||
"args": ["User defined", "", true, true, false, false, false, false, "Highlight matches"]
|
||||
},
|
||||
{
|
||||
"op": "Remove whitespace",
|
||||
"args": [true, true, true, true, true, false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Regex: Dot matches all",
|
||||
input: "Hello\nWorld",
|
||||
expectedOutput: "Hello\nWorld",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Regular expression",
|
||||
"args": ["User defined", ".+", true, true, true, false, false, false, "List matches"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Regex: Astral off",
|
||||
input: "𝌆😆",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Regular expression",
|
||||
"args": ["User defined", "\\pS", true, true, false, false, false, false, "List matches"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Regex: Astral on",
|
||||
input: "𝌆😆",
|
||||
expectedOutput: "𝌆\n😆",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Regular expression",
|
||||
"args": ["User defined", "\\pS", true, true, false, false, true, false, "List matches"]
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
@@ -8,21 +8,6 @@
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Regex, non-HTML op",
|
||||
input: "/<>",
|
||||
expectedOutput: "/<>",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Regular expression",
|
||||
"args": ["User defined", "", true, true, false, "Highlight matches"]
|
||||
},
|
||||
{
|
||||
"op": "Remove whitespace",
|
||||
"args": [true, true, true, true, true, false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Diff, basic usage",
|
||||
input: "testing23\n\ntesting123",
|
||||
|
||||
@@ -109,9 +109,13 @@ module.exports = {
|
||||
children: false,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
entrypoints: false,
|
||||
warningsFilter: /source-map/,
|
||||
},
|
||||
node: {
|
||||
fs: "empty"
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user