mirror of
https://github.com/gchq/CyberChef.git
synced 2026-02-25 11:11:43 +01:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26b19350f2 | ||
|
|
2018b7e247 | ||
|
|
cbff4161a1 | ||
|
|
130bdfb7f2 | ||
|
|
d0c43f5aa9 | ||
|
|
f864a5f31e | ||
|
|
cecae671d8 | ||
|
|
b4e23ac454 | ||
|
|
e7209ca085 | ||
|
|
022ef71d2c | ||
|
|
0fad891a3a | ||
|
|
47f608b502 | ||
|
|
4ab745f730 | ||
|
|
1f89ac11d2 | ||
|
|
1a5dae76c2 | ||
|
|
032c7f529a | ||
|
|
707818abcc | ||
|
|
58e8b4c618 | ||
|
|
9c0c2867dd | ||
|
|
4308c717c3 | ||
|
|
342b67581b | ||
|
|
75da5b650c | ||
|
|
9d09146f68 | ||
|
|
1b19d20d0c | ||
|
|
0eacab5ddc | ||
|
|
0d7874bac1 | ||
|
|
5cddfafbd0 | ||
|
|
5ce133c47e | ||
|
|
a68bfd7223 | ||
|
|
54cb2d268b | ||
|
|
0e40daecb6 | ||
|
|
ef61735f64 | ||
|
|
a2780ca056 | ||
|
|
d025c8bd9a | ||
|
|
acf38e47ba | ||
|
|
4122d4207d | ||
|
|
d550ae7d93 | ||
|
|
815a542cc1 |
@@ -11,7 +11,7 @@ before_script:
|
||||
- export NODE_OPTIONS=--max_old_space_size=2048
|
||||
script:
|
||||
- grunt lint
|
||||
- grunt test
|
||||
- npm test
|
||||
- grunt testnodeconsumer
|
||||
- grunt prod --msg="$COMPILE_MSG"
|
||||
- xvfb-run --server-args="-screen 0 1200x800x24" grunt testui
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -2,6 +2,12 @@
|
||||
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
|
||||
|
||||
|
||||
### [9.18.0] - 2020-03-13
|
||||
- 'Convert to NATO alphabet' operation added [@MarvinJWendt] | [#674]
|
||||
|
||||
### [9.17.0] - 2020-03-13
|
||||
- 'Generate Image' operation added [@pointhi] | [#683]
|
||||
|
||||
### [9.16.0] - 2020-03-06
|
||||
- 'Colossus' operation added [@VirtualColossus] | [#917]
|
||||
|
||||
@@ -212,6 +218,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
|
||||
|
||||
[9.18.0]: https://github.com/gchq/CyberChef/releases/tag/v9.18.0
|
||||
[9.17.0]: https://github.com/gchq/CyberChef/releases/tag/v9.17.0
|
||||
[9.16.0]: https://github.com/gchq/CyberChef/releases/tag/v9.16.0
|
||||
[9.15.0]: https://github.com/gchq/CyberChef/releases/tag/v9.15.0
|
||||
[9.14.0]: https://github.com/gchq/CyberChef/releases/tag/v9.14.0
|
||||
@@ -304,6 +312,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[@cbeuw]: https://github.com/cbeuw
|
||||
[@matthieuxyz]: https://github.com/matthieuxyz
|
||||
[@Flavsditz]: https://github.com/Flavsditz
|
||||
[@pointhi]: https://github.com/pointhi
|
||||
[@MarvinJWendt]: https://github.com/MarvinJWendt
|
||||
|
||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||
@@ -366,6 +376,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#627]: https://github.com/gchq/CyberChef/pull/627
|
||||
[#632]: https://github.com/gchq/CyberChef/pull/632
|
||||
[#653]: https://github.com/gchq/CyberChef/pull/653
|
||||
[#674]: https://github.com/gchq/CyberChef/pull/674
|
||||
[#683]: https://github.com/gchq/CyberChef/pull/683
|
||||
[#865]: https://github.com/gchq/CyberChef/pull/865
|
||||
[#912]: https://github.com/gchq/CyberChef/pull/912
|
||||
[#917]: https://github.com/gchq/CyberChef/pull/917
|
||||
|
||||
14
Gruntfile.js
14
Gruntfile.js
@@ -36,11 +36,10 @@ module.exports = function (grunt) {
|
||||
"clean:node", "clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
|
||||
]);
|
||||
|
||||
grunt.registerTask("test",
|
||||
"A task which runs all the operation tests in the tests directory.",
|
||||
grunt.registerTask("configTests",
|
||||
"A task which configures config files in preparation for tests to be run. Use `npm tests` to run tests.",
|
||||
[
|
||||
"clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex",
|
||||
"exec:nodeTests", "exec:opTests"
|
||||
"clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
|
||||
]);
|
||||
|
||||
grunt.registerTask("testui",
|
||||
@@ -55,7 +54,6 @@ module.exports = function (grunt) {
|
||||
"Lints the code base",
|
||||
["eslint", "exec:repoSize"]);
|
||||
|
||||
grunt.registerTask("tests", "test");
|
||||
grunt.registerTask("lint", "eslint");
|
||||
|
||||
grunt.registerTask("findModules",
|
||||
@@ -385,15 +383,9 @@ module.exports = function (grunt) {
|
||||
]),
|
||||
sync: true
|
||||
},
|
||||
opTests: {
|
||||
command: "node --experimental-modules --no-warnings --no-deprecation tests/operations/index.mjs"
|
||||
},
|
||||
browserTests: {
|
||||
command: "./node_modules/.bin/nightwatch --env prod"
|
||||
},
|
||||
nodeTests: {
|
||||
command: "node --experimental-modules --no-warnings --no-deprecation tests/node/index.mjs"
|
||||
},
|
||||
setupNodeConsumers: {
|
||||
command: chainCommands([
|
||||
"echo '\n--- Testing node consumers ---'",
|
||||
|
||||
7874
package-lock.json
generated
7874
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
89
package.json
89
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.16.2",
|
||||
"version": "9.18.2",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -36,21 +36,22 @@
|
||||
"node >= 10"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.7.5",
|
||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||
"@babel/preset-env": "^7.7.6",
|
||||
"autoprefixer": "^9.7.3",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"@babel/core": "^7.8.7",
|
||||
"@babel/plugin-transform-runtime": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"autoprefixer": "^9.7.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.0",
|
||||
"chromedriver": "^80.0.1",
|
||||
"cli-progress": "^3.6.0",
|
||||
"colors": "^1.4.0",
|
||||
"copy-webpack-plugin": "^5.0.5",
|
||||
"css-loader": "^3.2.1",
|
||||
"eslint": "^6.7.2",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"eslint": "^6.8.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"file-loader": "^5.0.2",
|
||||
"grunt": "^1.0.4",
|
||||
"file-loader": "^6.0.0",
|
||||
"grunt": "^1.1.0",
|
||||
"grunt-accessibility": "~6.0.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-concurrent": "^3.0.0",
|
||||
@@ -64,29 +65,29 @@
|
||||
"grunt-zip": "^0.18.2",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"imports-loader": "^0.8.0",
|
||||
"mini-css-extract-plugin": "^0.8.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"nightwatch": "^1.3.4",
|
||||
"node-sass": "^4.13.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"postcss-css-variables": "^0.14.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"sass-loader": "^8.0.0",
|
||||
"sitemap": "^5.1.0",
|
||||
"style-loader": "^1.0.1",
|
||||
"svg-url-loader": "^3.0.3",
|
||||
"url-loader": "^3.0.0",
|
||||
"webpack": "^4.41.2",
|
||||
"webpack-bundle-analyzer": "^3.6.0",
|
||||
"webpack-dev-server": "^3.9.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"sitemap": "^6.1.0",
|
||||
"style-loader": "^1.1.3",
|
||||
"svg-url-loader": "^5.0.0",
|
||||
"url-loader": "^4.0.0",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-bundle-analyzer": "^3.6.1",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-node-externals": "^1.7.2",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.7.0",
|
||||
"@babel/runtime": "^7.7.6",
|
||||
"@babel/polyfill": "^7.8.7",
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"arrive": "^2.4.1",
|
||||
"avsc": "^5.4.16",
|
||||
"avsc": "^5.4.19",
|
||||
"babel-plugin-transform-builtin-extend": "1.1.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"bignumber.js": "^9.0.0",
|
||||
@@ -94,26 +95,26 @@
|
||||
"bootstrap": "4.4.1",
|
||||
"bootstrap-colorpicker": "^3.2.0",
|
||||
"bootstrap-material-design": "^4.1.2",
|
||||
"bson": "^4.0.2",
|
||||
"bson": "^4.0.3",
|
||||
"chi-squared": "^1.1.0",
|
||||
"codepage": "^1.14.0",
|
||||
"core-js": "^3.4.8",
|
||||
"core-js": "^3.6.4",
|
||||
"crypto-api": "^0.8.5",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"crypto-js": "^4.0.0",
|
||||
"ctph.js": "0.0.5",
|
||||
"d3": "^5.14.2",
|
||||
"d3": "^5.15.0",
|
||||
"d3-hexbin": "^0.2.2",
|
||||
"diff": "^4.0.1",
|
||||
"es6-promisify": "^6.0.2",
|
||||
"escodegen": "^1.12.0",
|
||||
"diff": "^4.0.2",
|
||||
"es6-promisify": "^6.1.0",
|
||||
"escodegen": "^1.14.1",
|
||||
"esm": "^3.2.25",
|
||||
"esmangle": "^1.0.1",
|
||||
"esprima": "^4.0.1",
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^2.0.2",
|
||||
"geodesy": "^1.1.3",
|
||||
"highlight.js": "^9.16.2",
|
||||
"jimp": "^0.9.3",
|
||||
"highlight.js": "^9.18.1",
|
||||
"jimp": "^0.9.5",
|
||||
"jquery": "3.4.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
@@ -122,44 +123,44 @@
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jsqr": "^1.2.0",
|
||||
"jsrsasign": "8.0.12",
|
||||
"kbpgp": "2.1.6",
|
||||
"kbpgp": "2.1.13",
|
||||
"libbzip2-wasm": "0.0.4",
|
||||
"libyara-wasm": "^1.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"loglevel": "^1.6.6",
|
||||
"loglevel": "^1.6.7",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"markdown-it": "^10.0.0",
|
||||
"moment": "^2.24.0",
|
||||
"moment-timezone": "^0.5.27",
|
||||
"moment-timezone": "^0.5.28",
|
||||
"ngeohash": "^0.6.3",
|
||||
"node-forge": "^0.9.1",
|
||||
"node-md6": "^0.1.0",
|
||||
"nodom": "^2.4.0",
|
||||
"notepack.io": "^2.2.0",
|
||||
"notepack.io": "^2.3.0",
|
||||
"nwmatcher": "^1.4.4",
|
||||
"otp": "^0.1.3",
|
||||
"popper.js": "^1.16.0",
|
||||
"popper.js": "^1.16.1",
|
||||
"qr-image": "^3.2.0",
|
||||
"scryptsy": "^2.1.0",
|
||||
"snackbarjs": "^1.1.0",
|
||||
"sortablejs": "^1.10.1",
|
||||
"sortablejs": "^1.10.2",
|
||||
"split.js": "^1.5.11",
|
||||
"ssdeep.js": "0.0.2",
|
||||
"tesseract.js": "^2.0.0-alpha.15",
|
||||
"ua-parser-js": "^0.7.20",
|
||||
"tesseract.js": "^2.0.2",
|
||||
"ua-parser-js": "^0.7.21",
|
||||
"unorm": "^1.6.0",
|
||||
"utf8": "^3.0.0",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.1.27",
|
||||
"xmldom": "^0.3.0",
|
||||
"xpath": "0.0.27",
|
||||
"xregexp": "^4.2.4",
|
||||
"xregexp": "^4.3.0",
|
||||
"zlibjs": "^0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "grunt dev",
|
||||
"build": "grunt prod",
|
||||
"repl": "node src/node/repl.js",
|
||||
"test": "grunt test",
|
||||
"test": "grunt configTests && node --experimental-modules --no-warnings --no-deprecation tests/node/index.mjs && node --experimental-modules --no-warnings --no-deprecation tests/operations/index.mjs",
|
||||
"test-node-consumer": "grunt testnodeconsumer",
|
||||
"testui": "grunt testui",
|
||||
"testuidev": "npx nightwatch --env=dev",
|
||||
|
||||
@@ -39,7 +39,7 @@ class Chef {
|
||||
*/
|
||||
async bake(input, recipeConfig, options) {
|
||||
log.debug("Chef baking");
|
||||
const startTime = new Date().getTime(),
|
||||
const startTime = Date.now(),
|
||||
recipe = new Recipe(recipeConfig),
|
||||
containsFc = recipe.containsFlowControl(),
|
||||
notUTF8 = options && "treatAsUtf8" in options && !options.treatAsUtf8;
|
||||
@@ -84,7 +84,7 @@ class Chef {
|
||||
result: await this.dish.get(returnType, notUTF8),
|
||||
type: Dish.enumLookup(this.dish.type),
|
||||
progress: progress,
|
||||
duration: new Date().getTime() - startTime,
|
||||
duration: Date.now() - startTime,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class Chef {
|
||||
silentBake(recipeConfig) {
|
||||
log.debug("Running silent bake");
|
||||
|
||||
const startTime = new Date().getTime(),
|
||||
const startTime = Date.now(),
|
||||
recipe = new Recipe(recipeConfig),
|
||||
dish = new Dish();
|
||||
|
||||
@@ -119,7 +119,7 @@ class Chef {
|
||||
} catch (err) {
|
||||
// Suppress all errors
|
||||
}
|
||||
return new Date().getTime() - startTime;
|
||||
return Date.now() - startTime;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,12 @@ class Chef {
|
||||
const func = direction === "forward" ? highlights[i].f : highlights[i].b;
|
||||
|
||||
if (typeof func == "function") {
|
||||
pos = func(pos, highlights[i].args);
|
||||
try {
|
||||
pos = func(pos, highlights[i].args);
|
||||
} catch (err) {
|
||||
// Throw away highlighting errors
|
||||
pos = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1335,7 +1335,7 @@ export function sendStatusMessage(msg) {
|
||||
self.sendStatusMessage(msg);
|
||||
else if (isWebEnvironment())
|
||||
app.alert(msg, 10000);
|
||||
else if (isNodeEnvironment())
|
||||
else if (isNodeEnvironment() && !global.TESTING)
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(msg);
|
||||
}
|
||||
|
||||
@@ -201,7 +201,8 @@
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Remove Diacritics",
|
||||
"Unescape Unicode Characters"
|
||||
"Unescape Unicode Characters",
|
||||
"Convert to NATO alphabet"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -395,6 +396,7 @@
|
||||
"ops": [
|
||||
"Render Image",
|
||||
"Play Media",
|
||||
"Generate Image",
|
||||
"Optical Character Recognition",
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { ColossusComputer } from "../lib/Colossus.mjs";
|
||||
import { SWITCHES, VALID_ITA2 } from "../lib/Lorenz.mjs";
|
||||
|
||||
82
src/core/operations/ConvertToNATOAlphabet.mjs
Normal file
82
src/core/operations/ConvertToNATOAlphabet.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @author MarvinJWendt [git@marvinjwendt.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* Convert to NATO alphabet operation
|
||||
*/
|
||||
class ConvertToNATOAlphabet extends Operation {
|
||||
/**
|
||||
* ConvertToNATOAlphabet constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Convert to NATO alphabet";
|
||||
this.module = "Default";
|
||||
this.description = "Converts characters to their representation in the NATO phonetic alphabet.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/NATO_phonetic_alphabet";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return input.replace(/[a-z0-9,/.]/ig, letter => {
|
||||
return lookup[letter.toUpperCase()];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const lookup = {
|
||||
"A": "Alfa ",
|
||||
"B": "Bravo ",
|
||||
"C": "Charlie ",
|
||||
"D": "Delta ",
|
||||
"E": "Echo ",
|
||||
"F": "Foxtrot ",
|
||||
"G": "Golf ",
|
||||
"H": "Hotel ",
|
||||
"I": "India ",
|
||||
"J": "Juliett ",
|
||||
"K": "Kilo ",
|
||||
"L": "Lima ",
|
||||
"M": "Mike ",
|
||||
"N": "November ",
|
||||
"O": "Oscar ",
|
||||
"P": "Papa ",
|
||||
"Q": "Quebec ",
|
||||
"R": "Romeo ",
|
||||
"S": "Sierra ",
|
||||
"T": "Tango ",
|
||||
"U": "Uniform ",
|
||||
"V": "Victor ",
|
||||
"W": "Whiskey ",
|
||||
"X": "X-ray ",
|
||||
"Y": "Yankee ",
|
||||
"Z": "Zulu ",
|
||||
"0": "Zero ",
|
||||
"1": "One ",
|
||||
"2": "Two ",
|
||||
"3": "Three ",
|
||||
"4": "Four ",
|
||||
"5": "Five ",
|
||||
"6": "Six ",
|
||||
"7": "Seven ",
|
||||
"8": "Eight ",
|
||||
"9": "Nine ",
|
||||
",": "Comma ",
|
||||
"/": "Fraction bar ",
|
||||
".": "Full stop ",
|
||||
};
|
||||
|
||||
export default ConvertToNATOAlphabet;
|
||||
184
src/core/operations/GenerateImage.mjs
Normal file
184
src/core/operations/GenerateImage.mjs
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @author pointhi [thomas.pointhuber@gmx.at]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import {isImage} from "../lib/FileType";
|
||||
import {toBase64} from "../lib/Base64";
|
||||
import jimp from "jimp";
|
||||
import {isWorkerEnvironment} from "../Utils";
|
||||
|
||||
/**
|
||||
* Generate Image operation
|
||||
*/
|
||||
class GenerateImage extends Operation {
|
||||
|
||||
/**
|
||||
* GenerateImage constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Generate Image";
|
||||
this.module = "Image";
|
||||
this.description = "Generates an image using the input as pixel values.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Mode",
|
||||
"type": "option",
|
||||
"value": ["Greyscale", "RG", "RGB", "RGBA", "Bits"]
|
||||
},
|
||||
{
|
||||
"name": "Pixel Scale Factor",
|
||||
"type": "number",
|
||||
"value": 8,
|
||||
},
|
||||
{
|
||||
"name": "Pixels per row",
|
||||
"type": "number",
|
||||
"value": 64,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const [mode, scale, width] = args;
|
||||
input = new Uint8Array(input);
|
||||
|
||||
if (scale <= 0) {
|
||||
throw new OperationError("Pixel Scale Factor needs to be > 0");
|
||||
}
|
||||
|
||||
if (width <= 0) {
|
||||
throw new OperationError("Pixels per Row needs to be > 0");
|
||||
}
|
||||
|
||||
const bytePerPixelMap = {
|
||||
"Greyscale": 1,
|
||||
"RG": 2,
|
||||
"RGB": 3,
|
||||
"RGBA": 4,
|
||||
"Bits": 1/8,
|
||||
};
|
||||
|
||||
const bytesPerPixel = bytePerPixelMap[mode];
|
||||
|
||||
if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) {
|
||||
throw new OperationError(`Number of bytes is not a divisor of ${bytesPerPixel}`);
|
||||
}
|
||||
|
||||
const height = Math.ceil(input.length / bytesPerPixel / width);
|
||||
const image = await new jimp(width, height, (err, image) => {});
|
||||
|
||||
if (isWorkerEnvironment())
|
||||
self.sendStatusMessage("Generating image from data...");
|
||||
|
||||
if (mode === "Bits") {
|
||||
let index = 0;
|
||||
for (let j = 0; j < input.length; j++) {
|
||||
const curByte = Utils.bin(input[j]);
|
||||
for (let k = 0; k < 8; k++, index++) {
|
||||
const x = index % width;
|
||||
const y = Math.floor(index / width);
|
||||
|
||||
const value = curByte[k] === "0" ? 0xFF : 0x00;
|
||||
const pixel = jimp.rgbaToInt(value, value, value, 0xFF);
|
||||
image.setPixelColor(pixel, x, y);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let i = 0;
|
||||
while (i < input.length) {
|
||||
const index = i / bytesPerPixel;
|
||||
const x = index % width;
|
||||
const y = Math.floor(index / width);
|
||||
|
||||
let red = 0x00;
|
||||
let green = 0x00;
|
||||
let blue = 0x00;
|
||||
let alpha = 0xFF;
|
||||
|
||||
switch (mode) {
|
||||
case "Greyscale":
|
||||
red = green = blue = input[i++];
|
||||
break;
|
||||
|
||||
case "RG":
|
||||
red = input[i++];
|
||||
green = input[i++];
|
||||
break;
|
||||
|
||||
case "RGB":
|
||||
red = input[i++];
|
||||
green = input[i++];
|
||||
blue = input[i++];
|
||||
break;
|
||||
|
||||
case "RGBA":
|
||||
red = input[i++];
|
||||
green = input[i++];
|
||||
blue = input[i++];
|
||||
alpha = input[i++];
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new OperationError(`Unsupported Mode: (${mode})`);
|
||||
}
|
||||
|
||||
try {
|
||||
const pixel = jimp.rgbaToInt(red, green, blue, alpha);
|
||||
image.setPixelColor(pixel, x, y);
|
||||
} catch (err) {
|
||||
throw new OperationError(`Error while generating image from pixel values. (${err})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scale !== 1) {
|
||||
if (isWorkerEnvironment())
|
||||
self.sendStatusMessage("Scaling image...");
|
||||
|
||||
image.scaleToFit(width*scale, height*scale, jimp.RESIZE_NEAREST_NEIGHBOR);
|
||||
}
|
||||
|
||||
try {
|
||||
const imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
|
||||
return imageBuffer.buffer;
|
||||
} catch (err) {
|
||||
throw new OperationError(`Error generating image. (${err})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the generated image using HTML for web apps
|
||||
* @param {ArrayBuffer} data
|
||||
* @returns {html}
|
||||
*/
|
||||
present(data) {
|
||||
if (!data.byteLength) return "";
|
||||
const dataArray = new Uint8Array(data);
|
||||
|
||||
const type = isImage(dataArray);
|
||||
if (!type) {
|
||||
throw new OperationError("Invalid file type.");
|
||||
}
|
||||
|
||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GenerateImage;
|
||||
@@ -293,8 +293,8 @@ class Lorenz extends Operation {
|
||||
chosenSetting.S[3] = this.readLugs(lugs3);
|
||||
chosenSetting.S[4] = this.readLugs(lugs4);
|
||||
chosenSetting.S[5] = this.readLugs(lugs5);
|
||||
chosenSetting.M[1] = this.readLugs(lugm37);
|
||||
chosenSetting.M[2] = this.readLugs(lugm61);
|
||||
chosenSetting.M[1] = this.readLugs(lugm61);
|
||||
chosenSetting.M[2] = this.readLugs(lugm37);
|
||||
chosenSetting.X[1] = this.readLugs(lugx1);
|
||||
chosenSetting.X[2] = this.readLugs(lugx2);
|
||||
chosenSetting.X[3] = this.readLugs(lugx3);
|
||||
|
||||
@@ -23,19 +23,19 @@ class LuhnChecksum extends Operation {
|
||||
this.description = "The Luhn algorithm, also known as the modulus 10 or mod 10 algorithm, is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers and Canadian Social Insurance Numbers.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Luhn_algorithm";
|
||||
this.inputType = "string";
|
||||
this.outputType = "number";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* Generates the Luhn Checksum from the input.
|
||||
*
|
||||
* @param {string} inputStr
|
||||
* @returns {number}
|
||||
*/
|
||||
run(input, args) {
|
||||
checksum(inputStr) {
|
||||
let even = false;
|
||||
return input.split("").reverse().reduce((acc, elem) => {
|
||||
|
||||
return inputStr.split("").reverse().reduce((acc, elem) => {
|
||||
// Convert element to integer.
|
||||
let temp = parseInt(elem, 10);
|
||||
|
||||
@@ -45,7 +45,6 @@ class LuhnChecksum extends Operation {
|
||||
|
||||
// If element is in an even position
|
||||
if (even) {
|
||||
|
||||
// Double the element and add the quotient and remainder together.
|
||||
temp = 2 * elem;
|
||||
temp = Math.floor(temp/10) + (temp % 10);
|
||||
@@ -53,10 +52,26 @@ class LuhnChecksum extends Operation {
|
||||
|
||||
even = !even;
|
||||
return acc + temp;
|
||||
|
||||
}, 0) % 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
const checkSum = this.checksum(input);
|
||||
let checkDigit = this.checksum(input + "0");
|
||||
checkDigit = checkDigit === 0 ? 0 : (10-checkDigit);
|
||||
|
||||
return `Checksum: ${checkSum}
|
||||
Checkdigit: ${checkDigit}
|
||||
Luhn Validated String: ${input + "" + checkDigit}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default LuhnChecksum;
|
||||
|
||||
@@ -144,7 +144,7 @@ class MultipleBombe extends Operation {
|
||||
* @param {number} progress - Progress (as a float in the range 0..1)
|
||||
*/
|
||||
updateStatus(nLoops, nStops, progress, start) {
|
||||
const elapsed = new Date().getTime() - start;
|
||||
const elapsed = Date.now() - start;
|
||||
const remaining = (elapsed / progress) * (1 - progress) / 1000;
|
||||
const hours = Math.floor(remaining / 3600);
|
||||
const minutes = `0${Math.floor((remaining % 3600) / 60)}`.slice(-2);
|
||||
@@ -237,7 +237,7 @@ class MultipleBombe extends Operation {
|
||||
const totalRuns = choose(rotors.length, 3) * 6 * fourthRotors.length * reflectors.length;
|
||||
let nRuns = 0;
|
||||
let nStops = 0;
|
||||
const start = new Date().getTime();
|
||||
const start = Date.now();
|
||||
for (const rotor1 of rotors) {
|
||||
for (const rotor2 of rotors) {
|
||||
if (rotor2 === rotor1) {
|
||||
|
||||
4
src/core/vendor/gost/gostRandom.mjs
vendored
4
src/core/vendor/gost/gostRandom.mjs
vendored
@@ -70,7 +70,7 @@ if (typeof document !== 'undefined') {
|
||||
try {
|
||||
// Mouse move event to fill random array
|
||||
document.addEventListener('mousemove', function (e) {
|
||||
randomRing.set((new Date().getTime() & 255) ^
|
||||
randomRing.set((Date.now() & 255) ^
|
||||
((e.clientX || e.pageX) & 255) ^
|
||||
((e.clientY || e.pageY) & 255));
|
||||
}, false);
|
||||
@@ -80,7 +80,7 @@ if (typeof document !== 'undefined') {
|
||||
try {
|
||||
// Keypress event to fill random array
|
||||
document.addEventListener('keydown', function (e) {
|
||||
randomRing.set((new Date().getTime() & 255) ^
|
||||
randomRing.set((Date.now() & 255) ^
|
||||
(e.keyCode & 255));
|
||||
}, false);
|
||||
} catch (e) {
|
||||
|
||||
@@ -282,11 +282,11 @@ export function help(input) {
|
||||
.map(result => result.hydrated);
|
||||
|
||||
if (matches && matches.length) {
|
||||
console.log(`${matches.length} result${matches.length > 1 ? "s" : ""} found.`);
|
||||
// console.log(`${matches.length} result${matches.length > 1 ? "s" : ""} found.`);
|
||||
return matches;
|
||||
}
|
||||
|
||||
console.log("No results found.");
|
||||
// console.log("No results found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Sitemap from "sitemap";
|
||||
import sm from "sitemap";
|
||||
import OperationConfig from "../../core/config/OperationConfig.json";
|
||||
|
||||
|
||||
@@ -10,24 +10,25 @@ import OperationConfig from "../../core/config/OperationConfig.json";
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
const sitemap = Sitemap.createSitemap({
|
||||
const smStream = new sm.SitemapStream({
|
||||
hostname: "https://gchq.github.io/CyberChef",
|
||||
});
|
||||
|
||||
sitemap.add({
|
||||
smStream.write({
|
||||
url: "/",
|
||||
changefreq: "weekly",
|
||||
priority: 1.0
|
||||
});
|
||||
|
||||
for (const op in OperationConfig) {
|
||||
sitemap.add({
|
||||
smStream.write({
|
||||
url: `/?op=${encodeURIComponent(op)}`,
|
||||
changeFreq: "yearly",
|
||||
priority: 0.5
|
||||
});
|
||||
}
|
||||
smStream.end();
|
||||
|
||||
const xml = sitemap.toString();
|
||||
|
||||
console.log(xml); // eslint-disable-line no-console
|
||||
sm.streamToPromise(smStream).then(
|
||||
buffer => console.log(buffer.toString()) // eslint-disable-line no-console
|
||||
);
|
||||
|
||||
@@ -28,6 +28,10 @@ class SeasonalWaiter {
|
||||
// Konami code
|
||||
this.kkeys = [];
|
||||
window.addEventListener("keydown", this.konamiCodeListener.bind(this));
|
||||
|
||||
// CyberChef Challenge
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("43 6f 6e 67 72 61 74 75 6c 61 74 69 6f 6e 73 2c 20 79 6f 75 20 68 61 76 65 20 63 6f 6d 70 6c 65 74 65 64 20 43 79 62 65 72 43 68 65 66 20 63 68 61 6c 6c 65 6e 67 65 20 23 31 21 0a 0a 54 68 69 73 20 63 68 61 6c 6c 65 6e 67 65 20 65 78 70 6c 6f 72 65 64 20 68 65 78 61 64 65 63 69 6d 61 6c 20 65 6e 63 6f 64 69 6e 67 2e 20 54 6f 20 6c 65 61 72 6e 20 6d 6f 72 65 2c 20 76 69 73 69 74 20 77 69 6b 69 70 65 64 69 61 2e 6f 72 67 2f 77 69 6b 69 2f 48 65 78 61 64 65 63 69 6d 61 6c 2e 0a 0a 54 68 65 20 63 6f 64 65 20 66 6f 72 20 74 68 69 73 20 63 68 61 6c 6c 65 6e 67 65 20 69 73 20 39 64 34 63 62 63 65 66 2d 62 65 35 32 2d 34 37 35 31 2d 61 32 62 32 2d 38 33 33 38 65 36 34 30 39 34 31 36 20 28 6b 65 65 70 20 74 68 69 73 20 70 72 69 76 61 74 65 29 2e 0a 0a 54 68 65 20 6e 65 78 74 20 63 68 61 6c 6c 65 6e 67 65 20 63 61 6e 20 62 65 20 66 6f 75 6e 64 20 61 74 20 68 74 74 70 73 3a 2f 2f 70 61 73 74 65 62 69 6e 2e 63 6f 6d 2f 47 53 6e 54 41 6d 6b 56 2e");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class WindowWaiter {
|
||||
* focus is returned.
|
||||
*/
|
||||
windowBlur() {
|
||||
this.windowBlurTime = new Date().getTime();
|
||||
this.windowBlurTime = Date.now();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class WindowWaiter {
|
||||
* a long time and the browser has swapped out all its memory.
|
||||
*/
|
||||
windowFocus() {
|
||||
const unfocusedTime = new Date().getTime() - this.windowBlurTime;
|
||||
const unfocusedTime = Date.now() - this.windowBlurTime;
|
||||
if (unfocusedTime > 60000) {
|
||||
this.app.silentBake();
|
||||
}
|
||||
|
||||
@@ -375,7 +375,7 @@ class WorkerWaiter {
|
||||
*/
|
||||
bakingComplete() {
|
||||
this.setBakingStatus(false);
|
||||
let duration = new Date().getTime() - this.bakeStartTime;
|
||||
let duration = Date.now() - this.bakeStartTime;
|
||||
duration = duration.toLocaleString() + "ms";
|
||||
const progress = this.getBakeProgress();
|
||||
|
||||
@@ -489,7 +489,7 @@ class WorkerWaiter {
|
||||
bake(recipeConfig, options, progress, step) {
|
||||
this.setBakingStatus(true);
|
||||
this.manager.recipe.updateBreakpointIndicator(false);
|
||||
this.bakeStartTime = new Date().getTime();
|
||||
this.bakeStartTime = Date.now();
|
||||
this.bakeId++;
|
||||
this.recipeConfig = recipeConfig;
|
||||
this.options = options;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import Chef from "../../src/core/Chef.mjs";
|
||||
import Utils from "../../src/core/Utils.mjs";
|
||||
import cliProgress from "cli-progress";
|
||||
|
||||
/**
|
||||
* Object to store and run the list of tests.
|
||||
@@ -47,68 +49,99 @@ class TestRegister {
|
||||
/**
|
||||
* Runs all the tests in the register.
|
||||
*/
|
||||
runTests () {
|
||||
console.log("Running tests...");
|
||||
return Promise.all(
|
||||
this.tests.map(function(test, i) {
|
||||
const chef = new Chef();
|
||||
async runTests () {
|
||||
const progBar = new cliProgress.SingleBar({
|
||||
format: formatter,
|
||||
stopOnComplete: true
|
||||
}, cliProgress.Presets.shades_classic);
|
||||
const testResults = [];
|
||||
|
||||
return chef.bake(
|
||||
test.input,
|
||||
test.recipeConfig,
|
||||
{},
|
||||
0,
|
||||
false
|
||||
).then(function(result) {
|
||||
const ret = {
|
||||
test: test,
|
||||
status: null,
|
||||
output: null,
|
||||
};
|
||||
console.log("Running operation tests...");
|
||||
progBar.start(this.tests.length, 0, {
|
||||
msg: "Setting up"
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
if (test.expectedError) {
|
||||
ret.status = "passing";
|
||||
} else {
|
||||
ret.status = "erroring";
|
||||
ret.output = result.error.displayStr;
|
||||
}
|
||||
} else {
|
||||
if (test.expectedError) {
|
||||
ret.status = "failing";
|
||||
ret.output = "Expected an error but did not receive one.";
|
||||
} else if (result.result === test.expectedOutput) {
|
||||
ret.status = "passing";
|
||||
} else if ("expectedMatch" in test && test.expectedMatch.test(result.result)) {
|
||||
ret.status = "passing";
|
||||
} else {
|
||||
ret.status = "failing";
|
||||
const expected = test.expectedOutput ? test.expectedOutput :
|
||||
test.expectedMatch ? test.expectedMatch.toString() : "unknown";
|
||||
ret.output = [
|
||||
"Expected",
|
||||
"\t" + expected.replace(/\n/g, "\n\t"),
|
||||
"Received",
|
||||
"\t" + result.result.replace(/\n/g, "\n\t"),
|
||||
].join("\n");
|
||||
}
|
||||
}
|
||||
for (const test of this.tests) {
|
||||
progBar.update(testResults.length, {
|
||||
msg: test.name
|
||||
});
|
||||
|
||||
return ret;
|
||||
});
|
||||
})
|
||||
);
|
||||
const chef = new Chef();
|
||||
const result = await chef.bake(
|
||||
test.input,
|
||||
test.recipeConfig,
|
||||
{},
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
const ret = {
|
||||
test: test,
|
||||
status: null,
|
||||
output: null,
|
||||
duration: result.duration
|
||||
};
|
||||
|
||||
if (result.error) {
|
||||
if (test.expectedError) {
|
||||
ret.status = "passing";
|
||||
} else {
|
||||
ret.status = "erroring";
|
||||
ret.output = result.error.displayStr;
|
||||
}
|
||||
} else {
|
||||
if (test.expectedError) {
|
||||
ret.status = "failing";
|
||||
ret.output = "Expected an error but did not receive one.";
|
||||
} else if (result.result === test.expectedOutput) {
|
||||
ret.status = "passing";
|
||||
} else if ("expectedMatch" in test && test.expectedMatch.test(result.result)) {
|
||||
ret.status = "passing";
|
||||
} else {
|
||||
ret.status = "failing";
|
||||
const expected = test.expectedOutput ? test.expectedOutput :
|
||||
test.expectedMatch ? test.expectedMatch.toString() : "unknown";
|
||||
ret.output = [
|
||||
"Expected",
|
||||
"\t" + expected.replace(/\n/g, "\n\t"),
|
||||
"Received",
|
||||
"\t" + result.result.replace(/\n/g, "\n\t"),
|
||||
].join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
testResults.push(ret);
|
||||
progBar.increment();
|
||||
}
|
||||
|
||||
return testResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all api related tests and wrap results in report format
|
||||
*/
|
||||
runApiTests() {
|
||||
return Promise.all(this.apiTests.map(async function(test, i) {
|
||||
async runApiTests() {
|
||||
const progBar = new cliProgress.SingleBar({
|
||||
format: formatter,
|
||||
stopOnComplete: true
|
||||
}, cliProgress.Presets.shades_classic);
|
||||
const testResults = [];
|
||||
|
||||
console.log("Running Node API tests...");
|
||||
progBar.start(this.apiTests.length, 0, {
|
||||
msg: "Setting up"
|
||||
});
|
||||
|
||||
global.TESTING = true;
|
||||
for (const test of this.apiTests) {
|
||||
progBar.update(testResults.length, {
|
||||
msg: test.name
|
||||
});
|
||||
|
||||
const result = {
|
||||
test: test,
|
||||
status: null,
|
||||
output: null,
|
||||
output: null
|
||||
};
|
||||
try {
|
||||
await test.run();
|
||||
@@ -117,10 +150,37 @@ class TestRegister {
|
||||
result.status = "erroring";
|
||||
result.output = e.message;
|
||||
}
|
||||
return result;
|
||||
}));
|
||||
|
||||
testResults.push(result);
|
||||
progBar.increment();
|
||||
}
|
||||
|
||||
return testResults;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formatter for the progress bar
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Object} params
|
||||
* @param {Object} payload
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatter(options, params, payload) {
|
||||
const bar = options.barCompleteString.substr(0, Math.round(params.progress * options.barsize)) +
|
||||
options.barIncompleteString.substr(0, Math.round((1-params.progress) * options.barsize));
|
||||
|
||||
const percentage = Math.floor(params.progress * 100),
|
||||
duration = Math.floor((Date.now() - params.startTime) / 1000);
|
||||
|
||||
let testName = payload.msg ? payload.msg : "";
|
||||
if (params.value >= params.total) testName = "Tests completed";
|
||||
testName = Utils.truncate(testName, 25).padEnd(25, " ");
|
||||
|
||||
return `${testName} ${bar} ${params.value}/${params.total} | ${percentage}% | Duration: ${duration}s`;
|
||||
}
|
||||
|
||||
// Export an instance to make a singleton
|
||||
export default new TestRegister();
|
||||
|
||||
@@ -33,6 +33,10 @@ function handleTestResult(testStatus, testResult) {
|
||||
testStatus.allTestsPassing = testStatus.allTestsPassing && testResult.status === "passing";
|
||||
testStatus.counts[testResult.status] = (testStatus.counts[testResult.status] || 0) + 1;
|
||||
testStatus.counts.total += 1;
|
||||
|
||||
if (testResult.duration > 2000) {
|
||||
console.log(`'${testResult.test.name}' took ${(testResult.duration / 1000).toFixed(1)}s to complete`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,8 +46,6 @@ function handleTestResult(testStatus, testResult) {
|
||||
* @param {Object[]} results - results from TestRegister
|
||||
*/
|
||||
export function logTestReport(testStatus, results) {
|
||||
console.log("Tests completed.");
|
||||
|
||||
results.forEach(r => handleTestResult(testStatus, r));
|
||||
|
||||
console.log();
|
||||
@@ -80,8 +82,9 @@ export function logTestReport(testStatus, results) {
|
||||
* Fail if the process takes longer than 60 seconds.
|
||||
*/
|
||||
export function setLongTestFailure() {
|
||||
const timeLimit = 120;
|
||||
setTimeout(function() {
|
||||
console.log("Tests took longer than 60 seconds to run, returning.");
|
||||
console.log(`Tests took longer than ${timeLimit} seconds to run, returning.`);
|
||||
process.exit(1);
|
||||
}, 60 * 1000);
|
||||
}, timeLimit * 1000);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ setLongTestFailure();
|
||||
|
||||
const logOpsTestReport = logTestReport.bind(null, testStatus);
|
||||
|
||||
TestRegister.runApiTests()
|
||||
.then(logOpsTestReport);
|
||||
|
||||
(async function() {
|
||||
const results = await TestRegister.runApiTests();
|
||||
logOpsTestReport(results);
|
||||
})();
|
||||
|
||||
@@ -588,7 +588,7 @@ Password: 034148`;
|
||||
const result = await chef.generatePGPKeyPair("Back To the Drawing Board", {
|
||||
keyType: "ECC-256",
|
||||
});
|
||||
assert.strictEqual(result.toString().length, 2005);
|
||||
assert.strictEqual(result.toString().length, 2007);
|
||||
}),
|
||||
|
||||
it("Generate UUID", () => {
|
||||
|
||||
@@ -116,5 +116,8 @@ setLongTestFailure();
|
||||
|
||||
const logOpsTestReport = logTestReport.bind(null, testStatus);
|
||||
|
||||
TestRegister.runTests()
|
||||
.then(logOpsTestReport);
|
||||
(async function() {
|
||||
const results = await TestRegister.runTests();
|
||||
logOpsTestReport(results);
|
||||
})();
|
||||
|
||||
|
||||
32
tests/operations/tests/ConvertToNATOAlphabet.mjs
Normal file
32
tests/operations/tests/ConvertToNATOAlphabet.mjs
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @author MarvinJWendt [git@marvinjwendt.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Convert to NATO alphabet: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Convert to NATO alphabet",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Convert to NATO alphabet: full alphabet with numbers",
|
||||
input: "abcdefghijklmnopqrstuvwxyz0123456789,/.",
|
||||
expectedOutput: "Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett Kilo Lima Mike November Oscar Papa Quebec Romeo Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu Zero One Two Three Four Five Six Seven Eight Nine Comma Fraction bar Full stop ",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Convert to NATO alphabet",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
@@ -11,7 +11,29 @@ TestRegister.addTests([
|
||||
{
|
||||
name: "Luhn Checksum on standard data",
|
||||
input: "35641709012469",
|
||||
expectedOutput: "7",
|
||||
expectedOutput: "Checksum: 7\nCheckdigit: 0\nLuhn Validated String: 356417090124690",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Luhn Checksum",
|
||||
args: []
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Luhn Checksum on standard data 2",
|
||||
input: "896101950123440000",
|
||||
expectedOutput: "Checksum: 5\nCheckdigit: 1\nLuhn Validated String: 8961019501234400001",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Luhn Checksum",
|
||||
args: []
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Luhn Checksum on standard data 3",
|
||||
input: "35726908971331",
|
||||
expectedOutput: "Checksum: 6\nCheckdigit: 7\nLuhn Validated String: 357269089713317",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Luhn Checksum",
|
||||
@@ -33,7 +55,7 @@ TestRegister.addTests([
|
||||
{
|
||||
name: "Luhn Checksum on empty data",
|
||||
input: "",
|
||||
expectedOutput: "0",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Luhn Checksum",
|
||||
|
||||
Reference in New Issue
Block a user