mirror of
https://github.com/gchq/CyberChef.git
synced 2025-05-07 06:57:12 -04:00
parent
de3ef202d5
commit
c5a1b69c30
693 changed files with 26685 additions and 51240 deletions
3
.github/workflows/pull_requests.yml
vendored
3
.github/workflows/pull_requests.yml
vendored
|
@ -21,9 +21,6 @@ jobs:
|
||||||
npm install
|
npm install
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
- name: Format
|
|
||||||
run: npx @biomejs/biome format . --write
|
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npx grunt lint
|
run: npx grunt lint
|
||||||
|
|
||||||
|
|
336
Gruntfile.js
336
Gruntfile.js
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||||
const BundleAnalyzerPlugin =
|
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
|
||||||
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
|
|
||||||
const glob = require("glob");
|
const glob = require("glob");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const nodeFlags =
|
const nodeFlags = "--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation";
|
||||||
"--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grunt configuration for building the app in various formats.
|
* Grunt configuration for building the app in various formats.
|
||||||
|
@ -23,100 +21,56 @@ module.exports = function (grunt) {
|
||||||
grunt.file.preserveBOM = false;
|
grunt.file.preserveBOM = false;
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
grunt.registerTask(
|
grunt.registerTask("dev",
|
||||||
"dev",
|
|
||||||
"A persistent task which creates a development build whenever source files are modified.",
|
"A persistent task which creates a development build whenever source files are modified.",
|
||||||
["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"],
|
["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"]);
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask(
|
grunt.registerTask("prod",
|
||||||
"prod",
|
|
||||||
"Creates a production-ready build. Use the --msg flag to add a compile message.",
|
"Creates a production-ready build. Use the --msg flag to add a compile message.",
|
||||||
[
|
[
|
||||||
"eslint",
|
"eslint", "clean:prod", "clean:config", "exec:generateConfig", "findModules", "webpack:web",
|
||||||
"clean:prod",
|
"copy:standalone", "zip:standalone", "clean:standalone", "exec:calcDownloadHash", "chmod"
|
||||||
"clean:config",
|
|
||||||
"exec:generateConfig",
|
|
||||||
"findModules",
|
|
||||||
"webpack:web",
|
|
||||||
"copy:standalone",
|
|
||||||
"zip:standalone",
|
|
||||||
"clean:standalone",
|
|
||||||
"exec:calcDownloadHash",
|
|
||||||
"chmod",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask(
|
|
||||||
"node",
|
|
||||||
"Compiles CyberChef into a single NodeJS module.",
|
|
||||||
[
|
|
||||||
"clean:node",
|
|
||||||
"clean:config",
|
|
||||||
"clean:nodeConfig",
|
|
||||||
"exec:generateConfig",
|
|
||||||
"exec:generateNodeIndex",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask(
|
|
||||||
"configTests",
|
|
||||||
"A task which configures config files in preparation for tests to be run. Use `npm test` to run tests.",
|
|
||||||
[
|
|
||||||
"clean:config",
|
|
||||||
"clean:nodeConfig",
|
|
||||||
"exec:generateConfig",
|
|
||||||
"exec:generateNodeIndex",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask(
|
|
||||||
"testui",
|
|
||||||
"A task which runs all the UI tests in the tests directory. The prod task must already have been run.",
|
|
||||||
["connect:prod", "exec:browserTests"],
|
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask(
|
|
||||||
"testnodeconsumer",
|
|
||||||
"A task which checks whether consuming CJS and ESM apps work with the CyberChef build",
|
|
||||||
[
|
|
||||||
"exec:setupNodeConsumers",
|
|
||||||
"exec:testCJSNodeConsumer",
|
|
||||||
"exec:testESMNodeConsumer",
|
|
||||||
"exec:teardownNodeConsumers",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask("default", "Lints the code base", [
|
|
||||||
"prettier",
|
|
||||||
"eslint",
|
|
||||||
"exec:repoSize",
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
grunt.registerTask("lint", "eslint");
|
grunt.registerTask("node",
|
||||||
grunt.registerTask("format", ["prettier"]);
|
"Compiles CyberChef into a single NodeJS module.",
|
||||||
|
[
|
||||||
|
"clean:node", "clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
|
||||||
|
]);
|
||||||
|
|
||||||
grunt.registerTask(
|
grunt.registerTask("configTests",
|
||||||
"findModules",
|
"A task which configures config files in preparation for tests to be run. Use `npm test` to run tests.",
|
||||||
|
[
|
||||||
|
"clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
|
||||||
|
]);
|
||||||
|
|
||||||
|
grunt.registerTask("testui",
|
||||||
|
"A task which runs all the UI tests in the tests directory. The prod task must already have been run.",
|
||||||
|
["connect:prod", "exec:browserTests"]);
|
||||||
|
|
||||||
|
grunt.registerTask("testnodeconsumer",
|
||||||
|
"A task which checks whether consuming CJS and ESM apps work with the CyberChef build",
|
||||||
|
["exec:setupNodeConsumers", "exec:testCJSNodeConsumer", "exec:testESMNodeConsumer", "exec:teardownNodeConsumers"]);
|
||||||
|
|
||||||
|
grunt.registerTask("default",
|
||||||
|
"Lints the code base",
|
||||||
|
["eslint", "exec:repoSize"]);
|
||||||
|
|
||||||
|
grunt.registerTask("lint", "eslint");
|
||||||
|
|
||||||
|
grunt.registerTask("findModules",
|
||||||
"Finds all generated modules and updates the entry point list for Webpack",
|
"Finds all generated modules and updates the entry point list for Webpack",
|
||||||
function (arg1, arg2) {
|
function(arg1, arg2) {
|
||||||
const moduleEntryPoints = listEntryModules();
|
const moduleEntryPoints = listEntryModules();
|
||||||
|
|
||||||
grunt.log.writeln(
|
grunt.log.writeln(`Found ${Object.keys(moduleEntryPoints).length} modules.`);
|
||||||
`Found ${Object.keys(moduleEntryPoints).length} modules.`,
|
|
||||||
);
|
grunt.config.set("webpack.web.entry",
|
||||||
|
Object.assign({
|
||||||
|
main: "./src/web/index.js"
|
||||||
|
}, moduleEntryPoints));
|
||||||
|
});
|
||||||
|
|
||||||
grunt.config.set(
|
|
||||||
"webpack.web.entry",
|
|
||||||
Object.assign(
|
|
||||||
{
|
|
||||||
main: "./src/web/index.js",
|
|
||||||
},
|
|
||||||
moduleEntryPoints,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load tasks provided by each plugin
|
// Load tasks provided by each plugin
|
||||||
grunt.loadNpmTasks("grunt-eslint");
|
grunt.loadNpmTasks("grunt-eslint");
|
||||||
|
@ -129,18 +83,15 @@ module.exports = function (grunt) {
|
||||||
grunt.loadNpmTasks("grunt-concurrent");
|
grunt.loadNpmTasks("grunt-concurrent");
|
||||||
grunt.loadNpmTasks("grunt-contrib-connect");
|
grunt.loadNpmTasks("grunt-contrib-connect");
|
||||||
grunt.loadNpmTasks("grunt-zip");
|
grunt.loadNpmTasks("grunt-zip");
|
||||||
grunt.loadNpmTasks("grunt-prettier");
|
|
||||||
|
|
||||||
// Project configuration
|
// Project configuration
|
||||||
const compileTime =
|
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||||
grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
|
||||||
pkg = grunt.file.readJSON("package.json"),
|
pkg = grunt.file.readJSON("package.json"),
|
||||||
webpackConfig = require("./webpack.config.js"),
|
webpackConfig = require("./webpack.config.js"),
|
||||||
BUILD_CONSTANTS = {
|
BUILD_CONSTANTS = {
|
||||||
COMPILE_TIME: JSON.stringify(compileTime),
|
COMPILE_TIME: JSON.stringify(compileTime),
|
||||||
COMPILE_MSG: JSON.stringify(
|
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
|
||||||
grunt.option("compile-msg") || grunt.option("msg") || "",
|
|
||||||
),
|
|
||||||
PKG_VERSION: JSON.stringify(pkg.version),
|
PKG_VERSION: JSON.stringify(pkg.version),
|
||||||
},
|
},
|
||||||
moduleEntryPoints = listEntryModules(),
|
moduleEntryPoints = listEntryModules(),
|
||||||
|
@ -153,26 +104,20 @@ module.exports = function (grunt) {
|
||||||
return {
|
return {
|
||||||
mode: "production",
|
mode: "production",
|
||||||
target: "web",
|
target: "web",
|
||||||
entry: Object.assign(
|
entry: Object.assign({
|
||||||
{
|
main: "./src/web/index.js"
|
||||||
main: "./src/web/index.js",
|
}, moduleEntryPoints),
|
||||||
},
|
|
||||||
moduleEntryPoints,
|
|
||||||
),
|
|
||||||
output: {
|
output: {
|
||||||
path: __dirname + "/build/prod",
|
path: __dirname + "/build/prod",
|
||||||
filename: (chunkData) => {
|
filename: chunkData => {
|
||||||
return chunkData.chunk.name === "main"
|
return chunkData.chunk.name === "main" ? "assets/[name].js": "[name].js";
|
||||||
? "assets/[name].js"
|
|
||||||
: "[name].js";
|
|
||||||
},
|
},
|
||||||
globalObject: "this",
|
globalObject: "this"
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"./config/modules/OpModules.mjs":
|
"./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
|
||||||
"./config/modules/Default.mjs",
|
}
|
||||||
},
|
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||||
|
@ -186,29 +131,29 @@ module.exports = function (grunt) {
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
minifyJS: true,
|
minifyJS: true,
|
||||||
minifyCSS: true,
|
minifyCSS: true
|
||||||
},
|
}
|
||||||
}),
|
}),
|
||||||
new BundleAnalyzerPlugin({
|
new BundleAnalyzerPlugin({
|
||||||
analyzerMode: "static",
|
analyzerMode: "static",
|
||||||
reportFilename: "BundleAnalyzerReport.html",
|
reportFilename: "BundleAnalyzerReport.html",
|
||||||
openAnalyzer: false,
|
openAnalyzer: false
|
||||||
}),
|
}),
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an entry list for all the modules.
|
* Generates an entry list for all the modules.
|
||||||
*/
|
*/
|
||||||
function listEntryModules() {
|
function listEntryModules() {
|
||||||
const entryModules = {};
|
const entryModules = {};
|
||||||
|
|
||||||
glob.sync("./src/core/config/modules/*.mjs").forEach((file) => {
|
glob.sync("./src/core/config/modules/*.mjs").forEach(file => {
|
||||||
const basename = path.basename(file);
|
const basename = path.basename(file);
|
||||||
if (basename !== "Default.mjs" && basename !== "OpModules.mjs")
|
if (basename !== "Default.mjs" && basename !== "OpModules.mjs")
|
||||||
entryModules["modules/" + basename.split(".mjs")[0]] =
|
entryModules["modules/" + basename.split(".mjs")[0]] = path.resolve(file);
|
||||||
path.resolve(file);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return entryModules;
|
return entryModules;
|
||||||
|
@ -226,14 +171,12 @@ module.exports = function (grunt) {
|
||||||
if (!win) {
|
if (!win) {
|
||||||
return cmds.join(";");
|
return cmds.join(";");
|
||||||
}
|
}
|
||||||
return (
|
return cmds
|
||||||
cmds
|
|
||||||
// && means that subsequent commands will not be executed if the
|
// && means that subsequent commands will not be executed if the
|
||||||
// previous one fails. & would coninue on a fail
|
// previous one fails. & would coninue on a fail
|
||||||
.join("&&")
|
.join("&&")
|
||||||
// Windows does not support \n properly
|
// Windows does not support \n properly
|
||||||
.replace(/\n/g, "\\n")
|
.replace(/\n/g, "\\n");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
|
@ -241,36 +184,17 @@ module.exports = function (grunt) {
|
||||||
dev: ["build/dev/*"],
|
dev: ["build/dev/*"],
|
||||||
prod: ["build/prod/*"],
|
prod: ["build/prod/*"],
|
||||||
node: ["build/node/*"],
|
node: ["build/node/*"],
|
||||||
config: [
|
config: ["src/core/config/OperationConfig.json", "src/core/config/modules/*", "src/code/operations/index.mjs"],
|
||||||
"src/core/config/OperationConfig.json",
|
nodeConfig: ["src/node/index.mjs", "src/node/config/OperationConfig.json"],
|
||||||
"src/core/config/modules/*",
|
standalone: ["build/prod/CyberChef*.html"]
|
||||||
"src/code/operations/index.mjs",
|
|
||||||
],
|
|
||||||
nodeConfig: [
|
|
||||||
"src/node/index.mjs",
|
|
||||||
"src/node/config/OperationConfig.json",
|
|
||||||
],
|
|
||||||
standalone: ["build/prod/CyberChef*.html"],
|
|
||||||
},
|
},
|
||||||
eslint: {
|
eslint: {
|
||||||
configs: ["*.{js,mjs}"],
|
configs: ["*.{js,mjs}"],
|
||||||
core: [
|
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
|
||||||
"src/core/**/*.{js,mjs}",
|
|
||||||
"!src/core/vendor/**/*",
|
|
||||||
"!src/core/operations/legacy/**/*",
|
|
||||||
],
|
|
||||||
web: ["src/web/**/*.{js,mjs}", "!src/web/static/**/*"],
|
web: ["src/web/**/*.{js,mjs}", "!src/web/static/**/*"],
|
||||||
node: ["src/node/**/*.{js,mjs}"],
|
node: ["src/node/**/*.{js,mjs}"],
|
||||||
tests: ["tests/**/*.{js,mjs}"],
|
tests: ["tests/**/*.{js,mjs}"],
|
||||||
},
|
},
|
||||||
prettier: {
|
|
||||||
options: {
|
|
||||||
progress: false,
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
src: ["*.{js,mjs}", "src/**/*.{js,mjs}", "tests/**/*.{js,mjs}"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
webpack: {
|
webpack: {
|
||||||
options: webpackConfig,
|
options: webpackConfig,
|
||||||
myConfig: webpackConfig,
|
myConfig: webpackConfig,
|
||||||
|
@ -281,25 +205,21 @@ module.exports = function (grunt) {
|
||||||
start: {
|
start: {
|
||||||
mode: "development",
|
mode: "development",
|
||||||
target: "web",
|
target: "web",
|
||||||
entry: Object.assign(
|
entry: Object.assign({
|
||||||
{
|
main: "./src/web/index.js"
|
||||||
main: "./src/web/index.js",
|
}, moduleEntryPoints),
|
||||||
},
|
|
||||||
moduleEntryPoints,
|
|
||||||
),
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"./config/modules/OpModules.mjs":
|
"./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
|
||||||
"./config/modules/Default.mjs",
|
}
|
||||||
},
|
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
port: grunt.option("port") || 8080,
|
port: grunt.option("port") || 8080,
|
||||||
client: {
|
client: {
|
||||||
logging: "error",
|
logging: "error",
|
||||||
overlay: true,
|
overlay: true
|
||||||
},
|
},
|
||||||
hot: "only",
|
hot: "only"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||||
|
@ -309,9 +229,9 @@ module.exports = function (grunt) {
|
||||||
chunks: ["main"],
|
chunks: ["main"],
|
||||||
compileTime: compileTime,
|
compileTime: compileTime,
|
||||||
version: pkg.version,
|
version: pkg.version,
|
||||||
}),
|
})
|
||||||
],
|
]
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
zip: {
|
zip: {
|
||||||
standalone: {
|
standalone: {
|
||||||
|
@ -321,16 +241,16 @@ module.exports = function (grunt) {
|
||||||
"!build/prod/index.html",
|
"!build/prod/index.html",
|
||||||
"!build/prod/BundleAnalyzerReport.html",
|
"!build/prod/BundleAnalyzerReport.html",
|
||||||
],
|
],
|
||||||
dest: `build/prod/CyberChef_v${pkg.version}.zip`,
|
dest: `build/prod/CyberChef_v${pkg.version}.zip`
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
connect: {
|
connect: {
|
||||||
prod: {
|
prod: {
|
||||||
options: {
|
options: {
|
||||||
port: grunt.option("port") || 8000,
|
port: grunt.option("port") || 8000,
|
||||||
base: "build/prod/",
|
base: "build/prod/"
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
copy: {
|
copy: {
|
||||||
ghPages: {
|
ghPages: {
|
||||||
|
@ -338,86 +258,70 @@ module.exports = function (grunt) {
|
||||||
process: function (content, srcpath) {
|
process: function (content, srcpath) {
|
||||||
if (srcpath.indexOf("index.html") >= 0) {
|
if (srcpath.indexOf("index.html") >= 0) {
|
||||||
// Add Google Analytics code to index.html
|
// Add Google Analytics code to index.html
|
||||||
content = content.replace(
|
content = content.replace("</body></html>",
|
||||||
"</body></html>",
|
grunt.file.read("src/web/static/ga.html") + "</body></html>");
|
||||||
grunt.file.read("src/web/static/ga.html") +
|
|
||||||
"</body></html>",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add Structured Data for SEO
|
// Add Structured Data for SEO
|
||||||
content = content.replace(
|
content = content.replace("</head>",
|
||||||
"</head>",
|
|
||||||
"<script type='application/ld+json'>" +
|
"<script type='application/ld+json'>" +
|
||||||
JSON.stringify(
|
JSON.stringify(JSON.parse(grunt.file.read("src/web/static/structuredData.json"))) +
|
||||||
JSON.parse(
|
"</script></head>");
|
||||||
grunt.file.read(
|
|
||||||
"src/web/static/structuredData.json",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
) +
|
|
||||||
"</script></head>",
|
|
||||||
);
|
|
||||||
return grunt.template.process(content, srcpath);
|
return grunt.template.process(content, srcpath);
|
||||||
} else {
|
} else {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
noProcess: ["**", "!**/*.html"],
|
noProcess: ["**", "!**/*.html"]
|
||||||
},
|
},
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
src: ["build/prod/index.html"],
|
src: ["build/prod/index.html"],
|
||||||
dest: "build/prod/index.html",
|
dest: "build/prod/index.html"
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
standalone: {
|
standalone: {
|
||||||
options: {
|
options: {
|
||||||
process: function (content, srcpath) {
|
process: function (content, srcpath) {
|
||||||
if (srcpath.indexOf("index.html") >= 0) {
|
if (srcpath.indexOf("index.html") >= 0) {
|
||||||
// Replace download link with version number
|
// Replace download link with version number
|
||||||
content = content.replace(
|
content = content.replace(/<a [^>]+>Download CyberChef.+?<\/a>/,
|
||||||
/<a [^>]+>Download CyberChef.+?<\/a>/,
|
`<span>Version ${pkg.version}</span>`);
|
||||||
`<span>Version ${pkg.version}</span>`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return grunt.template.process(content, srcpath);
|
return grunt.template.process(content, srcpath);
|
||||||
} else {
|
} else {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
noProcess: ["**", "!**/*.html"],
|
noProcess: ["**", "!**/*.html"]
|
||||||
},
|
},
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
src: ["build/prod/index.html"],
|
src: ["build/prod/index.html"],
|
||||||
dest: `build/prod/CyberChef_v${pkg.version}.html`,
|
dest: `build/prod/CyberChef_v${pkg.version}.html`
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
chmod: {
|
chmod: {
|
||||||
build: {
|
build: {
|
||||||
options: {
|
options: {
|
||||||
mode: "755",
|
mode: "755",
|
||||||
},
|
},
|
||||||
src: ["build/**/*", "build/"],
|
src: ["build/**/*", "build/"]
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
config: {
|
config: {
|
||||||
files: [
|
files: ["src/core/operations/**/*", "!src/core/operations/index.mjs"],
|
||||||
"src/core/operations/**/*",
|
tasks: ["exec:generateNodeIndex", "exec:generateConfig"]
|
||||||
"!src/core/operations/index.mjs",
|
}
|
||||||
],
|
|
||||||
tasks: ["exec:generateNodeIndex", "exec:generateConfig"],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
concurrent: {
|
concurrent: {
|
||||||
dev: ["watch:config", "webpack-dev-server:start"],
|
dev: ["watch:config", "webpack-dev-server:start"],
|
||||||
options: {
|
options: {
|
||||||
logConcurrentOutput: true,
|
logConcurrentOutput: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
exec: {
|
exec: {
|
||||||
calcDownloadHash: {
|
calcDownloadHash: {
|
||||||
|
@ -426,12 +330,12 @@ module.exports = function (grunt) {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return chainCommands([
|
return chainCommands([
|
||||||
`shasum -a 256 build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
`shasum -a 256 build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
||||||
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`,
|
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
||||||
]);
|
]);
|
||||||
default:
|
default:
|
||||||
return chainCommands([
|
return chainCommands([
|
||||||
`sha256sum build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
`sha256sum build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
||||||
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`,
|
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -439,16 +343,16 @@ module.exports = function (grunt) {
|
||||||
repoSize: {
|
repoSize: {
|
||||||
command: chainCommands([
|
command: chainCommands([
|
||||||
"git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'",
|
"git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'",
|
||||||
"du -hs | egrep -o '^[^\t]*' | xargs printf '%b\trepository size\n'",
|
"du -hs | egrep -o '^[^\t]*' | xargs printf '%b\trepository size\n'"
|
||||||
]),
|
]),
|
||||||
stderr: false,
|
stderr: false
|
||||||
},
|
},
|
||||||
cleanGit: {
|
cleanGit: {
|
||||||
command: "git gc --prune=now --aggressive",
|
command: "git gc --prune=now --aggressive"
|
||||||
},
|
},
|
||||||
sitemap: {
|
sitemap: {
|
||||||
command: `node ${nodeFlags} src/web/static/sitemap.mjs > build/prod/sitemap.xml`,
|
command: `node ${nodeFlags} src/web/static/sitemap.mjs > build/prod/sitemap.xml`,
|
||||||
sync: true,
|
sync: true
|
||||||
},
|
},
|
||||||
generateConfig: {
|
generateConfig: {
|
||||||
command: chainCommands([
|
command: chainCommands([
|
||||||
|
@ -456,20 +360,20 @@ module.exports = function (grunt) {
|
||||||
"echo [] > src/core/config/OperationConfig.json",
|
"echo [] > src/core/config/OperationConfig.json",
|
||||||
`node ${nodeFlags} src/core/config/scripts/generateOpsIndex.mjs`,
|
`node ${nodeFlags} src/core/config/scripts/generateOpsIndex.mjs`,
|
||||||
`node ${nodeFlags} src/core/config/scripts/generateConfig.mjs`,
|
`node ${nodeFlags} src/core/config/scripts/generateConfig.mjs`,
|
||||||
"echo '--- Config scripts finished. ---\n'",
|
"echo '--- Config scripts finished. ---\n'"
|
||||||
]),
|
]),
|
||||||
sync: true,
|
sync: true
|
||||||
},
|
},
|
||||||
generateNodeIndex: {
|
generateNodeIndex: {
|
||||||
command: chainCommands([
|
command: chainCommands([
|
||||||
"echo '\n--- Regenerating node index ---'",
|
"echo '\n--- Regenerating node index ---'",
|
||||||
`node ${nodeFlags} src/node/config/scripts/generateNodeIndex.mjs`,
|
`node ${nodeFlags} src/node/config/scripts/generateNodeIndex.mjs`,
|
||||||
"echo '--- Node index generated. ---\n'",
|
"echo '--- Node index generated. ---\n'"
|
||||||
]),
|
]),
|
||||||
sync: true,
|
sync: true
|
||||||
},
|
},
|
||||||
browserTests: {
|
browserTests: {
|
||||||
command: "./node_modules/.bin/nightwatch --env prod",
|
command: "./node_modules/.bin/nightwatch --env prod"
|
||||||
},
|
},
|
||||||
setupNodeConsumers: {
|
setupNodeConsumers: {
|
||||||
command: chainCommands([
|
command: chainCommands([
|
||||||
|
@ -478,14 +382,14 @@ module.exports = function (grunt) {
|
||||||
`mkdir ${nodeConsumerTestPath}`,
|
`mkdir ${nodeConsumerTestPath}`,
|
||||||
`cp tests/node/consumers/* ${nodeConsumerTestPath}`,
|
`cp tests/node/consumers/* ${nodeConsumerTestPath}`,
|
||||||
`cd ${nodeConsumerTestPath}`,
|
`cd ${nodeConsumerTestPath}`,
|
||||||
"npm link cyberchef",
|
"npm link cyberchef"
|
||||||
]),
|
]),
|
||||||
sync: true,
|
sync: true
|
||||||
},
|
},
|
||||||
teardownNodeConsumers: {
|
teardownNodeConsumers: {
|
||||||
command: chainCommands([
|
command: chainCommands([
|
||||||
`rm -rf ${nodeConsumerTestPath}`,
|
`rm -rf ${nodeConsumerTestPath}`,
|
||||||
"echo '\n--- Node consumer tests complete ---'",
|
"echo '\n--- Node consumer tests complete ---'"
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
testCJSNodeConsumer: {
|
testCJSNodeConsumer: {
|
||||||
|
@ -511,7 +415,7 @@ module.exports = function (grunt) {
|
||||||
return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`;
|
return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stdout: false,
|
stdout: false
|
||||||
},
|
},
|
||||||
fixSnackbarMarkup: {
|
fixSnackbarMarkup: {
|
||||||
command: function () {
|
command: function () {
|
||||||
|
@ -522,8 +426,8 @@ module.exports = function (grunt) {
|
||||||
return `sed -i 's/<div id=snackbar-container\\/>/<div id=snackbar-container>/g' ./node_modules/snackbarjs/src/snackbar.js`;
|
return `sed -i 's/<div id=snackbar-container\\/>/<div id=snackbar-container>/g' ./node_modules/snackbarjs/src/snackbar.js`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stdout: false,
|
stdout: false
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,32 +1,27 @@
|
||||||
module.exports = function (api) {
|
module.exports = function(api) {
|
||||||
api.cache.forever();
|
api.cache.forever();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
presets: [
|
"presets": [
|
||||||
[
|
["@babel/preset-env", {
|
||||||
"@babel/preset-env",
|
"modules": false,
|
||||||
{
|
"useBuiltIns": "entry",
|
||||||
modules: false,
|
"corejs": 3
|
||||||
useBuiltIns: "entry",
|
}]
|
||||||
corejs: 3,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
],
|
"plugins": [
|
||||||
plugins: [
|
|
||||||
"dynamic-import-node",
|
"dynamic-import-node",
|
||||||
"@babel/plugin-syntax-import-assertions",
|
"@babel/plugin-syntax-import-assertions",
|
||||||
[
|
[
|
||||||
"babel-plugin-transform-builtin-extend",
|
"babel-plugin-transform-builtin-extend", {
|
||||||
{
|
"globals": ["Error"]
|
||||||
globals: ["Error"],
|
}
|
||||||
},
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"@babel/plugin-transform-runtime",
|
"@babel/plugin-transform-runtime", {
|
||||||
{
|
"regenerator": true
|
||||||
regenerator: true,
|
}
|
||||||
},
|
]
|
||||||
],
|
]
|
||||||
],
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
20
biome.json
20
biome.json
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://biomejs.dev/schemas/1.5.3/schema.json",
|
|
||||||
"organizeImports": {
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"linter": {
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"formatter": {
|
|
||||||
"enabled": true,
|
|
||||||
"formatWithErrors": false,
|
|
||||||
"indentStyle": "space",
|
|
||||||
"indentWidth": 4,
|
|
||||||
"lineWidth": 80,
|
|
||||||
"ignore": []
|
|
||||||
},
|
|
||||||
"files": {
|
|
||||||
"include": ["**/*.*js"]
|
|
||||||
}
|
|
||||||
}
|
|
38
package-lock.json
generated
38
package-lock.json
generated
|
@ -130,7 +130,6 @@
|
||||||
"grunt-contrib-watch": "^1.1.0",
|
"grunt-contrib-watch": "^1.1.0",
|
||||||
"grunt-eslint": "^24.3.0",
|
"grunt-eslint": "^24.3.0",
|
||||||
"grunt-exec": "~3.0.0",
|
"grunt-exec": "~3.0.0",
|
||||||
"grunt-prettier": "^2.2.0",
|
|
||||||
"grunt-webpack": "^6.0.0",
|
"grunt-webpack": "^6.0.0",
|
||||||
"grunt-zip": "^1.0.0",
|
"grunt-zip": "^1.0.0",
|
||||||
"html-webpack-plugin": "^5.6.0",
|
"html-webpack-plugin": "^5.6.0",
|
||||||
|
@ -8118,28 +8117,6 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/grunt-prettier": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/grunt-prettier/-/grunt-prettier-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-kl6+1sYEM7HezxZS0DEFYYpD7JtwsToD8ZK2kDpAd3SvHINbz2iwsghpPsmdGihUJ2FVo8XBIzACmNxBBCytqQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"prettier": "^2.0.5",
|
|
||||||
"progress": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/grunt-prettier/node_modules/progress": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/grunt-retro": {
|
"node_modules/grunt-retro": {
|
||||||
"version": "0.6.4",
|
"version": "0.6.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -12197,21 +12174,6 @@
|
||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier": {
|
|
||||||
"version": "2.8.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
|
||||||
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"prettier": "bin-prettier.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pretty-error": {
|
"node_modules/pretty-error": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
|
@ -189,7 +189,6 @@
|
||||||
"testui": "npx grunt testui",
|
"testui": "npx grunt testui",
|
||||||
"testuidev": "npx nightwatch --env=dev",
|
"testuidev": "npx nightwatch --env=dev",
|
||||||
"lint": "npx grunt lint",
|
"lint": "npx grunt lint",
|
||||||
"format": "npx @biomejs/biome format . --write",
|
|
||||||
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup",
|
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup",
|
||||||
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
||||||
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
|
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
|
||||||
|
|
|
@ -3,7 +3,7 @@ module.exports = {
|
||||||
require("postcss-import"),
|
require("postcss-import"),
|
||||||
require("autoprefixer"),
|
require("autoprefixer"),
|
||||||
require("postcss-css-variables")({
|
require("postcss-css-variables")({
|
||||||
preserve: true,
|
preserve: true
|
||||||
}),
|
}),
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { isWorkerEnvironment } from "./Utils.mjs";
|
||||||
* The main controller for CyberChef.
|
* The main controller for CyberChef.
|
||||||
*/
|
*/
|
||||||
class Chef {
|
class Chef {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chef constructor
|
* Chef constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,6 +21,7 @@ class Chef {
|
||||||
this.dish = new Dish();
|
this.dish = new Dish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the recipe over the input.
|
* Runs the recipe over the input.
|
||||||
*
|
*
|
||||||
|
@ -35,7 +37,7 @@ class Chef {
|
||||||
* @returns {number} response.duration - The number of ms it took to execute the recipe
|
* @returns {number} response.duration - The number of ms it took to execute the recipe
|
||||||
* @returns {number} response.error - The error object thrown by a failed operation (false if no error)
|
* @returns {number} response.error - The error object thrown by a failed operation (false if no error)
|
||||||
*/
|
*/
|
||||||
async bake(input, recipeConfig, options = {}) {
|
async bake(input, recipeConfig, options={}) {
|
||||||
log.debug("Chef baking");
|
log.debug("Chef baking");
|
||||||
const startTime = Date.now(),
|
const startTime = Date.now(),
|
||||||
recipe = new Recipe(recipeConfig),
|
recipe = new Recipe(recipeConfig),
|
||||||
|
@ -43,12 +45,10 @@ class Chef {
|
||||||
let error = false,
|
let error = false,
|
||||||
progress = 0;
|
progress = 0;
|
||||||
|
|
||||||
if (containsFc && isWorkerEnvironment())
|
if (containsFc && isWorkerEnvironment()) self.setOption("attemptHighlight", false);
|
||||||
self.setOption("attemptHighlight", false);
|
|
||||||
|
|
||||||
// Load data
|
// Load data
|
||||||
const type =
|
const type = input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING;
|
||||||
input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING;
|
|
||||||
this.dish.set(input, type);
|
this.dish.set(input, type);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -68,11 +68,8 @@ class Chef {
|
||||||
await recipe.present(this.dish);
|
await recipe.present(this.dish);
|
||||||
|
|
||||||
const returnType =
|
const returnType =
|
||||||
this.dish.type === Dish.HTML
|
this.dish.type === Dish.HTML ? Dish.HTML :
|
||||||
? Dish.HTML
|
options?.returnType ? options.returnType : Dish.ARRAY_BUFFER;
|
||||||
: options?.returnType
|
|
||||||
? options.returnType
|
|
||||||
: Dish.ARRAY_BUFFER;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dish: rawDish,
|
dish: rawDish,
|
||||||
|
@ -80,10 +77,11 @@ class Chef {
|
||||||
type: Dish.enumLookup(this.dish.type),
|
type: Dish.enumLookup(this.dish.type),
|
||||||
progress: progress,
|
progress: progress,
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error,
|
error: error
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a browser tab is unfocused and the browser has to run lots of dynamic content in other tabs,
|
* When a browser tab is unfocused and the browser has to run lots of dynamic content in other tabs,
|
||||||
* it swaps out the memory for that tab. If the CyberChef tab has been unfocused for more than a
|
* it swaps out the memory for that tab. If the CyberChef tab has been unfocused for more than a
|
||||||
|
@ -116,6 +114,7 @@ class Chef {
|
||||||
return Date.now() - startTime;
|
return Date.now() - startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates highlight offsets if possible.
|
* Calculates highlight offsets if possible.
|
||||||
*
|
*
|
||||||
|
@ -136,8 +135,7 @@ class Chef {
|
||||||
// Remove multiple highlights before processing again
|
// Remove multiple highlights before processing again
|
||||||
pos = [pos[0]];
|
pos = [pos[0]];
|
||||||
|
|
||||||
const func =
|
const func = direction === "forward" ? highlights[i].f : highlights[i].b;
|
||||||
direction === "forward" ? highlights[i].f : highlights[i].b;
|
|
||||||
|
|
||||||
if (typeof func == "function") {
|
if (typeof func == "function") {
|
||||||
try {
|
try {
|
||||||
|
@ -151,10 +149,11 @@ class Chef {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
direction: direction,
|
direction: direction
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the dish to a specified type and returns it.
|
* Translates the dish to a specified type and returns it.
|
||||||
*
|
*
|
||||||
|
@ -174,10 +173,11 @@ class Chef {
|
||||||
* @param {number} [maxLength=100]
|
* @param {number} [maxLength=100]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
async getDishTitle(dish, maxLength = 100) {
|
async getDishTitle(dish, maxLength=100) {
|
||||||
const newDish = new Dish(dish);
|
const newDish = new Dish(dish);
|
||||||
return await newDish.getTitle(maxLength);
|
return await newDish.getTitle(maxLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Chef;
|
export default Chef;
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Chef from "./Chef.mjs";
|
import Chef from "./Chef.mjs";
|
||||||
import OperationConfig from "./config/OperationConfig.json" assert {
|
import OperationConfig from "./config/OperationConfig.json" assert {type: "json"};
|
||||||
type: "json",
|
|
||||||
};
|
|
||||||
import OpModules from "./config/modules/OpModules.mjs";
|
import OpModules from "./config/modules/OpModules.mjs";
|
||||||
import loglevelMessagePrefix from "loglevel-message-prefix";
|
import loglevelMessagePrefix from "loglevel-message-prefix";
|
||||||
|
|
||||||
|
|
||||||
// Set up Chef instance
|
// Set up Chef instance
|
||||||
self.chef = new Chef();
|
self.chef = new Chef();
|
||||||
|
|
||||||
|
@ -20,10 +19,11 @@ self.OpModules = OpModules;
|
||||||
self.OperationConfig = OperationConfig;
|
self.OperationConfig = OperationConfig;
|
||||||
self.inputNum = -1;
|
self.inputNum = -1;
|
||||||
|
|
||||||
|
|
||||||
// Tell the app that the worker has loaded and is ready to operate
|
// Tell the app that the worker has loaded and is ready to operate
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "workerLoaded",
|
action: "workerLoaded",
|
||||||
data: {},
|
data: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +45,7 @@ self.postMessage({
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
self.addEventListener("message", function (e) {
|
self.addEventListener("message", function(e) {
|
||||||
// Handle message
|
// Handle message
|
||||||
const r = e.data;
|
const r = e.data;
|
||||||
log.debug(`Receiving command '${r.action}'`);
|
log.debug(`Receiving command '${r.action}'`);
|
||||||
|
@ -72,7 +72,7 @@ self.addEventListener("message", function (e) {
|
||||||
calculateHighlights(
|
calculateHighlights(
|
||||||
r.data.recipeConfig,
|
r.data.recipeConfig,
|
||||||
r.data.direction,
|
r.data.direction,
|
||||||
r.data.pos,
|
r.data.pos
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "setLogLevel":
|
case "setLogLevel":
|
||||||
|
@ -81,7 +81,7 @@ self.addEventListener("message", function (e) {
|
||||||
case "setLogPrefix":
|
case "setLogPrefix":
|
||||||
loglevelMessagePrefix(log, {
|
loglevelMessagePrefix(log, {
|
||||||
prefixes: [],
|
prefixes: [],
|
||||||
staticPrefixes: [r.data],
|
staticPrefixes: [r.data]
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -89,6 +89,7 @@ self.addEventListener("message", function (e) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Baking handler
|
* Baking handler
|
||||||
*
|
*
|
||||||
|
@ -102,38 +103,36 @@ async function bake(data) {
|
||||||
const response = await self.chef.bake(
|
const response = await self.chef.bake(
|
||||||
data.input, // The user's input
|
data.input, // The user's input
|
||||||
data.recipeConfig, // The configuration of the recipe
|
data.recipeConfig, // The configuration of the recipe
|
||||||
data.options, // Options set by the user
|
data.options // Options set by the user
|
||||||
);
|
);
|
||||||
|
|
||||||
const transferable =
|
const transferable = (response.dish.value instanceof ArrayBuffer) ?
|
||||||
response.dish.value instanceof ArrayBuffer
|
[response.dish.value] :
|
||||||
? [response.dish.value]
|
undefined;
|
||||||
: undefined;
|
|
||||||
|
|
||||||
self.postMessage(
|
self.postMessage({
|
||||||
{
|
|
||||||
action: "bakeComplete",
|
action: "bakeComplete",
|
||||||
data: Object.assign(response, {
|
data: Object.assign(response, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
inputNum: data.inputNum,
|
inputNum: data.inputNum,
|
||||||
bakeId: data.bakeId,
|
bakeId: data.bakeId
|
||||||
}),
|
})
|
||||||
},
|
}, transferable);
|
||||||
transferable,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "bakeError",
|
action: "bakeError",
|
||||||
data: {
|
data: {
|
||||||
error: err.message || err,
|
error: err.message || err,
|
||||||
id: data.id,
|
id: data.id,
|
||||||
inputNum: data.inputNum,
|
inputNum: data.inputNum
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.inputNum = -1;
|
self.inputNum = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Silent baking handler
|
* Silent baking handler
|
||||||
*/
|
*/
|
||||||
|
@ -142,28 +141,27 @@ function silentBake(data) {
|
||||||
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "silentBakeComplete",
|
action: "silentBakeComplete",
|
||||||
data: duration,
|
data: duration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the dish to a given type.
|
* Translates the dish to a given type.
|
||||||
*/
|
*/
|
||||||
async function getDishAs(data) {
|
async function getDishAs(data) {
|
||||||
const value = await self.chef.getDishAs(data.dish, data.type);
|
const value = await self.chef.getDishAs(data.dish, data.type);
|
||||||
const transferable = data.type === "ArrayBuffer" ? [value] : undefined;
|
const transferable = (data.type === "ArrayBuffer") ? [value] : undefined;
|
||||||
self.postMessage(
|
self.postMessage({
|
||||||
{
|
|
||||||
action: "dishReturned",
|
action: "dishReturned",
|
||||||
data: {
|
data: {
|
||||||
value: value,
|
value: value,
|
||||||
id: data.id,
|
id: data.id
|
||||||
},
|
}
|
||||||
},
|
}, transferable);
|
||||||
transferable,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the dish title
|
* Gets the dish title
|
||||||
*
|
*
|
||||||
|
@ -178,11 +176,12 @@ async function getDishTitle(data) {
|
||||||
action: "dishReturned",
|
action: "dishReturned",
|
||||||
data: {
|
data: {
|
||||||
value: title,
|
value: title,
|
||||||
id: data.id,
|
id: data.id
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates highlight offsets if possible.
|
* Calculates highlight offsets if possible.
|
||||||
*
|
*
|
||||||
|
@ -197,17 +196,18 @@ async function calculateHighlights(recipeConfig, direction, pos) {
|
||||||
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "highlightsCalculated",
|
action: "highlightsCalculated",
|
||||||
data: pos,
|
data: pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that all required modules are loaded and loads them if not.
|
* Checks that all required modules are loaded and loads them if not.
|
||||||
*
|
*
|
||||||
* @param {Object} recipeConfig
|
* @param {Object} recipeConfig
|
||||||
*/
|
*/
|
||||||
self.loadRequiredModules = function (recipeConfig) {
|
self.loadRequiredModules = function(recipeConfig) {
|
||||||
recipeConfig.forEach((op) => {
|
recipeConfig.forEach(op => {
|
||||||
const module = self.OperationConfig[op.op].module;
|
const module = self.OperationConfig[op.op].module;
|
||||||
|
|
||||||
if (!(module in OpModules)) {
|
if (!(module in OpModules)) {
|
||||||
|
@ -219,54 +219,58 @@ self.loadRequiredModules = function (recipeConfig) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send status update to the app.
|
* Send status update to the app.
|
||||||
*
|
*
|
||||||
* @param {string} msg
|
* @param {string} msg
|
||||||
*/
|
*/
|
||||||
self.sendStatusMessage = function (msg) {
|
self.sendStatusMessage = function(msg) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "statusMessage",
|
action: "statusMessage",
|
||||||
data: {
|
data: {
|
||||||
message: msg,
|
message: msg,
|
||||||
inputNum: self.inputNum,
|
inputNum: self.inputNum
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send progress update to the app.
|
* Send progress update to the app.
|
||||||
*
|
*
|
||||||
* @param {number} progress
|
* @param {number} progress
|
||||||
* @param {number} total
|
* @param {number} total
|
||||||
*/
|
*/
|
||||||
self.sendProgressMessage = function (progress, total) {
|
self.sendProgressMessage = function(progress, total) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "progressMessage",
|
action: "progressMessage",
|
||||||
data: {
|
data: {
|
||||||
progress: progress,
|
progress: progress,
|
||||||
total: total,
|
total: total,
|
||||||
inputNum: self.inputNum,
|
inputNum: self.inputNum
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an option value update to the app.
|
* Send an option value update to the app.
|
||||||
*
|
*
|
||||||
* @param {string} option
|
* @param {string} option
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
*/
|
*/
|
||||||
self.setOption = function (option, value) {
|
self.setOption = function(option, value) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "optionUpdate",
|
action: "optionUpdate",
|
||||||
data: {
|
data: {
|
||||||
option: option,
|
option: option,
|
||||||
value: value,
|
value: value
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send register values back to the app.
|
* Send register values back to the app.
|
||||||
*
|
*
|
||||||
|
@ -274,13 +278,13 @@ self.setOption = function (option, value) {
|
||||||
* @param {number} numPrevRegisters
|
* @param {number} numPrevRegisters
|
||||||
* @param {string[]} registers
|
* @param {string[]} registers
|
||||||
*/
|
*/
|
||||||
self.setRegisters = function (opIndex, numPrevRegisters, registers) {
|
self.setRegisters = function(opIndex, numPrevRegisters, registers) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "setRegisters",
|
action: "setRegisters",
|
||||||
data: {
|
data: {
|
||||||
opIndex: opIndex,
|
opIndex: opIndex,
|
||||||
numPrevRegisters: numPrevRegisters,
|
numPrevRegisters: numPrevRegisters,
|
||||||
registers: registers,
|
registers: registers
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,10 +20,12 @@ import DishListFile from "./dishTypes/DishListFile.mjs";
|
||||||
import DishNumber from "./dishTypes/DishNumber.mjs";
|
import DishNumber from "./dishTypes/DishNumber.mjs";
|
||||||
import DishString from "./dishTypes/DishString.mjs";
|
import DishString from "./dishTypes/DishString.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data being operated on by each operation.
|
* The data being operated on by each operation.
|
||||||
*/
|
*/
|
||||||
class Dish {
|
class Dish {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dish constructor
|
* Dish constructor
|
||||||
*
|
*
|
||||||
|
@ -32,16 +34,14 @@ class Dish {
|
||||||
* @param {Enum} [type=null] (optional) - A type to accompany object
|
* @param {Enum} [type=null] (optional) - A type to accompany object
|
||||||
* literal input
|
* literal input
|
||||||
*/
|
*/
|
||||||
constructor(dishOrInput = null, type = null) {
|
constructor(dishOrInput=null, type = null) {
|
||||||
this.value = new ArrayBuffer(0);
|
this.value = new ArrayBuffer(0);
|
||||||
this.type = Dish.ARRAY_BUFFER;
|
this.type = Dish.ARRAY_BUFFER;
|
||||||
|
|
||||||
// Case: dishOrInput is dish object
|
// Case: dishOrInput is dish object
|
||||||
if (
|
if (dishOrInput &&
|
||||||
dishOrInput &&
|
|
||||||
Object.prototype.hasOwnProperty.call(dishOrInput, "value") &&
|
Object.prototype.hasOwnProperty.call(dishOrInput, "value") &&
|
||||||
Object.prototype.hasOwnProperty.call(dishOrInput, "type")
|
Object.prototype.hasOwnProperty.call(dishOrInput, "type")) {
|
||||||
) {
|
|
||||||
this.set(dishOrInput.value, dishOrInput.type);
|
this.set(dishOrInput.value, dishOrInput.type);
|
||||||
// input and type defined separately
|
// input and type defined separately
|
||||||
} else if (dishOrInput && type !== null) {
|
} else if (dishOrInput && type !== null) {
|
||||||
|
@ -53,6 +53,7 @@ class Dish {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data type enum for the given type string.
|
* Returns the data type enum for the given type string.
|
||||||
*
|
*
|
||||||
|
@ -84,12 +85,11 @@ class Dish {
|
||||||
case "list<file>":
|
case "list<file>":
|
||||||
return Dish.LIST_FILE;
|
return Dish.LIST_FILE;
|
||||||
default:
|
default:
|
||||||
throw new DishError(
|
throw new DishError("Invalid data type string. No matching enum.");
|
||||||
"Invalid data type string. No matching enum.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data type string for the given type enum.
|
* Returns the data type string for the given type enum.
|
||||||
*
|
*
|
||||||
|
@ -117,12 +117,11 @@ class Dish {
|
||||||
case Dish.LIST_FILE:
|
case Dish.LIST_FILE:
|
||||||
return "List<File>";
|
return "List<File>";
|
||||||
default:
|
default:
|
||||||
throw new DishError(
|
throw new DishError("Invalid data type enum. No matching type.");
|
||||||
"Invalid data type enum. No matching type.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the data in the type format specified.
|
* Returns the value of the data in the type format specified.
|
||||||
*
|
*
|
||||||
|
@ -137,6 +136,7 @@ class Dish {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.type !== type) {
|
if (this.type !== type) {
|
||||||
|
|
||||||
// Node environment => _translate is sync
|
// Node environment => _translate is sync
|
||||||
if (isNodeEnvironment()) {
|
if (isNodeEnvironment()) {
|
||||||
this._translate(type);
|
this._translate(type);
|
||||||
|
@ -157,6 +157,7 @@ class Dish {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data value and type and then validates them.
|
* Sets the data value and type and then validates them.
|
||||||
*
|
*
|
||||||
|
@ -176,9 +177,7 @@ class Dish {
|
||||||
|
|
||||||
if (!this.valid()) {
|
if (!this.valid()) {
|
||||||
const sample = Utils.truncate(JSON.stringify(this.value), 25);
|
const sample = Utils.truncate(JSON.stringify(this.value), 25);
|
||||||
throw new DishError(
|
throw new DishError(`Data is not a valid ${Dish.enumLookup(type)}: ${sample}`);
|
||||||
`Data is not a valid ${Dish.enumLookup(type)}: ${sample}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +196,7 @@ class Dish {
|
||||||
return clone.get(type);
|
return clone.get(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects the MIME type of the current dish
|
* Detects the MIME type of the current dish
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
@ -205,17 +205,14 @@ class Dish {
|
||||||
const data = new Uint8Array(this.value.slice(0, 2048)),
|
const data = new Uint8Array(this.value.slice(0, 2048)),
|
||||||
types = detectFileType(data);
|
types = detectFileType(data);
|
||||||
|
|
||||||
if (
|
if (!types.length || !types[0].mime || !(types[0].mime === "text/plain")) {
|
||||||
!types.length ||
|
|
||||||
!types[0].mime ||
|
|
||||||
!(types[0].mime === "text/plain")
|
|
||||||
) {
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return types[0].mime;
|
return types[0].mime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the title of the data up to the specified length
|
* Returns the title of the data up to the specified length
|
||||||
*
|
*
|
||||||
|
@ -251,11 +248,7 @@ class Dish {
|
||||||
cloned.value = cloned.value.slice(0, 256);
|
cloned.value = cloned.value.slice(0, 256);
|
||||||
title = await cloned.get(Dish.STRING);
|
title = await cloned.get(Dish.STRING);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error(
|
log.error(`${Dish.enumLookup(this.type)} cannot be sliced. ${err}`);
|
||||||
`${Dish.enumLookup(
|
|
||||||
this.type,
|
|
||||||
)} cannot be sliced. ${err}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,20 +264,15 @@ class Dish {
|
||||||
valid() {
|
valid() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case Dish.BYTE_ARRAY:
|
case Dish.BYTE_ARRAY:
|
||||||
if (
|
if (!(this.value instanceof Uint8Array) && !(this.value instanceof Array)) {
|
||||||
!(this.value instanceof Uint8Array) &&
|
|
||||||
!(this.value instanceof Array)
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that every value is a number between 0 - 255
|
// Check that every value is a number between 0 - 255
|
||||||
for (let i = 0; i < this.value.length; i++) {
|
for (let i = 0; i < this.value.length; i++) {
|
||||||
if (
|
if (typeof this.value[i] !== "number" ||
|
||||||
typeof this.value[i] !== "number" ||
|
|
||||||
this.value[i] < 0 ||
|
this.value[i] < 0 ||
|
||||||
this.value[i] > 255
|
this.value[i] > 255) {
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,18 +306,14 @@ class Dish {
|
||||||
case Dish.FILE:
|
case Dish.FILE:
|
||||||
return this.value instanceof File;
|
return this.value instanceof File;
|
||||||
case Dish.LIST_FILE:
|
case Dish.LIST_FILE:
|
||||||
return (
|
return this.value instanceof Array &&
|
||||||
this.value instanceof Array &&
|
this.value.reduce((acc, curr) => acc && curr instanceof File, true);
|
||||||
this.value.reduce(
|
|
||||||
(acc, curr) => acc && curr instanceof File,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines how much space the Dish takes up.
|
* Determines how much space the Dish takes up.
|
||||||
* Numbers in JavaScript are 64-bit floating point, however for the purposes of the Dish,
|
* Numbers in JavaScript are 64-bit floating point, however for the purposes of the Dish,
|
||||||
|
@ -359,6 +343,7 @@ class Dish {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a deep clone of the current Dish.
|
* Returns a deep clone of the current Dish.
|
||||||
*
|
*
|
||||||
|
@ -373,37 +358,45 @@ class Dish {
|
||||||
case Dish.NUMBER:
|
case Dish.NUMBER:
|
||||||
case Dish.BIG_NUMBER:
|
case Dish.BIG_NUMBER:
|
||||||
// These data types are immutable so it is acceptable to copy them by reference
|
// These data types are immutable so it is acceptable to copy them by reference
|
||||||
newDish.set(this.value, this.type);
|
newDish.set(
|
||||||
|
this.value,
|
||||||
|
this.type
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case Dish.BYTE_ARRAY:
|
case Dish.BYTE_ARRAY:
|
||||||
case Dish.JSON:
|
case Dish.JSON:
|
||||||
// These data types are mutable so they need to be copied by value
|
// These data types are mutable so they need to be copied by value
|
||||||
newDish.set(JSON.parse(JSON.stringify(this.value)), this.type);
|
newDish.set(
|
||||||
|
JSON.parse(JSON.stringify(this.value)),
|
||||||
|
this.type
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case Dish.ARRAY_BUFFER:
|
case Dish.ARRAY_BUFFER:
|
||||||
// Slicing an ArrayBuffer returns a new ArrayBuffer with a copy its contents
|
// Slicing an ArrayBuffer returns a new ArrayBuffer with a copy its contents
|
||||||
newDish.set(this.value.slice(0), this.type);
|
newDish.set(
|
||||||
|
this.value.slice(0),
|
||||||
|
this.type
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case Dish.FILE:
|
case Dish.FILE:
|
||||||
// A new file can be created by copying over all the values from the original
|
// A new file can be created by copying over all the values from the original
|
||||||
newDish.set(
|
newDish.set(
|
||||||
new File([this.value], this.value.name, {
|
new File([this.value], this.value.name, {
|
||||||
type: this.value.type,
|
"type": this.value.type,
|
||||||
lastModified: this.value.lastModified,
|
"lastModified": this.value.lastModified
|
||||||
}),
|
}),
|
||||||
this.type,
|
this.type
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case Dish.LIST_FILE:
|
case Dish.LIST_FILE:
|
||||||
newDish.set(
|
newDish.set(
|
||||||
this.value.map(
|
this.value.map(f =>
|
||||||
(f) =>
|
|
||||||
new File([f], f.name, {
|
new File([f], f.name, {
|
||||||
type: f.type,
|
"type": f.type,
|
||||||
lastModified: f.lastModified,
|
"lastModified": f.lastModified
|
||||||
}),
|
})
|
||||||
),
|
),
|
||||||
this.type,
|
this.type
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -422,11 +415,7 @@ class Dish {
|
||||||
* @returns {Promise || undefined}
|
* @returns {Promise || undefined}
|
||||||
*/
|
*/
|
||||||
_translate(toType) {
|
_translate(toType) {
|
||||||
log.debug(
|
log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`);
|
||||||
`Translating Dish from ${Dish.enumLookup(
|
|
||||||
this.type,
|
|
||||||
)} to ${Dish.enumLookup(toType)}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Node environment => translate is sync
|
// Node environment => translate is sync
|
||||||
if (isNodeEnvironment()) {
|
if (isNodeEnvironment()) {
|
||||||
|
@ -438,7 +427,7 @@ class Dish {
|
||||||
} else {
|
} else {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this._toArrayBuffer()
|
this._toArrayBuffer()
|
||||||
.then(() => (this.type = Dish.ARRAY_BUFFER))
|
.then(() => this.type = Dish.ARRAY_BUFFER)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this._fromArrayBuffer(toType);
|
this._fromArrayBuffer(toType);
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -446,6 +435,7 @@ class Dish {
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -459,48 +449,33 @@ class Dish {
|
||||||
// Using 'bind' here to allow this.value to be mutated within translation functions
|
// Using 'bind' here to allow this.value to be mutated within translation functions
|
||||||
const toByteArrayFuncs = {
|
const toByteArrayFuncs = {
|
||||||
browser: {
|
browser: {
|
||||||
[Dish.STRING]: () =>
|
[Dish.STRING]: () => Promise.resolve(DishString.toArrayBuffer.bind(this)()),
|
||||||
Promise.resolve(DishString.toArrayBuffer.bind(this)()),
|
[Dish.NUMBER]: () => Promise.resolve(DishNumber.toArrayBuffer.bind(this)()),
|
||||||
[Dish.NUMBER]: () =>
|
[Dish.HTML]: () => Promise.resolve(DishHTML.toArrayBuffer.bind(this)()),
|
||||||
Promise.resolve(DishNumber.toArrayBuffer.bind(this)()),
|
|
||||||
[Dish.HTML]: () =>
|
|
||||||
Promise.resolve(DishHTML.toArrayBuffer.bind(this)()),
|
|
||||||
[Dish.ARRAY_BUFFER]: () => Promise.resolve(),
|
[Dish.ARRAY_BUFFER]: () => Promise.resolve(),
|
||||||
[Dish.BIG_NUMBER]: () =>
|
[Dish.BIG_NUMBER]: () => Promise.resolve(DishBigNumber.toArrayBuffer.bind(this)()),
|
||||||
Promise.resolve(DishBigNumber.toArrayBuffer.bind(this)()),
|
[Dish.JSON]: () => Promise.resolve(DishJSON.toArrayBuffer.bind(this)()),
|
||||||
[Dish.JSON]: () =>
|
|
||||||
Promise.resolve(DishJSON.toArrayBuffer.bind(this)()),
|
|
||||||
[Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(),
|
[Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(),
|
||||||
[Dish.LIST_FILE]: () =>
|
[Dish.LIST_FILE]: () => Promise.resolve(DishListFile.toArrayBuffer.bind(this)()),
|
||||||
Promise.resolve(DishListFile.toArrayBuffer.bind(this)()),
|
[Dish.BYTE_ARRAY]: () => Promise.resolve(DishByteArray.toArrayBuffer.bind(this)()),
|
||||||
[Dish.BYTE_ARRAY]: () =>
|
|
||||||
Promise.resolve(DishByteArray.toArrayBuffer.bind(this)()),
|
|
||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
[Dish.STRING]: () => DishString.toArrayBuffer.bind(this)(),
|
[Dish.STRING]: () => DishString.toArrayBuffer.bind(this)(),
|
||||||
[Dish.NUMBER]: () => DishNumber.toArrayBuffer.bind(this)(),
|
[Dish.NUMBER]: () => DishNumber.toArrayBuffer.bind(this)(),
|
||||||
[Dish.HTML]: () => DishHTML.toArrayBuffer.bind(this)(),
|
[Dish.HTML]: () => DishHTML.toArrayBuffer.bind(this)(),
|
||||||
[Dish.ARRAY_BUFFER]: () => {},
|
[Dish.ARRAY_BUFFER]: () => {},
|
||||||
[Dish.BIG_NUMBER]: () =>
|
[Dish.BIG_NUMBER]: () => DishBigNumber.toArrayBuffer.bind(this)(),
|
||||||
DishBigNumber.toArrayBuffer.bind(this)(),
|
|
||||||
[Dish.JSON]: () => DishJSON.toArrayBuffer.bind(this)(),
|
[Dish.JSON]: () => DishJSON.toArrayBuffer.bind(this)(),
|
||||||
[Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(),
|
[Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(),
|
||||||
[Dish.LIST_FILE]: () => DishListFile.toArrayBuffer.bind(this)(),
|
[Dish.LIST_FILE]: () => DishListFile.toArrayBuffer.bind(this)(),
|
||||||
[Dish.BYTE_ARRAY]: () =>
|
[Dish.BYTE_ARRAY]: () => DishByteArray.toArrayBuffer.bind(this)(),
|
||||||
DishByteArray.toArrayBuffer.bind(this)(),
|
}
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return toByteArrayFuncs[
|
return toByteArrayFuncs[isNodeEnvironment() && "node" || "browser"][this.type]();
|
||||||
(isNodeEnvironment() && "node") || "browser"
|
|
||||||
][this.type]();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new DishError(
|
throw new DishError(`Error translating from ${Dish.enumLookup(this.type)} to ArrayBuffer: ${err}`);
|
||||||
`Error translating from ${Dish.enumLookup(
|
|
||||||
this.type,
|
|
||||||
)} to ArrayBuffer: ${err}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +485,7 @@ class Dish {
|
||||||
* @param {number} toType - the Dish enum to convert to
|
* @param {number} toType - the Dish enum to convert to
|
||||||
*/
|
*/
|
||||||
_fromArrayBuffer(toType) {
|
_fromArrayBuffer(toType) {
|
||||||
|
|
||||||
// Using 'bind' here to allow this.value to be mutated within translation functions
|
// Using 'bind' here to allow this.value to be mutated within translation functions
|
||||||
const toTypeFunctions = {
|
const toTypeFunctions = {
|
||||||
[Dish.STRING]: () => DishString.fromArrayBuffer.bind(this)(),
|
[Dish.STRING]: () => DishString.fromArrayBuffer.bind(this)(),
|
||||||
|
@ -527,15 +503,13 @@ class Dish {
|
||||||
toTypeFunctions[toType]();
|
toTypeFunctions[toType]();
|
||||||
this.type = toType;
|
this.type = toType;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new DishError(
|
throw new DishError(`Error translating from ArrayBuffer to ${Dish.enumLookup(toType)}: ${err}`);
|
||||||
`Error translating from ArrayBuffer to ${Dish.enumLookup(
|
|
||||||
toType,
|
|
||||||
)}: ${err}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dish data type enum for byte arrays.
|
* Dish data type enum for byte arrays.
|
||||||
* @readonly
|
* @readonly
|
||||||
|
@ -585,10 +559,11 @@ Dish.JSON = 6;
|
||||||
*/
|
*/
|
||||||
Dish.FILE = 7;
|
Dish.FILE = 7;
|
||||||
/**
|
/**
|
||||||
* Dish data type enum for lists of files.
|
* Dish data type enum for lists of files.
|
||||||
* @readonly
|
* @readonly
|
||||||
* @enum
|
* @enum
|
||||||
*/
|
*/
|
||||||
Dish.LIST_FILE = 8;
|
Dish.LIST_FILE = 8;
|
||||||
|
|
||||||
|
|
||||||
export default Dish;
|
export default Dish;
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Utils from "./Utils.mjs";
|
import Utils from "./Utils.mjs";
|
||||||
import { fromHex } from "./lib/Hex.mjs";
|
import {fromHex} from "./lib/Hex.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The arguments to operations.
|
* The arguments to operations.
|
||||||
*/
|
*/
|
||||||
class Ingredient {
|
class Ingredient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ingredient constructor
|
* Ingredient constructor
|
||||||
*
|
*
|
||||||
|
@ -36,6 +37,7 @@ class Ingredient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and parses the given config.
|
* Reads and parses the given config.
|
||||||
*
|
*
|
||||||
|
@ -50,20 +52,15 @@ class Ingredient {
|
||||||
this.hint = ingredientConfig.hint || false;
|
this.hint = ingredientConfig.hint || false;
|
||||||
this.rows = ingredientConfig.rows || false;
|
this.rows = ingredientConfig.rows || false;
|
||||||
this.toggleValues = ingredientConfig.toggleValues;
|
this.toggleValues = ingredientConfig.toggleValues;
|
||||||
this.target =
|
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
||||||
typeof ingredientConfig.target !== "undefined"
|
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
||||||
? ingredientConfig.target
|
|
||||||
: null;
|
|
||||||
this.defaultIndex =
|
|
||||||
typeof ingredientConfig.defaultIndex !== "undefined"
|
|
||||||
? ingredientConfig.defaultIndex
|
|
||||||
: 0;
|
|
||||||
this.maxLength = ingredientConfig.maxLength || null;
|
this.maxLength = ingredientConfig.maxLength || null;
|
||||||
this.min = ingredientConfig.min;
|
this.min = ingredientConfig.min;
|
||||||
this.max = ingredientConfig.max;
|
this.max = ingredientConfig.max;
|
||||||
this.step = ingredientConfig.step;
|
this.step = ingredientConfig.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the Ingredient as it should be displayed in a recipe config.
|
* Returns the value of the Ingredient as it should be displayed in a recipe config.
|
||||||
*
|
*
|
||||||
|
@ -73,6 +70,7 @@ class Ingredient {
|
||||||
return this._value;
|
return this._value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the Ingredient.
|
* Sets the value of the Ingredient.
|
||||||
*
|
*
|
||||||
|
@ -82,6 +80,7 @@ class Ingredient {
|
||||||
this._value = Ingredient.prepare(value, this.type);
|
this._value = Ingredient.prepare(value, this.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the Ingredient.
|
* Gets the value of the Ingredient.
|
||||||
*
|
*
|
||||||
|
@ -91,6 +90,7 @@ class Ingredient {
|
||||||
return this._value;
|
return this._value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Most values will be strings when they are entered. This function converts them to the correct
|
* Most values will be strings when they are entered. This function converts them to the correct
|
||||||
* type.
|
* type.
|
||||||
|
@ -126,6 +126,7 @@ class Ingredient {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Ingredient;
|
export default Ingredient;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Ingredient from "./Ingredient.mjs";
|
||||||
* The Operation specified by the user to be run.
|
* The Operation specified by the user to be run.
|
||||||
*/
|
*/
|
||||||
class Operation {
|
class Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation constructor
|
* Operation constructor
|
||||||
*/
|
*/
|
||||||
|
@ -32,6 +33,7 @@ class Operation {
|
||||||
this.infoURL = null;
|
this.infoURL = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for operation runner
|
* Interface for operation runner
|
||||||
*
|
*
|
||||||
|
@ -43,6 +45,7 @@ class Operation {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for forward highlighter
|
* Interface for forward highlighter
|
||||||
*
|
*
|
||||||
|
@ -56,6 +59,7 @@ class Operation {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for reverse highlighter
|
* Interface for reverse highlighter
|
||||||
*
|
*
|
||||||
|
@ -69,6 +73,7 @@ class Operation {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to be called when displaying the result of an operation in a human-readable
|
* Method to be called when displaying the result of an operation in a human-readable
|
||||||
* format. This allows operations to return usable data from their run() method and
|
* format. This allows operations to return usable data from their run() method and
|
||||||
|
@ -85,6 +90,7 @@ class Operation {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the input type as a Dish enum.
|
* Sets the input type as a Dish enum.
|
||||||
*
|
*
|
||||||
|
@ -94,6 +100,7 @@ class Operation {
|
||||||
this._inputType = Dish.typeEnum(typeStr);
|
this._inputType = Dish.typeEnum(typeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the input type as a readable string.
|
* Gets the input type as a readable string.
|
||||||
*
|
*
|
||||||
|
@ -103,6 +110,7 @@ class Operation {
|
||||||
return Dish.enumLookup(this._inputType);
|
return Dish.enumLookup(this._inputType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the output type as a Dish enum.
|
* Sets the output type as a Dish enum.
|
||||||
*
|
*
|
||||||
|
@ -113,6 +121,7 @@ class Operation {
|
||||||
if (this._presentType < 0) this._presentType = this._outputType;
|
if (this._presentType < 0) this._presentType = this._outputType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the output type as a readable string.
|
* Gets the output type as a readable string.
|
||||||
*
|
*
|
||||||
|
@ -122,6 +131,7 @@ class Operation {
|
||||||
return Dish.enumLookup(this._outputType);
|
return Dish.enumLookup(this._outputType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the presentation type as a Dish enum.
|
* Sets the presentation type as a Dish enum.
|
||||||
*
|
*
|
||||||
|
@ -131,6 +141,7 @@ class Operation {
|
||||||
this._presentType = Dish.typeEnum(typeStr);
|
this._presentType = Dish.typeEnum(typeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the presentation type as a readable string.
|
* Gets the presentation type as a readable string.
|
||||||
*
|
*
|
||||||
|
@ -140,29 +151,31 @@ class Operation {
|
||||||
return Dish.enumLookup(this._presentType);
|
return Dish.enumLookup(this._presentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the args for the current operation.
|
* Sets the args for the current operation.
|
||||||
*
|
*
|
||||||
* @param {Object[]} conf
|
* @param {Object[]} conf
|
||||||
*/
|
*/
|
||||||
set args(conf) {
|
set args(conf) {
|
||||||
conf.forEach((arg) => {
|
conf.forEach(arg => {
|
||||||
const ingredient = new Ingredient(arg);
|
const ingredient = new Ingredient(arg);
|
||||||
this.addIngredient(ingredient);
|
this.addIngredient(ingredient);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the args for the current operation.
|
* Gets the args for the current operation.
|
||||||
*
|
*
|
||||||
* @param {Object[]} conf
|
* @param {Object[]} conf
|
||||||
*/
|
*/
|
||||||
get args() {
|
get args() {
|
||||||
return this._ingList.map((ing) => {
|
return this._ingList.map(ing => {
|
||||||
const conf = {
|
const conf = {
|
||||||
name: ing.name,
|
name: ing.name,
|
||||||
type: ing.type,
|
type: ing.type,
|
||||||
value: ing.defaultValue,
|
value: ing.defaultValue
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ing.toggleValues) conf.toggleValues = ing.toggleValues;
|
if (ing.toggleValues) conf.toggleValues = ing.toggleValues;
|
||||||
|
@ -179,6 +192,7 @@ class Operation {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the Operation as it should be displayed in a recipe config.
|
* Returns the value of the Operation as it should be displayed in a recipe config.
|
||||||
*
|
*
|
||||||
|
@ -186,11 +200,12 @@ class Operation {
|
||||||
*/
|
*/
|
||||||
get config() {
|
get config() {
|
||||||
return {
|
return {
|
||||||
op: this.name,
|
"op": this.name,
|
||||||
args: this._ingList.map((ing) => ing.config),
|
"args": this._ingList.map(ing => ing.config)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new Ingredient to this Operation.
|
* Adds a new Ingredient to this Operation.
|
||||||
*
|
*
|
||||||
|
@ -200,6 +215,7 @@ class Operation {
|
||||||
this._ingList.push(ingredient);
|
this._ingList.push(ingredient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the Ingredient values for this Operation.
|
* Set the Ingredient values for this Operation.
|
||||||
*
|
*
|
||||||
|
@ -211,15 +227,17 @@ class Operation {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Ingredient values for this Operation.
|
* Get the Ingredient values for this Operation.
|
||||||
*
|
*
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
get ingValues() {
|
get ingValues() {
|
||||||
return this._ingList.map((ing) => ing.value);
|
return this._ingList.map(ing => ing.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this Operation has a breakpoint.
|
* Set whether this Operation has a breakpoint.
|
||||||
*
|
*
|
||||||
|
@ -229,6 +247,7 @@ class Operation {
|
||||||
this._breakpoint = !!value;
|
this._breakpoint = !!value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Operation has a breakpoint set.
|
* Returns true if this Operation has a breakpoint set.
|
||||||
*
|
*
|
||||||
|
@ -238,6 +257,7 @@ class Operation {
|
||||||
return this._breakpoint;
|
return this._breakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this Operation is disabled.
|
* Set whether this Operation is disabled.
|
||||||
*
|
*
|
||||||
|
@ -247,6 +267,7 @@ class Operation {
|
||||||
this._disabled = !!value;
|
this._disabled = !!value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Operation is disabled.
|
* Returns true if this Operation is disabled.
|
||||||
*
|
*
|
||||||
|
@ -256,6 +277,7 @@ class Operation {
|
||||||
return this._disabled;
|
return this._disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Operation is a flow control.
|
* Returns true if this Operation is a flow control.
|
||||||
*
|
*
|
||||||
|
@ -265,6 +287,7 @@ class Operation {
|
||||||
return this._flowControl;
|
return this._flowControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this Operation is a flowcontrol op.
|
* Set whether this Operation is a flowcontrol op.
|
||||||
*
|
*
|
||||||
|
@ -274,6 +297,7 @@ class Operation {
|
||||||
this._flowControl = !!value;
|
this._flowControl = !!value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Operation should not trigger AutoBake.
|
* Returns true if this Operation should not trigger AutoBake.
|
||||||
*
|
*
|
||||||
|
@ -283,6 +307,7 @@ class Operation {
|
||||||
return this._manualBake;
|
return this._manualBake;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this Operation should trigger AutoBake.
|
* Set whether this Operation should trigger AutoBake.
|
||||||
*
|
*
|
||||||
|
@ -291,6 +316,7 @@ class Operation {
|
||||||
set manualBake(value) {
|
set manualBake(value) {
|
||||||
this._manualBake = !!value;
|
this._manualBake = !!value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Operation;
|
export default Operation;
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import OperationConfig from "./config/OperationConfig.json" assert {
|
import OperationConfig from "./config/OperationConfig.json" assert {type: "json"};
|
||||||
type: "json",
|
|
||||||
};
|
|
||||||
import OperationError from "./errors/OperationError.mjs";
|
import OperationError from "./errors/OperationError.mjs";
|
||||||
import Operation from "./Operation.mjs";
|
import Operation from "./Operation.mjs";
|
||||||
import DishError from "./errors/DishError.mjs";
|
import DishError from "./errors/DishError.mjs";
|
||||||
|
@ -20,6 +18,7 @@ let modules = null;
|
||||||
* The Recipe controls a list of Operations and the Dish they operate on.
|
* The Recipe controls a list of Operations and the Dish they operate on.
|
||||||
*/
|
*/
|
||||||
class Recipe {
|
class Recipe {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recipe constructor
|
* Recipe constructor
|
||||||
*
|
*
|
||||||
|
@ -33,6 +32,7 @@ class Recipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and parses the given config.
|
* Reads and parses the given config.
|
||||||
*
|
*
|
||||||
|
@ -40,7 +40,7 @@ class Recipe {
|
||||||
* @param {Object} recipeConfig
|
* @param {Object} recipeConfig
|
||||||
*/
|
*/
|
||||||
_parseConfig(recipeConfig) {
|
_parseConfig(recipeConfig) {
|
||||||
recipeConfig.forEach((c) => {
|
recipeConfig.forEach(c => {
|
||||||
this.opList.push({
|
this.opList.push({
|
||||||
name: c.op,
|
name: c.op,
|
||||||
module: OperationConfig[c.op].module,
|
module: OperationConfig[c.op].module,
|
||||||
|
@ -51,6 +51,7 @@ class Recipe {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate elements of opList with operation instances.
|
* Populate elements of opList with operation instances.
|
||||||
* Dynamic import here removes top-level cyclic dependency issue.
|
* Dynamic import here removes top-level cyclic dependency issue.
|
||||||
|
@ -61,13 +62,11 @@ class Recipe {
|
||||||
if (!modules) {
|
if (!modules) {
|
||||||
// Using Webpack Magic Comments to force the dynamic import to be included in the main chunk
|
// Using Webpack Magic Comments to force the dynamic import to be included in the main chunk
|
||||||
// https://webpack.js.org/api/module-methods/
|
// https://webpack.js.org/api/module-methods/
|
||||||
modules = await import(
|
modules = await import(/* webpackMode: "eager" */ "./config/modules/OpModules.mjs");
|
||||||
/* webpackMode: "eager" */ "./config/modules/OpModules.mjs"
|
|
||||||
);
|
|
||||||
modules = modules.default;
|
modules = modules.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.opList = this.opList.map((o) => {
|
this.opList = this.opList.map(o => {
|
||||||
if (o instanceof Operation) {
|
if (o instanceof Operation) {
|
||||||
return o;
|
return o;
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,18 +79,20 @@ class Recipe {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the Recipe as it should be displayed in a recipe config.
|
* Returns the value of the Recipe as it should be displayed in a recipe config.
|
||||||
*
|
*
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
get config() {
|
get config() {
|
||||||
return this.opList.map((op) => ({
|
return this.opList.map(op => ({
|
||||||
op: op.name,
|
op: op.name,
|
||||||
args: op.ingValues,
|
args: op.ingValues,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new Operation to this Recipe.
|
* Adds a new Operation to this Recipe.
|
||||||
*
|
*
|
||||||
|
@ -101,13 +102,14 @@ class Recipe {
|
||||||
this.opList.push(operation);
|
this.opList.push(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a list of Operations to this Recipe.
|
* Adds a list of Operations to this Recipe.
|
||||||
*
|
*
|
||||||
* @param {Operation[]} operations
|
* @param {Operation[]} operations
|
||||||
*/
|
*/
|
||||||
addOperations(operations) {
|
addOperations(operations) {
|
||||||
operations.forEach((o) => {
|
operations.forEach(o => {
|
||||||
if (o instanceof Operation) {
|
if (o instanceof Operation) {
|
||||||
this.opList.push(o);
|
this.opList.push(o);
|
||||||
} else {
|
} else {
|
||||||
|
@ -122,6 +124,7 @@ class Recipe {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a breakpoint on a specified Operation.
|
* Set a breakpoint on a specified Operation.
|
||||||
*
|
*
|
||||||
|
@ -136,6 +139,7 @@ class Recipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove breakpoints on all Operations in the Recipe up to the specified position. Used by Flow
|
* Remove breakpoints on all Operations in the Recipe up to the specified position. Used by Flow
|
||||||
* Control Fork operation.
|
* Control Fork operation.
|
||||||
|
@ -148,6 +152,7 @@ class Recipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there is a Flow Control Operation in this Recipe.
|
* Returns true if there is a Flow Control Operation in this Recipe.
|
||||||
*
|
*
|
||||||
|
@ -159,6 +164,7 @@ class Recipe {
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes each operation in the recipe over the given Dish.
|
* Executes each operation in the recipe over the given Dish.
|
||||||
*
|
*
|
||||||
|
@ -170,10 +176,8 @@ class Recipe {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
* - The final progress through the recipe
|
* - The final progress through the recipe
|
||||||
*/
|
*/
|
||||||
async execute(dish, startFrom = 0, forkState = {}) {
|
async execute(dish, startFrom=0, forkState={}) {
|
||||||
let op,
|
let op, input, output,
|
||||||
input,
|
|
||||||
output,
|
|
||||||
numJumps = 0,
|
numJumps = 0,
|
||||||
numRegisters = forkState.numRegisters || 0;
|
numRegisters = forkState.numRegisters || 0;
|
||||||
|
|
||||||
|
@ -181,9 +185,7 @@ class Recipe {
|
||||||
|
|
||||||
await this._hydrateOpList();
|
await this._hydrateOpList();
|
||||||
|
|
||||||
log.debug(
|
log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`);
|
||||||
`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let i = startFrom; i < this.opList.length; i++) {
|
for (let i = startFrom; i < this.opList.length; i++) {
|
||||||
op = this.opList[i];
|
op = this.opList[i];
|
||||||
|
@ -202,21 +204,19 @@ class Recipe {
|
||||||
log.debug(`Executing operation '${op.name}'`);
|
log.debug(`Executing operation '${op.name}'`);
|
||||||
|
|
||||||
if (isWorkerEnvironment()) {
|
if (isWorkerEnvironment()) {
|
||||||
self.sendStatusMessage(
|
self.sendStatusMessage(`Baking... (${i+1}/${this.opList.length})`);
|
||||||
`Baking... (${i + 1}/${this.opList.length})`,
|
|
||||||
);
|
|
||||||
self.sendProgressMessage(i + 1, this.opList.length);
|
self.sendProgressMessage(i + 1, this.opList.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op.flowControl) {
|
if (op.flowControl) {
|
||||||
// Package up the current state
|
// Package up the current state
|
||||||
let state = {
|
let state = {
|
||||||
progress: i,
|
"progress": i,
|
||||||
dish: dish,
|
"dish": dish,
|
||||||
opList: this.opList,
|
"opList": this.opList,
|
||||||
numJumps: numJumps,
|
"numJumps": numJumps,
|
||||||
numRegisters: numRegisters,
|
"numRegisters": numRegisters,
|
||||||
forkOffset: forkState.forkOffset || 0,
|
"forkOffset": forkState.forkOffset || 0
|
||||||
};
|
};
|
||||||
|
|
||||||
state = await op.run(state);
|
state = await op.run(state);
|
||||||
|
@ -230,18 +230,12 @@ class Recipe {
|
||||||
this.lastRunOp = op;
|
this.lastRunOp = op;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Return expected errors as output
|
// Return expected errors as output
|
||||||
if (
|
if (err instanceof OperationError || err?.type === "OperationError") {
|
||||||
err instanceof OperationError ||
|
|
||||||
err?.type === "OperationError"
|
|
||||||
) {
|
|
||||||
// Cannot rely on `err instanceof OperationError` here as extending
|
// Cannot rely on `err instanceof OperationError` here as extending
|
||||||
// native types is not fully supported yet.
|
// native types is not fully supported yet.
|
||||||
dish.set(err.message, "string");
|
dish.set(err.message, "string");
|
||||||
return i;
|
return i;
|
||||||
} else if (
|
} else if (err instanceof DishError || err?.type === "DishError") {
|
||||||
err instanceof DishError ||
|
|
||||||
err?.type === "DishError"
|
|
||||||
) {
|
|
||||||
dish.set(err.message, "string");
|
dish.set(err.message, "string");
|
||||||
return i;
|
return i;
|
||||||
} else {
|
} else {
|
||||||
|
@ -249,15 +243,10 @@ class Recipe {
|
||||||
|
|
||||||
e.progress = i;
|
e.progress = i;
|
||||||
if (e.fileName) {
|
if (e.fileName) {
|
||||||
e.displayStr =
|
e.displayStr = `${op.name} - ${e.name} in ${e.fileName} on line ` +
|
||||||
`${op.name} - ${e.name} in ${e.fileName} on line ` +
|
`${e.lineNumber}.<br><br>Message: ${e.displayStr || e.message}`;
|
||||||
`${e.lineNumber}.<br><br>Message: ${
|
|
||||||
e.displayStr || e.message
|
|
||||||
}`;
|
|
||||||
} else {
|
} else {
|
||||||
e.displayStr = `${op.name} - ${
|
e.displayStr = `${op.name} - ${e.displayStr || e.message}`;
|
||||||
e.displayStr || e.message
|
|
||||||
}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -269,6 +258,7 @@ class Recipe {
|
||||||
return this.opList.length;
|
return this.opList.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Present the results of the final operation.
|
* Present the results of the final operation.
|
||||||
*
|
*
|
||||||
|
@ -279,11 +269,12 @@ class Recipe {
|
||||||
|
|
||||||
const output = await this.lastRunOp.present(
|
const output = await this.lastRunOp.present(
|
||||||
await dish.get(this.lastRunOp.outputType),
|
await dish.get(this.lastRunOp.outputType),
|
||||||
this.lastRunOp.ingValues,
|
this.lastRunOp.ingValues
|
||||||
);
|
);
|
||||||
dish.set(output, this.lastRunOp.presentType);
|
dish.set(output, this.lastRunOp.presentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the recipe configuration in string format.
|
* Returns the recipe configuration in string format.
|
||||||
*
|
*
|
||||||
|
@ -293,6 +284,7 @@ class Recipe {
|
||||||
return JSON.stringify(this.config);
|
return JSON.stringify(this.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Recipe from a given configuration string.
|
* Creates a Recipe from a given configuration string.
|
||||||
*
|
*
|
||||||
|
@ -303,6 +295,7 @@ class Recipe {
|
||||||
this._parseConfig(recipeConfig);
|
this._parseConfig(recipeConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
|
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
|
||||||
* entire recipe supports highlighting.
|
* entire recipe supports highlighting.
|
||||||
|
@ -324,19 +317,19 @@ class Recipe {
|
||||||
if (op.breakpoint) return false;
|
if (op.breakpoint) return false;
|
||||||
|
|
||||||
// If any of the operations do not support highlighting, fail immediately.
|
// If any of the operations do not support highlighting, fail immediately.
|
||||||
if (op.highlight === false || op.highlight === undefined)
|
if (op.highlight === false || op.highlight === undefined) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
highlights.push({
|
highlights.push({
|
||||||
f: op.highlight,
|
f: op.highlight,
|
||||||
b: op.highlightReverse,
|
b: op.highlightReverse,
|
||||||
args: op.ingValues,
|
args: op.ingValues
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return highlights;
|
return highlights;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the previous operation has a different presentation type to its normal output.
|
* Determines whether the previous operation has a different presentation type to its normal output.
|
||||||
*
|
*
|
||||||
|
@ -345,11 +338,9 @@ class Recipe {
|
||||||
*/
|
*/
|
||||||
lastOpPresented(progress) {
|
lastOpPresented(progress) {
|
||||||
if (progress < 1) return false;
|
if (progress < 1) return false;
|
||||||
return (
|
return this.opList[progress-1].presentType !== this.opList[progress-1].outputType;
|
||||||
this.opList[progress - 1].presentType !==
|
|
||||||
this.opList[progress - 1].outputType
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Recipe;
|
export default Recipe;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,15 +19,12 @@ import * as Ops from "../../operations/index.mjs";
|
||||||
const dir = path.join(process.cwd() + "/src/core/config/");
|
const dir = path.join(process.cwd() + "/src/core/config/");
|
||||||
if (!fs.existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
console.log("\nCWD: " + process.cwd());
|
console.log("\nCWD: " + process.cwd());
|
||||||
console.log(
|
console.log("Error: generateConfig.mjs should be run from the project root");
|
||||||
"Error: generateConfig.mjs should be run from the project root",
|
console.log("Example> node --experimental-modules src/core/config/scripts/generateConfig.mjs");
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
"Example> node --experimental-modules src/core/config/scripts/generateConfig.mjs",
|
|
||||||
);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const operationConfig = {},
|
const operationConfig = {},
|
||||||
modules = {};
|
modules = {};
|
||||||
|
|
||||||
|
@ -46,22 +43,25 @@ for (const opObj in Ops) {
|
||||||
flowControl: op.flowControl,
|
flowControl: op.flowControl,
|
||||||
manualBake: op.manualBake,
|
manualBake: op.manualBake,
|
||||||
args: op.args,
|
args: op.args,
|
||||||
checks: op.checks,
|
checks: op.checks
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(op.module in modules)) modules[op.module] = {};
|
if (!(op.module in modules))
|
||||||
|
modules[op.module] = {};
|
||||||
modules[op.module][op.name] = opObj;
|
modules[op.module][op.name] = opObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write OperationConfig.
|
* Write OperationConfig.
|
||||||
*/
|
*/
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(dir, "OperationConfig.json"),
|
path.join(dir, "OperationConfig.json"),
|
||||||
JSON.stringify(operationConfig, null, 4),
|
JSON.stringify(operationConfig, null, 4)
|
||||||
);
|
);
|
||||||
console.log("Written OperationConfig.json");
|
console.log("Written OperationConfig.json");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write modules.
|
* Write modules.
|
||||||
*/
|
*/
|
||||||
|
@ -98,10 +98,14 @@ OpModules.${module} = {
|
||||||
|
|
||||||
export default OpModules;
|
export default OpModules;
|
||||||
`;
|
`;
|
||||||
fs.writeFileSync(path.join(dir, `modules/${module}.mjs`), code);
|
fs.writeFileSync(
|
||||||
|
path.join(dir, `modules/${module}.mjs`),
|
||||||
|
code
|
||||||
|
);
|
||||||
console.log(`Written ${module} module`);
|
console.log(`Written ${module} module`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write OpModules wrapper.
|
* Write OpModules wrapper.
|
||||||
*/
|
*/
|
||||||
|
@ -136,5 +140,8 @@ opModulesCode += `);
|
||||||
export default OpModules;
|
export default OpModules;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
fs.writeFileSync(path.join(dir, "modules/OpModules.mjs"), opModulesCode);
|
fs.writeFileSync(
|
||||||
|
path.join(dir, "modules/OpModules.mjs"),
|
||||||
|
opModulesCode
|
||||||
|
);
|
||||||
console.log("Written OpModules.mjs");
|
console.log("Written OpModules.mjs");
|
||||||
|
|
|
@ -16,18 +16,14 @@ import process from "process";
|
||||||
const dir = path.join(process.cwd() + "/src/core/config/");
|
const dir = path.join(process.cwd() + "/src/core/config/");
|
||||||
if (!fs.existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
console.log("\nCWD: " + process.cwd());
|
console.log("\nCWD: " + process.cwd());
|
||||||
console.log(
|
console.log("Error: generateOpsIndex.mjs should be run from the project root");
|
||||||
"Error: generateOpsIndex.mjs should be run from the project root",
|
console.log("Example> node --experimental-modules src/core/config/scripts/generateOpsIndex.mjs");
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
"Example> node --experimental-modules src/core/config/scripts/generateOpsIndex.mjs",
|
|
||||||
);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all operation files
|
// Find all operation files
|
||||||
const opObjs = [];
|
const opObjs = [];
|
||||||
fs.readdirSync(path.join(dir, "../operations")).forEach((file) => {
|
fs.readdirSync(path.join(dir, "../operations")).forEach(file => {
|
||||||
if (!file.endsWith(".mjs") || file === "index.mjs") return;
|
if (!file.endsWith(".mjs") || file === "index.mjs") return;
|
||||||
opObjs.push(file.split(".mjs")[0]);
|
opObjs.push(file.split(".mjs")[0]);
|
||||||
});
|
});
|
||||||
|
@ -42,7 +38,7 @@ let code = `/**
|
||||||
*/
|
*/
|
||||||
`;
|
`;
|
||||||
|
|
||||||
opObjs.forEach((obj) => {
|
opObjs.forEach(obj => {
|
||||||
code += `import ${obj} from "./${obj}.mjs";\n`;
|
code += `import ${obj} from "./${obj}.mjs";\n`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -50,12 +46,15 @@ code += `
|
||||||
export {
|
export {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
opObjs.forEach((obj) => {
|
opObjs.forEach(obj => {
|
||||||
code += ` ${obj},\n`;
|
code += ` ${obj},\n`;
|
||||||
});
|
});
|
||||||
|
|
||||||
code += "};\n";
|
code += "};\n";
|
||||||
|
|
||||||
// Write file
|
// Write file
|
||||||
fs.writeFileSync(path.join(dir, "../operations/index.mjs"), code);
|
fs.writeFileSync(
|
||||||
|
path.join(dir, "../operations/index.mjs"),
|
||||||
|
code
|
||||||
|
);
|
||||||
console.log("Written operation index.");
|
console.log("Written operation index.");
|
||||||
|
|
|
@ -17,56 +17,45 @@ import process from "process";
|
||||||
const dir = path.join(process.cwd() + "/src/core/config/");
|
const dir = path.join(process.cwd() + "/src/core/config/");
|
||||||
if (!fs.existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
console.log("\nCWD: " + process.cwd());
|
console.log("\nCWD: " + process.cwd());
|
||||||
console.log(
|
console.log("Error: newMinorVersion.mjs should be run from the project root");
|
||||||
"Error: newMinorVersion.mjs should be run from the project root",
|
console.log("Example> node --experimental-modules src/core/config/scripts/newMinorVersion.mjs");
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
"Example> node --experimental-modules src/core/config/scripts/newMinorVersion.mjs",
|
|
||||||
);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let changelogData = fs.readFileSync(
|
let changelogData = fs.readFileSync(path.join(process.cwd(), "CHANGELOG.md"), "utf8");
|
||||||
path.join(process.cwd(), "CHANGELOG.md"),
|
const lastVersion = changelogData.match(/## Details\s+### \[(\d+)\.(\d+)\.(\d+)\]/);
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
const lastVersion = changelogData.match(
|
|
||||||
/## Details\s+### \[(\d+)\.(\d+)\.(\d+)\]/,
|
|
||||||
);
|
|
||||||
const newVersion = [
|
const newVersion = [
|
||||||
parseInt(lastVersion[1], 10),
|
parseInt(lastVersion[1], 10),
|
||||||
parseInt(lastVersion[2], 10) + 1,
|
parseInt(lastVersion[2], 10) + 1,
|
||||||
0,
|
0
|
||||||
];
|
];
|
||||||
|
|
||||||
let knownContributors = changelogData.match(/^\[@([^\]]+)\]/gm);
|
let knownContributors = changelogData.match(/^\[@([^\]]+)\]/gm);
|
||||||
knownContributors = knownContributors.map((c) => c.slice(2, -1));
|
knownContributors = knownContributors.map(c => c.slice(2, -1));
|
||||||
|
|
||||||
const date = new Date().toISOString().split("T")[0];
|
const date = (new Date()).toISOString().split("T")[0];
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
properties: {
|
properties: {
|
||||||
message: {
|
message: {
|
||||||
description:
|
description: "A short but descriptive summary of a feature in this version",
|
||||||
"A short but descriptive summary of a feature in this version",
|
|
||||||
example: "Added 'Op name' operation",
|
example: "Added 'Op name' operation",
|
||||||
prompt: "Feature description",
|
prompt: "Feature description",
|
||||||
type: "string",
|
type: "string",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
author: {
|
author: {
|
||||||
description:
|
description: "The author of the feature (only one supported, edit manually to add more)",
|
||||||
"The author of the feature (only one supported, edit manually to add more)",
|
|
||||||
example: "n1474335",
|
example: "n1474335",
|
||||||
prompt: "Author",
|
prompt: "Author",
|
||||||
type: "string",
|
type: "string",
|
||||||
default: "n1474335",
|
default: "n1474335"
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
description: "The PR number or full commit hash for this feature.",
|
description: "The PR number or full commit hash for this feature.",
|
||||||
example: "1200",
|
example: "1200",
|
||||||
prompt: "Pull request or commit ID",
|
prompt: "Pull request or commit ID",
|
||||||
type: "string",
|
type: "string"
|
||||||
},
|
},
|
||||||
another: {
|
another: {
|
||||||
description: "y/n",
|
description: "y/n",
|
||||||
|
@ -74,19 +63,14 @@ const schema = {
|
||||||
prompt: "Add another feature?",
|
prompt: "Add another feature?",
|
||||||
type: "string",
|
type: "string",
|
||||||
pattern: /^[yn]$/,
|
pattern: /^[yn]$/,
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build schema
|
// Build schema
|
||||||
for (const prop in schema.properties) {
|
for (const prop in schema.properties) {
|
||||||
const p = schema.properties[prop];
|
const p = schema.properties[prop];
|
||||||
p.description =
|
p.description = "\n" + colors.white(p.description) + colors.cyan("\nExample: " + p.example) + "\n" + colors.green(p.prompt);
|
||||||
"\n" +
|
|
||||||
colors.white(p.description) +
|
|
||||||
colors.cyan("\nExample: " + p.example) +
|
|
||||||
"\n" +
|
|
||||||
colors.green(p.prompt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt.message = "";
|
prompt.message = "";
|
||||||
|
@ -99,7 +83,7 @@ const commitIDs = [];
|
||||||
|
|
||||||
prompt.start();
|
prompt.start();
|
||||||
|
|
||||||
const getFeature = function () {
|
const getFeature = function() {
|
||||||
prompt.get(schema, (err, result) => {
|
prompt.get(schema, (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("\nExiting script.");
|
console.log("\nExiting script.");
|
||||||
|
@ -113,75 +97,46 @@ const getFeature = function () {
|
||||||
} else {
|
} else {
|
||||||
let message = `### [${newVersion[0]}.${newVersion[1]}.${newVersion[2]}] - ${date}\n`;
|
let message = `### [${newVersion[0]}.${newVersion[1]}.${newVersion[2]}] - ${date}\n`;
|
||||||
|
|
||||||
features.forEach((feature) => {
|
features.forEach(feature => {
|
||||||
const id =
|
const id = feature.id.length > 10 ? feature.id.slice(0, 7) : "#" + feature.id;
|
||||||
feature.id.length > 10
|
|
||||||
? feature.id.slice(0, 7)
|
|
||||||
: "#" + feature.id;
|
|
||||||
message += `- ${feature.message} [@${feature.author}] | [${id}]\n`;
|
message += `- ${feature.message} [@${feature.author}] | [${id}]\n`;
|
||||||
|
|
||||||
if (!knownContributors.includes(feature.author)) {
|
if (!knownContributors.includes(feature.author)) {
|
||||||
authors.push(
|
authors.push(`[@${feature.author}]: https://github.com/${feature.author}`);
|
||||||
`[@${feature.author}]: https://github.com/${feature.author}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feature.id.length > 10) {
|
if (feature.id.length > 10) {
|
||||||
commitIDs.push(
|
commitIDs.push(`[${id}]: https://github.com/gchq/CyberChef/commit/${feature.id}`);
|
||||||
`[${id}]: https://github.com/gchq/CyberChef/commit/${feature.id}`,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
prIDs.push(
|
prIDs.push(`[#${feature.id}]: https://github.com/gchq/CyberChef/pull/${feature.id}`);
|
||||||
`[#${feature.id}]: https://github.com/gchq/CyberChef/pull/${feature.id}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Message
|
// Message
|
||||||
changelogData = changelogData.replace(
|
changelogData = changelogData.replace(/## Details\n\n/, "## Details\n\n" + message + "\n");
|
||||||
/## Details\n\n/,
|
|
||||||
"## Details\n\n" + message + "\n",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Tag
|
// Tag
|
||||||
const newTag = `[${newVersion[0]}.${newVersion[1]}.${newVersion[2]}]: https://github.com/gchq/CyberChef/releases/tag/v${newVersion[0]}.${newVersion[1]}.${newVersion[2]}\n`;
|
const newTag = `[${newVersion[0]}.${newVersion[1]}.${newVersion[2]}]: https://github.com/gchq/CyberChef/releases/tag/v${newVersion[0]}.${newVersion[1]}.${newVersion[2]}\n`;
|
||||||
changelogData = changelogData.replace(
|
changelogData = changelogData.replace(/\n\n(\[\d+\.\d+\.\d+\]: https)/, "\n\n" + newTag + "$1");
|
||||||
/\n\n(\[\d+\.\d+\.\d+\]: https)/,
|
|
||||||
"\n\n" + newTag + "$1",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Author
|
// Author
|
||||||
authors.forEach((author) => {
|
authors.forEach(author => {
|
||||||
changelogData = changelogData.replace(
|
changelogData = changelogData.replace(/(\n\[@[^\]]+\]: https:\/\/github\.com\/[^\n]+\n)\n/, "$1" + author + "\n\n");
|
||||||
/(\n\[@[^\]]+\]: https:\/\/github\.com\/[^\n]+\n)\n/,
|
|
||||||
"$1" + author + "\n\n",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Commit IDs
|
// Commit IDs
|
||||||
commitIDs.forEach((commitID) => {
|
commitIDs.forEach(commitID => {
|
||||||
changelogData = changelogData.replace(
|
changelogData = changelogData.replace(/(\n\[[^\].]+\]: https:\/\/github.com\/gchq\/CyberChef\/commit\/[^\n]+\n)\n/, "$1" + commitID + "\n\n");
|
||||||
/(\n\[[^\].]+\]: https:\/\/github.com\/gchq\/CyberChef\/commit\/[^\n]+\n)\n/,
|
|
||||||
"$1" + commitID + "\n\n",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// PR IDs
|
// PR IDs
|
||||||
prIDs.forEach((prID) => {
|
prIDs.forEach(prID => {
|
||||||
changelogData = changelogData.replace(
|
changelogData = changelogData.replace(/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/pull\/[^\n]+\n)\n*$/, "$1" + prID + "\n\n");
|
||||||
/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/pull\/[^\n]+\n)\n*$/,
|
|
||||||
"$1" + prID + "\n\n",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
||||||
path.join(process.cwd(), "CHANGELOG.md"),
|
|
||||||
changelogData,
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(
|
console.log("Written CHANGELOG.md\nCommit changes and then run `npm version minor`.");
|
||||||
"Written CHANGELOG.md\nCommit changes and then run `npm version minor`.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,27 +15,16 @@ import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import EscapeString from "../../operations/EscapeString.mjs";
|
import EscapeString from "../../operations/EscapeString.mjs";
|
||||||
|
|
||||||
|
|
||||||
const dir = path.join(process.cwd() + "/src/core/operations/");
|
const dir = path.join(process.cwd() + "/src/core/operations/");
|
||||||
if (!fs.existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
console.log("\nCWD: " + process.cwd());
|
console.log("\nCWD: " + process.cwd());
|
||||||
console.log("Error: newOperation.mjs should be run from the project root");
|
console.log("Error: newOperation.mjs should be run from the project root");
|
||||||
console.log(
|
console.log("Example> node --experimental-modules src/core/config/scripts/newOperation.mjs");
|
||||||
"Example> node --experimental-modules src/core/config/scripts/newOperation.mjs",
|
|
||||||
);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ioTypes = [
|
const ioTypes = ["string", "byteArray", "number", "html", "ArrayBuffer", "BigNumber", "JSON", "File", "List<File>"];
|
||||||
"string",
|
|
||||||
"byteArray",
|
|
||||||
"number",
|
|
||||||
"html",
|
|
||||||
"ArrayBuffer",
|
|
||||||
"BigNumber",
|
|
||||||
"JSON",
|
|
||||||
"File",
|
|
||||||
"List<File>",
|
|
||||||
];
|
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -46,8 +35,7 @@ const schema = {
|
||||||
type: "string",
|
type: "string",
|
||||||
pattern: /^[\w\s-/().]+$/,
|
pattern: /^[\w\s-/().]+$/,
|
||||||
required: true,
|
required: true,
|
||||||
message:
|
message: "Operation names should consist of letters, numbers or the following symbols: _-/()."
|
||||||
"Operation names should consist of letters, numbers or the following symbols: _-/().",
|
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
description: `Modules are used to group operations that rely on large libraries. Any operation that is not in the Default module will be loaded in dynamically when it is first called. All operations in the same module will also be loaded at this time. This system prevents the CyberChef web app from getting too bloated and taking a long time to load initially.
|
description: `Modules are used to group operations that rely on large libraries. Any operation that is not in the Default module will be loaded in dynamically when it is first called. All operations in the same module will also be loaded at this time. This system prevents the CyberChef web app from getting too bloated and taking a long time to load initially.
|
||||||
|
@ -56,89 +44,69 @@ If your operation does not rely on a library, just leave this blank and it will
|
||||||
prompt: "Module",
|
prompt: "Module",
|
||||||
type: "string",
|
type: "string",
|
||||||
pattern: /^[A-Z][A-Za-z\d]+$/,
|
pattern: /^[A-Z][A-Za-z\d]+$/,
|
||||||
message:
|
message: "Module names should start with a capital letter and not contain any spaces or symbols.",
|
||||||
"Module names should start with a capital letter and not contain any spaces or symbols.",
|
default: "Default"
|
||||||
default: "Default",
|
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
description:
|
description: "The description should explain what the operation is and how it works. It can describe how the arguments should be entered and give examples of expected input and output. HTML markup is supported. Use <code> tags for examples. The description is scanned during searches, so include terms that are likely to be searched for when someone is looking for your operation.",
|
||||||
"The description should explain what the operation is and how it works. It can describe how the arguments should be entered and give examples of expected input and output. HTML markup is supported. Use <code> tags for examples. The description is scanned during searches, so include terms that are likely to be searched for when someone is looking for your operation.",
|
example: "Converts URI/URL percent-encoded characters back to their raw values.<br><br>e.g. <code>%3d</code> becomes <code>=</code>",
|
||||||
example:
|
|
||||||
"Converts URI/URL percent-encoded characters back to their raw values.<br><br>e.g. <code>%3d</code> becomes <code>=</code>",
|
|
||||||
prompt: "Description",
|
prompt: "Description",
|
||||||
type: "string",
|
type: "string"
|
||||||
},
|
},
|
||||||
infoURL: {
|
infoURL: {
|
||||||
description:
|
description: "An optional URL for an external site can be added to give more information about the operation. Wikipedia links are often suitable. If linking to Wikipedia, use an international link (e.g. https://wikipedia.org/...) rather than a localised link (e.g. https://en.wikipedia.org/...).",
|
||||||
"An optional URL for an external site can be added to give more information about the operation. Wikipedia links are often suitable. If linking to Wikipedia, use an international link (e.g. https://wikipedia.org/...) rather than a localised link (e.g. https://en.wikipedia.org/...).",
|
|
||||||
example: "https://wikipedia.org/wiki/Percent-encoding",
|
example: "https://wikipedia.org/wiki/Percent-encoding",
|
||||||
prompt: "Information URL",
|
prompt: "Information URL",
|
||||||
type: "string",
|
type: "string",
|
||||||
},
|
},
|
||||||
inputType: {
|
inputType: {
|
||||||
description: `The input type defines how the input data will be presented to your operation. Check the project wiki for a full description of each type. The options are: ${ioTypes.join(
|
description: `The input type defines how the input data will be presented to your operation. Check the project wiki for a full description of each type. The options are: ${ioTypes.join(", ")}.`,
|
||||||
", ",
|
|
||||||
)}.`,
|
|
||||||
example: "string",
|
example: "string",
|
||||||
prompt: "Input type",
|
prompt: "Input type",
|
||||||
type: "string",
|
type: "string",
|
||||||
pattern: new RegExp(`^(${ioTypes.join("|")})$`),
|
pattern: new RegExp(`^(${ioTypes.join("|")})$`),
|
||||||
required: true,
|
required: true,
|
||||||
message: `The input type should be one of: ${ioTypes.join(", ")}.`,
|
message: `The input type should be one of: ${ioTypes.join(", ")}.`
|
||||||
},
|
},
|
||||||
outputType: {
|
outputType: {
|
||||||
description: `The output type tells CyberChef what sort of data you are returning from your operation. Check the project wiki for a full description of each type. The options are: ${ioTypes.join(
|
description: `The output type tells CyberChef what sort of data you are returning from your operation. Check the project wiki for a full description of each type. The options are: ${ioTypes.join(", ")}.`,
|
||||||
", ",
|
|
||||||
)}.`,
|
|
||||||
example: "string",
|
example: "string",
|
||||||
prompt: "Output type",
|
prompt: "Output type",
|
||||||
type: "string",
|
type: "string",
|
||||||
pattern: new RegExp(`^(${ioTypes.join("|")})$`),
|
pattern: new RegExp(`^(${ioTypes.join("|")})$`),
|
||||||
required: true,
|
required: true,
|
||||||
message: `The output type should be one of: ${ioTypes.join(", ")}.`,
|
message: `The output type should be one of: ${ioTypes.join(", ")}.`
|
||||||
},
|
},
|
||||||
highlight: {
|
highlight: {
|
||||||
description:
|
description: "If your operation does not change the length of the input in any way, we can enable highlighting. If it does change the length in a predictable way, we may still be able to enable highlighting and calculate the correct offsets. If this is not possible, we will disable highlighting for this operation.",
|
||||||
"If your operation does not change the length of the input in any way, we can enable highlighting. If it does change the length in a predictable way, we may still be able to enable highlighting and calculate the correct offsets. If this is not possible, we will disable highlighting for this operation.",
|
|
||||||
example: "true/false",
|
example: "true/false",
|
||||||
prompt: "Enable highlighting",
|
prompt: "Enable highlighting",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
default: "false",
|
default: "false",
|
||||||
message:
|
message: "Enter true or false to specify if highlighting should be enabled."
|
||||||
"Enter true or false to specify if highlighting should be enabled.",
|
|
||||||
},
|
},
|
||||||
authorName: {
|
authorName: {
|
||||||
description:
|
description: "Your name or username will be added to the @author tag for this operation.",
|
||||||
"Your name or username will be added to the @author tag for this operation.",
|
|
||||||
example: "n1474335",
|
example: "n1474335",
|
||||||
prompt: "Username",
|
prompt: "Username",
|
||||||
type: "string",
|
type: "string"
|
||||||
},
|
},
|
||||||
authorEmail: {
|
authorEmail: {
|
||||||
description:
|
description: "Your email address will also be added to the @author tag for this operation.",
|
||||||
"Your email address will also be added to the @author tag for this operation.",
|
|
||||||
example: "n1474335@gmail.com",
|
example: "n1474335@gmail.com",
|
||||||
prompt: "Email",
|
prompt: "Email",
|
||||||
type: "string",
|
type: "string"
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build schema
|
// Build schema
|
||||||
for (const prop in schema.properties) {
|
for (const prop in schema.properties) {
|
||||||
const p = schema.properties[prop];
|
const p = schema.properties[prop];
|
||||||
p.description =
|
p.description = "\n" + colors.white(p.description) + colors.cyan("\nExample: " + p.example) + "\n" + colors.green(p.prompt);
|
||||||
"\n" +
|
|
||||||
colors.white(p.description) +
|
|
||||||
colors.cyan("\nExample: " + p.example) +
|
|
||||||
"\n" +
|
|
||||||
colors.green(p.prompt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log("\n\nThis script will generate a new operation template based on the information you provide. These values can be changed manually later.".yellow);
|
||||||
"\n\nThis script will generate a new operation template based on the information you provide. These values can be changed manually later."
|
|
||||||
.yellow,
|
|
||||||
);
|
|
||||||
|
|
||||||
prompt.message = "";
|
prompt.message = "";
|
||||||
prompt.delimiter = ":".green;
|
prompt.delimiter = ":".green;
|
||||||
|
@ -151,15 +119,14 @@ prompt.get(schema, (err, result) => {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleName = result.opName
|
const moduleName = result.opName.replace(/\w\S*/g, txt => {
|
||||||
.replace(/\w\S*/g, (txt) => {
|
|
||||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||||
})
|
}).replace(/[\s-()./]/g, "");
|
||||||
.replace(/[\s-()./]/g, "");
|
|
||||||
|
|
||||||
const template = `/**
|
const template = `/**
|
||||||
* @author ${result.authorName} [${result.authorEmail}]
|
* @author ${result.authorName} [${result.authorEmail}]
|
||||||
* @copyright Crown Copyright ${new Date().getFullYear()}
|
* @copyright Crown Copyright ${(new Date()).getFullYear()}
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -179,10 +146,7 @@ class ${moduleName} extends Operation {
|
||||||
|
|
||||||
this.name = "${result.opName}";
|
this.name = "${result.opName}";
|
||||||
this.module = "${result.module}";
|
this.module = "${result.module}";
|
||||||
this.description = "${new EscapeString().run(result.description, [
|
this.description = "${(new EscapeString).run(result.description, ["Special chars", "Double"])}";
|
||||||
"Special chars",
|
|
||||||
"Double",
|
|
||||||
])}";
|
|
||||||
this.infoURL = "${result.infoURL}";
|
this.infoURL = "${result.infoURL}";
|
||||||
this.inputType = "${result.inputType}";
|
this.inputType = "${result.inputType}";
|
||||||
this.outputType = "${result.outputType}";
|
this.outputType = "${result.outputType}";
|
||||||
|
@ -212,9 +176,7 @@ class ${moduleName} extends Operation {
|
||||||
|
|
||||||
throw new OperationError("Test");
|
throw new OperationError("Test");
|
||||||
}
|
}
|
||||||
${
|
${result.highlight ? `
|
||||||
result.highlight
|
|
||||||
? `
|
|
||||||
/**
|
/**
|
||||||
* Highlight ${result.opName}
|
* Highlight ${result.opName}
|
||||||
*
|
*
|
||||||
|
@ -240,9 +202,7 @@ ${
|
||||||
highlightReverse(pos, args) {
|
highlightReverse(pos, args) {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
`
|
` : ""}
|
||||||
: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ${moduleName};
|
export default ${moduleName};
|
||||||
|
@ -252,9 +212,7 @@ export default ${moduleName};
|
||||||
|
|
||||||
const filename = path.join(dir, `./${moduleName}.mjs`);
|
const filename = path.join(dir, `./${moduleName}.mjs`);
|
||||||
if (fs.existsSync(filename)) {
|
if (fs.existsSync(filename)) {
|
||||||
console.log(
|
console.log(`${filename} already exists. It has NOT been overwritten.`.red);
|
||||||
`${filename} already exists. It has NOT been overwritten.`.red,
|
|
||||||
);
|
|
||||||
console.log("Choose a different operation name to avoid conflicts.");
|
console.log("Choose a different operation name to avoid conflicts.");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
@ -267,4 +225,6 @@ export default ${moduleName};
|
||||||
3. Write tests in ${colors.green("tests/operations/tests/")}
|
3. Write tests in ${colors.green("tests/operations/tests/")}
|
||||||
4. Run ${colors.cyan("npm run lint")} and ${colors.cyan("npm run test")}
|
4. Run ${colors.cyan("npm run lint")} and ${colors.cyan("npm run test")}
|
||||||
5. Submit a Pull Request to get your operation added to the official CyberChef repository.`);
|
5. Submit a Pull Request to get your operation added to the official CyberChef repository.`);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,15 +12,14 @@ import BigNumber from "bignumber.js";
|
||||||
* translation methods for BigNumber Dishes
|
* translation methods for BigNumber Dishes
|
||||||
*/
|
*/
|
||||||
class DishBigNumber extends DishType {
|
class DishBigNumber extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
* @param {BigNumber} value
|
* @param {BigNumber} value
|
||||||
*/
|
*/
|
||||||
static toArrayBuffer() {
|
static toArrayBuffer() {
|
||||||
DishBigNumber.checkForValue(this.value);
|
DishBigNumber.checkForValue(this.value);
|
||||||
this.value = BigNumber.isBigNumber(this.value)
|
this.value = BigNumber.isBigNumber(this.value) ? Utils.strToArrayBuffer(this.value.toFixed()) : new ArrayBuffer;
|
||||||
? Utils.strToArrayBuffer(this.value.toFixed())
|
|
||||||
: new ArrayBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,6 +10,7 @@ import DishType from "./DishType.mjs";
|
||||||
* Translation methods for ArrayBuffer Dishes
|
* Translation methods for ArrayBuffer Dishes
|
||||||
*/
|
*/
|
||||||
class DishByteArray extends DishType {
|
class DishByteArray extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Utils, { isNodeEnvironment } from "../Utils.mjs";
|
||||||
* Translation methods for file Dishes
|
* Translation methods for file Dishes
|
||||||
*/
|
*/
|
||||||
class DishFile extends DishType {
|
class DishFile extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to an ArrayBuffer
|
* convert the given value to an ArrayBuffer
|
||||||
* @param {File} value
|
* @param {File} value
|
||||||
|
@ -22,7 +23,7 @@ class DishFile extends DishType {
|
||||||
} else {
|
} else {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Utils.readFile(this.value)
|
Utils.readFile(this.value)
|
||||||
.then((v) => (this.value = v.buffer))
|
.then(v => this.value = v.buffer)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,18 +11,16 @@ import Utils from "../Utils.mjs";
|
||||||
* Translation methods for HTML Dishes
|
* Translation methods for HTML Dishes
|
||||||
*/
|
*/
|
||||||
class DishHTML extends DishString {
|
class DishHTML extends DishString {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
* @param {String} value
|
* @param {String} value
|
||||||
*/
|
*/
|
||||||
static toArrayBuffer() {
|
static toArrayBuffer() {
|
||||||
DishHTML.checkForValue(this.value);
|
DishHTML.checkForValue(this.value);
|
||||||
this.value = this.value
|
this.value = this.value ? Utils.strToArrayBuffer(Utils.unescapeHtml(Utils.stripHtmlTags(this.value, true))) : new ArrayBuffer;
|
||||||
? Utils.strToArrayBuffer(
|
|
||||||
Utils.unescapeHtml(Utils.stripHtmlTags(this.value, true)),
|
|
||||||
)
|
|
||||||
: new ArrayBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DishHTML;
|
export default DishHTML;
|
||||||
|
|
|
@ -11,15 +11,13 @@ import Utils from "../Utils.mjs";
|
||||||
* Translation methods for JSON dishes
|
* Translation methods for JSON dishes
|
||||||
*/
|
*/
|
||||||
class DishJSON extends DishType {
|
class DishJSON extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
*/
|
*/
|
||||||
static toArrayBuffer() {
|
static toArrayBuffer() {
|
||||||
DishJSON.checkForValue(this.value);
|
DishJSON.checkForValue(this.value);
|
||||||
this.value =
|
this.value = this.value !== undefined ? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4)) : new ArrayBuffer;
|
||||||
this.value !== undefined
|
|
||||||
? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4))
|
|
||||||
: new ArrayBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
import DishType from "./DishType.mjs";
|
import DishType from "./DishType.mjs";
|
||||||
import Utils, { isNodeEnvironment } from "../Utils.mjs";
|
import Utils, { isNodeEnvironment } from "../Utils.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translation methods for ListFile Dishes
|
* Translation methods for ListFile Dishes
|
||||||
*/
|
*/
|
||||||
class DishListFile extends DishType {
|
class DishListFile extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
*/
|
*/
|
||||||
|
@ -18,12 +20,9 @@ class DishListFile extends DishType {
|
||||||
DishListFile.checkForValue(this.value);
|
DishListFile.checkForValue(this.value);
|
||||||
|
|
||||||
if (isNodeEnvironment()) {
|
if (isNodeEnvironment()) {
|
||||||
this.value = this.value.map((file) => Uint8Array.from(file.data));
|
this.value = this.value.map(file => Uint8Array.from(file.data));
|
||||||
} else {
|
} else {
|
||||||
this.value =
|
this.value = await DishListFile.concatenateTypedArraysWithTypedElements(...this.value);
|
||||||
await DishListFile.concatenateTypedArraysWithTypedElements(
|
|
||||||
...this.value,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import DishType from "./DishType.mjs";
|
import DishType from "./DishType.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
|
@ -11,15 +12,13 @@ import Utils from "../Utils.mjs";
|
||||||
* Translation methods for number dishes
|
* Translation methods for number dishes
|
||||||
*/
|
*/
|
||||||
class DishNumber extends DishType {
|
class DishNumber extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
*/
|
*/
|
||||||
static toArrayBuffer() {
|
static toArrayBuffer() {
|
||||||
DishNumber.checkForValue(this.value);
|
DishNumber.checkForValue(this.value);
|
||||||
this.value =
|
this.value = typeof this.value === "number" ? Utils.strToArrayBuffer(this.value.toString()) : new ArrayBuffer;
|
||||||
typeof this.value === "number"
|
|
||||||
? Utils.strToArrayBuffer(this.value.toString())
|
|
||||||
: new ArrayBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,9 +26,7 @@ class DishNumber extends DishType {
|
||||||
*/
|
*/
|
||||||
static fromArrayBuffer() {
|
static fromArrayBuffer() {
|
||||||
DishNumber.checkForValue(this.value);
|
DishNumber.checkForValue(this.value);
|
||||||
this.value = this.value
|
this.value = this.value ? parseFloat(Utils.arrayBufferToStr(this.value)) : 0;
|
||||||
? parseFloat(Utils.arrayBufferToStr(this.value))
|
|
||||||
: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import DishType from "./DishType.mjs";
|
import DishType from "./DishType.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
|
@ -11,14 +12,13 @@ import Utils from "../Utils.mjs";
|
||||||
* Translation methods for string dishes
|
* Translation methods for string dishes
|
||||||
*/
|
*/
|
||||||
class DishString extends DishType {
|
class DishString extends DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert the given value to a ArrayBuffer
|
* convert the given value to a ArrayBuffer
|
||||||
*/
|
*/
|
||||||
static toArrayBuffer() {
|
static toArrayBuffer() {
|
||||||
DishString.checkForValue(this.value);
|
DishString.checkForValue(this.value);
|
||||||
this.value = this.value
|
this.value = this.value ? Utils.strToArrayBuffer(this.value) : new ArrayBuffer;
|
||||||
? Utils.strToArrayBuffer(this.value)
|
|
||||||
: new ArrayBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for dish translation methods
|
* Abstract class for dish translation methods
|
||||||
*/
|
*/
|
||||||
class DishType {
|
class DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Warn translations dont work without value from bind
|
* Warn translations dont work without value from bind
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import DishByteArray from "./DishByteArray.mjs";
|
import DishByteArray from "./DishByteArray.mjs";
|
||||||
import DishBigNumber from "./DishBigNumber.mjs";
|
import DishBigNumber from "./DishBigNumber.mjs";
|
||||||
import DishFile from "./DishFile.mjs";
|
import DishFile from "./DishFile.mjs";
|
||||||
|
|
|
@ -2,4 +2,8 @@ import OperationError from "./OperationError.mjs";
|
||||||
import DishError from "./DishError.mjs";
|
import DishError from "./DishError.mjs";
|
||||||
import ExcludedOperationError from "./ExcludedOperationError.mjs";
|
import ExcludedOperationError from "./ExcludedOperationError.mjs";
|
||||||
|
|
||||||
export { OperationError, DishError, ExcludedOperationError };
|
export {
|
||||||
|
OperationError,
|
||||||
|
DishError,
|
||||||
|
ExcludedOperationError,
|
||||||
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import BigNumber from "bignumber.js";
|
import BigNumber from "bignumber.js";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string array to a number array.
|
* Converts a string array to a number array.
|
||||||
*
|
*
|
||||||
|
@ -34,6 +35,7 @@ export function createNumArray(input, delim) {
|
||||||
return numbers;
|
return numbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an array of numbers and returns the value.
|
* Adds an array of numbers and returns the value.
|
||||||
*
|
*
|
||||||
|
@ -46,6 +48,7 @@ export function sum(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtracts an array of numbers and returns the value.
|
* Subtracts an array of numbers and returns the value.
|
||||||
*
|
*
|
||||||
|
@ -58,6 +61,7 @@ export function sub(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplies an array of numbers and returns the value.
|
* Multiplies an array of numbers and returns the value.
|
||||||
*
|
*
|
||||||
|
@ -70,6 +74,7 @@ export function multi(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divides an array of numbers and returns the value.
|
* Divides an array of numbers and returns the value.
|
||||||
*
|
*
|
||||||
|
@ -82,6 +87,7 @@ export function div(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes mean of a number array and returns the value.
|
* Computes mean of a number array and returns the value.
|
||||||
*
|
*
|
||||||
|
@ -94,6 +100,7 @@ export function mean(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes median of a number array and returns the value.
|
* Computes median of a number array and returns the value.
|
||||||
*
|
*
|
||||||
|
@ -101,8 +108,8 @@ export function mean(data) {
|
||||||
* @returns {BigNumber}
|
* @returns {BigNumber}
|
||||||
*/
|
*/
|
||||||
export function median(data) {
|
export function median(data) {
|
||||||
if (data.length % 2 === 0 && data.length > 0) {
|
if ((data.length % 2) === 0 && data.length > 0) {
|
||||||
data.sort(function (a, b) {
|
data.sort(function(a, b) {
|
||||||
return a.minus(b);
|
return a.minus(b);
|
||||||
});
|
});
|
||||||
const first = data[Math.floor(data.length / 2)];
|
const first = data[Math.floor(data.length / 2)];
|
||||||
|
@ -113,6 +120,7 @@ export function median(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes standard deviation of a number array and returns the value.
|
* Computes standard deviation of a number array and returns the value.
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,14 +12,11 @@
|
||||||
export const BACON_ALPHABETS = {
|
export const BACON_ALPHABETS = {
|
||||||
"Standard (I=J and U=V)": {
|
"Standard (I=J and U=V)": {
|
||||||
alphabet: "ABCDEFGHIKLMNOPQRSTUWXYZ",
|
alphabet: "ABCDEFGHIKLMNOPQRSTUWXYZ",
|
||||||
codes: [
|
codes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23]
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
|
||||||
19, 19, 20, 21, 22, 23,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Complete: {
|
|
||||||
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
||||||
},
|
},
|
||||||
|
"Complete": {
|
||||||
|
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
export const BACON_TRANSLATION_01 = "0/1";
|
export const BACON_TRANSLATION_01 = "0/1";
|
||||||
export const BACON_TRANSLATION_AB = "A/B";
|
export const BACON_TRANSLATION_AB = "A/B";
|
||||||
|
@ -33,7 +30,7 @@ export const BACON_TRANSLATIONS = [
|
||||||
];
|
];
|
||||||
export const BACON_TRANSLATIONS_FOR_ENCODING = [
|
export const BACON_TRANSLATIONS_FOR_ENCODING = [
|
||||||
BACON_TRANSLATION_01,
|
BACON_TRANSLATION_01,
|
||||||
BACON_TRANSLATION_AB,
|
BACON_TRANSLATION_AB
|
||||||
];
|
];
|
||||||
export const BACON_CLEARER_MAP = {
|
export const BACON_CLEARER_MAP = {
|
||||||
[BACON_TRANSLATION_01]: /[^01]/g,
|
[BACON_TRANSLATION_01]: /[^01]/g,
|
||||||
|
@ -42,10 +39,10 @@ export const BACON_CLEARER_MAP = {
|
||||||
};
|
};
|
||||||
export const BACON_NORMALIZE_MAP = {
|
export const BACON_NORMALIZE_MAP = {
|
||||||
[BACON_TRANSLATION_AB]: {
|
[BACON_TRANSLATION_AB]: {
|
||||||
A: "0",
|
"A": "0",
|
||||||
B: "1",
|
"B": "1",
|
||||||
a: "0",
|
"a": "0",
|
||||||
b: "1",
|
"b": "1"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,8 +59,8 @@ export const BACON_NORMALIZE_MAP = {
|
||||||
export function swapZeroAndOne(string) {
|
export function swapZeroAndOne(string) {
|
||||||
return string.replace(/[01]/g, function (c) {
|
return string.replace(/[01]/g, function (c) {
|
||||||
return {
|
return {
|
||||||
0: "1",
|
"0": "1",
|
||||||
1: "0",
|
"1": "0"
|
||||||
}[c];
|
}[c];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* // returns "SGVsbG8="
|
* // returns "SGVsbG8="
|
||||||
* toBase64("Hello");
|
* toBase64("Hello");
|
||||||
*/
|
*/
|
||||||
export function toBase64(data, alphabet = "A-Za-z0-9+/=") {
|
export function toBase64(data, alphabet="A-Za-z0-9+/=") {
|
||||||
if (!data) return "";
|
if (!data) return "";
|
||||||
if (typeof data == "string") {
|
if (typeof data == "string") {
|
||||||
data = Utils.strToArrayBuffer(data);
|
data = Utils.strToArrayBuffer(data);
|
||||||
|
@ -33,21 +33,13 @@ export function toBase64(data, alphabet = "A-Za-z0-9+/=") {
|
||||||
}
|
}
|
||||||
|
|
||||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||||
if (alphabet.length !== 64 && alphabet.length !== 65) {
|
if (alphabet.length !== 64 && alphabet.length !== 65) { // Allow for padding
|
||||||
// Allow for padding
|
throw new OperationError(`Invalid Base64 alphabet length (${alphabet.length}): ${alphabet}`);
|
||||||
throw new OperationError(
|
|
||||||
`Invalid Base64 alphabet length (${alphabet.length}): ${alphabet}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = "",
|
let output = "",
|
||||||
chr1,
|
chr1, chr2, chr3,
|
||||||
chr2,
|
enc1, enc2, enc3, enc4,
|
||||||
chr3,
|
|
||||||
enc1,
|
|
||||||
enc2,
|
|
||||||
enc3,
|
|
||||||
enc4,
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
while (i < data.length) {
|
while (i < data.length) {
|
||||||
|
@ -66,16 +58,14 @@ export function toBase64(data, alphabet = "A-Za-z0-9+/=") {
|
||||||
enc4 = 64;
|
enc4 = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
output +=
|
output += alphabet.charAt(enc1) + alphabet.charAt(enc2) +
|
||||||
alphabet.charAt(enc1) +
|
alphabet.charAt(enc3) + alphabet.charAt(enc4);
|
||||||
alphabet.charAt(enc2) +
|
|
||||||
alphabet.charAt(enc3) +
|
|
||||||
alphabet.charAt(enc4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UnBase64's the input string using the given alphabet, returning a byte array.
|
* UnBase64's the input string using the given alphabet, returning a byte array.
|
||||||
*
|
*
|
||||||
|
@ -92,13 +82,7 @@ export function toBase64(data, alphabet = "A-Za-z0-9+/=") {
|
||||||
* // returns [72, 101, 108, 108, 111]
|
* // returns [72, 101, 108, 108, 111]
|
||||||
* fromBase64("SGVsbG8=", null, "byteArray");
|
* fromBase64("SGVsbG8=", null, "byteArray");
|
||||||
*/
|
*/
|
||||||
export function fromBase64(
|
export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", removeNonAlphChars=true, strictMode=false) {
|
||||||
data,
|
|
||||||
alphabet = "A-Za-z0-9+/=",
|
|
||||||
returnType = "string",
|
|
||||||
removeNonAlphChars = true,
|
|
||||||
strictMode = false,
|
|
||||||
) {
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return returnType === "string" ? "" : [];
|
return returnType === "string" ? "" : [];
|
||||||
}
|
}
|
||||||
|
@ -107,63 +91,42 @@ export function fromBase64(
|
||||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||||
|
|
||||||
// Confirm alphabet is a valid length
|
// Confirm alphabet is a valid length
|
||||||
if (alphabet.length !== 64 && alphabet.length !== 65) {
|
if (alphabet.length !== 64 && alphabet.length !== 65) { // Allow for padding
|
||||||
// Allow for padding
|
throw new OperationError(`Error: Base64 alphabet should be 64 characters long, or 65 with a padding character. Found ${alphabet.length}: ${alphabet}`);
|
||||||
throw new OperationError(
|
|
||||||
`Error: Base64 alphabet should be 64 characters long, or 65 with a padding character. Found ${alphabet.length}: ${alphabet}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove non-alphabet characters
|
// Remove non-alphabet characters
|
||||||
if (removeNonAlphChars) {
|
if (removeNonAlphChars) {
|
||||||
const re = new RegExp(
|
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||||
"[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]",
|
|
||||||
"g",
|
|
||||||
);
|
|
||||||
data = data.replace(re, "");
|
data = data.replace(re, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strictMode) {
|
if (strictMode) {
|
||||||
// Check for incorrect lengths (even without padding)
|
// Check for incorrect lengths (even without padding)
|
||||||
if (data.length % 4 === 1) {
|
if (data.length % 4 === 1) {
|
||||||
throw new OperationError(
|
throw new OperationError(`Error: Invalid Base64 input length (${data.length}). Cannot be 4n+1, even without padding chars.`);
|
||||||
`Error: Invalid Base64 input length (${data.length}). Cannot be 4n+1, even without padding chars.`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alphabet.length === 65) {
|
if (alphabet.length === 65) { // Padding character included
|
||||||
// Padding character included
|
|
||||||
const pad = alphabet.charAt(64);
|
const pad = alphabet.charAt(64);
|
||||||
const padPos = data.indexOf(pad);
|
const padPos = data.indexOf(pad);
|
||||||
if (padPos >= 0) {
|
if (padPos >= 0) {
|
||||||
// Check that the padding character is only used at the end and maximum of twice
|
// Check that the padding character is only used at the end and maximum of twice
|
||||||
if (
|
if (padPos < data.length - 2 || data.charAt(data.length - 1) !== pad) {
|
||||||
padPos < data.length - 2 ||
|
throw new OperationError(`Error: Base64 padding character (${pad}) not used in the correct place.`);
|
||||||
data.charAt(data.length - 1) !== pad
|
|
||||||
) {
|
|
||||||
throw new OperationError(
|
|
||||||
`Error: Base64 padding character (${pad}) not used in the correct place.`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that input is padded to the correct length
|
// Check that input is padded to the correct length
|
||||||
if (data.length % 4 !== 0) {
|
if (data.length % 4 !== 0) {
|
||||||
throw new OperationError(
|
throw new OperationError("Error: Base64 not padded to a multiple of 4.");
|
||||||
"Error: Base64 not padded to a multiple of 4.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = [];
|
const output = [];
|
||||||
let chr1,
|
let chr1, chr2, chr3,
|
||||||
chr2,
|
enc1, enc2, enc3, enc4,
|
||||||
chr3,
|
|
||||||
enc1,
|
|
||||||
enc2,
|
|
||||||
enc3,
|
|
||||||
enc4,
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
while (i < data.length) {
|
while (i < data.length) {
|
||||||
|
@ -174,9 +137,7 @@ export function fromBase64(
|
||||||
enc4 = alphabet.indexOf(data.charAt(i++) || null);
|
enc4 = alphabet.indexOf(data.charAt(i++) || null);
|
||||||
|
|
||||||
if (strictMode && (enc1 < 0 || enc2 < 0 || enc3 < 0 || enc4 < 0)) {
|
if (strictMode && (enc1 < 0 || enc2 < 0 || enc3 < 0 || enc4 < 0)) {
|
||||||
throw new OperationError(
|
throw new OperationError("Error: Base64 input contains non-alphabet char(s)");
|
||||||
"Error: Base64 input contains non-alphabet char(s)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||||
|
@ -197,40 +158,26 @@ export function fromBase64(
|
||||||
return returnType === "string" ? Utils.byteArrayToUtf8(output) : output;
|
return returnType === "string" ? Utils.byteArrayToUtf8(output) : output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64 alphabets.
|
* Base64 alphabets.
|
||||||
*/
|
*/
|
||||||
export const ALPHABET_OPTIONS = [
|
export const ALPHABET_OPTIONS = [
|
||||||
{ name: "Standard (RFC 4648): A-Za-z0-9+/=", value: "A-Za-z0-9+/=" },
|
{name: "Standard (RFC 4648): A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
|
||||||
{ name: "URL safe (RFC 4648 \u00A75): A-Za-z0-9-_", value: "A-Za-z0-9-_" },
|
{name: "URL safe (RFC 4648 \u00A75): A-Za-z0-9-_", value: "A-Za-z0-9-_"},
|
||||||
{ name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-=" },
|
{name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-="},
|
||||||
{ name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z=" },
|
{name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z="},
|
||||||
{ name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_." },
|
{name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_."},
|
||||||
{ name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-" },
|
{name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-"},
|
||||||
{ name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/=" },
|
{name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/="},
|
||||||
{ name: "Radix-64 (RFC 4880): 0-9A-Za-z+/=", value: "0-9A-Za-z+/=" },
|
{name: "Radix-64 (RFC 4880): 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
|
||||||
{ name: "Uuencoding: [space]-_", value: " -_" },
|
{name: "Uuencoding: [space]-_", value: " -_"},
|
||||||
{ name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z" },
|
{name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z"},
|
||||||
{
|
{name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r", value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r"},
|
||||||
name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r",
|
{name: "ROT13: N-ZA-Mn-za-m0-9+/=", value: "N-ZA-Mn-za-m0-9+/="},
|
||||||
value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r",
|
{name: "UNIX crypt: ./0-9A-Za-z", value: "./0-9A-Za-z"},
|
||||||
},
|
{name: "Atom128: /128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC", value: "/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC"},
|
||||||
{ name: "ROT13: N-ZA-Mn-za-m0-9+/=", value: "N-ZA-Mn-za-m0-9+/=" },
|
{name: "Megan35: 3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5", value: "3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5"},
|
||||||
{ name: "UNIX crypt: ./0-9A-Za-z", value: "./0-9A-Za-z" },
|
{name: "Zong22: ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2", value: "ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2"},
|
||||||
{
|
{name: "Hazz15: HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5", value: "HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5"}
|
||||||
name: "Atom128: /128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC",
|
|
||||||
value: "/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Megan35: 3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5",
|
|
||||||
value: "3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Zong22: ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2",
|
|
||||||
value: "ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Hazz15: HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5",
|
|
||||||
value: "HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5",
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -23,9 +23,10 @@ export const ALPHABET_OPTIONS = [
|
||||||
{
|
{
|
||||||
name: "IPv6",
|
name: "IPv6",
|
||||||
value: "0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~",
|
value: "0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~",
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the alphabet, when given the alphabet.
|
* Returns the name of the alphabet, when given the alphabet.
|
||||||
*
|
*
|
||||||
|
@ -36,7 +37,7 @@ export function alphabetName(alphabet) {
|
||||||
alphabet = escape(alphabet);
|
alphabet = escape(alphabet);
|
||||||
let name;
|
let name;
|
||||||
|
|
||||||
ALPHABET_OPTIONS.forEach(function (a) {
|
ALPHABET_OPTIONS.forEach(function(a) {
|
||||||
const expanded = Utils.expandAlphRange(a.value).join("");
|
const expanded = Utils.expandAlphRange(a.value).join("");
|
||||||
if (alphabet === escape(expanded)) name = a.name;
|
if (alphabet === escape(expanded)) name = a.name;
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,9 +18,12 @@ export function base92Chr(val) {
|
||||||
if (val < 0 || val >= 91) {
|
if (val < 0 || val >= 91) {
|
||||||
throw new OperationError("Invalid value");
|
throw new OperationError("Invalid value");
|
||||||
}
|
}
|
||||||
if (val === 0) return "!".charCodeAt(0);
|
if (val === 0)
|
||||||
else if (val <= 61) return "#".charCodeAt(0) + val - 1;
|
return "!".charCodeAt(0);
|
||||||
else return "a".charCodeAt(0) + val - 62;
|
else if (val <= 61)
|
||||||
|
return "#".charCodeAt(0) + val - 1;
|
||||||
|
else
|
||||||
|
return "a".charCodeAt(0) + val - 62;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,10 +33,12 @@ export function base92Chr(val) {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export function base92Ord(val) {
|
export function base92Ord(val) {
|
||||||
if (val === "!") return 0;
|
if (val === "!")
|
||||||
|
return 0;
|
||||||
else if ("#" <= val && val <= "_")
|
else if ("#" <= val && val <= "_")
|
||||||
return val.charCodeAt(0) - "#".charCodeAt(0) + 1;
|
return val.charCodeAt(0) - "#".charCodeAt(0) + 1;
|
||||||
else if ("a" <= val && val <= "}")
|
else if ("a" <= val && val <= "}")
|
||||||
return val.charCodeAt(0) - "a".charCodeAt(0) + 62;
|
return val.charCodeAt(0) - "a".charCodeAt(0) + 62;
|
||||||
throw new OperationError(`${val} is not a base92 character`);
|
throw new OperationError(`${val} is not a base92 character`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a byte array into a binary string.
|
* Convert a byte array into a binary string.
|
||||||
*
|
*
|
||||||
|
@ -27,23 +28,19 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* // returns "1010:10100:11110"
|
* // returns "1010:10100:11110"
|
||||||
* toBinary([10,20,30], "Colon", 0);
|
* toBinary([10,20,30], "Colon", 0);
|
||||||
*/
|
*/
|
||||||
export function toBinary(data, delim = "Space", padding = 8) {
|
export function toBinary(data, delim="Space", padding=8) {
|
||||||
if (data === undefined || data === null)
|
if (data === undefined || data === null)
|
||||||
throw new OperationError(
|
throw new OperationError("Unable to convert to binary: Empty input data enocuntered");
|
||||||
"Unable to convert to binary: Empty input data enocuntered",
|
|
||||||
);
|
|
||||||
|
|
||||||
delim = Utils.charRep(delim);
|
delim = Utils.charRep(delim);
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
if (data.length) {
|
if (data.length) { // array
|
||||||
// array
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
output += data[i].toString(2).padStart(padding, "0");
|
output += data[i].toString(2).padStart(padding, "0");
|
||||||
if (i !== data.length - 1) output += delim;
|
if (i !== data.length - 1) output += delim;
|
||||||
}
|
}
|
||||||
} else if (typeof data === "number") {
|
} else if (typeof data === "number") { // Single value
|
||||||
// Single value
|
|
||||||
return data.toString(2).padStart(padding, "0");
|
return data.toString(2).padStart(padding, "0");
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
@ -51,6 +48,7 @@ export function toBinary(data, delim = "Space", padding = 8) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a binary string into a byte array.
|
* Convert a binary string into a byte array.
|
||||||
*
|
*
|
||||||
|
@ -66,7 +64,7 @@ export function toBinary(data, delim = "Space", padding = 8) {
|
||||||
* // returns [10,20,30]
|
* // returns [10,20,30]
|
||||||
* fromBinary("00001010:00010100:00011110", "Colon");
|
* fromBinary("00001010:00010100:00011110", "Colon");
|
||||||
*/
|
*/
|
||||||
export function fromBinary(data, delim = "Space", byteLen = 8) {
|
export function fromBinary(data, delim="Space", byteLen=8) {
|
||||||
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
|
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
|
||||||
throw new OperationError("Byte length must be a positive integer");
|
throw new OperationError("Byte length must be a positive integer");
|
||||||
|
|
||||||
|
@ -79,3 +77,4 @@ export function fromBinary(data, delim = "Space", byteLen = 8) {
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* @param {string} scheme
|
* @param {string} scheme
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
export function bitOp(input, key, func, nullPreserving, scheme) {
|
export function bitOp (input, key, func, nullPreserving, scheme) {
|
||||||
if (!key || !key.length) key = [0];
|
if (!key || !key.length) key = [0];
|
||||||
const result = [];
|
const result = [];
|
||||||
let x = null,
|
let x = null,
|
||||||
|
@ -29,11 +29,9 @@ export function bitOp(input, key, func, nullPreserving, scheme) {
|
||||||
o = input[i];
|
o = input[i];
|
||||||
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
|
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
|
||||||
result.push(x);
|
result.push(x);
|
||||||
if (
|
if (scheme &&
|
||||||
scheme &&
|
|
||||||
scheme !== "Standard" &&
|
scheme !== "Standard" &&
|
||||||
!(nullPreserving && (o === 0 || o === k))
|
!(nullPreserving && (o === 0 || o === k))) {
|
||||||
) {
|
|
||||||
switch (scheme) {
|
switch (scheme) {
|
||||||
case "Input differential":
|
case "Input differential":
|
||||||
key[i % key.length] = o;
|
key[i % key.length] = o;
|
||||||
|
@ -59,6 +57,7 @@ export function xor(operand, key) {
|
||||||
return operand ^ key;
|
return operand ^ key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOT bitwise calculation.
|
* NOT bitwise calculation.
|
||||||
*
|
*
|
||||||
|
@ -69,6 +68,7 @@ export function not(operand, _) {
|
||||||
return ~operand & 0xff;
|
return ~operand & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AND bitwise calculation.
|
* AND bitwise calculation.
|
||||||
*
|
*
|
||||||
|
@ -80,6 +80,7 @@ export function and(operand, key) {
|
||||||
return operand & key;
|
return operand & key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OR bitwise calculation.
|
* OR bitwise calculation.
|
||||||
*
|
*
|
||||||
|
@ -91,6 +92,7 @@ export function or(operand, key) {
|
||||||
return operand | key;
|
return operand | key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ADD bitwise calculation.
|
* ADD bitwise calculation.
|
||||||
*
|
*
|
||||||
|
@ -102,6 +104,7 @@ export function add(operand, key) {
|
||||||
return (operand + key) % 256;
|
return (operand + key) % 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SUB bitwise calculation.
|
* SUB bitwise calculation.
|
||||||
*
|
*
|
||||||
|
@ -111,17 +114,11 @@ export function add(operand, key) {
|
||||||
*/
|
*/
|
||||||
export function sub(operand, key) {
|
export function sub(operand, key) {
|
||||||
const result = operand - key;
|
const result = operand - key;
|
||||||
return result < 0 ? 256 + result : result;
|
return (result < 0) ? 256 + result : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delimiter options for bitwise operations
|
* Delimiter options for bitwise operations
|
||||||
*/
|
*/
|
||||||
export const BITWISE_OP_DELIMS = [
|
export const BITWISE_OP_DELIMS = ["Hex", "Decimal", "Binary", "Base64", "UTF8", "Latin1"];
|
||||||
"Hex",
|
|
||||||
"Decimal",
|
|
||||||
"Binary",
|
|
||||||
"Base64",
|
|
||||||
"UTF8",
|
|
||||||
"Latin1",
|
|
||||||
];
|
|
||||||
|
|
|
@ -40,21 +40,23 @@ const crypto = {};
|
||||||
|
|
||||||
import forge from "node-forge";
|
import forge from "node-forge";
|
||||||
|
|
||||||
|
|
||||||
/* dojo-release-1.8.1/dojo/_base/lang.js.uncompressed.js */
|
/* dojo-release-1.8.1/dojo/_base/lang.js.uncompressed.js */
|
||||||
|
|
||||||
const lang = {};
|
const lang = {};
|
||||||
lang.isString = function (it) {
|
lang.isString = function(it) {
|
||||||
// summary:
|
// summary:
|
||||||
// Return true if it is a String
|
// Return true if it is a String
|
||||||
// it: anything
|
// it: anything
|
||||||
// Item to test.
|
// Item to test.
|
||||||
return typeof it == "string" || it instanceof String; // Boolean
|
return (typeof it == "string" || it instanceof String); // Boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* dojo-release-1.8.1/dojo/_base/array.js.uncompressed.js */
|
/* dojo-release-1.8.1/dojo/_base/array.js.uncompressed.js */
|
||||||
|
|
||||||
const arrayUtil = {};
|
const arrayUtil = {};
|
||||||
arrayUtil.map = function (arr, callback, thisObject, Ctr) {
|
arrayUtil.map = function(arr, callback, thisObject, Ctr) {
|
||||||
// summary:
|
// summary:
|
||||||
// applies callback to each element of arr and returns
|
// applies callback to each element of arr and returns
|
||||||
// an Array with the results
|
// an Array with the results
|
||||||
|
@ -79,8 +81,7 @@ arrayUtil.map = function (arr, callback, thisObject, Ctr) {
|
||||||
|
|
||||||
// TODO: why do we have a non-standard signature here? do we need "Ctr"?
|
// TODO: why do we have a non-standard signature here? do we need "Ctr"?
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const l = (arr && arr.length) || 0,
|
const l = arr && arr.length || 0, out = new (Ctr || Array)(l);
|
||||||
out = new (Ctr || Array)(l);
|
|
||||||
if (l && typeof arr == "string") arr = arr.split("");
|
if (l && typeof arr == "string") arr = arr.split("");
|
||||||
if (thisObject) {
|
if (thisObject) {
|
||||||
for (; i < l; ++i) {
|
for (; i < l; ++i) {
|
||||||
|
@ -101,394 +102,332 @@ arrayUtil.map = function (arr, callback, thisObject, Ctr) {
|
||||||
* Unsigned math based on Paul Johnstone and Peter Wood patches.
|
* Unsigned math based on Paul Johnstone and Peter Wood patches.
|
||||||
* 2005-12-08
|
* 2005-12-08
|
||||||
*/
|
*/
|
||||||
const boxes = {
|
const boxes={
|
||||||
p: [
|
p: [
|
||||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||||
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
0x9216d5d9, 0x8979fb1b
|
||||||
],
|
],
|
||||||
s0: [
|
s0: [
|
||||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||||
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||||
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||||
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||||
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||||
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||||
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||||
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||||
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||||
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||||
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||||
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||||
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||||
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||||
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||||
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||||
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
||||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
|
||||||
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
|
||||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
|
||||||
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
|
||||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
|
||||||
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
|
||||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
|
||||||
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
|
||||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
|
||||||
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
|
||||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
|
||||||
],
|
],
|
||||||
s1: [
|
s1: [
|
||||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||||
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||||
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||||
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||||
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||||
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||||
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||||
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||||
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||||
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||||
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||||
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||||
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||||
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||||
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||||
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||||
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
||||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
|
||||||
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
|
||||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
|
||||||
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
|
||||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
|
||||||
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
|
||||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
|
||||||
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
|
||||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
|
||||||
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
|
||||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
|
||||||
],
|
],
|
||||||
s2: [
|
s2: [
|
||||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||||
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||||
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||||
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||||
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||||
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||||
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||||
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||||
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||||
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||||
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||||
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||||
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||||
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||||
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||||
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||||
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
||||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
|
||||||
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
|
||||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
|
||||||
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
|
||||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
|
||||||
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
|
||||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
|
||||||
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
|
||||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
|
||||||
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
|
||||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
|
||||||
],
|
],
|
||||||
s3: [
|
s3: [
|
||||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||||
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||||
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||||
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||||
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||||
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||||
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||||
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||||
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||||
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||||
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||||
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||||
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||||
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||||
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||||
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||||
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
||||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
]
|
||||||
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
|
||||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
|
||||||
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
|
||||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
|
||||||
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
|
||||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
|
||||||
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
|
||||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
|
||||||
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
|
||||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// fixes based on patch submitted by Peter Wood (#5791)
|
// fixes based on patch submitted by Peter Wood (#5791)
|
||||||
const xor = function (x, y) {
|
const xor = function(x, y) {
|
||||||
return (
|
return (((x>>0x10)^(y>>0x10))<<0x10)|(((x&0xffff)^(y&0xffff))&0xffff);
|
||||||
(((x >> 0x10) ^ (y >> 0x10)) << 0x10) |
|
|
||||||
(((x & 0xffff) ^ (y & 0xffff)) & 0xffff)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const f = function (v, box) {
|
|
||||||
const d = box.s3[v & 0xff];
|
|
||||||
v >>= 8;
|
|
||||||
const c = box.s2[v & 0xff];
|
|
||||||
v >>= 8;
|
|
||||||
const b = box.s1[v & 0xff];
|
|
||||||
v >>= 8;
|
|
||||||
const a = box.s0[v & 0xff];
|
|
||||||
|
|
||||||
let r =
|
const f = function(v, box) {
|
||||||
(((a >> 0x10) +
|
const d=box.s3[v&0xff]; v>>=8;
|
||||||
(b >> 0x10) +
|
const c=box.s2[v&0xff]; v>>=8;
|
||||||
(((a & 0xffff) + (b & 0xffff)) >> 0x10)) <<
|
const b=box.s1[v&0xff]; v>>=8;
|
||||||
0x10) |
|
const a=box.s0[v&0xff];
|
||||||
(((a & 0xffff) + (b & 0xffff)) & 0xffff);
|
|
||||||
r =
|
let r = (((a>>0x10)+(b>>0x10)+(((a&0xffff)+(b&0xffff))>>0x10))<<0x10)|(((a&0xffff)+(b&0xffff))&0xffff);
|
||||||
(((r >> 0x10) ^ (c >> 0x10)) << 0x10) |
|
r = (((r>>0x10)^(c>>0x10))<<0x10)|(((r&0xffff)^(c&0xffff))&0xffff);
|
||||||
(((r & 0xffff) ^ (c & 0xffff)) & 0xffff);
|
return (((r>>0x10)+(d>>0x10)+(((r&0xffff)+(d&0xffff))>>0x10))<<0x10)|(((r&0xffff)+(d&0xffff))&0xffff);
|
||||||
return (
|
|
||||||
(((r >> 0x10) +
|
|
||||||
(d >> 0x10) +
|
|
||||||
(((r & 0xffff) + (d & 0xffff)) >> 0x10)) <<
|
|
||||||
0x10) |
|
|
||||||
(((r & 0xffff) + (d & 0xffff)) & 0xffff)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const eb = function (o, box) {
|
|
||||||
|
const eb = function(o, box) {
|
||||||
// TODO: see if this can't be made more efficient
|
// TODO: see if this can't be made more efficient
|
||||||
let l = o.left;
|
let l=o.left;
|
||||||
let r = o.right;
|
let r=o.right;
|
||||||
l = xor(l, box.p[0]);
|
l=xor(l, box.p[0]);
|
||||||
r = xor(r, xor(f(l, box), box.p[1]));
|
r=xor(r, xor(f(l, box), box.p[1]));
|
||||||
l = xor(l, xor(f(r, box), box.p[2]));
|
l=xor(l, xor(f(r, box), box.p[2]));
|
||||||
r = xor(r, xor(f(l, box), box.p[3]));
|
r=xor(r, xor(f(l, box), box.p[3]));
|
||||||
l = xor(l, xor(f(r, box), box.p[4]));
|
l=xor(l, xor(f(r, box), box.p[4]));
|
||||||
r = xor(r, xor(f(l, box), box.p[5]));
|
r=xor(r, xor(f(l, box), box.p[5]));
|
||||||
l = xor(l, xor(f(r, box), box.p[6]));
|
l=xor(l, xor(f(r, box), box.p[6]));
|
||||||
r = xor(r, xor(f(l, box), box.p[7]));
|
r=xor(r, xor(f(l, box), box.p[7]));
|
||||||
l = xor(l, xor(f(r, box), box.p[8]));
|
l=xor(l, xor(f(r, box), box.p[8]));
|
||||||
r = xor(r, xor(f(l, box), box.p[9]));
|
r=xor(r, xor(f(l, box), box.p[9]));
|
||||||
l = xor(l, xor(f(r, box), box.p[10]));
|
l=xor(l, xor(f(r, box), box.p[10]));
|
||||||
r = xor(r, xor(f(l, box), box.p[11]));
|
r=xor(r, xor(f(l, box), box.p[11]));
|
||||||
l = xor(l, xor(f(r, box), box.p[12]));
|
l=xor(l, xor(f(r, box), box.p[12]));
|
||||||
r = xor(r, xor(f(l, box), box.p[13]));
|
r=xor(r, xor(f(l, box), box.p[13]));
|
||||||
l = xor(l, xor(f(r, box), box.p[14]));
|
l=xor(l, xor(f(r, box), box.p[14]));
|
||||||
r = xor(r, xor(f(l, box), box.p[15]));
|
r=xor(r, xor(f(l, box), box.p[15]));
|
||||||
l = xor(l, xor(f(r, box), box.p[16]));
|
l=xor(l, xor(f(r, box), box.p[16]));
|
||||||
o.right = l;
|
o.right=l;
|
||||||
o.left = xor(r, box.p[17]);
|
o.left=xor(r, box.p[17]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const db = function (o, box) {
|
const db = function(o, box) {
|
||||||
let l = o.left;
|
let l=o.left;
|
||||||
let r = o.right;
|
let r=o.right;
|
||||||
l = xor(l, box.p[17]);
|
l=xor(l, box.p[17]);
|
||||||
r = xor(r, xor(f(l, box), box.p[16]));
|
r=xor(r, xor(f(l, box), box.p[16]));
|
||||||
l = xor(l, xor(f(r, box), box.p[15]));
|
l=xor(l, xor(f(r, box), box.p[15]));
|
||||||
r = xor(r, xor(f(l, box), box.p[14]));
|
r=xor(r, xor(f(l, box), box.p[14]));
|
||||||
l = xor(l, xor(f(r, box), box.p[13]));
|
l=xor(l, xor(f(r, box), box.p[13]));
|
||||||
r = xor(r, xor(f(l, box), box.p[12]));
|
r=xor(r, xor(f(l, box), box.p[12]));
|
||||||
l = xor(l, xor(f(r, box), box.p[11]));
|
l=xor(l, xor(f(r, box), box.p[11]));
|
||||||
r = xor(r, xor(f(l, box), box.p[10]));
|
r=xor(r, xor(f(l, box), box.p[10]));
|
||||||
l = xor(l, xor(f(r, box), box.p[9]));
|
l=xor(l, xor(f(r, box), box.p[9]));
|
||||||
r = xor(r, xor(f(l, box), box.p[8]));
|
r=xor(r, xor(f(l, box), box.p[8]));
|
||||||
l = xor(l, xor(f(r, box), box.p[7]));
|
l=xor(l, xor(f(r, box), box.p[7]));
|
||||||
r = xor(r, xor(f(l, box), box.p[6]));
|
r=xor(r, xor(f(l, box), box.p[6]));
|
||||||
l = xor(l, xor(f(r, box), box.p[5]));
|
l=xor(l, xor(f(r, box), box.p[5]));
|
||||||
r = xor(r, xor(f(l, box), box.p[4]));
|
r=xor(r, xor(f(l, box), box.p[4]));
|
||||||
l = xor(l, xor(f(r, box), box.p[3]));
|
l=xor(l, xor(f(r, box), box.p[3]));
|
||||||
r = xor(r, xor(f(l, box), box.p[2]));
|
r=xor(r, xor(f(l, box), box.p[2]));
|
||||||
l = xor(l, xor(f(r, box), box.p[1]));
|
l=xor(l, xor(f(r, box), box.p[1]));
|
||||||
o.right = l;
|
o.right=l;
|
||||||
o.left = xor(r, box.p[0]);
|
o.left=xor(r, box.p[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const encryptBlock = function (inblock, outblock, box) {
|
const encryptBlock=function(inblock, outblock, box) {
|
||||||
const o = {};
|
const o = {};
|
||||||
o.left = inblock[0];
|
o.left=inblock[0];
|
||||||
o.right = inblock[1];
|
o.right=inblock[1];
|
||||||
eb(o, box);
|
eb(o, box);
|
||||||
outblock[0] = o.left;
|
outblock[0] = o.left;
|
||||||
outblock[1] = o.right;
|
outblock[1] = o.right;
|
||||||
};
|
};
|
||||||
|
|
||||||
const decryptBlock = function (inblock, outblock, box) {
|
const decryptBlock=function(inblock, outblock, box) {
|
||||||
const o = {};
|
const o= {};
|
||||||
o.left = inblock[0];
|
o.left=inblock[0];
|
||||||
o.right = inblock[1];
|
o.right=inblock[1];
|
||||||
db(o, box);
|
db(o, box);
|
||||||
outblock[0] = o.left;
|
outblock[0] = o.left;
|
||||||
outblock[1] = o.right;
|
outblock[1] = o.right;
|
||||||
};
|
};
|
||||||
|
|
||||||
crypto.Blowfish = new (function () {
|
crypto.Blowfish = new function() {
|
||||||
this.createCipher = function (key, modeName) {
|
this.createCipher=function(key, modeName) {
|
||||||
return new forge.cipher.BlockCipher({
|
return new forge.cipher.BlockCipher({
|
||||||
algorithm: new Blowfish.Algorithm(key, modeName),
|
algorithm: new Blowfish.Algorithm(key, modeName),
|
||||||
key: key,
|
key: key,
|
||||||
decrypt: false,
|
decrypt: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.createDecipher = function (key, modeName) {
|
this.createDecipher=function(key, modeName) {
|
||||||
return new forge.cipher.BlockCipher({
|
return new forge.cipher.BlockCipher({
|
||||||
algorithm: new Blowfish.Algorithm(key, modeName),
|
algorithm: new Blowfish.Algorithm(key, modeName),
|
||||||
key: key,
|
key: key,
|
||||||
decrypt: true,
|
decrypt: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
})();
|
}();
|
||||||
|
|
||||||
crypto.Blowfish.Algorithm = function (key, modeName) {
|
|
||||||
this.initialize({ key: key });
|
crypto.Blowfish.Algorithm=function(key, modeName) {
|
||||||
|
this.initialize({key: key});
|
||||||
const _box = this.box;
|
const _box = this.box;
|
||||||
const modeOption = {
|
const modeOption = {
|
||||||
blockSize: 8,
|
blockSize: 8,
|
||||||
cipher: {
|
cipher: {
|
||||||
encrypt: function (inblock, outblock) {
|
encrypt: function(inblock, outblock) {
|
||||||
encryptBlock(inblock, outblock, _box);
|
encryptBlock(inblock, outblock, _box);
|
||||||
},
|
},
|
||||||
decrypt: function (inblock, outblock) {
|
decrypt: function(inblock, outblock) {
|
||||||
decryptBlock(inblock, outblock, _box);
|
decryptBlock(inblock, outblock, _box);
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (modeName.toLowerCase()) {
|
switch (modeName.toLowerCase()) {
|
||||||
case "ecb":
|
case "ecb":
|
||||||
this.mode = new forge.cipher.modes.ecb(modeOption);
|
this.mode=new forge.cipher.modes.ecb(modeOption);
|
||||||
break;
|
break;
|
||||||
case "cbc":
|
case "cbc":
|
||||||
this.mode = new forge.cipher.modes.cbc(modeOption);
|
this.mode=new forge.cipher.modes.cbc(modeOption);
|
||||||
break;
|
break;
|
||||||
case "cfb":
|
case "cfb":
|
||||||
this.mode = new forge.cipher.modes.cfb(modeOption);
|
this.mode=new forge.cipher.modes.cfb(modeOption);
|
||||||
break;
|
break;
|
||||||
case "ofb":
|
case "ofb":
|
||||||
this.mode = new forge.cipher.modes.ofb(modeOption);
|
this.mode=new forge.cipher.modes.ofb(modeOption);
|
||||||
break;
|
break;
|
||||||
case "ctr":
|
case "ctr":
|
||||||
this.mode = new forge.cipher.modes.ctr(modeOption);
|
this.mode=new forge.cipher.modes.ctr(modeOption);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.mode = new forge.cipher.modes.ecb(modeOption);
|
this.mode=new forge.cipher.modes.ecb(modeOption);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
crypto.Blowfish.Algorithm.prototype.initialize = function (options) {
|
crypto.Blowfish.Algorithm.prototype.initialize=function(options) {
|
||||||
const POW8 = Math.pow(2, 8);
|
const POW8=Math.pow(2, 8);
|
||||||
|
|
||||||
let k = options.key;
|
let k=options.key;
|
||||||
if (lang.isString(k)) {
|
if (lang.isString(k)) {
|
||||||
k = arrayUtil.map(k.split(""), function (item) {
|
k = arrayUtil.map(k.split(""), function(item) {
|
||||||
return item.charCodeAt(0) & 0xff;
|
return item.charCodeAt(0) & 0xff;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// init the boxes
|
// init the boxes
|
||||||
let pos = 0,
|
let pos=0, data=0;
|
||||||
data = 0;
|
const res={ left: 0, right: 0 };
|
||||||
const res = { left: 0, right: 0 };
|
|
||||||
const box = {
|
const box = {
|
||||||
p: arrayUtil.map(boxes.p.slice(0), function (item) {
|
p: arrayUtil.map(boxes.p.slice(0), function(item) {
|
||||||
const l = k.length;
|
const l=k.length;
|
||||||
for (let j = 0; j < 4; j++) {
|
for (let j=0; j<4; j++) {
|
||||||
data = (data * POW8) | k[pos++ % l];
|
data=(data*POW8)|k[pos++ % l];
|
||||||
}
|
}
|
||||||
return (
|
return (((item>>0x10)^(data>>0x10))<<0x10)|(((item&0xffff)^(data&0xffff))&0xffff);
|
||||||
(((item >> 0x10) ^ (data >> 0x10)) << 0x10) |
|
|
||||||
(((item & 0xffff) ^ (data & 0xffff)) & 0xffff)
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
s0: boxes.s0.slice(0),
|
s0: boxes.s0.slice(0),
|
||||||
s1: boxes.s1.slice(0),
|
s1: boxes.s1.slice(0),
|
||||||
s2: boxes.s2.slice(0),
|
s2: boxes.s2.slice(0),
|
||||||
s3: boxes.s3.slice(0),
|
s3: boxes.s3.slice(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// encrypt p and the s boxes
|
// encrypt p and the s boxes
|
||||||
for (let i = 0, l = box.p.length; i < l; ) {
|
for (let i=0, l=box.p.length; i<l;) {
|
||||||
eb(res, box);
|
eb(res, box);
|
||||||
box.p[i++] = res.left;
|
box.p[i++]=res.left;
|
||||||
box.p[i++] = res.right;
|
box.p[i++]=res.right;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < 4; i++) {
|
for (let i=0; i<4; i++) {
|
||||||
for (let j = 0, l = box["s" + i].length; j < l; ) {
|
for (let j=0, l=box["s"+i].length; j<l;) {
|
||||||
eb(res, box);
|
eb(res, box);
|
||||||
box["s" + i][j++] = res.left;
|
box["s"+i][j++]=res.left;
|
||||||
box["s" + i][j++] = res.right;
|
box["s"+i][j++]=res.right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.box = box;
|
this.box = box;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import { Rotor, Plugboard, a2i, i2a } from "./Enigma.mjs";
|
import {Rotor, Plugboard, a2i, i2a} from "./Enigma.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience/optimisation subclass of Rotor
|
* Convenience/optimisation subclass of Rotor
|
||||||
|
@ -96,7 +96,7 @@ class SharedScrambler {
|
||||||
constructor(rotors, reflector) {
|
constructor(rotors, reflector) {
|
||||||
this.lowerCache = new Array(26);
|
this.lowerCache = new Array(26);
|
||||||
this.higherCache = new Array(26);
|
this.higherCache = new Array(26);
|
||||||
for (let i = 0; i < 26; i++) {
|
for (let i=0; i<26; i++) {
|
||||||
this.higherCache[i] = new Array(26);
|
this.higherCache[i] = new Array(26);
|
||||||
}
|
}
|
||||||
this.changeRotors(rotors, reflector);
|
this.changeRotors(rotors, reflector);
|
||||||
|
@ -121,7 +121,7 @@ class SharedScrambler {
|
||||||
* the shared state, so should be 2 or more.
|
* the shared state, so should be 2 or more.
|
||||||
*/
|
*/
|
||||||
step(n) {
|
step(n) {
|
||||||
for (let i = 0; i < n - 1; i++) {
|
for (let i=0; i<n-1; i++) {
|
||||||
this.rotors[i].step();
|
this.rotors[i].step();
|
||||||
}
|
}
|
||||||
this.cacheGen();
|
this.cacheGen();
|
||||||
|
@ -136,13 +136,13 @@ class SharedScrambler {
|
||||||
* iterations.
|
* iterations.
|
||||||
*/
|
*/
|
||||||
cacheGen() {
|
cacheGen() {
|
||||||
for (let i = 0; i < 26; i++) {
|
for (let i=0; i<26; i++) {
|
||||||
this.lowerCache[i] = undefined;
|
this.lowerCache[i] = undefined;
|
||||||
for (let j = 0; j < 26; j++) {
|
for (let j=0; j<26; j++) {
|
||||||
this.higherCache[i][j] = undefined;
|
this.higherCache[i][j] = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = 0; i < 26; i++) {
|
for (let i=0; i<26; i++) {
|
||||||
if (this.lowerCache[i] !== undefined) {
|
if (this.lowerCache[i] !== undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,7 @@ class Scrambler {
|
||||||
this.cache = this.baseScrambler.higherCache[this.rotor.pos];
|
this.cache = this.baseScrambler.higherCache[this.rotor.pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a letter through the scrambler.
|
* Run a letter through the scrambler.
|
||||||
* @param {number} i - The letter to transform (as a number)
|
* @param {number} i - The letter to transform (as a number)
|
||||||
|
@ -261,7 +262,7 @@ class Scrambler {
|
||||||
// Roll back the fast rotor by one step
|
// Roll back the fast rotor by one step
|
||||||
let pos = Utils.mod(this.rotor.pos - 1, 26);
|
let pos = Utils.mod(this.rotor.pos - 1, 26);
|
||||||
result += i2a(pos);
|
result += i2a(pos);
|
||||||
for (let i = 0; i < this.baseScrambler.rotors.length; i++) {
|
for (let i=0; i<this.baseScrambler.rotors.length; i++) {
|
||||||
pos = this.baseScrambler.rotors[i].pos;
|
pos = this.baseScrambler.rotors[i].pos;
|
||||||
result += i2a(pos);
|
result += i2a(pos);
|
||||||
}
|
}
|
||||||
|
@ -295,14 +296,7 @@ export class BombeMachine {
|
||||||
* @param {boolean} check - Whether to use the checking machine
|
* @param {boolean} check - Whether to use the checking machine
|
||||||
* @param {function} update - Function to call to send status updates (optional)
|
* @param {function} update - Function to call to send status updates (optional)
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(rotors, reflector, ciphertext, crib, check, update=undefined) {
|
||||||
rotors,
|
|
||||||
reflector,
|
|
||||||
ciphertext,
|
|
||||||
crib,
|
|
||||||
check,
|
|
||||||
update = undefined,
|
|
||||||
) {
|
|
||||||
if (ciphertext.length < crib.length) {
|
if (ciphertext.length < crib.length) {
|
||||||
throw new OperationError("Crib overruns supplied ciphertext");
|
throw new OperationError("Crib overruns supplied ciphertext");
|
||||||
}
|
}
|
||||||
|
@ -316,11 +310,9 @@ export class BombeMachine {
|
||||||
// A shorter crib is preferable to reduce this chance, of course
|
// A shorter crib is preferable to reduce this chance, of course
|
||||||
throw new OperationError("Crib is too long");
|
throw new OperationError("Crib is too long");
|
||||||
}
|
}
|
||||||
for (let i = 0; i < crib.length; i++) {
|
for (let i=0; i<crib.length; i++) {
|
||||||
if (ciphertext[i] === crib[i]) {
|
if (ciphertext[i] === crib[i]) {
|
||||||
throw new OperationError(
|
throw new OperationError(`Invalid crib: character ${ciphertext[i]} at pos ${i} in both ciphertext and crib`);
|
||||||
`Invalid crib: character ${ciphertext[i]} at pos ${i} in both ciphertext and crib`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ciphertext = ciphertext;
|
this.ciphertext = ciphertext;
|
||||||
|
@ -333,31 +325,22 @@ export class BombeMachine {
|
||||||
|
|
||||||
// This is the bundle of wires corresponding to the 26 letters within each of the 26
|
// This is the bundle of wires corresponding to the 26 letters within each of the 26
|
||||||
// possible nodes in the menu
|
// possible nodes in the menu
|
||||||
this.wires = new Array(26 * 26);
|
this.wires = new Array(26*26);
|
||||||
|
|
||||||
// These are the pseudo-Engima devices corresponding to each edge in the menu, and the
|
// These are the pseudo-Engima devices corresponding to each edge in the menu, and the
|
||||||
// nodes in the menu they each connect to
|
// nodes in the menu they each connect to
|
||||||
this.scramblers = new Array();
|
this.scramblers = new Array();
|
||||||
for (let i = 0; i < 26; i++) {
|
for (let i=0; i<26; i++) {
|
||||||
this.scramblers.push(new Array());
|
this.scramblers.push(new Array());
|
||||||
}
|
}
|
||||||
this.sharedScrambler = new SharedScrambler(
|
this.sharedScrambler = new SharedScrambler(this.baseRotors.slice(1), reflector);
|
||||||
this.baseRotors.slice(1),
|
|
||||||
reflector,
|
|
||||||
);
|
|
||||||
this.allScramblers = new Array();
|
this.allScramblers = new Array();
|
||||||
this.indicator = undefined;
|
this.indicator = undefined;
|
||||||
for (const edge of edges) {
|
for (const edge of edges) {
|
||||||
const cRotor = this.baseRotors[0].copy();
|
const cRotor = this.baseRotors[0].copy();
|
||||||
const end1 = a2i(edge.node1.letter);
|
const end1 = a2i(edge.node1.letter);
|
||||||
const end2 = a2i(edge.node2.letter);
|
const end2 = a2i(edge.node2.letter);
|
||||||
const scrambler = new Scrambler(
|
const scrambler = new Scrambler(this.sharedScrambler, cRotor, edge.pos, end1, end2);
|
||||||
this.sharedScrambler,
|
|
||||||
cRotor,
|
|
||||||
edge.pos,
|
|
||||||
end1,
|
|
||||||
end2,
|
|
||||||
);
|
|
||||||
if (edge.pos === 0) {
|
if (edge.pos === 0) {
|
||||||
this.indicator = scrambler;
|
this.indicator = scrambler;
|
||||||
}
|
}
|
||||||
|
@ -369,23 +352,14 @@ export class BombeMachine {
|
||||||
// use one of the actual scramblers if there's one in the right position, but if not we'll
|
// use one of the actual scramblers if there's one in the right position, but if not we'll
|
||||||
// just create one.
|
// just create one.
|
||||||
if (this.indicator === undefined) {
|
if (this.indicator === undefined) {
|
||||||
this.indicator = new Scrambler(
|
this.indicator = new Scrambler(this.sharedScrambler, this.baseRotors[0].copy(), 0, undefined, undefined);
|
||||||
this.sharedScrambler,
|
|
||||||
this.baseRotors[0].copy(),
|
|
||||||
0,
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
this.allScramblers.push(this.indicator);
|
this.allScramblers.push(this.indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.testRegister = a2i(mostConnected.letter);
|
this.testRegister = a2i(mostConnected.letter);
|
||||||
// This is an arbitrary letter other than the most connected letter
|
// This is an arbitrary letter other than the most connected letter
|
||||||
for (const edge of mostConnected.edges) {
|
for (const edge of mostConnected.edges) {
|
||||||
this.testInput = [
|
this.testInput = [this.testRegister, a2i(edge.getOther(mostConnected).letter)];
|
||||||
this.testRegister,
|
|
||||||
a2i(edge.getOther(mostConnected).letter),
|
|
||||||
];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,8 +430,7 @@ export class BombeMachine {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// This is a newly visited node
|
// This is a newly visited node
|
||||||
const [oLoops, oNNodes, oMostConnected, oNConnections, oEdges] =
|
const [oLoops, oNNodes, oMostConnected, oNConnections, oEdges] = this.dfs(other);
|
||||||
this.dfs(other);
|
|
||||||
loops += oLoops;
|
loops += oLoops;
|
||||||
nNodes += oNNodes;
|
nNodes += oNNodes;
|
||||||
edges = new Set([...edges, ...oEdges]);
|
edges = new Set([...edges, ...oEdges]);
|
||||||
|
@ -492,7 +465,7 @@ export class BombeMachine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Then all edges
|
// Then all edges
|
||||||
for (let i = 0; i < this.crib.length; i++) {
|
for (let i=0; i<this.crib.length; i++) {
|
||||||
const a = this.crib[i];
|
const a = this.crib[i];
|
||||||
const b = this.ciphertext[i];
|
const b = this.ciphertext[i];
|
||||||
new Edge(i, nodes.get(a), nodes.get(b));
|
new Edge(i, nodes.get(a), nodes.get(b));
|
||||||
|
@ -526,14 +499,14 @@ export class BombeMachine {
|
||||||
* @param {number} j - Bombe stecker hypothesis wire within bundle
|
* @param {number} j - Bombe stecker hypothesis wire within bundle
|
||||||
*/
|
*/
|
||||||
energise(i, j) {
|
energise(i, j) {
|
||||||
const idx = 26 * i + j;
|
const idx = 26*i + j;
|
||||||
if (this.wires[idx]) {
|
if (this.wires[idx]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.wires[idx] = true;
|
this.wires[idx] = true;
|
||||||
// Welchman's diagonal board: if A steckers to B, that implies B steckers to A. Handle
|
// Welchman's diagonal board: if A steckers to B, that implies B steckers to A. Handle
|
||||||
// both.
|
// both.
|
||||||
const idxPair = 26 * j + i;
|
const idxPair = 26*j + i;
|
||||||
this.wires[idxPair] = true;
|
this.wires[idxPair] = true;
|
||||||
if (i === this.testRegister || j === this.testRegister) {
|
if (i === this.testRegister || j === this.testRegister) {
|
||||||
this.energiseCount++;
|
this.energiseCount++;
|
||||||
|
@ -543,12 +516,12 @@ export class BombeMachine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let k = 0; k < this.scramblers[i].length; k++) {
|
for (let k=0; k<this.scramblers[i].length; k++) {
|
||||||
const scrambler = this.scramblers[i][k];
|
const scrambler = this.scramblers[i][k];
|
||||||
const out = scrambler.transform(j);
|
const out = scrambler.transform(j);
|
||||||
const other = scrambler.getOtherEnd(i);
|
const other = scrambler.getOtherEnd(i);
|
||||||
// Lift the pre-check before the call, to save some function call overhead
|
// Lift the pre-check before the call, to save some function call overhead
|
||||||
const otherIdx = 26 * other + out;
|
const otherIdx = 26*other + out;
|
||||||
if (!this.wires[otherIdx]) {
|
if (!this.wires[otherIdx]) {
|
||||||
this.energise(other, out);
|
this.energise(other, out);
|
||||||
if (this.energiseCount === 26) {
|
if (this.energiseCount === 26) {
|
||||||
|
@ -559,11 +532,11 @@ export class BombeMachine {
|
||||||
if (i === j) {
|
if (i === j) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let k = 0; k < this.scramblers[j].length; k++) {
|
for (let k=0; k<this.scramblers[j].length; k++) {
|
||||||
const scrambler = this.scramblers[j][k];
|
const scrambler = this.scramblers[j][k];
|
||||||
const out = scrambler.transform(i);
|
const out = scrambler.transform(i);
|
||||||
const other = scrambler.getOtherEnd(j);
|
const other = scrambler.getOtherEnd(j);
|
||||||
const otherIdx = 26 * other + out;
|
const otherIdx = 26*other + out;
|
||||||
if (!this.wires[otherIdx]) {
|
if (!this.wires[otherIdx]) {
|
||||||
this.energise(other, out);
|
this.energise(other, out);
|
||||||
if (this.energiseCount === 26) {
|
if (this.energiseCount === 26) {
|
||||||
|
@ -588,10 +561,8 @@ export class BombeMachine {
|
||||||
const res = [];
|
const res = [];
|
||||||
const plugboard = new Plugboard(stecker);
|
const plugboard = new Plugboard(stecker);
|
||||||
// The indicator scrambler starts in the right place for the beginning of the ciphertext.
|
// The indicator scrambler starts in the right place for the beginning of the ciphertext.
|
||||||
for (let i = 0; i < Math.min(26, this.ciphertext.length); i++) {
|
for (let i=0; i<Math.min(26, this.ciphertext.length); i++) {
|
||||||
const t = this.indicator.transform(
|
const t = this.indicator.transform(plugboard.transform(a2i(this.ciphertext[i])));
|
||||||
plugboard.transform(a2i(this.ciphertext[i])),
|
|
||||||
);
|
|
||||||
res.push(i2a(plugboard.transform(t)));
|
res.push(i2a(plugboard.transform(t)));
|
||||||
this.indicator.step(1);
|
this.indicator.step(1);
|
||||||
}
|
}
|
||||||
|
@ -631,7 +602,7 @@ export class BombeMachine {
|
||||||
if (pair !== this.testInput[1]) {
|
if (pair !== this.testInput[1]) {
|
||||||
// We have a new hypothesis for this stop - apply the new one.
|
// We have a new hypothesis for this stop - apply the new one.
|
||||||
// De-energise the board
|
// De-energise the board
|
||||||
for (let i = 0; i < this.wires.length; i++) {
|
for (let i=0; i<this.wires.length; i++) {
|
||||||
this.wires[i] = false;
|
this.wires[i] = false;
|
||||||
}
|
}
|
||||||
this.energiseCount = 0;
|
this.energiseCount = 0;
|
||||||
|
@ -641,11 +612,11 @@ export class BombeMachine {
|
||||||
|
|
||||||
const results = new Set();
|
const results = new Set();
|
||||||
results.add(this.formatPair(this.testRegister, pair));
|
results.add(this.formatPair(this.testRegister, pair));
|
||||||
for (let i = 0; i < 26; i++) {
|
for (let i=0; i<26; i++) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let other;
|
let other;
|
||||||
for (let j = 0; j < 26; j++) {
|
for (let j=0; j<26; j++) {
|
||||||
if (this.wires[i * 26 + j]) {
|
if (this.wires[i*26 + j]) {
|
||||||
count++;
|
count++;
|
||||||
other = j;
|
other = j;
|
||||||
}
|
}
|
||||||
|
@ -678,8 +649,8 @@ export class BombeMachine {
|
||||||
// started with are hypothesised to be a stecker pair.
|
// started with are hypothesised to be a stecker pair.
|
||||||
if (count === 25) {
|
if (count === 25) {
|
||||||
// Our steckering hypothesis is wrong. Correct value is the un-energised wire.
|
// Our steckering hypothesis is wrong. Correct value is the un-energised wire.
|
||||||
for (let j = 0; j < 26; j++) {
|
for (let j=0; j<26; j++) {
|
||||||
if (!this.wires[26 * this.testRegister + j]) {
|
if (!this.wires[26*this.testRegister + j]) {
|
||||||
steckerPair = j;
|
steckerPair = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -705,11 +676,7 @@ export class BombeMachine {
|
||||||
if (newStecker !== "") {
|
if (newStecker !== "") {
|
||||||
if (stecker !== undefined) {
|
if (stecker !== undefined) {
|
||||||
// Multiple hypotheses can't be ruled out.
|
// Multiple hypotheses can't be ruled out.
|
||||||
return [
|
return [this.indicator.getPos(), "??", this.tryDecrypt("")];
|
||||||
this.indicator.getPos(),
|
|
||||||
"??",
|
|
||||||
this.tryDecrypt(""),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
stecker = newStecker;
|
stecker = newStecker;
|
||||||
}
|
}
|
||||||
|
@ -746,9 +713,9 @@ export class BombeMachine {
|
||||||
const result = [];
|
const result = [];
|
||||||
// For each possible rotor setting
|
// For each possible rotor setting
|
||||||
const nChecks = Math.pow(26, this.baseRotors.length);
|
const nChecks = Math.pow(26, this.baseRotors.length);
|
||||||
for (let i = 1; i <= nChecks; i++) {
|
for (let i=1; i<=nChecks; i++) {
|
||||||
// Benchmarking suggests this is faster than using .fill()
|
// Benchmarking suggests this is faster than using .fill()
|
||||||
for (let i = 0; i < this.wires.length; i++) {
|
for (let i=0; i<this.wires.length; i++) {
|
||||||
this.wires[i] = false;
|
this.wires[i] = false;
|
||||||
}
|
}
|
||||||
this.energiseCount = 0;
|
this.energiseCount = 0;
|
||||||
|
@ -765,8 +732,8 @@ export class BombeMachine {
|
||||||
// This loop counts how many rotors have reached their starting position (meaning the
|
// This loop counts how many rotors have reached their starting position (meaning the
|
||||||
// next one needs to step as well)
|
// next one needs to step as well)
|
||||||
let n = 1;
|
let n = 1;
|
||||||
for (let j = 1; j < this.baseRotors.length; j++) {
|
for (let j=1; j<this.baseRotors.length; j++) {
|
||||||
if (i % Math.pow(26, j) === 0) {
|
if ((i % Math.pow(26, j)) === 0) {
|
||||||
n++;
|
n++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -781,7 +748,7 @@ export class BombeMachine {
|
||||||
// Send status messages at what seems to be a reasonably sensible frequency
|
// Send status messages at what seems to be a reasonably sensible frequency
|
||||||
// (note this won't be triggered on 3-rotor runs - they run fast enough it doesn't seem necessary)
|
// (note this won't be triggered on 3-rotor runs - they run fast enough it doesn't seem necessary)
|
||||||
if (n > 3) {
|
if (n > 3) {
|
||||||
this.update(this.nLoops, stops, i / nChecks);
|
this.update(this.nLoops, stops, i/nChecks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
*/
|
*/
|
||||||
export const BRAILLE_LOOKUP = {
|
export const BRAILLE_LOOKUP = {
|
||||||
ascii: " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)=",
|
ascii: " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)=",
|
||||||
dot6: "⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿",
|
dot6: "⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿"
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,15 +34,7 @@ export function drawLine(ctx, startX, startY, endX, endY) {
|
||||||
* @param numYLabels
|
* @param numYLabels
|
||||||
* @param fontSize
|
* @param fontSize
|
||||||
*/
|
*/
|
||||||
export function drawBarChart(
|
export function drawBarChart(canvas, scores, xAxisLabel, yAxisLabel, numXLabels, numYLabels, fontSize) {
|
||||||
canvas,
|
|
||||||
scores,
|
|
||||||
xAxisLabel,
|
|
||||||
yAxisLabel,
|
|
||||||
numXLabels,
|
|
||||||
numYLabels,
|
|
||||||
fontSize,
|
|
||||||
) {
|
|
||||||
fontSize = fontSize || 15;
|
fontSize = fontSize || 15;
|
||||||
if (!numXLabels || numXLabels > Math.round(canvas.width / 50)) {
|
if (!numXLabels || numXLabels > Math.round(canvas.width / 50)) {
|
||||||
numXLabels = Math.round(canvas.width / 50);
|
numXLabels = Math.round(canvas.width / 50);
|
||||||
|
@ -72,14 +64,14 @@ export function drawBarChart(
|
||||||
|
|
||||||
// Bar properties
|
// Bar properties
|
||||||
const barPadding = graphWidth * 0.003,
|
const barPadding = graphWidth * 0.003,
|
||||||
barWidth = (graphWidth - barPadding * scores.length) / scores.length,
|
barWidth = (graphWidth - (barPadding * scores.length)) / scores.length,
|
||||||
max = Math.max.apply(Math, scores);
|
max = Math.max.apply(Math, scores);
|
||||||
let currX = leftPadding + barPadding;
|
let currX = leftPadding + barPadding;
|
||||||
|
|
||||||
// Draw bars
|
// Draw bars
|
||||||
ctx.fillStyle = "green";
|
ctx.fillStyle = "green";
|
||||||
for (let i = 0; i < scores.length; i++) {
|
for (let i = 0; i < scores.length; i++) {
|
||||||
const h = (scores[i] / max) * graphHeight;
|
const h = scores[i] / max * graphHeight;
|
||||||
ctx.fillRect(currX, base - h, barWidth, h);
|
ctx.fillRect(currX, base - h, barWidth, h);
|
||||||
currX += barWidth + barPadding;
|
currX += barWidth + barPadding;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +83,7 @@ export function drawBarChart(
|
||||||
if (numXLabels >= scores.length) {
|
if (numXLabels >= scores.length) {
|
||||||
// Mark every score
|
// Mark every score
|
||||||
for (let i = 0; i <= scores.length; i++) {
|
for (let i = 0; i <= scores.length; i++) {
|
||||||
ctx.fillText(i, currX, base + bottomPadding * 0.3);
|
ctx.fillText(i, currX, base + (bottomPadding * 0.3));
|
||||||
currX += barWidth + barPadding;
|
currX += barWidth + barPadding;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -99,7 +91,7 @@ export function drawBarChart(
|
||||||
for (let i = 0; i <= numXLabels; i++) {
|
for (let i = 0; i <= numXLabels; i++) {
|
||||||
const val = Math.ceil((scores.length / numXLabels) * i);
|
const val = Math.ceil((scores.length / numXLabels) * i);
|
||||||
currX = (graphWidth / numXLabels) * i + leftPadding;
|
currX = (graphWidth / numXLabels) * i + leftPadding;
|
||||||
ctx.fillText(val, currX, base + bottomPadding * 0.3);
|
ctx.fillText(val, currX, base + (bottomPadding * 0.3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,14 +101,14 @@ export function drawBarChart(
|
||||||
if (numYLabels >= max) {
|
if (numYLabels >= max) {
|
||||||
// Mark every increment
|
// Mark every increment
|
||||||
for (let i = 0; i <= max; i++) {
|
for (let i = 0; i <= max; i++) {
|
||||||
currY = base - (i / max) * graphHeight + fontSize / 3;
|
currY = base - (i / max * graphHeight) + fontSize / 3;
|
||||||
ctx.fillText(i, leftPadding * 0.8, currY);
|
ctx.fillText(i, leftPadding * 0.8, currY);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Mark some increments
|
// Mark some increments
|
||||||
for (let i = 0; i <= numYLabels; i++) {
|
for (let i = 0; i <= numYLabels; i++) {
|
||||||
const val = Math.ceil((max / numYLabels) * i);
|
const val = Math.ceil((max / numYLabels) * i);
|
||||||
currY = base - (val / max) * graphHeight + fontSize / 3;
|
currY = base - (val / max * graphHeight) + fontSize / 3;
|
||||||
ctx.fillText(val, leftPadding * 0.8, currY);
|
ctx.fillText(val, leftPadding * 0.8, currY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,11 +116,7 @@ export function drawBarChart(
|
||||||
// Label x axis
|
// Label x axis
|
||||||
if (xAxisLabel) {
|
if (xAxisLabel) {
|
||||||
ctx.textAlign = "center";
|
ctx.textAlign = "center";
|
||||||
ctx.fillText(
|
ctx.fillText(xAxisLabel, graphWidth / 2 + leftPadding, base + bottomPadding * 0.8);
|
||||||
xAxisLabel,
|
|
||||||
graphWidth / 2 + leftPadding,
|
|
||||||
base + bottomPadding * 0.8,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label y axis
|
// Label y axis
|
||||||
|
@ -169,12 +157,7 @@ export function drawScaleBar(canvas, score, max, markings) {
|
||||||
ctx.strokeRect(leftPadding, topPadding, barWidth, barHeight);
|
ctx.strokeRect(leftPadding, topPadding, barWidth, barHeight);
|
||||||
|
|
||||||
// Shade in up to proportion
|
// Shade in up to proportion
|
||||||
const grad = ctx.createLinearGradient(
|
const grad = ctx.createLinearGradient(leftPadding, 0, barWidth + leftPadding, 0);
|
||||||
leftPadding,
|
|
||||||
0,
|
|
||||||
barWidth + leftPadding,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
grad.addColorStop(0, "green");
|
grad.addColorStop(0, "green");
|
||||||
grad.addColorStop(0.5, "gold");
|
grad.addColorStop(0.5, "gold");
|
||||||
grad.addColorStop(1, "red");
|
grad.addColorStop(1, "red");
|
||||||
|
@ -188,21 +171,21 @@ export function drawScaleBar(canvas, score, max, markings) {
|
||||||
ctx.font = "13px Arial";
|
ctx.font = "13px Arial";
|
||||||
for (let i = 0; i < markings.length; i++) {
|
for (let i = 0; i < markings.length; i++) {
|
||||||
// Draw min line down
|
// Draw min line down
|
||||||
x0 = (barWidth / max) * markings[i].min + leftPadding;
|
x0 = barWidth / max * markings[i].min + leftPadding;
|
||||||
y0 = topPadding + barHeight + bottomPadding * 0.1;
|
y0 = topPadding + barHeight + (bottomPadding * 0.1);
|
||||||
x1 = x0;
|
x1 = x0;
|
||||||
y1 = topPadding + barHeight + bottomPadding * 0.3;
|
y1 = topPadding + barHeight + (bottomPadding * 0.3);
|
||||||
drawLine(ctx, x0, y0, x1, y1);
|
drawLine(ctx, x0, y0, x1, y1);
|
||||||
|
|
||||||
// Draw max line down
|
// Draw max line down
|
||||||
x0 = (barWidth / max) * markings[i].max + leftPadding;
|
x0 = barWidth / max * markings[i].max + leftPadding;
|
||||||
x1 = x0;
|
x1 = x0;
|
||||||
drawLine(ctx, x0, y0, x1, y1);
|
drawLine(ctx, x0, y0, x1, y1);
|
||||||
|
|
||||||
// Join min and max lines
|
// Join min and max lines
|
||||||
x0 = (barWidth / max) * markings[i].min + leftPadding;
|
x0 = barWidth / max * markings[i].min + leftPadding;
|
||||||
y0 = topPadding + barHeight + bottomPadding * 0.3;
|
y0 = topPadding + barHeight + (bottomPadding * 0.3);
|
||||||
x1 = (barWidth / max) * markings[i].max + leftPadding;
|
x1 = barWidth / max * markings[i].max + leftPadding;
|
||||||
y1 = y0;
|
y1 = y0;
|
||||||
drawLine(ctx, x0, y0, x1, y1);
|
drawLine(ctx, x0, y0, x1, y1);
|
||||||
|
|
||||||
|
@ -215,7 +198,7 @@ export function drawScaleBar(canvas, score, max, markings) {
|
||||||
} else {
|
} else {
|
||||||
x0 = x0 + (x1 - x0) / 2;
|
x0 = x0 + (x1 - x0) / 2;
|
||||||
}
|
}
|
||||||
y0 = topPadding + barHeight + bottomPadding * 0.8;
|
y0 = topPadding + barHeight + (bottomPadding * 0.8);
|
||||||
ctx.fillText(markings[i].label, x0, y0);
|
ctx.fillText(markings[i].label, x0, y0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,13 @@ import Utils from "../Utils.mjs";
|
||||||
*/
|
*/
|
||||||
export const RECORD_DELIMITER_OPTIONS = ["Line feed", "CRLF"];
|
export const RECORD_DELIMITER_OPTIONS = ["Line feed", "CRLF"];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constant
|
* @constant
|
||||||
* @default
|
* @default
|
||||||
*/
|
*/
|
||||||
export const FIELD_DELIMITER_OPTIONS = [
|
export const FIELD_DELIMITER_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Tab"];
|
||||||
"Space",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
"Tab",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default from colour
|
* Default from colour
|
||||||
|
@ -34,9 +30,10 @@ export const FIELD_DELIMITER_OPTIONS = [
|
||||||
*/
|
*/
|
||||||
export const COLOURS = {
|
export const COLOURS = {
|
||||||
min: "white",
|
min: "white",
|
||||||
max: "black",
|
max: "black"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets values from input for a plot.
|
* Gets values from input for a plot.
|
||||||
*
|
*
|
||||||
|
@ -47,20 +44,15 @@ export const COLOURS = {
|
||||||
* @param {number} length
|
* @param {number} length
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
export function getValues(
|
export function getValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded, length) {
|
||||||
input,
|
|
||||||
recordDelimiter,
|
|
||||||
fieldDelimiter,
|
|
||||||
columnHeadingsAreIncluded,
|
|
||||||
length,
|
|
||||||
) {
|
|
||||||
let headings;
|
let headings;
|
||||||
const values = [];
|
const values = [];
|
||||||
|
|
||||||
input.split(recordDelimiter).forEach((row, rowIndex) => {
|
input
|
||||||
|
.split(recordDelimiter)
|
||||||
|
.forEach((row, rowIndex) => {
|
||||||
const split = row.split(fieldDelimiter);
|
const split = row.split(fieldDelimiter);
|
||||||
if (split.length !== length)
|
if (split.length !== length) throw new OperationError(`Each row must have length ${length}.`);
|
||||||
throw new OperationError(`Each row must have length ${length}.`);
|
|
||||||
|
|
||||||
if (columnHeadingsAreIncluded && rowIndex === 0) {
|
if (columnHeadingsAreIncluded && rowIndex === 0) {
|
||||||
headings = split;
|
headings = split;
|
||||||
|
@ -71,6 +63,7 @@ export function getValues(
|
||||||
return { headings, values };
|
return { headings, values };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets values from input for a scatter plot.
|
* Gets values from input for a scatter plot.
|
||||||
*
|
*
|
||||||
|
@ -80,32 +73,25 @@ export function getValues(
|
||||||
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
|
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
export function getScatterValues(
|
export function getScatterValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
|
||||||
input,
|
|
||||||
recordDelimiter,
|
|
||||||
fieldDelimiter,
|
|
||||||
columnHeadingsAreIncluded,
|
|
||||||
) {
|
|
||||||
let { headings, values } = getValues(
|
let { headings, values } = getValues(
|
||||||
input,
|
input,
|
||||||
recordDelimiter,
|
recordDelimiter,
|
||||||
fieldDelimiter,
|
fieldDelimiter,
|
||||||
columnHeadingsAreIncluded,
|
columnHeadingsAreIncluded,
|
||||||
2,
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
if (headings) {
|
if (headings) {
|
||||||
headings = { x: headings[0], y: headings[1] };
|
headings = {x: headings[0], y: headings[1]};
|
||||||
}
|
}
|
||||||
|
|
||||||
values = values.map((row) => {
|
values = values.map(row => {
|
||||||
const x = parseFloat(row[0]),
|
const x = parseFloat(row[0]),
|
||||||
y = parseFloat(row[1]);
|
y = parseFloat(row[1]);
|
||||||
|
|
||||||
if (Number.isNaN(x))
|
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
throw new OperationError("Values must be numbers in base 10.");
|
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
if (Number.isNaN(y))
|
|
||||||
throw new OperationError("Values must be numbers in base 10.");
|
|
||||||
|
|
||||||
return [x, y];
|
return [x, y];
|
||||||
});
|
});
|
||||||
|
@ -113,6 +99,7 @@ export function getScatterValues(
|
||||||
return { headings, values };
|
return { headings, values };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets values from input for a scatter plot with colour from the third column.
|
* Gets values from input for a scatter plot with colour from the third column.
|
||||||
*
|
*
|
||||||
|
@ -122,33 +109,25 @@ export function getScatterValues(
|
||||||
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
|
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
export function getScatterValuesWithColour(
|
export function getScatterValuesWithColour(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
|
||||||
input,
|
|
||||||
recordDelimiter,
|
|
||||||
fieldDelimiter,
|
|
||||||
columnHeadingsAreIncluded,
|
|
||||||
) {
|
|
||||||
let { headings, values } = getValues(
|
let { headings, values } = getValues(
|
||||||
input,
|
input,
|
||||||
recordDelimiter,
|
recordDelimiter, fieldDelimiter,
|
||||||
fieldDelimiter,
|
|
||||||
columnHeadingsAreIncluded,
|
columnHeadingsAreIncluded,
|
||||||
3,
|
3
|
||||||
);
|
);
|
||||||
|
|
||||||
if (headings) {
|
if (headings) {
|
||||||
headings = { x: headings[0], y: headings[1] };
|
headings = {x: headings[0], y: headings[1]};
|
||||||
}
|
}
|
||||||
|
|
||||||
values = values.map((row) => {
|
values = values.map(row => {
|
||||||
const x = parseFloat(row[0]),
|
const x = parseFloat(row[0]),
|
||||||
y = parseFloat(row[1]),
|
y = parseFloat(row[1]),
|
||||||
colour = row[2];
|
colour = row[2];
|
||||||
|
|
||||||
if (Number.isNaN(x))
|
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
throw new OperationError("Values must be numbers in base 10.");
|
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
if (Number.isNaN(y))
|
|
||||||
throw new OperationError("Values must be numbers in base 10.");
|
|
||||||
|
|
||||||
return [x, y, Utils.escapeHtml(colour)];
|
return [x, y, Utils.escapeHtml(colour)];
|
||||||
});
|
});
|
||||||
|
@ -165,30 +144,23 @@ export function getScatterValuesWithColour(
|
||||||
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
|
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
export function getSeriesValues(
|
export function getSeriesValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
|
||||||
input,
|
|
||||||
recordDelimiter,
|
|
||||||
fieldDelimiter,
|
|
||||||
columnHeadingsAreIncluded,
|
|
||||||
) {
|
|
||||||
const { values } = getValues(
|
const { values } = getValues(
|
||||||
input,
|
input,
|
||||||
recordDelimiter,
|
recordDelimiter, fieldDelimiter,
|
||||||
fieldDelimiter,
|
|
||||||
false,
|
false,
|
||||||
3,
|
3
|
||||||
);
|
);
|
||||||
|
|
||||||
let xValues = new Set();
|
let xValues = new Set();
|
||||||
const series = {};
|
const series = {};
|
||||||
|
|
||||||
values.forEach((row) => {
|
values.forEach(row => {
|
||||||
const serie = row[0],
|
const serie = row[0],
|
||||||
xVal = row[1],
|
xVal = row[1],
|
||||||
val = parseFloat(row[2]);
|
val = parseFloat(row[2]);
|
||||||
|
|
||||||
if (Number.isNaN(val))
|
if (Number.isNaN(val)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
throw new OperationError("Values must be numbers in base 10.");
|
|
||||||
|
|
||||||
xValues.add(xVal);
|
xValues.add(xVal);
|
||||||
if (typeof series[serie] === "undefined") series[serie] = {};
|
if (typeof series[serie] === "undefined") series[serie] = {};
|
||||||
|
@ -200,7 +172,7 @@ export function getSeriesValues(
|
||||||
const seriesList = [];
|
const seriesList = [];
|
||||||
for (const seriesName in series) {
|
for (const seriesName in series) {
|
||||||
const serie = series[seriesName];
|
const serie = series[seriesName];
|
||||||
seriesList.push({ name: seriesName, data: serie });
|
seriesList.push({name: seriesName, data: serie});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { xValues, series: seriesList };
|
return { xValues, series: seriesList };
|
||||||
|
|
|
@ -166,6 +166,7 @@ export const CHR_ENC_CODE_PAGES = {
|
||||||
"Simplified Chinese GB18030 (54936)": 54936,
|
"Simplified Chinese GB18030 (54936)": 54936,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const CHR_ENC_SIMPLE_LOOKUP = {};
|
export const CHR_ENC_SIMPLE_LOOKUP = {};
|
||||||
export const CHR_ENC_SIMPLE_REVERSE_LOOKUP = {};
|
export const CHR_ENC_SIMPLE_REVERSE_LOOKUP = {};
|
||||||
|
|
||||||
|
@ -176,6 +177,7 @@ for (const name in CHR_ENC_CODE_PAGES) {
|
||||||
CHR_ENC_SIMPLE_REVERSE_LOOKUP[CHR_ENC_CODE_PAGES[name]] = simpleName;
|
CHR_ENC_SIMPLE_REVERSE_LOOKUP[CHR_ENC_CODE_PAGES[name]] = simpleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the width of the character set for the given codepage.
|
* Returns the width of the character set for the given codepage.
|
||||||
* For example, UTF-8 is a Single Byte Character Set, whereas
|
* For example, UTF-8 is a Single Byte Character Set, whereas
|
||||||
|
@ -192,12 +194,7 @@ export function chrEncWidth(page) {
|
||||||
|
|
||||||
const pageStr = page.toString();
|
const pageStr = page.toString();
|
||||||
// Confirm this page is legitimate
|
// Confirm this page is legitimate
|
||||||
if (
|
if (!Object.prototype.hasOwnProperty.call(CHR_ENC_SIMPLE_REVERSE_LOOKUP, pageStr))
|
||||||
!Object.prototype.hasOwnProperty.call(
|
|
||||||
CHR_ENC_SIMPLE_REVERSE_LOOKUP,
|
|
||||||
pageStr,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Statically defined code pages
|
// Statically defined code pages
|
||||||
|
@ -205,8 +202,10 @@ export function chrEncWidth(page) {
|
||||||
return cptable[pageStr].dec.length > 256 ? 2 : 1;
|
return cptable[pageStr].dec.length > 256 ? 2 : 1;
|
||||||
|
|
||||||
// Cached code pages
|
// Cached code pages
|
||||||
if (cptable.utils.cache.sbcs.includes(pageStr)) return 1;
|
if (cptable.utils.cache.sbcs.includes(pageStr))
|
||||||
if (cptable.utils.cache.dbcs.includes(pageStr)) return 2;
|
return 1;
|
||||||
|
if (cptable.utils.cache.dbcs.includes(pageStr))
|
||||||
|
return 2;
|
||||||
|
|
||||||
// Dynamically generated code pages
|
// Dynamically generated code pages
|
||||||
if (Object.prototype.hasOwnProperty.call(cptable.utils.magic, pageStr)) {
|
if (Object.prototype.hasOwnProperty.call(cptable.utils.magic, pageStr)) {
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
export function encode(tempIVP, key, rounds, input) {
|
export function encode(tempIVP, key, rounds, input) {
|
||||||
const ivp = new Uint8Array(key.concat(tempIVP));
|
const ivp = new Uint8Array(key.concat(tempIVP));
|
||||||
const state = new Array(256).fill(0);
|
const state = new Array(256).fill(0);
|
||||||
let j = 0,
|
let j = 0, i = 0;
|
||||||
i = 0;
|
|
||||||
const result = [];
|
const result = [];
|
||||||
|
|
||||||
// Mixing states based off of IV.
|
// Mixing states based off of IV.
|
||||||
for (let i = 0; i < 256; i++) state[i] = i;
|
for (let i = 0; i < 256; i++)
|
||||||
|
state[i] = i;
|
||||||
const ivpLength = ivp.length;
|
const ivpLength = ivp.length;
|
||||||
for (let r = 0; r < rounds; r++) {
|
for (let r = 0; r < rounds; r ++) {
|
||||||
for (let k = 0; k < 256; k++) {
|
for (let k = 0; k < 256; k++) {
|
||||||
j = (j + state[k] + ivp[k % ivpLength]) % 256;
|
j = (j + state[k] + ivp[k % ivpLength]) % 256;
|
||||||
[state[k], state[j]] = [state[j], state[k]];
|
[state[k], state[j]] = [state[j], state[k]];
|
||||||
|
@ -24,7 +24,7 @@ export function encode(tempIVP, key, rounds, input) {
|
||||||
|
|
||||||
// XOR cipher with key.
|
// XOR cipher with key.
|
||||||
for (let x = 0; x < input.length; x++) {
|
for (let x = 0; x < input.length; x++) {
|
||||||
i = ++i % 256;
|
i = (++i) % 256;
|
||||||
j = (j + state[i]) % 256;
|
j = (j + state[i]) % 256;
|
||||||
[state[i], state[j]] = [state[j], state[i]];
|
[state[i], state[j]] = [state[j], state[i]];
|
||||||
const n = (state[i] + state[j]) % 256;
|
const n = (state[i] + state[j]) % 256;
|
||||||
|
|
|
@ -33,13 +33,10 @@ export function affineEncode(input, args) {
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
if (alphabet.indexOf(input[i]) >= 0) {
|
if (alphabet.indexOf(input[i]) >= 0) {
|
||||||
// Uses the affine function ax+b % m = y (where m is length of the alphabet)
|
// Uses the affine function ax+b % m = y (where m is length of the alphabet)
|
||||||
output += alphabet[(a * alphabet.indexOf(input[i]) + b) % 26];
|
output += alphabet[((a * alphabet.indexOf(input[i])) + b) % 26];
|
||||||
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
||||||
// Same as above, accounting for uppercase
|
// Same as above, accounting for uppercase
|
||||||
output +=
|
output += alphabet[((a * alphabet.indexOf(input[i].toLowerCase())) + b) % 26].toUpperCase();
|
||||||
alphabet[
|
|
||||||
(a * alphabet.indexOf(input[i].toLowerCase()) + b) % 26
|
|
||||||
].toUpperCase();
|
|
||||||
} else {
|
} else {
|
||||||
// Non-alphabetic characters
|
// Non-alphabetic characters
|
||||||
output += input[i];
|
output += input[i];
|
||||||
|
@ -56,13 +53,13 @@ export function affineEncode(input, args) {
|
||||||
* @param {string} keyword - Must be upper case
|
* @param {string} keyword - Must be upper case
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function genPolybiusSquare(keyword) {
|
export function genPolybiusSquare (keyword) {
|
||||||
const alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ",
|
const alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ",
|
||||||
polArray = `${keyword}${alpha}`.split("").unique(),
|
polArray = `${keyword}${alpha}`.split("").unique(),
|
||||||
polybius = [];
|
polybius = [];
|
||||||
|
|
||||||
for (let i = 0; i < 5; i++) {
|
for (let i = 0; i < 5; i++) {
|
||||||
polybius[i] = polArray.slice(i * 5, i * 5 + 5);
|
polybius[i] = polArray.slice(i*5, i*5 + 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
return polybius;
|
return polybius;
|
||||||
|
@ -75,11 +72,11 @@ export function genPolybiusSquare(keyword) {
|
||||||
* @constant
|
* @constant
|
||||||
*/
|
*/
|
||||||
export const format = {
|
export const format = {
|
||||||
Hex: CryptoJS.enc.Hex,
|
"Hex": CryptoJS.enc.Hex,
|
||||||
Base64: CryptoJS.enc.Base64,
|
"Base64": CryptoJS.enc.Base64,
|
||||||
UTF8: CryptoJS.enc.Utf8,
|
"UTF8": CryptoJS.enc.Utf8,
|
||||||
UTF16: CryptoJS.enc.Utf16,
|
"UTF16": CryptoJS.enc.Utf16,
|
||||||
UTF16LE: CryptoJS.enc.Utf16LE,
|
"UTF16LE": CryptoJS.enc.Utf16LE,
|
||||||
UTF16BE: CryptoJS.enc.Utf16BE,
|
"UTF16BE": CryptoJS.enc.Utf16BE,
|
||||||
Latin1: CryptoJS.enc.Latin1,
|
"Latin1": CryptoJS.enc.Latin1,
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function replaceVariableNames(input, replacer) {
|
export function replaceVariableNames(input, replacer) {
|
||||||
const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/gi;
|
const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig;
|
||||||
|
|
||||||
return input.replace(tokenRegex, (...args) => {
|
return input.replace(tokenRegex, (...args) => {
|
||||||
const match = args[0],
|
const match = args[0],
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* @copyright Crown Copyright 2019
|
* @copyright Crown Copyright 2019
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
import { INIT_PATTERNS, ITA2_TABLE, ROTOR_SIZES } from "../lib/Lorenz.mjs";
|
import {INIT_PATTERNS, ITA2_TABLE, ROTOR_SIZES} from "../lib/Lorenz.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Colossus simulator class.
|
* Colossus simulator class.
|
||||||
|
@ -21,16 +21,7 @@ export class ColossusComputer {
|
||||||
* @param {Object} control - control switches which specify stepping modes
|
* @param {Object} control - control switches which specify stepping modes
|
||||||
* @param {Object} starts - rotor start positions
|
* @param {Object} starts - rotor start positions
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(ciphertext, pattern, qbusin, qbusswitches, control, starts, settotal, limit) {
|
||||||
ciphertext,
|
|
||||||
pattern,
|
|
||||||
qbusin,
|
|
||||||
qbusswitches,
|
|
||||||
control,
|
|
||||||
starts,
|
|
||||||
settotal,
|
|
||||||
limit,
|
|
||||||
) {
|
|
||||||
this.ITAlookup = ITA2_TABLE;
|
this.ITAlookup = ITA2_TABLE;
|
||||||
this.ReverseITAlookup = {};
|
this.ReverseITAlookup = {};
|
||||||
for (const letter in this.ITAlookup) {
|
for (const letter in this.ITAlookup) {
|
||||||
|
@ -48,6 +39,7 @@ export class ColossusComputer {
|
||||||
this.settotal = settotal;
|
this.settotal = settotal;
|
||||||
this.limitations = limit;
|
this.limitations = limit;
|
||||||
|
|
||||||
|
|
||||||
this.allCounters = [0, 0, 0, 0, 0];
|
this.allCounters = [0, 0, 0, 0, 0];
|
||||||
|
|
||||||
this.Zbits = [0, 0, 0, 0, 0]; // Z input is the cipher tape
|
this.Zbits = [0, 0, 0, 0, 0]; // Z input is the cipher tape
|
||||||
|
@ -77,24 +69,11 @@ export class ColossusComputer {
|
||||||
*/
|
*/
|
||||||
run() {
|
run() {
|
||||||
const result = {
|
const result = {
|
||||||
printout: "",
|
printout: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
// loop until our start positions are back to the beginning
|
// loop until our start positions are back to the beginning
|
||||||
this.rotorPtrs = {
|
this.rotorPtrs = {X1: this.starts.X1, X2: this.starts.X2, X3: this.starts.X3, X4: this.starts.X4, X5: this.starts.X5, M61: this.starts.M61, M37: this.starts.M37, S1: this.starts.S1, S2: this.starts.S2, S3: this.starts.S3, S4: this.starts.S4, S5: this.starts.S5};
|
||||||
X1: this.starts.X1,
|
|
||||||
X2: this.starts.X2,
|
|
||||||
X3: this.starts.X3,
|
|
||||||
X4: this.starts.X4,
|
|
||||||
X5: this.starts.X5,
|
|
||||||
M61: this.starts.M61,
|
|
||||||
M37: this.starts.M37,
|
|
||||||
S1: this.starts.S1,
|
|
||||||
S2: this.starts.S2,
|
|
||||||
S3: this.starts.S3,
|
|
||||||
S4: this.starts.S4,
|
|
||||||
S5: this.starts.S5,
|
|
||||||
};
|
|
||||||
// this.rotorPtrs = this.starts;
|
// this.rotorPtrs = this.starts;
|
||||||
let runcount = 1;
|
let runcount = 1;
|
||||||
|
|
||||||
|
@ -115,15 +94,12 @@ export class ColossusComputer {
|
||||||
// Only print result if larger than set total
|
// Only print result if larger than set total
|
||||||
let fastRef = "00";
|
let fastRef = "00";
|
||||||
let slowRef = "00";
|
let slowRef = "00";
|
||||||
if (fast !== "")
|
if (fast !== "") fastRef = this.rotorPtrs[fast].toString().padStart(2, "0");
|
||||||
fastRef = this.rotorPtrs[fast].toString().padStart(2, "0");
|
if (slow !== "") slowRef = this.rotorPtrs[slow].toString().padStart(2, "0");
|
||||||
if (slow !== "")
|
|
||||||
slowRef = this.rotorPtrs[slow].toString().padStart(2, "0");
|
|
||||||
let printline = "";
|
let printline = "";
|
||||||
for (let c = 0; c < 5; c++) {
|
for (let c=0;c<5;c++) {
|
||||||
if (this.allCounters[c] > this.settotal) {
|
if (this.allCounters[c] > this.settotal) {
|
||||||
printline +=
|
printline += String.fromCharCode(c+97) + this.allCounters[c]+" ";
|
||||||
String.fromCharCode(c + 97) + this.allCounters[c] + " ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (printline !== "") {
|
if (printline !== "") {
|
||||||
|
@ -135,21 +111,17 @@ export class ColossusComputer {
|
||||||
// Step fast rotor if required
|
// Step fast rotor if required
|
||||||
if (fast !== "") {
|
if (fast !== "") {
|
||||||
this.rotorPtrs[fast]++;
|
this.rotorPtrs[fast]++;
|
||||||
if (this.rotorPtrs[fast] > ROTOR_SIZES[fast])
|
if (this.rotorPtrs[fast] > ROTOR_SIZES[fast]) this.rotorPtrs[fast] = 1;
|
||||||
this.rotorPtrs[fast] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step slow rotor if fast rotor has returned to initial start position
|
// Step slow rotor if fast rotor has returned to initial start position
|
||||||
if (slow !== "" && this.rotorPtrs[fast] === this.starts[fast]) {
|
if (slow !== "" && this.rotorPtrs[fast] === this.starts[fast]) {
|
||||||
this.rotorPtrs[slow]++;
|
this.rotorPtrs[slow]++;
|
||||||
if (this.rotorPtrs[slow] > ROTOR_SIZES[slow])
|
if (this.rotorPtrs[slow] > ROTOR_SIZES[slow]) this.rotorPtrs[slow] = 1;
|
||||||
this.rotorPtrs[slow] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runcount++;
|
runcount++;
|
||||||
} while (
|
} while (JSON.stringify(this.rotorPtrs) !== JSON.stringify(this.starts));
|
||||||
JSON.stringify(this.rotorPtrs) !== JSON.stringify(this.starts)
|
|
||||||
);
|
|
||||||
|
|
||||||
result.counters = this.allCounters;
|
result.counters = this.allCounters;
|
||||||
result.runcount = runcount;
|
result.runcount = runcount;
|
||||||
|
@ -163,24 +135,12 @@ export class ColossusComputer {
|
||||||
runTape() {
|
runTape() {
|
||||||
let charZin = "";
|
let charZin = "";
|
||||||
|
|
||||||
this.Xptr = [
|
this.Xptr = [this.rotorPtrs.X1, this.rotorPtrs.X2, this.rotorPtrs.X3, this.rotorPtrs.X4, this.rotorPtrs.X5];
|
||||||
this.rotorPtrs.X1,
|
|
||||||
this.rotorPtrs.X2,
|
|
||||||
this.rotorPtrs.X3,
|
|
||||||
this.rotorPtrs.X4,
|
|
||||||
this.rotorPtrs.X5,
|
|
||||||
];
|
|
||||||
this.Mptr = [this.rotorPtrs.M37, this.rotorPtrs.M61];
|
this.Mptr = [this.rotorPtrs.M37, this.rotorPtrs.M61];
|
||||||
this.Sptr = [
|
this.Sptr = [this.rotorPtrs.S1, this.rotorPtrs.S2, this.rotorPtrs.S3, this.rotorPtrs.S4, this.rotorPtrs.S5];
|
||||||
this.rotorPtrs.S1,
|
|
||||||
this.rotorPtrs.S2,
|
|
||||||
this.rotorPtrs.S3,
|
|
||||||
this.rotorPtrs.S4,
|
|
||||||
this.rotorPtrs.S5,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Run full loop of all character on the input tape (Z)
|
// Run full loop of all character on the input tape (Z)
|
||||||
for (let i = 0; i < this.ciphertext.length; i++) {
|
for (let i=0; i<this.ciphertext.length; i++) {
|
||||||
charZin = this.ciphertext.charAt(i);
|
charZin = this.ciphertext.charAt(i);
|
||||||
|
|
||||||
// Firstly, we check what inputs are specified on the Q-bus input switches
|
// Firstly, we check what inputs are specified on the Q-bus input switches
|
||||||
|
@ -204,6 +164,7 @@ export class ColossusComputer {
|
||||||
|
|
||||||
// Step rotors
|
// Step rotors
|
||||||
this.stepThyratrons();
|
this.stepThyratrons();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,44 +175,44 @@ export class ColossusComputer {
|
||||||
* Psi rotors only step dependant on M37 setting + limitation
|
* Psi rotors only step dependant on M37 setting + limitation
|
||||||
*/
|
*/
|
||||||
stepThyratrons() {
|
stepThyratrons() {
|
||||||
let X2bPtr = this.Xptr[1] - 1;
|
let X2bPtr = this.Xptr[1]-1;
|
||||||
if (X2bPtr === 0) X2bPtr = ROTOR_SIZES.X2;
|
if (X2bPtr===0) X2bPtr = ROTOR_SIZES.X2;
|
||||||
let S1bPtr = this.Sptr[0] - 1;
|
let S1bPtr = this.Sptr[0]-1;
|
||||||
if (S1bPtr === 0) S1bPtr = ROTOR_SIZES.S1;
|
if (S1bPtr===0) S1bPtr = ROTOR_SIZES.S1;
|
||||||
|
|
||||||
// Get Chi rotor 5 two back to calculate plaintext (Z+Chi+Psi=Plain)
|
// Get Chi rotor 5 two back to calculate plaintext (Z+Chi+Psi=Plain)
|
||||||
let X5bPtr = this.Xptr[4] - 1;
|
let X5bPtr=this.Xptr[4]-1;
|
||||||
if (X5bPtr === 0) X5bPtr = ROTOR_SIZES.X5;
|
if (X5bPtr===0) X5bPtr=ROTOR_SIZES.X5;
|
||||||
X5bPtr = X5bPtr - 1;
|
X5bPtr=X5bPtr-1;
|
||||||
if (X5bPtr === 0) X5bPtr = ROTOR_SIZES.X5;
|
if (X5bPtr===0) X5bPtr=ROTOR_SIZES.X5;
|
||||||
// Get Psi rotor 5 two back to calculate plaintext (Z+Chi+Psi=Plain)
|
// Get Psi rotor 5 two back to calculate plaintext (Z+Chi+Psi=Plain)
|
||||||
let S5bPtr = this.Sptr[4] - 1;
|
let S5bPtr=this.Sptr[4]-1;
|
||||||
if (S5bPtr === 0) S5bPtr = ROTOR_SIZES.S5;
|
if (S5bPtr===0) S5bPtr=ROTOR_SIZES.S5;
|
||||||
S5bPtr = S5bPtr - 1;
|
S5bPtr=S5bPtr-1;
|
||||||
if (S5bPtr === 0) S5bPtr = ROTOR_SIZES.S5;
|
if (S5bPtr===0) S5bPtr=ROTOR_SIZES.S5;
|
||||||
|
|
||||||
const x2sw = this.limitations.X2;
|
const x2sw = this.limitations.X2;
|
||||||
const s1sw = this.limitations.S1;
|
const s1sw = this.limitations.S1;
|
||||||
const p5sw = this.limitations.P5;
|
const p5sw = this.limitations.P5;
|
||||||
|
|
||||||
// Limitation calculations
|
// Limitation calculations
|
||||||
let lim = 1;
|
let lim=1;
|
||||||
if (x2sw) lim = this.rings.X[2][X2bPtr - 1];
|
if (x2sw) lim = this.rings.X[2][X2bPtr-1];
|
||||||
if (s1sw) lim = lim ^ this.rings.S[1][S1bPtr - 1];
|
if (s1sw) lim = lim ^ this.rings.S[1][S1bPtr-1];
|
||||||
|
|
||||||
// P5
|
// P5
|
||||||
if (p5sw) {
|
if (p5sw) {
|
||||||
let p5lim = this.P5Zbit[1];
|
let p5lim = this.P5Zbit[1];
|
||||||
p5lim = p5lim ^ this.rings.X[5][X5bPtr - 1];
|
p5lim = p5lim ^ this.rings.X[5][X5bPtr-1];
|
||||||
p5lim = p5lim ^ this.rings.S[5][S5bPtr - 1];
|
p5lim = p5lim ^ this.rings.S[5][S5bPtr-1];
|
||||||
lim = lim ^ p5lim;
|
lim = lim ^ p5lim;
|
||||||
}
|
}
|
||||||
|
|
||||||
const basicmotor = this.rings.M[2][this.Mptr[0] - 1];
|
const basicmotor = this.rings.M[2][this.Mptr[0]-1];
|
||||||
this.totalmotor = basicmotor;
|
this.totalmotor = basicmotor;
|
||||||
|
|
||||||
if (x2sw || s1sw) {
|
if (x2sw || s1sw) {
|
||||||
if (basicmotor === 0 && lim === 1) {
|
if (basicmotor===0 && lim===1) {
|
||||||
this.totalmotor = 0;
|
this.totalmotor = 0;
|
||||||
} else {
|
} else {
|
||||||
this.totalmotor = 1;
|
this.totalmotor = 1;
|
||||||
|
@ -259,26 +220,26 @@ export class ColossusComputer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step Chi rotors
|
// Step Chi rotors
|
||||||
for (let r = 0; r < 5; r++) {
|
for (let r=0; r<5; r++) {
|
||||||
this.Xptr[r]++;
|
this.Xptr[r]++;
|
||||||
if (this.Xptr[r] > ROTOR_SIZES["X" + (r + 1)]) this.Xptr[r] = 1;
|
if (this.Xptr[r] > ROTOR_SIZES["X"+(r+1)]) this.Xptr[r] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.totalmotor) {
|
if (this.totalmotor) {
|
||||||
// Step Psi rotors
|
// Step Psi rotors
|
||||||
for (let r = 0; r < 5; r++) {
|
for (let r=0; r<5; r++) {
|
||||||
this.Sptr[r]++;
|
this.Sptr[r]++;
|
||||||
if (this.Sptr[r] > ROTOR_SIZES["S" + (r + 1)]) this.Sptr[r] = 1;
|
if (this.Sptr[r] > ROTOR_SIZES["S"+(r+1)]) this.Sptr[r] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move M37 rotor if M61 set
|
// Move M37 rotor if M61 set
|
||||||
if (this.rings.M[1][this.Mptr[1] - 1] === 1) this.Mptr[0]++;
|
if (this.rings.M[1][this.Mptr[1]-1]===1) this.Mptr[0]++;
|
||||||
if (this.Mptr[0] > ROTOR_SIZES.M37) this.Mptr[0] = 1;
|
if (this.Mptr[0] > ROTOR_SIZES.M37) this.Mptr[0]=1;
|
||||||
|
|
||||||
// Always move M61 rotor
|
// Always move M61 rotor
|
||||||
this.Mptr[1]++;
|
this.Mptr[1]++;
|
||||||
if (this.Mptr[1] > ROTOR_SIZES.M61) this.Mptr[1] = 1;
|
if (this.Mptr[1] > ROTOR_SIZES.M61) this.Mptr[1]=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,25 +253,25 @@ export class ColossusComputer {
|
||||||
this.Qbits = this.Zbits;
|
this.Qbits = this.Zbits;
|
||||||
} else if (this.qbusin.Z === "ΔZ") {
|
} else if (this.qbusin.Z === "ΔZ") {
|
||||||
// delta Z, the Bitwise XOR of this character Zbits + last character Zbits
|
// delta Z, the Bitwise XOR of this character Zbits + last character Zbits
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Qbits[b] = this.Zbits[b] ^ this.ZbitsOneBack[b];
|
this.Qbits[b] = this.Zbits[b] ^ this.ZbitsOneBack[b];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ZbitsOneBack = this.Zbits.slice(); // copy value of object, not reference
|
this.ZbitsOneBack = this.Zbits.slice(); // copy value of object, not reference
|
||||||
|
|
||||||
// Xbits - the current Chi wheel bits
|
// Xbits - the current Chi wheel bits
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Xbits[b] = this.rings.X[b + 1][this.Xptr[b] - 1];
|
this.Xbits[b] = this.rings.X[b+1][this.Xptr[b]-1];
|
||||||
}
|
}
|
||||||
if (this.qbusin.Chi !== "") {
|
if (this.qbusin.Chi !== "") {
|
||||||
if (this.qbusin.Chi === "Χ") {
|
if (this.qbusin.Chi === "Χ") {
|
||||||
// direct X added to Qbits
|
// direct X added to Qbits
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Qbits[b] = this.Qbits[b] ^ this.Xbits[b];
|
this.Qbits[b] = this.Qbits[b] ^ this.Xbits[b];
|
||||||
}
|
}
|
||||||
} else if (this.qbusin.Chi === "ΔΧ") {
|
} else if (this.qbusin.Chi === "ΔΧ") {
|
||||||
// delta X
|
// delta X
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Qbits[b] = this.Qbits[b] ^ this.Xbits[b];
|
this.Qbits[b] = this.Qbits[b] ^ this.Xbits[b];
|
||||||
this.Qbits[b] = this.Qbits[b] ^ this.XbitsOneBack[b];
|
this.Qbits[b] = this.Qbits[b] ^ this.XbitsOneBack[b];
|
||||||
}
|
}
|
||||||
|
@ -319,18 +280,18 @@ export class ColossusComputer {
|
||||||
this.XbitsOneBack = this.Xbits.slice();
|
this.XbitsOneBack = this.Xbits.slice();
|
||||||
|
|
||||||
// Sbits - the current Psi wheel bits
|
// Sbits - the current Psi wheel bits
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Sbits[b] = this.rings.S[b + 1][this.Sptr[b] - 1];
|
this.Sbits[b] = this.rings.S[b+1][this.Sptr[b]-1];
|
||||||
}
|
}
|
||||||
if (this.qbusin.Psi !== "") {
|
if (this.qbusin.Psi !== "") {
|
||||||
if (this.qbusin.Psi === "Ψ") {
|
if (this.qbusin.Psi === "Ψ") {
|
||||||
// direct S added to Qbits
|
// direct S added to Qbits
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Qbits[b] = this.Qbits[b] ^ this.Sbits[b];
|
this.Qbits[b] = this.Qbits[b] ^ this.Sbits[b];
|
||||||
}
|
}
|
||||||
} else if (this.qbusin.Psi === "ΔΨ") {
|
} else if (this.qbusin.Psi === "ΔΨ") {
|
||||||
// delta S
|
// delta S
|
||||||
for (let b = 0; b < 5; b++) {
|
for (let b=0;b<5;b++) {
|
||||||
this.Qbits[b] = this.Qbits[b] ^ this.Sbits[b];
|
this.Qbits[b] = this.Qbits[b] ^ this.Sbits[b];
|
||||||
this.Qbits[b] = this.Qbits[b] ^ this.SbitsOneBack[b];
|
this.Qbits[b] = this.Qbits[b] ^ this.SbitsOneBack[b];
|
||||||
}
|
}
|
||||||
|
@ -346,19 +307,15 @@ export class ColossusComputer {
|
||||||
const cnt = [-1, -1, -1, -1, -1];
|
const cnt = [-1, -1, -1, -1, -1];
|
||||||
const numrows = this.qbusswitches.condition.length;
|
const numrows = this.qbusswitches.condition.length;
|
||||||
|
|
||||||
for (let r = 0; r < numrows; r++) {
|
for (let r=0;r<numrows;r++) {
|
||||||
const row = this.qbusswitches.condition[r];
|
const row = this.qbusswitches.condition[r];
|
||||||
if (row.Counter !== "") {
|
if (row.Counter !== "") {
|
||||||
let result = true;
|
let result = true;
|
||||||
const cPnt = row.Counter - 1;
|
const cPnt = row.Counter-1;
|
||||||
const Qswitch = this.readBusSwitches(row.Qswitches);
|
const Qswitch = this.readBusSwitches(row.Qswitches);
|
||||||
// Match switches to bit pattern
|
// Match switches to bit pattern
|
||||||
for (let s = 0; s < 5; s++) {
|
for (let s=0;s<5;s++) {
|
||||||
if (
|
if (Qswitch[s] >= 0 && Qswitch[s] !== parseInt(this.Qbits[s], 10)) result = false;
|
||||||
Qswitch[s] >= 0 &&
|
|
||||||
Qswitch[s] !== parseInt(this.Qbits[s], 10)
|
|
||||||
)
|
|
||||||
result = false;
|
|
||||||
}
|
}
|
||||||
// Check for NOT switch
|
// Check for NOT switch
|
||||||
if (row.Negate) result = !result;
|
if (row.Negate) result = !result;
|
||||||
|
@ -373,9 +330,8 @@ export class ColossusComputer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negate the whole column, this allows A OR B by doing NOT(NOT A AND NOT B)
|
// Negate the whole column, this allows A OR B by doing NOT(NOT A AND NOT B)
|
||||||
for (let c = 0; c < 5; c++) {
|
for (let c=0;c<5;c++) {
|
||||||
if (this.qbusswitches.condNegateAll && cnt[c] !== -1)
|
if (this.qbusswitches.condNegateAll && cnt[c] !== -1) cnt[c] = !cnt[c];
|
||||||
cnt[c] = !cnt[c];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
|
@ -392,13 +348,13 @@ export class ColossusComputer {
|
||||||
// Colossus could actually add into any of the five counters.
|
// Colossus could actually add into any of the five counters.
|
||||||
if (row.C1) {
|
if (row.C1) {
|
||||||
let addition = 0;
|
let addition = 0;
|
||||||
for (let s = 0; s < 5; s++) {
|
for (let s=0;s<5;s++) {
|
||||||
// XOR addition
|
// XOR addition
|
||||||
if (Qswitch[s]) {
|
if (Qswitch[s]) {
|
||||||
addition = addition ^ this.Qbits[s];
|
addition = addition ^ this.Qbits[s];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const equals = row.Equals === "" ? -1 : row.Equals === "." ? 0 : 1;
|
const equals = (row.Equals===""?-1:(row.Equals==="."?0:1));
|
||||||
if (addition === equals) {
|
if (addition === equals) {
|
||||||
// AND with conditional rows to get final result
|
// AND with conditional rows to get final result
|
||||||
if (cnt[0] === -1) cnt[0] = true;
|
if (cnt[0] === -1) cnt[0] = true;
|
||||||
|
@ -409,18 +365,13 @@ export class ColossusComputer {
|
||||||
|
|
||||||
// Final check, check for addition section negate
|
// Final check, check for addition section negate
|
||||||
// then, if any column set, from top to bottom of rack, add to counter.
|
// then, if any column set, from top to bottom of rack, add to counter.
|
||||||
for (let c = 0; c < 5; c++) {
|
for (let c=0;c<5;c++) {
|
||||||
if (this.qbusswitches.addNegateAll && cnt[c] !== -1)
|
if (this.qbusswitches.addNegateAll && cnt[c] !== -1) cnt[c] = !cnt[c];
|
||||||
cnt[c] = !cnt[c];
|
|
||||||
|
|
||||||
if (
|
if (this.qbusswitches.totalMotor === "" || (this.qbusswitches.totalMotor === "x" && this.totalmotor === 0) || (this.qbusswitches.totalMotor === "." && this.totalmotor === 1)) {
|
||||||
this.qbusswitches.totalMotor === "" ||
|
|
||||||
(this.qbusswitches.totalMotor === "x" &&
|
|
||||||
this.totalmotor === 0) ||
|
|
||||||
(this.qbusswitches.totalMotor === "." && this.totalmotor === 1)
|
|
||||||
) {
|
|
||||||
if (cnt[c] === true) this.allCounters[c]++;
|
if (cnt[c] === true) this.allCounters[c]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +386,7 @@ export class ColossusComputer {
|
||||||
2: INIT_PATTERNS[pattern].X[2].slice().reverse(),
|
2: INIT_PATTERNS[pattern].X[2].slice().reverse(),
|
||||||
3: INIT_PATTERNS[pattern].X[3].slice().reverse(),
|
3: INIT_PATTERNS[pattern].X[3].slice().reverse(),
|
||||||
4: INIT_PATTERNS[pattern].X[4].slice().reverse(),
|
4: INIT_PATTERNS[pattern].X[4].slice().reverse(),
|
||||||
5: INIT_PATTERNS[pattern].X[5].slice().reverse(),
|
5: INIT_PATTERNS[pattern].X[5].slice().reverse()
|
||||||
},
|
},
|
||||||
M: {
|
M: {
|
||||||
1: INIT_PATTERNS[pattern].M[1].slice().reverse(),
|
1: INIT_PATTERNS[pattern].M[1].slice().reverse(),
|
||||||
|
@ -446,8 +397,8 @@ export class ColossusComputer {
|
||||||
2: INIT_PATTERNS[pattern].S[2].slice().reverse(),
|
2: INIT_PATTERNS[pattern].S[2].slice().reverse(),
|
||||||
3: INIT_PATTERNS[pattern].S[3].slice().reverse(),
|
3: INIT_PATTERNS[pattern].S[3].slice().reverse(),
|
||||||
4: INIT_PATTERNS[pattern].S[4].slice().reverse(),
|
4: INIT_PATTERNS[pattern].S[4].slice().reverse(),
|
||||||
5: INIT_PATTERNS[pattern].S[5].slice().reverse(),
|
5: INIT_PATTERNS[pattern].S[5].slice().reverse()
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,10 +407,11 @@ export class ColossusComputer {
|
||||||
*/
|
*/
|
||||||
readBusSwitches(row) {
|
readBusSwitches(row) {
|
||||||
const output = [-1, -1, -1, -1, -1];
|
const output = [-1, -1, -1, -1, -1];
|
||||||
for (let c = 0; c < 5; c++) {
|
for (let c=0;c<5;c++) {
|
||||||
if (row[c] === ".") output[c] = 0;
|
if (row[c]===".") output[c] = 0;
|
||||||
if (row[c] === "x") output[c] = 1;
|
if (row[c]==="x") output[c] = 1;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const FORMATS = [
|
||||||
"Geohash",
|
"Geohash",
|
||||||
"Military Grid Reference System",
|
"Military Grid Reference System",
|
||||||
"Ordnance Survey National Grid",
|
"Ordnance Survey National Grid",
|
||||||
"Universal Transverse Mercator",
|
"Universal Transverse Mercator"
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,15 +58,7 @@ const NO_CHANGE = [
|
||||||
* @param {number} precision - Precision of the result
|
* @param {number} precision - Precision of the result
|
||||||
* @returns {string} A formatted string of the converted co-ordinates
|
* @returns {string} A formatted string of the converted co-ordinates
|
||||||
*/
|
*/
|
||||||
export function convertCoordinates(
|
export function convertCoordinates (input, inFormat, inDelim, outFormat, outDelim, includeDir, precision) {
|
||||||
input,
|
|
||||||
inFormat,
|
|
||||||
inDelim,
|
|
||||||
outFormat,
|
|
||||||
outDelim,
|
|
||||||
includeDir,
|
|
||||||
precision,
|
|
||||||
) {
|
|
||||||
let isPair = false,
|
let isPair = false,
|
||||||
split,
|
split,
|
||||||
latlon,
|
latlon,
|
||||||
|
@ -91,9 +83,7 @@ export function convertCoordinates(
|
||||||
// Try to detect a delimiter in the input.
|
// Try to detect a delimiter in the input.
|
||||||
inDelim = findDelim(input);
|
inDelim = findDelim(input);
|
||||||
if (inDelim === null) {
|
if (inDelim === null) {
|
||||||
throw new OperationError(
|
throw new OperationError("Unable to detect the input delimiter automatically.");
|
||||||
"Unable to detect the input delimiter automatically.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if (!inDelim.includes("Direction")) {
|
} else if (!inDelim.includes("Direction")) {
|
||||||
// Convert the delimiter argument value to the actual character
|
// Convert the delimiter argument value to the actual character
|
||||||
|
@ -104,9 +94,7 @@ export function convertCoordinates(
|
||||||
// Try to detect the format of the input data
|
// Try to detect the format of the input data
|
||||||
inFormat = findFormat(input, inDelim);
|
inFormat = findFormat(input, inDelim);
|
||||||
if (inFormat === null) {
|
if (inFormat === null) {
|
||||||
throw new OperationError(
|
throw new OperationError("Unable to detect the input format automatically.");
|
||||||
"Unable to detect the input format automatically.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,23 +154,11 @@ export function convertCoordinates(
|
||||||
splitLong = splitInput(split[1]);
|
splitLong = splitInput(split[1]);
|
||||||
|
|
||||||
if (splitLat.length >= 3 && splitLong.length >= 3) {
|
if (splitLat.length >= 3 && splitLong.length >= 3) {
|
||||||
lat = convDMSToDD(
|
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2], 10);
|
||||||
splitLat[0],
|
lon = convDMSToDD(splitLong[0], splitLong[1], splitLong[2], 10);
|
||||||
splitLat[1],
|
|
||||||
splitLat[2],
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
lon = convDMSToDD(
|
|
||||||
splitLong[0],
|
|
||||||
splitLong[1],
|
|
||||||
splitLong[2],
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
latlon = new LatLonEllipsoidal(lat.degrees, lon.degrees);
|
latlon = new LatLonEllipsoidal(lat.degrees, lon.degrees);
|
||||||
} else {
|
} else {
|
||||||
throw new OperationError(
|
throw new OperationError("Invalid co-ordinate format for Degrees Minutes Seconds");
|
||||||
"Invalid co-ordinate format for Degrees Minutes Seconds",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not a pair, so only try to convert one set of co-ordinates
|
// Not a pair, so only try to convert one set of co-ordinates
|
||||||
|
@ -191,9 +167,7 @@ export function convertCoordinates(
|
||||||
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2]);
|
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2]);
|
||||||
latlon = new LatLonEllipsoidal(lat.degrees, lat.degrees);
|
latlon = new LatLonEllipsoidal(lat.degrees, lat.degrees);
|
||||||
} else {
|
} else {
|
||||||
throw new OperationError(
|
throw new OperationError("Invalid co-ordinate format for Degrees Minutes Seconds");
|
||||||
"Invalid co-ordinate format for Degrees Minutes Seconds",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -202,9 +176,7 @@ export function convertCoordinates(
|
||||||
splitLat = splitInput(split[0]);
|
splitLat = splitInput(split[0]);
|
||||||
splitLong = splitInput(split[1]);
|
splitLong = splitInput(split[1]);
|
||||||
if (splitLat.length !== 2 || splitLong.length !== 2) {
|
if (splitLat.length !== 2 || splitLong.length !== 2) {
|
||||||
throw new OperationError(
|
throw new OperationError("Invalid co-ordinate format for Degrees Decimal Minutes.");
|
||||||
"Invalid co-ordinate format for Degrees Decimal Minutes.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Convert to decimal degrees, and then convert to a geodesy object
|
// Convert to decimal degrees, and then convert to a geodesy object
|
||||||
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
|
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
|
||||||
|
@ -214,9 +186,7 @@ export function convertCoordinates(
|
||||||
// Not a pair, so only try to convert one set of co-ordinates
|
// Not a pair, so only try to convert one set of co-ordinates
|
||||||
splitLat = splitInput(input);
|
splitLat = splitInput(input);
|
||||||
if (splitLat.length !== 2) {
|
if (splitLat.length !== 2) {
|
||||||
throw new OperationError(
|
throw new OperationError("Invalid co-ordinate format for Degrees Decimal Minutes.");
|
||||||
"Invalid co-ordinate format for Degrees Decimal Minutes.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
|
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
|
||||||
latlon = new LatLonEllipsoidal(lat.degrees, lat.degrees);
|
latlon = new LatLonEllipsoidal(lat.degrees, lat.degrees);
|
||||||
|
@ -227,18 +197,14 @@ export function convertCoordinates(
|
||||||
splitLat = splitInput(split[0]);
|
splitLat = splitInput(split[0]);
|
||||||
splitLong = splitInput(split[1]);
|
splitLong = splitInput(split[1]);
|
||||||
if (splitLat.length !== 1 || splitLong.length !== 1) {
|
if (splitLat.length !== 1 || splitLong.length !== 1) {
|
||||||
throw new OperationError(
|
throw new OperationError("Invalid co-ordinate format for Decimal Degrees.");
|
||||||
"Invalid co-ordinate format for Decimal Degrees.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
latlon = new LatLonEllipsoidal(splitLat[0], splitLong[0]);
|
latlon = new LatLonEllipsoidal(splitLat[0], splitLong[0]);
|
||||||
} else {
|
} else {
|
||||||
// Not a pair, so only try to convert one set of co-ordinates
|
// Not a pair, so only try to convert one set of co-ordinates
|
||||||
splitLat = splitInput(split[0]);
|
splitLat = splitInput(split[0]);
|
||||||
if (splitLat.length !== 1) {
|
if (splitLat.length !== 1) {
|
||||||
throw new OperationError(
|
throw new OperationError("Invalid co-ordinate format for Decimal Degrees.");
|
||||||
"Invalid co-ordinate format for Decimal Degrees.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
latlon = new LatLonEllipsoidal(splitLat[0], splitLat[0]);
|
latlon = new LatLonEllipsoidal(splitLat[0], splitLat[0]);
|
||||||
}
|
}
|
||||||
|
@ -255,11 +221,11 @@ export function convertCoordinates(
|
||||||
const dirs = input.toUpperCase().match(/[NESW]/g);
|
const dirs = input.toUpperCase().match(/[NESW]/g);
|
||||||
if (dirs && dirs.length >= 1) {
|
if (dirs && dirs.length >= 1) {
|
||||||
// Make positive lat/lon values with S/W directions into negative values
|
// Make positive lat/lon values with S/W directions into negative values
|
||||||
if (dirs[0] === "S" || (dirs[0] === "W" && latlon.lat > 0)) {
|
if (dirs[0] === "S" || dirs[0] === "W" && latlon.lat > 0) {
|
||||||
latlon.lat = -latlon.lat;
|
latlon.lat = -latlon.lat;
|
||||||
}
|
}
|
||||||
if (dirs.length >= 2) {
|
if (dirs.length >= 2) {
|
||||||
if (dirs[1] === "S" || (dirs[1] === "W" && latlon.lon > 0)) {
|
if (dirs[1] === "S" || dirs[1] === "W" && latlon.lon > 0) {
|
||||||
latlon.lon = -latlon.lon;
|
latlon.lon = -latlon.lon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,9 +275,7 @@ export function convertCoordinates(
|
||||||
case "Ordnance Survey National Grid":
|
case "Ordnance Survey National Grid":
|
||||||
osng = OsGridRef.latLonToOsGrid(latlon);
|
osng = OsGridRef.latLonToOsGrid(latlon);
|
||||||
if (osng.toString() === "") {
|
if (osng.toString() === "") {
|
||||||
throw new OperationError(
|
throw new OperationError("Could not convert co-ordinates to OS National Grid. Are the co-ordinates in range?");
|
||||||
"Could not convert co-ordinates to OS National Grid. Are the co-ordinates in range?",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// OSNG wants a precision that's an even number between 2 and 10
|
// OSNG wants a precision that's an even number between 2 and 10
|
||||||
if (precision % 2 !== 0) {
|
if (precision % 2 !== 0) {
|
||||||
|
@ -376,10 +340,10 @@ export function convertCoordinates(
|
||||||
* @param {string} input - The input data to be split
|
* @param {string} input - The input data to be split
|
||||||
* @returns {number[]} An array of the different items in the string, stored as floats
|
* @returns {number[]} An array of the different items in the string, stored as floats
|
||||||
*/
|
*/
|
||||||
function splitInput(input) {
|
function splitInput (input) {
|
||||||
const split = [];
|
const split = [];
|
||||||
|
|
||||||
input.split(/\s+/).forEach((item) => {
|
input.split(/\s+/).forEach(item => {
|
||||||
// Remove any character that isn't a digit, decimal point or negative sign
|
// Remove any character that isn't a digit, decimal point or negative sign
|
||||||
item = item.replace(/[^0-9.-]/g, "");
|
item = item.replace(/[^0-9.-]/g, "");
|
||||||
if (item.length > 0) {
|
if (item.length > 0) {
|
||||||
|
@ -399,17 +363,17 @@ function splitInput(input) {
|
||||||
* @param {number} precision - The precision the result should be rounded to
|
* @param {number} precision - The precision the result should be rounded to
|
||||||
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
|
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
|
||||||
*/
|
*/
|
||||||
function convDMSToDD(degrees, minutes, seconds, precision) {
|
function convDMSToDD (degrees, minutes, seconds, precision) {
|
||||||
const absDegrees = Math.abs(degrees);
|
const absDegrees = Math.abs(degrees);
|
||||||
let conv = absDegrees + minutes / 60 + seconds / 3600;
|
let conv = absDegrees + (minutes / 60) + (seconds / 3600);
|
||||||
let outString = round(conv, precision) + "°";
|
let outString = round(conv, precision) + "°";
|
||||||
if (isNegativeZero(degrees) || degrees < 0) {
|
if (isNegativeZero(degrees) || degrees < 0) {
|
||||||
conv = -conv;
|
conv = -conv;
|
||||||
outString = "-" + outString;
|
outString = "-" + outString;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
degrees: conv,
|
"degrees": conv,
|
||||||
string: outString,
|
"string": outString
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +385,7 @@ function convDMSToDD(degrees, minutes, seconds, precision) {
|
||||||
* @param {number} precision - The precision which the result should be rounded to
|
* @param {number} precision - The precision which the result should be rounded to
|
||||||
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
|
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
|
||||||
*/
|
*/
|
||||||
function convDDMToDD(degrees, minutes, precision) {
|
function convDDMToDD (degrees, minutes, precision) {
|
||||||
const absDegrees = Math.abs(degrees);
|
const absDegrees = Math.abs(degrees);
|
||||||
let conv = absDegrees + minutes / 60;
|
let conv = absDegrees + minutes / 60;
|
||||||
let outString = round(conv, precision) + "°";
|
let outString = round(conv, precision) + "°";
|
||||||
|
@ -430,8 +394,8 @@ function convDDMToDD(degrees, minutes, precision) {
|
||||||
outString = "-" + outString;
|
outString = "-" + outString;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
degrees: conv,
|
"degrees": conv,
|
||||||
string: outString,
|
"string": outString
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,10 +407,10 @@ function convDDMToDD(degrees, minutes, precision) {
|
||||||
* @param {number} precision - The precision which the result should be rounded to
|
* @param {number} precision - The precision which the result should be rounded to
|
||||||
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
|
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
|
||||||
*/
|
*/
|
||||||
function convDDToDD(degrees, precision) {
|
function convDDToDD (degrees, precision) {
|
||||||
return {
|
return {
|
||||||
degrees: degrees,
|
"degrees": degrees,
|
||||||
string: round(degrees, precision) + "°",
|
"string": round(degrees, precision) + "°"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,24 +421,21 @@ function convDDToDD(degrees, precision) {
|
||||||
* @param {number} precision - The precision which the result should be rounded to
|
* @param {number} precision - The precision which the result should be rounded to
|
||||||
* @returns {{string: string, degrees: number, minutes: number, seconds: number}} An object containing the raw converted value as separate numbers (.degrees, .minutes, .seconds), and a formatted string version (obj.string)
|
* @returns {{string: string, degrees: number, minutes: number, seconds: number}} An object containing the raw converted value as separate numbers (.degrees, .minutes, .seconds), and a formatted string version (obj.string)
|
||||||
*/
|
*/
|
||||||
function convDDToDMS(decDegrees, precision) {
|
function convDDToDMS (decDegrees, precision) {
|
||||||
const absDegrees = Math.abs(decDegrees);
|
const absDegrees = Math.abs(decDegrees);
|
||||||
let degrees = Math.floor(absDegrees);
|
let degrees = Math.floor(absDegrees);
|
||||||
const minutes = Math.floor(60 * (absDegrees - degrees)),
|
const minutes = Math.floor(60 * (absDegrees - degrees)),
|
||||||
seconds = round(
|
seconds = round(3600 * (absDegrees - degrees) - 60 * minutes, precision);
|
||||||
3600 * (absDegrees - degrees) - 60 * minutes,
|
let outString = degrees + "° " + minutes + "' " + seconds + "\"";
|
||||||
precision,
|
|
||||||
);
|
|
||||||
let outString = degrees + "° " + minutes + "' " + seconds + '"';
|
|
||||||
if (isNegativeZero(decDegrees) || decDegrees < 0) {
|
if (isNegativeZero(decDegrees) || decDegrees < 0) {
|
||||||
degrees = -degrees;
|
degrees = -degrees;
|
||||||
outString = "-" + outString;
|
outString = "-" + outString;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
degrees: degrees,
|
"degrees": degrees,
|
||||||
minutes: minutes,
|
"minutes": minutes,
|
||||||
seconds: seconds,
|
"seconds": seconds,
|
||||||
string: outString,
|
"string": outString
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,7 +446,7 @@ function convDDToDMS(decDegrees, precision) {
|
||||||
* @param {number} precision - The precision the input data should be rounded to
|
* @param {number} precision - The precision the input data should be rounded to
|
||||||
* @returns {{string: string, degrees: number, minutes: number}} An object containing the raw converted value as separate numbers (.degrees, .minutes), and a formatted string version (obj.string)
|
* @returns {{string: string, degrees: number, minutes: number}} An object containing the raw converted value as separate numbers (.degrees, .minutes), and a formatted string version (obj.string)
|
||||||
*/
|
*/
|
||||||
function convDDToDDM(decDegrees, precision) {
|
function convDDToDDM (decDegrees, precision) {
|
||||||
const absDegrees = Math.abs(decDegrees);
|
const absDegrees = Math.abs(decDegrees);
|
||||||
let degrees = Math.floor(absDegrees);
|
let degrees = Math.floor(absDegrees);
|
||||||
const minutes = absDegrees - degrees,
|
const minutes = absDegrees - degrees,
|
||||||
|
@ -497,9 +458,9 @@ function convDDToDDM(decDegrees, precision) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
degrees: degrees,
|
"degrees": degrees,
|
||||||
minutes: decMinutes,
|
"minutes": decMinutes,
|
||||||
string: outString,
|
"string": outString,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,11 +532,9 @@ export function findDirs(input, delim) {
|
||||||
* @param {string} delim - The delimiter separating the data in input
|
* @param {string} delim - The delimiter separating the data in input
|
||||||
* @returns {string} The input format
|
* @returns {string} The input format
|
||||||
*/
|
*/
|
||||||
export function findFormat(input, delim) {
|
export function findFormat (input, delim) {
|
||||||
let testData;
|
let testData;
|
||||||
const mgrsPattern = new RegExp(
|
const mgrsPattern = new RegExp(/^[0-9]{2}\s?[C-HJ-NP-X]{1}\s?[A-HJ-NP-Z][A-HJ-NP-V]\s?[0-9\s]+/),
|
||||||
/^[0-9]{2}\s?[C-HJ-NP-X]{1}\s?[A-HJ-NP-Z][A-HJ-NP-V]\s?[0-9\s]+/,
|
|
||||||
),
|
|
||||||
osngPattern = new RegExp(/^[A-HJ-Z]{2}\s+[0-9\s]+$/),
|
osngPattern = new RegExp(/^[A-HJ-Z]{2}\s+[0-9\s]+$/),
|
||||||
geohashPattern = new RegExp(/^[0123456789BCDEFGHJKMNPQRSTUVWXYZ]+$/),
|
geohashPattern = new RegExp(/^[0123456789BCDEFGHJKMNPQRSTUVWXYZ]+$/),
|
||||||
utmPattern = new RegExp(/^[0-9]{2}\s?[C-HJ-NP-X]\s[0-9.]+\s?[0-9.]+$/),
|
utmPattern = new RegExp(/^[0-9]{2}\s?[C-HJ-NP-X]\s[0-9.]+\s?[0-9.]+$/),
|
||||||
|
@ -638,7 +597,7 @@ export function findFormat(input, delim) {
|
||||||
* @param {string} input
|
* @param {string} input
|
||||||
* @returns {string} Delimiter type
|
* @returns {string} Delimiter type
|
||||||
*/
|
*/
|
||||||
export function findDelim(input) {
|
export function findDelim (input) {
|
||||||
input = input.trim();
|
input = input.trim();
|
||||||
const delims = [",", ";", ":"];
|
const delims = [",", ";", ":"];
|
||||||
const testDir = input.match(/[NnEeSsWw]/g);
|
const testDir = input.match(/[NnEeSsWw]/g);
|
||||||
|
@ -675,14 +634,14 @@ export function findDelim(input) {
|
||||||
* @param {string} delim The delimiter to be matched
|
* @param {string} delim The delimiter to be matched
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function realDelim(delim) {
|
export function realDelim (delim) {
|
||||||
return {
|
return {
|
||||||
Auto: "Auto",
|
"Auto": "Auto",
|
||||||
Space: " ",
|
"Space": " ",
|
||||||
"\\n": "\n",
|
"\\n": "\n",
|
||||||
Comma: ",",
|
"Comma": ",",
|
||||||
"Semi-colon": ";",
|
"Semi-colon": ";",
|
||||||
Colon: ":",
|
"Colon": ":"
|
||||||
}[delim];
|
}[delim];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +652,7 @@ export function realDelim(delim) {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function isNegativeZero(zero) {
|
function isNegativeZero(zero) {
|
||||||
return zero === 0 && 1 / zero < 0;
|
return zero === 0 && (1/zero < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,5 +6,4 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const cryptNotice =
|
export const cryptNotice = "WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
|
||||||
"WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
|
|
||||||
|
|
|
@ -9,12 +9,7 @@
|
||||||
/**
|
/**
|
||||||
* DateTime units.
|
* DateTime units.
|
||||||
*/
|
*/
|
||||||
export const UNITS = [
|
export const UNITS = ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"];
|
||||||
"Seconds (s)",
|
|
||||||
"Milliseconds (ms)",
|
|
||||||
"Microseconds (μs)",
|
|
||||||
"Nanoseconds (ns)",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DateTime formats.
|
* DateTime formats.
|
||||||
|
@ -22,31 +17,31 @@ export const UNITS = [
|
||||||
export const DATETIME_FORMATS = [
|
export const DATETIME_FORMATS = [
|
||||||
{
|
{
|
||||||
name: "Standard date and time",
|
name: "Standard date and time",
|
||||||
value: "DD/MM/YYYY HH:mm:ss",
|
value: "DD/MM/YYYY HH:mm:ss"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "American-style date and time",
|
name: "American-style date and time",
|
||||||
value: "MM/DD/YYYY HH:mm:ss",
|
value: "MM/DD/YYYY HH:mm:ss"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "International date and time",
|
name: "International date and time",
|
||||||
value: "YYYY-MM-DD HH:mm:ss",
|
value: "YYYY-MM-DD HH:mm:ss"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Verbose date and time",
|
name: "Verbose date and time",
|
||||||
value: "dddd Do MMMM YYYY HH:mm:ss Z z",
|
value: "dddd Do MMMM YYYY HH:mm:ss Z z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UNIX timestamp (seconds)",
|
name: "UNIX timestamp (seconds)",
|
||||||
value: "X",
|
value: "X"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UNIX timestamp offset (milliseconds)",
|
name: "UNIX timestamp offset (milliseconds)",
|
||||||
value: "x",
|
value: "x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Automatic",
|
name: "Automatic",
|
||||||
value: "",
|
value: ""
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -315,3 +310,4 @@ export const FORMAT_EXAMPLES = `Format string tokens:
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>`;
|
</table>`;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a string of decimal values into a byte array.
|
* Convert a string of decimal values into a byte array.
|
||||||
*
|
*
|
||||||
|
@ -22,12 +23,12 @@ import Utils from "../Utils.mjs";
|
||||||
* // returns [10,20,30]
|
* // returns [10,20,30]
|
||||||
* fromDecimal("10:20:30", "Colon");
|
* fromDecimal("10:20:30", "Colon");
|
||||||
*/
|
*/
|
||||||
export function fromDecimal(data, delim = "Auto") {
|
export function fromDecimal(data, delim="Auto") {
|
||||||
delim = Utils.charRep(delim);
|
delim = Utils.charRep(delim);
|
||||||
const output = [];
|
const output = [];
|
||||||
let byteStr = data.split(delim);
|
let byteStr = data.split(delim);
|
||||||
if (byteStr[byteStr.length - 1] === "")
|
if (byteStr[byteStr.length-1] === "")
|
||||||
byteStr = byteStr.slice(0, byteStr.length - 1);
|
byteStr = byteStr.slice(0, byteStr.length-1);
|
||||||
|
|
||||||
for (let i = 0; i < byteStr.length; i++) {
|
for (let i = 0; i < byteStr.length; i++) {
|
||||||
output[i] = parseInt(byteStr[i], 10);
|
output[i] = parseInt(byteStr[i], 10);
|
||||||
|
|
|
@ -9,79 +9,32 @@
|
||||||
/**
|
/**
|
||||||
* Generic sequence delimiters.
|
* Generic sequence delimiters.
|
||||||
*/
|
*/
|
||||||
export const DELIM_OPTIONS = [
|
export const DELIM_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF"];
|
||||||
"Space",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binary sequence delimiters.
|
* Binary sequence delimiters.
|
||||||
*/
|
*/
|
||||||
export const BIN_DELIM_OPTIONS = [
|
export const BIN_DELIM_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"];
|
||||||
"Space",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
"None",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Letter sequence delimiters.
|
* Letter sequence delimiters.
|
||||||
*/
|
*/
|
||||||
export const LETTER_DELIM_OPTIONS = [
|
export const LETTER_DELIM_OPTIONS = ["Space", "Line feed", "CRLF", "Forward slash", "Backslash", "Comma", "Semi-colon", "Colon"];
|
||||||
"Space",
|
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
"Forward slash",
|
|
||||||
"Backslash",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Word sequence delimiters.
|
* Word sequence delimiters.
|
||||||
*/
|
*/
|
||||||
export const WORD_DELIM_OPTIONS = [
|
export const WORD_DELIM_OPTIONS = ["Line feed", "CRLF", "Forward slash", "Backslash", "Comma", "Semi-colon", "Colon"];
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
"Forward slash",
|
|
||||||
"Backslash",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input sequence delimiters.
|
* Input sequence delimiters.
|
||||||
*/
|
*/
|
||||||
export const INPUT_DELIM_OPTIONS = [
|
export const INPUT_DELIM_OPTIONS = ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"];
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
"Space",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
"Nothing (separate chars)",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arithmetic sequence delimiters
|
* Arithmetic sequence delimiters
|
||||||
*/
|
*/
|
||||||
export const ARITHMETIC_DELIM_OPTIONS = [
|
export const ARITHMETIC_DELIM_OPTIONS = ["Line feed", "Space", "Comma", "Semi-colon", "Colon", "CRLF"];
|
||||||
"Line feed",
|
|
||||||
"Space",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
"CRLF",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash delimiters
|
* Hash delimiters
|
||||||
|
@ -91,46 +44,40 @@ export const HASH_DELIM_OPTIONS = ["Line feed", "CRLF", "Space", "Comma"];
|
||||||
/**
|
/**
|
||||||
* IP delimiters
|
* IP delimiters
|
||||||
*/
|
*/
|
||||||
export const IP_DELIM_OPTIONS = [
|
export const IP_DELIM_OPTIONS = ["Line feed", "CRLF", "Space", "Comma", "Semi-colon"];
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
"Space",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split delimiters.
|
* Split delimiters.
|
||||||
*/
|
*/
|
||||||
export const SPLIT_DELIM_OPTIONS = [
|
export const SPLIT_DELIM_OPTIONS = [
|
||||||
{ name: "Comma", value: "," },
|
{name: "Comma", value: ","},
|
||||||
{ name: "Space", value: " " },
|
{name: "Space", value: " "},
|
||||||
{ name: "Line feed", value: "\\n" },
|
{name: "Line feed", value: "\\n"},
|
||||||
{ name: "CRLF", value: "\\r\\n" },
|
{name: "CRLF", value: "\\r\\n"},
|
||||||
{ name: "Semi-colon", value: ";" },
|
{name: "Semi-colon", value: ";"},
|
||||||
{ name: "Colon", value: ":" },
|
{name: "Colon", value: ":"},
|
||||||
{ name: "Nothing (separate chars)", value: "" },
|
{name: "Nothing (separate chars)", value: ""}
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join delimiters.
|
* Join delimiters.
|
||||||
*/
|
*/
|
||||||
export const JOIN_DELIM_OPTIONS = [
|
export const JOIN_DELIM_OPTIONS = [
|
||||||
{ name: "Line feed", value: "\\n" },
|
{name: "Line feed", value: "\\n"},
|
||||||
{ name: "CRLF", value: "\\r\\n" },
|
{name: "CRLF", value: "\\r\\n"},
|
||||||
{ name: "Space", value: " " },
|
{name: "Space", value: " "},
|
||||||
{ name: "Comma", value: "," },
|
{name: "Comma", value: ","},
|
||||||
{ name: "Semi-colon", value: ";" },
|
{name: "Semi-colon", value: ";"},
|
||||||
{ name: "Colon", value: ":" },
|
{name: "Colon", value: ":"},
|
||||||
{ name: "Nothing (join chars)", value: "" },
|
{name: "Nothing (join chars)", value: ""}
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RGBA list delimiters.
|
* RGBA list delimiters.
|
||||||
*/
|
*/
|
||||||
export const RGBA_DELIM_OPTIONS = [
|
export const RGBA_DELIM_OPTIONS = [
|
||||||
{ name: "Comma", value: "," },
|
{name: "Comma", value: ","},
|
||||||
{ name: "Space", value: " " },
|
{name: "Space", value: " "},
|
||||||
{ name: "CRLF", value: "\\r\\n" },
|
{name: "CRLF", value: "\\r\\n"},
|
||||||
{ name: "Line Feed", value: "\n" },
|
{name: "Line Feed", value: "\n"}
|
||||||
];
|
];
|
||||||
|
|
|
@ -14,19 +14,19 @@ import Utils from "../Utils.mjs";
|
||||||
* followed by < and a list of letters at which the rotor steps.
|
* followed by < and a list of letters at which the rotor steps.
|
||||||
*/
|
*/
|
||||||
export const ROTORS = [
|
export const ROTORS = [
|
||||||
{ name: "I", value: "EKMFLGDQVZNTOWYHXUSPAIBRCJ<R" },
|
{name: "I", value: "EKMFLGDQVZNTOWYHXUSPAIBRCJ<R"},
|
||||||
{ name: "II", value: "AJDKSIRUXBLHWTMCQGZNPYFVOE<F" },
|
{name: "II", value: "AJDKSIRUXBLHWTMCQGZNPYFVOE<F"},
|
||||||
{ name: "III", value: "BDFHJLCPRTXVZNYEIWGAKMUSQO<W" },
|
{name: "III", value: "BDFHJLCPRTXVZNYEIWGAKMUSQO<W"},
|
||||||
{ name: "IV", value: "ESOVPZJAYQUIRHXLNFTGKDCMWB<K" },
|
{name: "IV", value: "ESOVPZJAYQUIRHXLNFTGKDCMWB<K"},
|
||||||
{ name: "V", value: "VZBRGITYUPSDNHLXAWMJQOFECK<A" },
|
{name: "V", value: "VZBRGITYUPSDNHLXAWMJQOFECK<A"},
|
||||||
{ name: "VI", value: "JPGVOUMFYQBENHZRDKASXLICTW<AN" },
|
{name: "VI", value: "JPGVOUMFYQBENHZRDKASXLICTW<AN"},
|
||||||
{ name: "VII", value: "NZJHGRCXMYSWBOUFAIVLPEKQDT<AN" },
|
{name: "VII", value: "NZJHGRCXMYSWBOUFAIVLPEKQDT<AN"},
|
||||||
{ name: "VIII", value: "FKQHTLXOCBJSPDZRAMEWNIUYGV<AN" },
|
{name: "VIII", value: "FKQHTLXOCBJSPDZRAMEWNIUYGV<AN"},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ROTORS_FOURTH = [
|
export const ROTORS_FOURTH = [
|
||||||
{ name: "Beta", value: "LEYJVCNIXWPBQMDRTAKZGFUHOS" },
|
{name: "Beta", value: "LEYJVCNIXWPBQMDRTAKZGFUHOS"},
|
||||||
{ name: "Gamma", value: "FSOKANUERHMBTIYCWLQPZXVGJD" },
|
{name: "Gamma", value: "FSOKANUERHMBTIYCWLQPZXVGJD"},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,10 +34,10 @@ export const ROTORS_FOURTH = [
|
||||||
* These are specified as 13 space-separated transposed pairs covering every letter.
|
* These are specified as 13 space-separated transposed pairs covering every letter.
|
||||||
*/
|
*/
|
||||||
export const REFLECTORS = [
|
export const REFLECTORS = [
|
||||||
{ name: "B", value: "AY BR CU DH EQ FS GL IP JX KN MO TZ VW" },
|
{name: "B", value: "AY BR CU DH EQ FS GL IP JX KN MO TZ VW"},
|
||||||
{ name: "C", value: "AF BV CP DJ EI GO HY KR LZ MX NW TQ SU" },
|
{name: "C", value: "AF BV CP DJ EI GO HY KR LZ MX NW TQ SU"},
|
||||||
{ name: "B Thin", value: "AE BN CK DQ FU GY HW IJ LO MP RX SZ TV" },
|
{name: "B Thin", value: "AE BN CK DQ FU GY HW IJ LO MP RX SZ TV"},
|
||||||
{ name: "C Thin", value: "AR BD CO EJ FN GT HK IV LM PW QZ SX UY" },
|
{name: "C Thin", value: "AR BD CO EJ FN GT HK IV LM PW QZ SX UY"},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
|
export const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
|
||||||
|
@ -49,7 +49,7 @@ export const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
|
||||||
* @param {boolean} permissive - Case insensitive; don't throw errors on other chars.
|
* @param {boolean} permissive - Case insensitive; don't throw errors on other chars.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export function a2i(c, permissive = false) {
|
export function a2i(c, permissive=false) {
|
||||||
const i = Utils.ord(c);
|
const i = Utils.ord(c);
|
||||||
if (i >= 65 && i <= 90) {
|
if (i >= 65 && i <= 90) {
|
||||||
return i - 65;
|
return i - 65;
|
||||||
|
@ -72,7 +72,7 @@ export function a2i(c, permissive = false) {
|
||||||
*/
|
*/
|
||||||
export function i2a(i) {
|
export function i2a(i) {
|
||||||
if (i >= 0 && i < 26) {
|
if (i >= 0 && i < 26) {
|
||||||
return Utils.chr(i + 65);
|
return Utils.chr(i+65);
|
||||||
}
|
}
|
||||||
throw new OperationError("i2a called on value outside 0..25");
|
throw new OperationError("i2a called on value outside 0..25");
|
||||||
}
|
}
|
||||||
|
@ -91,29 +91,21 @@ export class Rotor {
|
||||||
*/
|
*/
|
||||||
constructor(wiring, steps, ringSetting, initialPosition) {
|
constructor(wiring, steps, ringSetting, initialPosition) {
|
||||||
if (!/^[A-Z]{26}$/.test(wiring)) {
|
if (!/^[A-Z]{26}$/.test(wiring)) {
|
||||||
throw new OperationError(
|
throw new OperationError("Rotor wiring must be 26 unique uppercase letters");
|
||||||
"Rotor wiring must be 26 unique uppercase letters",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (!/^[A-Z]{0,26}$/.test(steps)) {
|
if (!/^[A-Z]{0,26}$/.test(steps)) {
|
||||||
throw new OperationError(
|
throw new OperationError("Rotor steps must be 0-26 unique uppercase letters");
|
||||||
"Rotor steps must be 0-26 unique uppercase letters",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (!/^[A-Z]$/.test(ringSetting)) {
|
if (!/^[A-Z]$/.test(ringSetting)) {
|
||||||
throw new OperationError(
|
throw new OperationError("Rotor ring setting must be exactly one uppercase letter");
|
||||||
"Rotor ring setting must be exactly one uppercase letter",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (!/^[A-Z]$/.test(initialPosition)) {
|
if (!/^[A-Z]$/.test(initialPosition)) {
|
||||||
throw new OperationError(
|
throw new OperationError("Rotor initial position must be exactly one uppercase letter");
|
||||||
"Rotor initial position must be exactly one uppercase letter",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this.map = new Array(26);
|
this.map = new Array(26);
|
||||||
this.revMap = new Array(26);
|
this.revMap = new Array(26);
|
||||||
const uniq = {};
|
const uniq = {};
|
||||||
for (let i = 0; i < LETTERS.length; i++) {
|
for (let i=0; i<LETTERS.length; i++) {
|
||||||
const a = a2i(LETTERS[i]);
|
const a = a2i(LETTERS[i]);
|
||||||
const b = a2i(wiring[i]);
|
const b = a2i(wiring[i]);
|
||||||
this.map[a] = b;
|
this.map[a] = b;
|
||||||
|
@ -121,9 +113,7 @@ export class Rotor {
|
||||||
uniq[b] = true;
|
uniq[b] = true;
|
||||||
}
|
}
|
||||||
if (Object.keys(uniq).length !== LETTERS.length) {
|
if (Object.keys(uniq).length !== LETTERS.length) {
|
||||||
throw new OperationError(
|
throw new OperationError("Rotor wiring must have each letter exactly once");
|
||||||
"Rotor wiring must have each letter exactly once",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const rs = a2i(ringSetting);
|
const rs = a2i(ringSetting);
|
||||||
this.steps = new Set();
|
this.steps = new Set();
|
||||||
|
@ -162,10 +152,7 @@ export class Rotor {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
revTransform(c) {
|
revTransform(c) {
|
||||||
return Utils.mod(
|
return Utils.mod(this.revMap[Utils.mod(c + this.pos, 26)] - this.pos, 26);
|
||||||
this.revMap[Utils.mod(c + this.pos, 26)] - this.pos,
|
|
||||||
26,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +167,7 @@ class PairMapBase {
|
||||||
* @param {string} pairs - A whitespace separated string of letter pairs to swap.
|
* @param {string} pairs - A whitespace separated string of letter pairs to swap.
|
||||||
* @param {string} [name='PairMapBase'] - For errors, the name of this object.
|
* @param {string} [name='PairMapBase'] - For errors, the name of this object.
|
||||||
*/
|
*/
|
||||||
constructor(pairs, name = "PairMapBase") {
|
constructor(pairs, name="PairMapBase") {
|
||||||
// I've chosen to make whitespace significant here to make a) code and
|
// I've chosen to make whitespace significant here to make a) code and
|
||||||
// b) inputs easier to read
|
// b) inputs easier to read
|
||||||
this.pairs = pairs;
|
this.pairs = pairs;
|
||||||
|
@ -188,28 +175,20 @@ class PairMapBase {
|
||||||
if (pairs === "") {
|
if (pairs === "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pairs.split(/\s+/).forEach((pair) => {
|
pairs.split(/\s+/).forEach(pair => {
|
||||||
if (!/^[A-Z]{2}$/.test(pair)) {
|
if (!/^[A-Z]{2}$/.test(pair)) {
|
||||||
throw new OperationError(
|
throw new OperationError(name + " must be a whitespace-separated list of uppercase letter pairs");
|
||||||
name +
|
|
||||||
" must be a whitespace-separated list of uppercase letter pairs",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const a = a2i(pair[0]),
|
const a = a2i(pair[0]), b = a2i(pair[1]);
|
||||||
b = a2i(pair[1]);
|
|
||||||
if (a === b) {
|
if (a === b) {
|
||||||
// self-stecker
|
// self-stecker
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(this.map, a)) {
|
if (Object.prototype.hasOwnProperty.call(this.map, a)) {
|
||||||
throw new OperationError(
|
throw new OperationError(`${name} connects ${pair[0]} more than once`);
|
||||||
`${name} connects ${pair[0]} more than once`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(this.map, b)) {
|
if (Object.prototype.hasOwnProperty.call(this.map, b)) {
|
||||||
throw new OperationError(
|
throw new OperationError(`${name} connects ${pair[1]} more than once`);
|
||||||
`${name} connects ${pair[1]} more than once`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this.map[a] = b;
|
this.map[a] = b;
|
||||||
this.map[b] = a;
|
this.map[b] = a;
|
||||||
|
@ -255,9 +234,7 @@ export class Reflector extends PairMapBase {
|
||||||
super(pairs, "Reflector");
|
super(pairs, "Reflector");
|
||||||
const s = Object.keys(this.map).length;
|
const s = Object.keys(this.map).length;
|
||||||
if (s !== 26) {
|
if (s !== 26) {
|
||||||
throw new OperationError(
|
throw new OperationError("Reflector must have exactly 13 pairs covering every letter");
|
||||||
"Reflector must have exactly 13 pairs covering every letter",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const optMap = new Array(26);
|
const optMap = new Array(26);
|
||||||
for (const x of Object.keys(this.map)) {
|
for (const x of Object.keys(this.map)) {
|
||||||
|
|
|
@ -18,13 +18,7 @@
|
||||||
* @param {boolean} [unique=false] - Whether to unique the results
|
* @param {boolean} [unique=false] - Whether to unique the results
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function search(
|
export function search(input, searchRegex, removeRegex=null, sortBy=null, unique=false) {
|
||||||
input,
|
|
||||||
searchRegex,
|
|
||||||
removeRegex = null,
|
|
||||||
sortBy = null,
|
|
||||||
unique = false,
|
|
||||||
) {
|
|
||||||
let results = [];
|
let results = [];
|
||||||
let match;
|
let match;
|
||||||
|
|
||||||
|
@ -34,7 +28,8 @@ export function search(
|
||||||
searchRegex.lastIndex++;
|
searchRegex.lastIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeRegex && removeRegex.test(match[0])) continue;
|
if (removeRegex && removeRegex.test(match[0]))
|
||||||
|
continue;
|
||||||
|
|
||||||
results.push(match[0]);
|
results.push(match[0]);
|
||||||
}
|
}
|
||||||
|
@ -50,23 +45,20 @@ export function search(
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL regular expression
|
* URL regular expression
|
||||||
*/
|
*/
|
||||||
const protocol = "[A-Z]+://",
|
const protocol = "[A-Z]+://",
|
||||||
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
||||||
port = ":\\d+",
|
port = ":\\d+",
|
||||||
path =
|
path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*" +
|
||||||
'/[^.!,?"<>\\[\\]{}\\s\\x7F-\\xFF]*' +
|
"(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||||
'(?:[.!,?]+[^.!,?"<>\\[\\]{}\\s\\x7F-\\xFF]+)*';
|
|
||||||
|
export const URL_REGEX = new RegExp(protocol + hostname + "(?:" + port + ")?(?:" + path + ")?", "ig");
|
||||||
|
|
||||||
export const URL_REGEX = new RegExp(
|
|
||||||
protocol + hostname + "(?:" + port + ")?(?:" + path + ")?",
|
|
||||||
"ig",
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain name regular expression
|
* Domain name regular expression
|
||||||
*/
|
*/
|
||||||
export const DOMAIN_REGEX =
|
export const DOMAIN_REGEX = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
||||||
/\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/gi;
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,8 +6,9 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
import { FILE_SIGNATURES } from "./FileSignatures.mjs";
|
import {FILE_SIGNATURES} from "./FileSignatures.mjs";
|
||||||
import { sendStatusMessage } from "../Utils.mjs";
|
import {sendStatusMessage} from "../Utils.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a signature matches a buffer.
|
* Checks whether a signature matches a buffer.
|
||||||
|
@ -19,7 +20,7 @@ import { sendStatusMessage } from "../Utils.mjs";
|
||||||
* @param {number} [offset=0] Where in the buffer to start searching from
|
* @param {number} [offset=0] Where in the buffer to start searching from
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function signatureMatches(sig, buf, offset = 0) {
|
function signatureMatches(sig, buf, offset=0) {
|
||||||
// Using a length check seems to be more performant than `sig instanceof Array`
|
// Using a length check seems to be more performant than `sig instanceof Array`
|
||||||
if (sig.length) {
|
if (sig.length) {
|
||||||
// sig is an Array - return true if any of them match
|
// sig is an Array - return true if any of them match
|
||||||
|
@ -35,6 +36,7 @@ function signatureMatches(sig, buf, offset = 0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a set of bytes match the given buffer.
|
* Checks whether a set of bytes match the given buffer.
|
||||||
*
|
*
|
||||||
|
@ -45,28 +47,30 @@ function signatureMatches(sig, buf, offset = 0) {
|
||||||
* @param {number} [offset=0] Where in the buffer to start searching from
|
* @param {number} [offset=0] Where in the buffer to start searching from
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function bytesMatch(sig, buf, offset = 0) {
|
function bytesMatch(sig, buf, offset=0) {
|
||||||
for (const sigoffset in sig) {
|
for (const sigoffset in sig) {
|
||||||
const pos = parseInt(sigoffset, 10) + offset;
|
const pos = parseInt(sigoffset, 10) + offset;
|
||||||
switch (typeof sig[sigoffset]) {
|
switch (typeof sig[sigoffset]) {
|
||||||
case "number": // Static check
|
case "number": // Static check
|
||||||
if (buf[pos] !== sig[sigoffset]) return false;
|
if (buf[pos] !== sig[sigoffset])
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
case "object": // Array of options
|
case "object": // Array of options
|
||||||
if (sig[sigoffset].indexOf(buf[pos]) < 0) return false;
|
if (sig[sigoffset].indexOf(buf[pos]) < 0)
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
case "function": // More complex calculation
|
case "function": // More complex calculation
|
||||||
if (!sig[sigoffset](buf[pos])) return false;
|
if (!sig[sigoffset](buf[pos]))
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(`Unrecognised signature type at offset ${sigoffset}`);
|
||||||
`Unrecognised signature type at offset ${sigoffset}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a buffer, detects magic byte sequences at specific positions and returns the
|
* Given a buffer, detects magic byte sequences at specific positions and returns the
|
||||||
* extension and mime type.
|
* extension and mime type.
|
||||||
|
@ -79,7 +83,7 @@ function bytesMatch(sig, buf, offset = 0) {
|
||||||
* @returns {string} type.mime - Mime type
|
* @returns {string} type.mime - Mime type
|
||||||
* @returns {string} [type.desc] - Description
|
* @returns {string} [type.desc] - Description
|
||||||
*/
|
*/
|
||||||
export function detectFileType(buf, categories = Object.keys(FILE_SIGNATURES)) {
|
export function detectFileType(buf, categories=Object.keys(FILE_SIGNATURES)) {
|
||||||
if (buf instanceof ArrayBuffer) {
|
if (buf instanceof ArrayBuffer) {
|
||||||
buf = new Uint8Array(buf);
|
buf = new Uint8Array(buf);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +104,7 @@ export function detectFileType(buf, categories = Object.keys(FILE_SIGNATURES)) {
|
||||||
for (const cat in signatures) {
|
for (const cat in signatures) {
|
||||||
const category = signatures[cat];
|
const category = signatures[cat];
|
||||||
|
|
||||||
category.forEach((filetype) => {
|
category.forEach(filetype => {
|
||||||
if (signatureMatches(filetype.signature, buf)) {
|
if (signatureMatches(filetype.signature, buf)) {
|
||||||
matchingFiles.push(filetype);
|
matchingFiles.push(filetype);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +113,7 @@ export function detectFileType(buf, categories = Object.keys(FILE_SIGNATURES)) {
|
||||||
return matchingFiles;
|
return matchingFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a buffer, searches for magic byte sequences at all possible positions and returns
|
* Given a buffer, searches for magic byte sequences at all possible positions and returns
|
||||||
* the extensions and mime types.
|
* the extensions and mime types.
|
||||||
|
@ -123,10 +128,7 @@ export function detectFileType(buf, categories = Object.keys(FILE_SIGNATURES)) {
|
||||||
* @returns {string} foundFiles.fileDetails.mime - Mime type
|
* @returns {string} foundFiles.fileDetails.mime - Mime type
|
||||||
* @returns {string} [foundFiles.fileDetails.desc] - Description
|
* @returns {string} [foundFiles.fileDetails.desc] - Description
|
||||||
*/
|
*/
|
||||||
export function scanForFileTypes(
|
export function scanForFileTypes(buf, categories=Object.keys(FILE_SIGNATURES)) {
|
||||||
buf,
|
|
||||||
categories = Object.keys(FILE_SIGNATURES),
|
|
||||||
) {
|
|
||||||
if (!(buf && buf.length > 1)) {
|
if (!(buf && buf.length > 1)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -145,20 +147,16 @@ export function scanForFileTypes(
|
||||||
|
|
||||||
for (let i = 0; i < category.length; i++) {
|
for (let i = 0; i < category.length; i++) {
|
||||||
const filetype = category[i];
|
const filetype = category[i];
|
||||||
const sigs = filetype.signature.length
|
const sigs = filetype.signature.length ? filetype.signature : [filetype.signature];
|
||||||
? filetype.signature
|
|
||||||
: [filetype.signature];
|
|
||||||
|
|
||||||
sigs.forEach((sig) => {
|
sigs.forEach(sig => {
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while ((pos = locatePotentialSig(buf, sig, pos)) >= 0) {
|
while ((pos = locatePotentialSig(buf, sig, pos)) >= 0) {
|
||||||
if (bytesMatch(sig, buf, pos)) {
|
if (bytesMatch(sig, buf, pos)) {
|
||||||
sendStatusMessage(
|
sendStatusMessage(`Found potential signature for ${filetype.name} at pos ${pos}`);
|
||||||
`Found potential signature for ${filetype.name} at pos ${pos}`,
|
|
||||||
);
|
|
||||||
foundFiles.push({
|
foundFiles.push({
|
||||||
offset: pos,
|
offset: pos,
|
||||||
fileDetails: filetype,
|
fileDetails: filetype
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -173,6 +171,7 @@ export function scanForFileTypes(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fastcheck function to quickly scan the buffer for the first byte in a signature.
|
* Fastcheck function to quickly scan the buffer for the first byte in a signature.
|
||||||
*
|
*
|
||||||
|
@ -203,6 +202,7 @@ function locatePotentialSig(buf, sig, offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects whether the given buffer is a file of the type specified.
|
* Detects whether the given buffer is a file of the type specified.
|
||||||
*
|
*
|
||||||
|
@ -230,6 +230,7 @@ export function isType(type, buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects whether the given buffer contains an image file.
|
* Detects whether the given buffer contains an image file.
|
||||||
*
|
*
|
||||||
|
@ -240,6 +241,7 @@ export function isImage(buf) {
|
||||||
return isType("image", buf);
|
return isType("image", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to extract a file from a data stream given its offset and extractor function.
|
* Attempts to extract a file from a data stream given its offset and extractor function.
|
||||||
*
|
*
|
||||||
|
@ -253,21 +255,13 @@ export function isImage(buf) {
|
||||||
*/
|
*/
|
||||||
export function extractFile(bytes, fileDetail, offset) {
|
export function extractFile(bytes, fileDetail, offset) {
|
||||||
if (fileDetail.extractor) {
|
if (fileDetail.extractor) {
|
||||||
sendStatusMessage(
|
sendStatusMessage(`Attempting to extract ${fileDetail.name} at pos ${offset}...`);
|
||||||
`Attempting to extract ${fileDetail.name} at pos ${offset}...`,
|
|
||||||
);
|
|
||||||
const fileData = fileDetail.extractor(bytes, offset);
|
const fileData = fileDetail.extractor(bytes, offset);
|
||||||
const ext = fileDetail.extension.split(",")[0];
|
const ext = fileDetail.extension.split(",")[0];
|
||||||
return new File(
|
return new File([fileData], `extracted_at_0x${offset.toString(16)}.${ext}`, {
|
||||||
[fileData],
|
type: fileDetail.mime
|
||||||
`extracted_at_0x${offset.toString(16)}.${ext}`,
|
});
|
||||||
{
|
|
||||||
type: fileDetail.mime,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(`No extraction algorithm available for "${fileDetail.mime}" files`);
|
||||||
`No extraction algorithm available for "${fileDetail.mime}" files`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@
|
||||||
*/
|
*/
|
||||||
export function getLabelIndex(name, state) {
|
export function getLabelIndex(name, state) {
|
||||||
return state.opList.findIndex((operation) => {
|
return state.opList.findIndex((operation) => {
|
||||||
return operation.name === "Label" && name === operation.ingValues[0];
|
return (operation.name === "Label") && (name === operation.ingValues[0]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const DEFAULT_WEIGHTS = {
|
||||||
|
|
||||||
leadingLetterPenalty: -5, // penalty applied for every letter in str before the first match
|
leadingLetterPenalty: -5, // penalty applied for every letter in str before the first match
|
||||||
maxLeadingLetterPenalty: -15, // maximum penalty for leading letters
|
maxLeadingLetterPenalty: -15, // maximum penalty for leading letters
|
||||||
unmatchedLetterPenalty: -1,
|
unmatchedLetterPenalty: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,12 +35,7 @@ export const DEFAULT_WEIGHTS = {
|
||||||
* @returns [boolean, number] a boolean which tells if pattern was
|
* @returns [boolean, number] a boolean which tells if pattern was
|
||||||
* found or not and a search score
|
* found or not and a search score
|
||||||
*/
|
*/
|
||||||
export function fuzzyMatch(
|
export function fuzzyMatch(pattern, str, global=false, weights=DEFAULT_WEIGHTS) {
|
||||||
pattern,
|
|
||||||
str,
|
|
||||||
global = false,
|
|
||||||
weights = DEFAULT_WEIGHTS,
|
|
||||||
) {
|
|
||||||
const recursionCount = 0;
|
const recursionCount = 0;
|
||||||
const recursionLimit = 10;
|
const recursionLimit = 10;
|
||||||
const matches = [];
|
const matches = [];
|
||||||
|
@ -58,7 +53,7 @@ export function fuzzyMatch(
|
||||||
0 /* nextMatch */,
|
0 /* nextMatch */,
|
||||||
recursionCount,
|
recursionCount,
|
||||||
recursionLimit,
|
recursionLimit,
|
||||||
weights,
|
weights
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +76,7 @@ export function fuzzyMatch(
|
||||||
0 /* nextMatch */,
|
0 /* nextMatch */,
|
||||||
recursionCount,
|
recursionCount,
|
||||||
recursionLimit,
|
recursionLimit,
|
||||||
weights,
|
weights
|
||||||
);
|
);
|
||||||
if (foundMatch) results.push([foundMatch, score, [...idxs]]);
|
if (foundMatch) results.push([foundMatch, score, [...idxs]]);
|
||||||
strCurrIndex = idxs[idxs.length - 1] + 1;
|
strCurrIndex = idxs[idxs.length - 1] + 1;
|
||||||
|
@ -103,7 +98,7 @@ function fuzzyMatchRecursive(
|
||||||
nextMatch,
|
nextMatch,
|
||||||
recursionCount,
|
recursionCount,
|
||||||
recursionLimit,
|
recursionLimit,
|
||||||
weights,
|
weights
|
||||||
) {
|
) {
|
||||||
let outScore = 0;
|
let outScore = 0;
|
||||||
|
|
||||||
|
@ -127,8 +122,7 @@ function fuzzyMatchRecursive(
|
||||||
while (patternCurIndex < pattern.length && strCurrIndex < str.length) {
|
while (patternCurIndex < pattern.length && strCurrIndex < str.length) {
|
||||||
// Match found.
|
// Match found.
|
||||||
if (
|
if (
|
||||||
pattern[patternCurIndex].toLowerCase() ===
|
pattern[patternCurIndex].toLowerCase() === str[strCurrIndex].toLowerCase()
|
||||||
str[strCurrIndex].toLowerCase()
|
|
||||||
) {
|
) {
|
||||||
if (nextMatch >= maxMatches) {
|
if (nextMatch >= maxMatches) {
|
||||||
return [false, outScore, []];
|
return [false, outScore, []];
|
||||||
|
@ -139,8 +133,7 @@ function fuzzyMatchRecursive(
|
||||||
firstMatch = false;
|
firstMatch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [matched, recursiveScore, recursiveMatches] =
|
const [matched, recursiveScore, recursiveMatches] = fuzzyMatchRecursive(
|
||||||
fuzzyMatchRecursive(
|
|
||||||
pattern,
|
pattern,
|
||||||
str,
|
str,
|
||||||
patternCurIndex,
|
patternCurIndex,
|
||||||
|
@ -151,7 +144,7 @@ function fuzzyMatchRecursive(
|
||||||
nextMatch,
|
nextMatch,
|
||||||
recursionCount,
|
recursionCount,
|
||||||
recursionLimit,
|
recursionLimit,
|
||||||
weights,
|
weights
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matched) {
|
if (matched) {
|
||||||
|
@ -177,9 +170,9 @@ function fuzzyMatchRecursive(
|
||||||
// Apply leading letter penalty
|
// Apply leading letter penalty
|
||||||
let penalty = weights.leadingLetterPenalty * matches[0];
|
let penalty = weights.leadingLetterPenalty * matches[0];
|
||||||
penalty =
|
penalty =
|
||||||
penalty < weights.maxLeadingLetterPenalty
|
penalty < weights.maxLeadingLetterPenalty ?
|
||||||
? weights.maxLeadingLetterPenalty
|
weights.maxLeadingLetterPenalty :
|
||||||
: penalty;
|
penalty;
|
||||||
outScore += penalty;
|
outScore += penalty;
|
||||||
|
|
||||||
// Apply unmatched penalty
|
// Apply unmatched penalty
|
||||||
|
@ -208,8 +201,7 @@ function fuzzyMatchRecursive(
|
||||||
) {
|
) {
|
||||||
outScore += weights.camelBonus;
|
outScore += weights.camelBonus;
|
||||||
}
|
}
|
||||||
const isNeighbourSeparator =
|
const isNeighbourSeparator = neighbor === "_" || neighbor === " ";
|
||||||
neighbor === "_" || neighbor === " ";
|
|
||||||
if (isNeighbourSeparator) {
|
if (isNeighbourSeparator) {
|
||||||
outScore += weights.separatorBonus;
|
outScore += weights.separatorBonus;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +239,7 @@ export function calcMatchRanges(matches) {
|
||||||
let start = matches[0],
|
let start = matches[0],
|
||||||
curr = start;
|
curr = start;
|
||||||
|
|
||||||
matches.forEach((m) => {
|
matches.forEach(m => {
|
||||||
if (m === curr || m === curr + 1) curr = m;
|
if (m === curr || m === curr + 1) curr = m;
|
||||||
else {
|
else {
|
||||||
ranges.push([start, curr - start + 1]);
|
ranges.push([start, curr - start + 1]);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import CryptoApi from "crypto-api/src/crypto-api.mjs";
|
import CryptoApi from "crypto-api/src/crypto-api.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic hash function.
|
* Generic hash function.
|
||||||
*
|
*
|
||||||
|
@ -18,9 +19,10 @@ import CryptoApi from "crypto-api/src/crypto-api.mjs";
|
||||||
* @param {Object} [options={}]
|
* @param {Object} [options={}]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function runHash(name, input, options = {}) {
|
export function runHash(name, input, options={}) {
|
||||||
const msg = Utils.arrayBufferToStr(input, false),
|
const msg = Utils.arrayBufferToStr(input, false),
|
||||||
hasher = CryptoApi.getHasher(name, options);
|
hasher = CryptoApi.getHasher(name, options);
|
||||||
hasher.update(msg);
|
hasher.update(msg);
|
||||||
return CryptoApi.encoder.toHex(hasher.finalize());
|
return CryptoApi.encoder.toHex(hasher.finalize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a byte array into a hex string.
|
* Convert a byte array into a hex string.
|
||||||
*
|
*
|
||||||
|
@ -27,18 +28,12 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* // returns "0x0a,0x14,0x1e"
|
* // returns "0x0a,0x14,0x1e"
|
||||||
* toHex([10,20,30], "0x", 2, ",")
|
* toHex([10,20,30], "0x", 2, ",")
|
||||||
*/
|
*/
|
||||||
export function toHex(
|
export function toHex(data, delim=" ", padding=2, extraDelim="", lineSize=0) {
|
||||||
data,
|
|
||||||
delim = " ",
|
|
||||||
padding = 2,
|
|
||||||
extraDelim = "",
|
|
||||||
lineSize = 0,
|
|
||||||
) {
|
|
||||||
if (!data) return "";
|
if (!data) return "";
|
||||||
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
||||||
|
|
||||||
let output = "";
|
let output = "";
|
||||||
const prepend = delim === "0x" || delim === "\\x";
|
const prepend = (delim === "0x" || delim === "\\x");
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const hex = data[i].toString(16).padStart(padding, "0");
|
const hex = data[i].toString(16).padStart(padding, "0");
|
||||||
|
@ -48,7 +43,7 @@ export function toHex(
|
||||||
output += extraDelim;
|
output += extraDelim;
|
||||||
}
|
}
|
||||||
// Add LF after each lineSize amount of bytes but not at the end
|
// Add LF after each lineSize amount of bytes but not at the end
|
||||||
if (i !== data.length - 1 && (i + 1) % lineSize === 0) {
|
if ((i !== data.length - 1) && ((i + 1) % lineSize === 0)) {
|
||||||
output += "\n";
|
output += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +59,7 @@ export function toHex(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a byte array into a hex string as efficiently as possible with no options.
|
* Convert a byte array into a hex string as efficiently as possible with no options.
|
||||||
*
|
*
|
||||||
|
@ -88,6 +84,7 @@ export function toHexFast(data) {
|
||||||
return output.join("");
|
return output.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a hex string into a byte array.
|
* Convert a hex string into a byte array.
|
||||||
*
|
*
|
||||||
|
@ -103,13 +100,12 @@ export function toHexFast(data) {
|
||||||
* // returns [10,20,30]
|
* // returns [10,20,30]
|
||||||
* fromHex("0a:14:1e", "Colon");
|
* fromHex("0a:14:1e", "Colon");
|
||||||
*/
|
*/
|
||||||
export function fromHex(data, delim = "Auto", byteLen = 2) {
|
export function fromHex(data, delim="Auto", byteLen=2) {
|
||||||
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
|
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
|
||||||
throw new OperationError("Byte length must be a positive integer");
|
throw new OperationError("Byte length must be a positive integer");
|
||||||
|
|
||||||
if (delim !== "None") {
|
if (delim !== "None") {
|
||||||
const delimRegex =
|
const delimRegex = delim === "Auto" ? /[^a-f\d]|0x/gi : Utils.regexRep(delim);
|
||||||
delim === "Auto" ? /[^a-f\d]|0x/gi : Utils.regexRep(delim);
|
|
||||||
data = data.split(delimRegex);
|
data = data.split(delimRegex);
|
||||||
} else {
|
} else {
|
||||||
data = [data];
|
data = [data];
|
||||||
|
@ -124,22 +120,12 @@ export function fromHex(data, delim = "Auto", byteLen = 2) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To Hexadecimal delimiters.
|
* To Hexadecimal delimiters.
|
||||||
*/
|
*/
|
||||||
export const TO_HEX_DELIM_OPTIONS = [
|
export const TO_HEX_DELIM_OPTIONS = ["Space", "Percent", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "0x with comma", "\\x", "None"];
|
||||||
"Space",
|
|
||||||
"Percent",
|
|
||||||
"Comma",
|
|
||||||
"Semi-colon",
|
|
||||||
"Colon",
|
|
||||||
"Line feed",
|
|
||||||
"CRLF",
|
|
||||||
"0x",
|
|
||||||
"0x with comma",
|
|
||||||
"\\x",
|
|
||||||
"None",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From Hexadecimal delimiters.
|
* From Hexadecimal delimiters.
|
||||||
|
|
|
@ -20,12 +20,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* @param {boolean} allowLargeList
|
* @param {boolean} allowLargeList
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function ipv4CidrRange(
|
export function ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||||
cidr,
|
|
||||||
includeNetworkInfo,
|
|
||||||
enumerateAddresses,
|
|
||||||
allowLargeList,
|
|
||||||
) {
|
|
||||||
const network = strToIpv4(cidr[1]),
|
const network = strToIpv4(cidr[1]),
|
||||||
cidrRange = parseInt(cidr[2], 10);
|
cidrRange = parseInt(cidr[2], 10);
|
||||||
let output = "";
|
let output = "";
|
||||||
|
@ -34,7 +29,7 @@ export function ipv4CidrRange(
|
||||||
throw new OperationError("IPv4 CIDR must be less than 32");
|
throw new OperationError("IPv4 CIDR must be less than 32");
|
||||||
}
|
}
|
||||||
|
|
||||||
const mask = ~(0xffffffff >>> cidrRange),
|
const mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||||
ip1 = network & mask,
|
ip1 = network & mask,
|
||||||
ip2 = ip1 | ~mask;
|
ip2 = ip1 | ~mask;
|
||||||
|
|
||||||
|
@ -43,8 +38,7 @@ export function ipv4CidrRange(
|
||||||
output += "CIDR: " + cidrRange + "\n";
|
output += "CIDR: " + cidrRange + "\n";
|
||||||
output += "Mask: " + ipv4ToStr(mask) + "\n";
|
output += "Mask: " + ipv4ToStr(mask) + "\n";
|
||||||
output += "Range: " + ipv4ToStr(ip1) + " - " + ipv4ToStr(ip2) + "\n";
|
output += "Range: " + ipv4ToStr(ip1) + " - " + ipv4ToStr(ip2) + "\n";
|
||||||
output +=
|
output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
|
||||||
"Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enumerateAddresses) {
|
if (enumerateAddresses) {
|
||||||
|
@ -67,7 +61,7 @@ export function ipv4CidrRange(
|
||||||
export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
||||||
let output = "";
|
let output = "";
|
||||||
const network = strToIpv6(cidr[1]),
|
const network = strToIpv6(cidr[1]),
|
||||||
cidrRange = parseInt(cidr[cidr.length - 1], 10);
|
cidrRange = parseInt(cidr[cidr.length-1], 10);
|
||||||
|
|
||||||
if (cidrRange < 0 || cidrRange > 127) {
|
if (cidrRange < 0 || cidrRange > 127) {
|
||||||
throw new OperationError("IPv6 CIDR must be less than 128");
|
throw new OperationError("IPv6 CIDR must be less than 128");
|
||||||
|
@ -80,14 +74,15 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
||||||
const mask = genIpv6Mask(cidrRange);
|
const mask = genIpv6Mask(cidrRange);
|
||||||
let totalDiff = "";
|
let totalDiff = "";
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
ip1[i] = network[i] & mask[i];
|
ip1[i] = network[i] & mask[i];
|
||||||
ip2[i] = ip1[i] | (~mask[i] & 0x0000ffff);
|
ip2[i] = ip1[i] | (~mask[i] & 0x0000FFFF);
|
||||||
totalDiff = (ip2[i] - ip1[i]).toString(2);
|
totalDiff = (ip2[i] - ip1[i]).toString(2);
|
||||||
|
|
||||||
if (totalDiff !== "0") {
|
if (totalDiff !== "0") {
|
||||||
for (let n = 0; n < totalDiff.length; n++) {
|
for (let n = 0; n < totalDiff.length; n++) {
|
||||||
total[i * 16 + 16 - (totalDiff.length - n)] = totalDiff[n];
|
total[i*16 + 16-(totalDiff.length-n)] = totalDiff[n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,10 +93,7 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
||||||
output += "CIDR: " + cidrRange + "\n";
|
output += "CIDR: " + cidrRange + "\n";
|
||||||
output += "Mask: " + ipv6ToStr(mask) + "\n";
|
output += "Mask: " + ipv6ToStr(mask) + "\n";
|
||||||
output += "Range: " + ipv6ToStr(ip1) + " - " + ipv6ToStr(ip2) + "\n";
|
output += "Range: " + ipv6ToStr(ip1) + " - " + ipv6ToStr(ip2) + "\n";
|
||||||
output +=
|
output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n";
|
||||||
"Total addresses in range: " +
|
|
||||||
(parseInt(total.join(""), 2) + 1) +
|
|
||||||
"\n\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
@ -117,12 +109,7 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
||||||
* @param {boolean} allowLargeList
|
* @param {boolean} allowLargeList
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function ipv4HyphenatedRange(
|
export function ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||||
range,
|
|
||||||
includeNetworkInfo,
|
|
||||||
enumerateAddresses,
|
|
||||||
allowLargeList,
|
|
||||||
) {
|
|
||||||
const ip1 = strToIpv4(range[0].split("-")[0].trim()),
|
const ip1 = strToIpv4(range[0].split("-")[0].trim()),
|
||||||
ip2 = strToIpv4(range[0].split("-")[1].trim());
|
ip2 = strToIpv4(range[0].split("-")[1].trim());
|
||||||
|
|
||||||
|
@ -150,16 +137,16 @@ export function ipv4HyphenatedRange(
|
||||||
\tCIDR: ${cidr}
|
\tCIDR: ${cidr}
|
||||||
\tMask: ${ipv4ToStr(mask)}
|
\tMask: ${ipv4ToStr(mask)}
|
||||||
\tSubnet range: ${ipv4ToStr(subIp1)} - ${ipv4ToStr(subIp2)}
|
\tSubnet range: ${ipv4ToStr(subIp1)} - ${ipv4ToStr(subIp2)}
|
||||||
\tTotal addresses in subnet: ${((subIp2 - subIp1) >>> 0) + 1}
|
\tTotal addresses in subnet: ${(((subIp2 - subIp1) >>> 0) + 1)}
|
||||||
|
|
||||||
Range: ${ipv4ToStr(ip1)} - ${ipv4ToStr(ip2)}
|
Range: ${ipv4ToStr(ip1)} - ${ipv4ToStr(ip2)}
|
||||||
Total addresses in range: ${((ip2 - ip1) >>> 0) + 1}
|
Total addresses in range: ${(((ip2 - ip1) >>> 0) + 1)}
|
||||||
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enumerateAddresses) {
|
if (enumerateAddresses) {
|
||||||
if ((ip2 - ip1) >>> 0 <= 65536 || allowLargeList) {
|
if (((ip2 - ip1) >>> 0) <= 65536 || allowLargeList) {
|
||||||
output += generateIpv4Range(ip1, ip2).join("\n");
|
output += generateIpv4Range(ip1, ip2).join("\n");
|
||||||
} else {
|
} else {
|
||||||
output += _LARGE_RANGE_ERROR;
|
output += _LARGE_RANGE_ERROR;
|
||||||
|
@ -188,23 +175,15 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) {
|
||||||
t = (ip2[i] - ip1[i]).toString(2);
|
t = (ip2[i] - ip1[i]).toString(2);
|
||||||
if (t !== "0") {
|
if (t !== "0") {
|
||||||
for (let n = 0; n < t.length; n++) {
|
for (let n = 0; n < t.length; n++) {
|
||||||
total[i * 16 + 16 - (t.length - n)] = t[n];
|
total[i*16 + 16-(t.length-n)] = t[n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeNetworkInfo) {
|
if (includeNetworkInfo) {
|
||||||
output += "Range: " + ipv6ToStr(ip1) + " - " + ipv6ToStr(ip2) + "\n";
|
output += "Range: " + ipv6ToStr(ip1) + " - " + ipv6ToStr(ip2) + "\n";
|
||||||
output +=
|
output += "Shorthand range: " + ipv6ToStr(ip1, true) + " - " + ipv6ToStr(ip2, true) + "\n";
|
||||||
"Shorthand range: " +
|
output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n";
|
||||||
ipv6ToStr(ip1, true) +
|
|
||||||
" - " +
|
|
||||||
ipv6ToStr(ip2, true) +
|
|
||||||
"\n";
|
|
||||||
output +=
|
|
||||||
"Total addresses in range: " +
|
|
||||||
(parseInt(total.join(""), 2) + 1) +
|
|
||||||
"\n\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
@ -220,16 +199,12 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) {
|
||||||
* @param {boolean} allowLargeList
|
* @param {boolean} allowLargeList
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function ipv4ListedRange(
|
export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||||
match,
|
|
||||||
includeNetworkInfo,
|
|
||||||
enumerateAddresses,
|
|
||||||
allowLargeList,
|
|
||||||
) {
|
|
||||||
let ipv4List = match[0].split("\n");
|
let ipv4List = match[0].split("\n");
|
||||||
ipv4List = ipv4List.filter(Boolean);
|
ipv4List = ipv4List.filter(Boolean);
|
||||||
|
|
||||||
const ipv4CidrList = ipv4List.filter(function (a) {
|
const ipv4CidrList = ipv4List.filter(function(a) {
|
||||||
return a.includes("/");
|
return a.includes("/");
|
||||||
});
|
});
|
||||||
for (let i = 0; i < ipv4CidrList.length; i++) {
|
for (let i = 0; i < ipv4CidrList.length; i++) {
|
||||||
|
@ -238,7 +213,7 @@ export function ipv4ListedRange(
|
||||||
if (cidrRange < 0 || cidrRange > 31) {
|
if (cidrRange < 0 || cidrRange > 31) {
|
||||||
throw new OperationError("IPv4 CIDR must be less than 32");
|
throw new OperationError("IPv4 CIDR must be less than 32");
|
||||||
}
|
}
|
||||||
const mask = ~(0xffffffff >>> cidrRange),
|
const mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||||
cidrIp1 = network & mask,
|
cidrIp1 = network & mask,
|
||||||
cidrIp2 = cidrIp1 | ~mask;
|
cidrIp2 = cidrIp1 | ~mask;
|
||||||
ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1);
|
ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1);
|
||||||
|
@ -249,12 +224,7 @@ export function ipv4ListedRange(
|
||||||
const ip1 = ipv4List[0];
|
const ip1 = ipv4List[0];
|
||||||
const ip2 = ipv4List[ipv4List.length - 1];
|
const ip2 = ipv4List[ipv4List.length - 1];
|
||||||
const range = [ip1 + " - " + ip2];
|
const range = [ip1 + " - " + ip2];
|
||||||
return ipv4HyphenatedRange(
|
return ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList);
|
||||||
range,
|
|
||||||
includeNetworkInfo,
|
|
||||||
enumerateAddresses,
|
|
||||||
allowLargeList,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -266,18 +236,20 @@ export function ipv4ListedRange(
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function ipv6ListedRange(match, includeNetworkInfo) {
|
export function ipv6ListedRange(match, includeNetworkInfo) {
|
||||||
|
|
||||||
let ipv6List = match[0].split("\n");
|
let ipv6List = match[0].split("\n");
|
||||||
ipv6List = ipv6List.filter(function (str) {
|
ipv6List = ipv6List.filter(function(str) {
|
||||||
return str.trim();
|
return str.trim();
|
||||||
});
|
});
|
||||||
for (let i = 0; i < ipv6List.length; i++) {
|
for (let i =0; i < ipv6List.length; i++) {
|
||||||
ipv6List[i] = ipv6List[i].trim();
|
ipv6List[i] = ipv6List[i].trim();
|
||||||
}
|
}
|
||||||
const ipv6CidrList = ipv6List.filter(function (a) {
|
const ipv6CidrList = ipv6List.filter(function(a) {
|
||||||
return a.includes("/");
|
return a.includes("/");
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < ipv6CidrList.length; i++) {
|
for (let i = 0; i < ipv6CidrList.length; i++) {
|
||||||
|
|
||||||
const network = strToIpv6(ipv6CidrList[i].split("/")[0]);
|
const network = strToIpv6(ipv6CidrList[i].split("/")[0]);
|
||||||
const cidrRange = parseInt(ipv6CidrList[i].split("/")[1], 10);
|
const cidrRange = parseInt(ipv6CidrList[i].split("/")[1], 10);
|
||||||
|
|
||||||
|
@ -292,7 +264,7 @@ export function ipv6ListedRange(match, includeNetworkInfo) {
|
||||||
|
|
||||||
for (let j = 0; j < 8; j++) {
|
for (let j = 0; j < 8; j++) {
|
||||||
cidrIp1[j] = network[j] & mask[j];
|
cidrIp1[j] = network[j] & mask[j];
|
||||||
cidrIp2[j] = cidrIp1[j] | (~mask[j] & 0x0000ffff);
|
cidrIp2[j] = cidrIp1[j] | (~mask[j] & 0x0000FFFF);
|
||||||
}
|
}
|
||||||
ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]), 1);
|
ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]), 1);
|
||||||
ipv6List.push(ipv6ToStr(cidrIp1), ipv6ToStr(cidrIp2));
|
ipv6List.push(ipv6ToStr(cidrIp1), ipv6ToStr(cidrIp2));
|
||||||
|
@ -362,6 +334,7 @@ export function ipv4ToStr(ipInt) {
|
||||||
return blockA + "." + blockB + "." + blockC + "." + blockD;
|
return blockA + "." + blockB + "." + blockC + "." + blockD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an IPv6 address from string format to numerical array format.
|
* Converts an IPv6 address from string format to numerical array format.
|
||||||
*
|
*
|
||||||
|
@ -381,7 +354,7 @@ export function strToIpv6(ipStr) {
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
if (isNaN(numBlocks[j])) {
|
if (isNaN(numBlocks[j])) {
|
||||||
ipv6[i] = 0;
|
ipv6[i] = 0;
|
||||||
if (i === 8 - numBlocks.slice(j).length) j++;
|
if (i === (8-numBlocks.slice(j).length)) j++;
|
||||||
} else {
|
} else {
|
||||||
ipv6[i] = numBlocks[j];
|
ipv6[i] = numBlocks[j];
|
||||||
j++;
|
j++;
|
||||||
|
@ -430,13 +403,12 @@ export function ipv6ToStr(ipv6, compact) {
|
||||||
e = -1;
|
e = -1;
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (ipv6[i] === 0 && e === i - 1) {
|
if (ipv6[i] === 0 && e === (i-1)) {
|
||||||
e = i;
|
e = i;
|
||||||
} else if (ipv6[i] === 0) {
|
} else if (ipv6[i] === 0) {
|
||||||
s = i;
|
s = i; e = i;
|
||||||
e = i;
|
|
||||||
}
|
}
|
||||||
if (e >= 0 && e - s > end - start) {
|
if (e >= 0 && (e-s) > (end - start)) {
|
||||||
start = s;
|
start = s;
|
||||||
end = e;
|
end = e;
|
||||||
}
|
}
|
||||||
|
@ -451,13 +423,14 @@ export function ipv6ToStr(ipv6, compact) {
|
||||||
if (end === 7) output += ":";
|
if (end === 7) output += ":";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (output[0] === ":") output = ":" + output;
|
if (output[0] === ":")
|
||||||
|
output = ":" + output;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
output += Utils.hex(ipv6[i], 4) + ":";
|
output += Utils.hex(ipv6[i], 4) + ":";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output.slice(0, output.length - 1);
|
return output.slice(0, output.length-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -494,12 +467,12 @@ export function genIpv6Mask(cidr) {
|
||||||
let shift;
|
let shift;
|
||||||
|
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
if (cidr > (i + 1) * 16) {
|
if (cidr > ((i+1)*16)) {
|
||||||
mask[i] = 0x0000ffff;
|
mask[i] = 0x0000FFFF;
|
||||||
} else {
|
} else {
|
||||||
shift = cidr - i * 16;
|
shift = cidr-(i*16);
|
||||||
if (shift < 0) shift = 0;
|
if (shift < 0) shift = 0;
|
||||||
mask[i] = ~((0x0000ffff >>> shift) | 0xffff0000);
|
mask[i] = ~((0x0000FFFF >>> shift) | 0xFFFF0000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,6 +498,7 @@ export function ipv4Compare(a, b) {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export function ipv6Compare(a, b) {
|
export function ipv6Compare(a, b) {
|
||||||
|
|
||||||
const a_ = strToIpv6(a),
|
const a_ = strToIpv6(a),
|
||||||
b_ = strToIpv6(b);
|
b_ = strToIpv6(b);
|
||||||
|
|
||||||
|
@ -536,8 +510,7 @@ export function ipv6Compare(a, b) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _LARGE_RANGE_ERROR =
|
const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges.";
|
||||||
'The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the "Allow large queries" option. You are advised to turn off "Auto Bake" whilst editing large ranges.';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A regular expression that matches an IPv4 address
|
* A regular expression that matches an IPv4 address
|
||||||
|
@ -547,174 +520,157 @@ export const IPV4_REGEX = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/;
|
||||||
/**
|
/**
|
||||||
* A regular expression that matches an IPv6 address
|
* A regular expression that matches an IPv6 address
|
||||||
*/
|
*/
|
||||||
export const IPV6_REGEX =
|
export const IPV6_REGEX = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i;
|
||||||
/^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup table for Internet Protocols.
|
* Lookup table for Internet Protocols.
|
||||||
* Taken from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
|
* Taken from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
|
||||||
*/
|
*/
|
||||||
export const protocolLookup = {
|
export const protocolLookup = {
|
||||||
0: { keyword: "HOPOPT", protocol: "IPv6 Hop-by-Hop Option" },
|
0: {keyword: "HOPOPT", protocol: "IPv6 Hop-by-Hop Option"},
|
||||||
1: { keyword: "ICMP", protocol: "Internet Control Message" },
|
1: {keyword: "ICMP", protocol: "Internet Control Message"},
|
||||||
2: { keyword: "IGMP", protocol: "Internet Group Management" },
|
2: {keyword: "IGMP", protocol: "Internet Group Management"},
|
||||||
3: { keyword: "GGP", protocol: "Gateway-to-Gateway" },
|
3: {keyword: "GGP", protocol: "Gateway-to-Gateway"},
|
||||||
4: { keyword: "IPv4", protocol: "IPv4 encapsulation" },
|
4: {keyword: "IPv4", protocol: "IPv4 encapsulation"},
|
||||||
5: { keyword: "ST", protocol: "Stream" },
|
5: {keyword: "ST", protocol: "Stream"},
|
||||||
6: { keyword: "TCP", protocol: "Transmission Control" },
|
6: {keyword: "TCP", protocol: "Transmission Control"},
|
||||||
7: { keyword: "CBT", protocol: "CBT" },
|
7: {keyword: "CBT", protocol: "CBT"},
|
||||||
8: { keyword: "EGP", protocol: "Exterior Gateway Protocol" },
|
8: {keyword: "EGP", protocol: "Exterior Gateway Protocol"},
|
||||||
9: {
|
9: {keyword: "IGP", protocol: "any private interior gateway (used by Cisco for their IGRP)"},
|
||||||
keyword: "IGP",
|
10: {keyword: "BBN-RCC-MON", protocol: "BBN RCC Monitoring"},
|
||||||
protocol: "any private interior gateway (used by Cisco for their IGRP)",
|
11: {keyword: "NVP-II", protocol: "Network Voice Protocol"},
|
||||||
},
|
12: {keyword: "PUP", protocol: "PUP"},
|
||||||
10: { keyword: "BBN-RCC-MON", protocol: "BBN RCC Monitoring" },
|
13: {keyword: "ARGUS (deprecated)", protocol: "ARGUS"},
|
||||||
11: { keyword: "NVP-II", protocol: "Network Voice Protocol" },
|
14: {keyword: "EMCON", protocol: "EMCON"},
|
||||||
12: { keyword: "PUP", protocol: "PUP" },
|
15: {keyword: "XNET", protocol: "Cross Net Debugger"},
|
||||||
13: { keyword: "ARGUS (deprecated)", protocol: "ARGUS" },
|
16: {keyword: "CHAOS", protocol: "Chaos"},
|
||||||
14: { keyword: "EMCON", protocol: "EMCON" },
|
17: {keyword: "UDP", protocol: "User Datagram"},
|
||||||
15: { keyword: "XNET", protocol: "Cross Net Debugger" },
|
18: {keyword: "MUX", protocol: "Multiplexing"},
|
||||||
16: { keyword: "CHAOS", protocol: "Chaos" },
|
19: {keyword: "DCN-MEAS", protocol: "DCN Measurement Subsystems"},
|
||||||
17: { keyword: "UDP", protocol: "User Datagram" },
|
20: {keyword: "HMP", protocol: "Host Monitoring"},
|
||||||
18: { keyword: "MUX", protocol: "Multiplexing" },
|
21: {keyword: "PRM", protocol: "Packet Radio Measurement"},
|
||||||
19: { keyword: "DCN-MEAS", protocol: "DCN Measurement Subsystems" },
|
22: {keyword: "XNS-IDP", protocol: "XEROX NS IDP"},
|
||||||
20: { keyword: "HMP", protocol: "Host Monitoring" },
|
23: {keyword: "TRUNK-1", protocol: "Trunk-1"},
|
||||||
21: { keyword: "PRM", protocol: "Packet Radio Measurement" },
|
24: {keyword: "TRUNK-2", protocol: "Trunk-2"},
|
||||||
22: { keyword: "XNS-IDP", protocol: "XEROX NS IDP" },
|
25: {keyword: "LEAF-1", protocol: "Leaf-1"},
|
||||||
23: { keyword: "TRUNK-1", protocol: "Trunk-1" },
|
26: {keyword: "LEAF-2", protocol: "Leaf-2"},
|
||||||
24: { keyword: "TRUNK-2", protocol: "Trunk-2" },
|
27: {keyword: "RDP", protocol: "Reliable Data Protocol"},
|
||||||
25: { keyword: "LEAF-1", protocol: "Leaf-1" },
|
28: {keyword: "IRTP", protocol: "Internet Reliable Transaction"},
|
||||||
26: { keyword: "LEAF-2", protocol: "Leaf-2" },
|
29: {keyword: "ISO-TP4", protocol: "ISO Transport Protocol Class 4"},
|
||||||
27: { keyword: "RDP", protocol: "Reliable Data Protocol" },
|
30: {keyword: "NETBLT", protocol: "Bulk Data Transfer Protocol"},
|
||||||
28: { keyword: "IRTP", protocol: "Internet Reliable Transaction" },
|
31: {keyword: "MFE-NSP", protocol: "MFE Network Services Protocol"},
|
||||||
29: { keyword: "ISO-TP4", protocol: "ISO Transport Protocol Class 4" },
|
32: {keyword: "MERIT-INP", protocol: "MERIT Internodal Protocol"},
|
||||||
30: { keyword: "NETBLT", protocol: "Bulk Data Transfer Protocol" },
|
33: {keyword: "DCCP", protocol: "Datagram Congestion Control Protocol"},
|
||||||
31: { keyword: "MFE-NSP", protocol: "MFE Network Services Protocol" },
|
34: {keyword: "3PC", protocol: "Third Party Connect Protocol"},
|
||||||
32: { keyword: "MERIT-INP", protocol: "MERIT Internodal Protocol" },
|
35: {keyword: "IDPR", protocol: "Inter-Domain Policy Routing Protocol"},
|
||||||
33: { keyword: "DCCP", protocol: "Datagram Congestion Control Protocol" },
|
36: {keyword: "XTP", protocol: "XTP"},
|
||||||
34: { keyword: "3PC", protocol: "Third Party Connect Protocol" },
|
37: {keyword: "DDP", protocol: "Datagram Delivery Protocol"},
|
||||||
35: { keyword: "IDPR", protocol: "Inter-Domain Policy Routing Protocol" },
|
38: {keyword: "IDPR-CMTP", protocol: "IDPR Control Message Transport Proto"},
|
||||||
36: { keyword: "XTP", protocol: "XTP" },
|
39: {keyword: "TP++", protocol: "TP++ Transport Protocol"},
|
||||||
37: { keyword: "DDP", protocol: "Datagram Delivery Protocol" },
|
40: {keyword: "IL", protocol: "IL Transport Protocol"},
|
||||||
38: {
|
41: {keyword: "IPv6", protocol: "IPv6 encapsulation"},
|
||||||
keyword: "IDPR-CMTP",
|
42: {keyword: "SDRP", protocol: "Source Demand Routing Protocol"},
|
||||||
protocol: "IDPR Control Message Transport Proto",
|
43: {keyword: "IPv6-Route", protocol: "Routing Header for IPv6"},
|
||||||
},
|
44: {keyword: "IPv6-Frag", protocol: "Fragment Header for IPv6"},
|
||||||
39: { keyword: "TP++", protocol: "TP++ Transport Protocol" },
|
45: {keyword: "IDRP", protocol: "Inter-Domain Routing Protocol"},
|
||||||
40: { keyword: "IL", protocol: "IL Transport Protocol" },
|
46: {keyword: "RSVP", protocol: "Reservation Protocol"},
|
||||||
41: { keyword: "IPv6", protocol: "IPv6 encapsulation" },
|
47: {keyword: "GRE", protocol: "Generic Routing Encapsulation"},
|
||||||
42: { keyword: "SDRP", protocol: "Source Demand Routing Protocol" },
|
48: {keyword: "DSR", protocol: "Dynamic Source Routing Protocol"},
|
||||||
43: { keyword: "IPv6-Route", protocol: "Routing Header for IPv6" },
|
49: {keyword: "BNA", protocol: "BNA"},
|
||||||
44: { keyword: "IPv6-Frag", protocol: "Fragment Header for IPv6" },
|
50: {keyword: "ESP", protocol: "Encap Security Payload"},
|
||||||
45: { keyword: "IDRP", protocol: "Inter-Domain Routing Protocol" },
|
51: {keyword: "AH", protocol: "Authentication Header"},
|
||||||
46: { keyword: "RSVP", protocol: "Reservation Protocol" },
|
52: {keyword: "I-NLSP", protocol: "Integrated Net Layer Security TUBA"},
|
||||||
47: { keyword: "GRE", protocol: "Generic Routing Encapsulation" },
|
53: {keyword: "SWIPE (deprecated)", protocol: "IP with Encryption"},
|
||||||
48: { keyword: "DSR", protocol: "Dynamic Source Routing Protocol" },
|
54: {keyword: "NARP", protocol: "NBMA Address Resolution Protocol"},
|
||||||
49: { keyword: "BNA", protocol: "BNA" },
|
55: {keyword: "MOBILE", protocol: "IP Mobility"},
|
||||||
50: { keyword: "ESP", protocol: "Encap Security Payload" },
|
56: {keyword: "TLSP", protocol: "Transport Layer Security Protocol using Kryptonet key management"},
|
||||||
51: { keyword: "AH", protocol: "Authentication Header" },
|
57: {keyword: "SKIP", protocol: "SKIP"},
|
||||||
52: { keyword: "I-NLSP", protocol: "Integrated Net Layer Security TUBA" },
|
58: {keyword: "IPv6-ICMP", protocol: "ICMP for IPv6"},
|
||||||
53: { keyword: "SWIPE (deprecated)", protocol: "IP with Encryption" },
|
59: {keyword: "IPv6-NoNxt", protocol: "No Next Header for IPv6"},
|
||||||
54: { keyword: "NARP", protocol: "NBMA Address Resolution Protocol" },
|
60: {keyword: "IPv6-Opts", protocol: "Destination Options for IPv6"},
|
||||||
55: { keyword: "MOBILE", protocol: "IP Mobility" },
|
61: {keyword: "", protocol: "any host internal protocol"},
|
||||||
56: {
|
62: {keyword: "CFTP", protocol: "CFTP"},
|
||||||
keyword: "TLSP",
|
63: {keyword: "", protocol: "any local network"},
|
||||||
protocol:
|
64: {keyword: "SAT-EXPAK", protocol: "SATNET and Backroom EXPAK"},
|
||||||
"Transport Layer Security Protocol using Kryptonet key management",
|
65: {keyword: "KRYPTOLAN", protocol: "Kryptolan"},
|
||||||
},
|
66: {keyword: "RVD", protocol: "MIT Remote Virtual Disk Protocol"},
|
||||||
57: { keyword: "SKIP", protocol: "SKIP" },
|
67: {keyword: "IPPC", protocol: "Internet Pluribus Packet Core"},
|
||||||
58: { keyword: "IPv6-ICMP", protocol: "ICMP for IPv6" },
|
68: {keyword: "", protocol: "any distributed file system"},
|
||||||
59: { keyword: "IPv6-NoNxt", protocol: "No Next Header for IPv6" },
|
69: {keyword: "SAT-MON", protocol: "SATNET Monitoring"},
|
||||||
60: { keyword: "IPv6-Opts", protocol: "Destination Options for IPv6" },
|
70: {keyword: "VISA", protocol: "VISA Protocol"},
|
||||||
61: { keyword: "", protocol: "any host internal protocol" },
|
71: {keyword: "IPCV", protocol: "Internet Packet Core Utility"},
|
||||||
62: { keyword: "CFTP", protocol: "CFTP" },
|
72: {keyword: "CPNX", protocol: "Computer Protocol Network Executive"},
|
||||||
63: { keyword: "", protocol: "any local network" },
|
73: {keyword: "CPHB", protocol: "Computer Protocol Heart Beat"},
|
||||||
64: { keyword: "SAT-EXPAK", protocol: "SATNET and Backroom EXPAK" },
|
74: {keyword: "WSN", protocol: "Wang Span Network"},
|
||||||
65: { keyword: "KRYPTOLAN", protocol: "Kryptolan" },
|
75: {keyword: "PVP", protocol: "Packet Video Protocol"},
|
||||||
66: { keyword: "RVD", protocol: "MIT Remote Virtual Disk Protocol" },
|
76: {keyword: "BR-SAT-MON", protocol: "Backroom SATNET Monitoring"},
|
||||||
67: { keyword: "IPPC", protocol: "Internet Pluribus Packet Core" },
|
77: {keyword: "SUN-ND", protocol: "SUN ND PROTOCOL-Temporary"},
|
||||||
68: { keyword: "", protocol: "any distributed file system" },
|
78: {keyword: "WB-MON", protocol: "WIDEBAND Monitoring"},
|
||||||
69: { keyword: "SAT-MON", protocol: "SATNET Monitoring" },
|
79: {keyword: "WB-EXPAK", protocol: "WIDEBAND EXPAK"},
|
||||||
70: { keyword: "VISA", protocol: "VISA Protocol" },
|
80: {keyword: "ISO-IP", protocol: "ISO Internet Protocol"},
|
||||||
71: { keyword: "IPCV", protocol: "Internet Packet Core Utility" },
|
81: {keyword: "VMTP", protocol: "VMTP"},
|
||||||
72: { keyword: "CPNX", protocol: "Computer Protocol Network Executive" },
|
82: {keyword: "SECURE-VMTP", protocol: "SECURE-VMTP"},
|
||||||
73: { keyword: "CPHB", protocol: "Computer Protocol Heart Beat" },
|
83: {keyword: "VINES", protocol: "VINES"},
|
||||||
74: { keyword: "WSN", protocol: "Wang Span Network" },
|
84: {keyword: "TTP", protocol: "Transaction Transport Protocol"},
|
||||||
75: { keyword: "PVP", protocol: "Packet Video Protocol" },
|
85: {keyword: "NSFNET-IGP", protocol: "NSFNET-IGP"},
|
||||||
76: { keyword: "BR-SAT-MON", protocol: "Backroom SATNET Monitoring" },
|
86: {keyword: "DGP", protocol: "Dissimilar Gateway Protocol"},
|
||||||
77: { keyword: "SUN-ND", protocol: "SUN ND PROTOCOL-Temporary" },
|
87: {keyword: "TCF", protocol: "TCF"},
|
||||||
78: { keyword: "WB-MON", protocol: "WIDEBAND Monitoring" },
|
88: {keyword: "EIGRP", protocol: "EIGRP"},
|
||||||
79: { keyword: "WB-EXPAK", protocol: "WIDEBAND EXPAK" },
|
89: {keyword: "OSPFIGP", protocol: "OSPFIGP"},
|
||||||
80: { keyword: "ISO-IP", protocol: "ISO Internet Protocol" },
|
90: {keyword: "Sprite-RPC", protocol: "Sprite RPC Protocol"},
|
||||||
81: { keyword: "VMTP", protocol: "VMTP" },
|
91: {keyword: "LARP", protocol: "Locus Address Resolution Protocol"},
|
||||||
82: { keyword: "SECURE-VMTP", protocol: "SECURE-VMTP" },
|
92: {keyword: "MTP", protocol: "Multicast Transport Protocol"},
|
||||||
83: { keyword: "VINES", protocol: "VINES" },
|
93: {keyword: "AX.25", protocol: "AX.25 Frames"},
|
||||||
84: { keyword: "TTP", protocol: "Transaction Transport Protocol" },
|
94: {keyword: "IPIP", protocol: "IP-within-IP Encapsulation Protocol"},
|
||||||
85: { keyword: "NSFNET-IGP", protocol: "NSFNET-IGP" },
|
95: {keyword: "MICP (deprecated)", protocol: "Mobile Internetworking Control Pro."},
|
||||||
86: { keyword: "DGP", protocol: "Dissimilar Gateway Protocol" },
|
96: {keyword: "SCC-SP", protocol: "Semaphore Communications Sec. Pro."},
|
||||||
87: { keyword: "TCF", protocol: "TCF" },
|
97: {keyword: "ETHERIP", protocol: "Ethernet-within-IP Encapsulation"},
|
||||||
88: { keyword: "EIGRP", protocol: "EIGRP" },
|
98: {keyword: "ENCAP", protocol: "Encapsulation Header"},
|
||||||
89: { keyword: "OSPFIGP", protocol: "OSPFIGP" },
|
99: {keyword: "", protocol: "any private encryption scheme"},
|
||||||
90: { keyword: "Sprite-RPC", protocol: "Sprite RPC Protocol" },
|
100: {keyword: "GMTP", protocol: "GMTP"},
|
||||||
91: { keyword: "LARP", protocol: "Locus Address Resolution Protocol" },
|
101: {keyword: "IFMP", protocol: "Ipsilon Flow Management Protocol"},
|
||||||
92: { keyword: "MTP", protocol: "Multicast Transport Protocol" },
|
102: {keyword: "PNNI", protocol: "PNNI over IP"},
|
||||||
93: { keyword: "AX.25", protocol: "AX.25 Frames" },
|
103: {keyword: "PIM", protocol: "Protocol Independent Multicast"},
|
||||||
94: { keyword: "IPIP", protocol: "IP-within-IP Encapsulation Protocol" },
|
104: {keyword: "ARIS", protocol: "ARIS"},
|
||||||
95: {
|
105: {keyword: "SCPS", protocol: "SCPS"},
|
||||||
keyword: "MICP (deprecated)",
|
106: {keyword: "QNX", protocol: "QNX"},
|
||||||
protocol: "Mobile Internetworking Control Pro.",
|
107: {keyword: "A/N", protocol: "Active Networks"},
|
||||||
},
|
108: {keyword: "IPComp", protocol: "IP Payload Compression Protocol"},
|
||||||
96: { keyword: "SCC-SP", protocol: "Semaphore Communications Sec. Pro." },
|
109: {keyword: "SNP", protocol: "Sitara Networks Protocol"},
|
||||||
97: { keyword: "ETHERIP", protocol: "Ethernet-within-IP Encapsulation" },
|
110: {keyword: "Compaq-Peer", protocol: "Compaq Peer Protocol"},
|
||||||
98: { keyword: "ENCAP", protocol: "Encapsulation Header" },
|
111: {keyword: "IPX-in-IP", protocol: "IPX in IP"},
|
||||||
99: { keyword: "", protocol: "any private encryption scheme" },
|
112: {keyword: "VRRP", protocol: "Virtual Router Redundancy Protocol"},
|
||||||
100: { keyword: "GMTP", protocol: "GMTP" },
|
113: {keyword: "PGM", protocol: "PGM Reliable Transport Protocol"},
|
||||||
101: { keyword: "IFMP", protocol: "Ipsilon Flow Management Protocol" },
|
114: {keyword: "", protocol: "any 0-hop protocol"},
|
||||||
102: { keyword: "PNNI", protocol: "PNNI over IP" },
|
115: {keyword: "L2TP", protocol: "Layer Two Tunneling Protocol"},
|
||||||
103: { keyword: "PIM", protocol: "Protocol Independent Multicast" },
|
116: {keyword: "DDX", protocol: "D-II Data Exchange (DDX)"},
|
||||||
104: { keyword: "ARIS", protocol: "ARIS" },
|
117: {keyword: "IATP", protocol: "Interactive Agent Transfer Protocol"},
|
||||||
105: { keyword: "SCPS", protocol: "SCPS" },
|
118: {keyword: "STP", protocol: "Schedule Transfer Protocol"},
|
||||||
106: { keyword: "QNX", protocol: "QNX" },
|
119: {keyword: "SRP", protocol: "SpectraLink Radio Protocol"},
|
||||||
107: { keyword: "A/N", protocol: "Active Networks" },
|
120: {keyword: "UTI", protocol: "UTI"},
|
||||||
108: { keyword: "IPComp", protocol: "IP Payload Compression Protocol" },
|
121: {keyword: "SMP", protocol: "Simple Message Protocol"},
|
||||||
109: { keyword: "SNP", protocol: "Sitara Networks Protocol" },
|
122: {keyword: "SM (deprecated)", protocol: "Simple Multicast Protocol"},
|
||||||
110: { keyword: "Compaq-Peer", protocol: "Compaq Peer Protocol" },
|
123: {keyword: "PTP", protocol: "Performance Transparency Protocol"},
|
||||||
111: { keyword: "IPX-in-IP", protocol: "IPX in IP" },
|
124: {keyword: "ISIS over IPv4", protocol: ""},
|
||||||
112: { keyword: "VRRP", protocol: "Virtual Router Redundancy Protocol" },
|
125: {keyword: "FIRE", protocol: ""},
|
||||||
113: { keyword: "PGM", protocol: "PGM Reliable Transport Protocol" },
|
126: {keyword: "CRTP", protocol: "Combat Radio Transport Protocol"},
|
||||||
114: { keyword: "", protocol: "any 0-hop protocol" },
|
127: {keyword: "CRUDP", protocol: "Combat Radio User Datagram"},
|
||||||
115: { keyword: "L2TP", protocol: "Layer Two Tunneling Protocol" },
|
128: {keyword: "SSCOPMCE", protocol: ""},
|
||||||
116: { keyword: "DDX", protocol: "D-II Data Exchange (DDX)" },
|
129: {keyword: "IPLT", protocol: ""},
|
||||||
117: { keyword: "IATP", protocol: "Interactive Agent Transfer Protocol" },
|
130: {keyword: "SPS", protocol: "Secure Packet Shield"},
|
||||||
118: { keyword: "STP", protocol: "Schedule Transfer Protocol" },
|
131: {keyword: "PIPE", protocol: "Private IP Encapsulation within IP"},
|
||||||
119: { keyword: "SRP", protocol: "SpectraLink Radio Protocol" },
|
132: {keyword: "SCTP", protocol: "Stream Control Transmission Protocol"},
|
||||||
120: { keyword: "UTI", protocol: "UTI" },
|
133: {keyword: "FC", protocol: "Fibre Channel"},
|
||||||
121: { keyword: "SMP", protocol: "Simple Message Protocol" },
|
134: {keyword: "RSVP-E2E-IGNORE", protocol: ""},
|
||||||
122: { keyword: "SM (deprecated)", protocol: "Simple Multicast Protocol" },
|
135: {keyword: "Mobility Header", protocol: ""},
|
||||||
123: { keyword: "PTP", protocol: "Performance Transparency Protocol" },
|
136: {keyword: "UDPLite", protocol: ""},
|
||||||
124: { keyword: "ISIS over IPv4", protocol: "" },
|
137: {keyword: "MPLS-in-IP", protocol: ""},
|
||||||
125: { keyword: "FIRE", protocol: "" },
|
138: {keyword: "manet", protocol: "MANET Protocols"},
|
||||||
126: { keyword: "CRTP", protocol: "Combat Radio Transport Protocol" },
|
139: {keyword: "HIP", protocol: "Host Identity Protocol"},
|
||||||
127: { keyword: "CRUDP", protocol: "Combat Radio User Datagram" },
|
140: {keyword: "Shim6", protocol: "Shim6 Protocol"},
|
||||||
128: { keyword: "SSCOPMCE", protocol: "" },
|
141: {keyword: "WESP", protocol: "Wrapped Encapsulating Security Payload"},
|
||||||
129: { keyword: "IPLT", protocol: "" },
|
142: {keyword: "ROHC", protocol: "Robust Header Compression"},
|
||||||
130: { keyword: "SPS", protocol: "Secure Packet Shield" },
|
253: {keyword: "", protocol: "Use for experimentation and testing"},
|
||||||
131: { keyword: "PIPE", protocol: "Private IP Encapsulation within IP" },
|
254: {keyword: "", protocol: "Use for experimentation and testing"},
|
||||||
132: { keyword: "SCTP", protocol: "Stream Control Transmission Protocol" },
|
255: {keyword: "Reserved", protocol: ""}
|
||||||
133: { keyword: "FC", protocol: "Fibre Channel" },
|
|
||||||
134: { keyword: "RSVP-E2E-IGNORE", protocol: "" },
|
|
||||||
135: { keyword: "Mobility Header", protocol: "" },
|
|
||||||
136: { keyword: "UDPLite", protocol: "" },
|
|
||||||
137: { keyword: "MPLS-in-IP", protocol: "" },
|
|
||||||
138: { keyword: "manet", protocol: "MANET Protocols" },
|
|
||||||
139: { keyword: "HIP", protocol: "Host Identity Protocol" },
|
|
||||||
140: { keyword: "Shim6", protocol: "Shim6 Protocol" },
|
|
||||||
141: {
|
|
||||||
keyword: "WESP",
|
|
||||||
protocol: "Wrapped Encapsulating Security Payload",
|
|
||||||
},
|
|
||||||
142: { keyword: "ROHC", protocol: "Robust Header Compression" },
|
|
||||||
253: { keyword: "", protocol: "Use for experimentation and testing" },
|
|
||||||
254: { keyword: "", protocol: "Use for experimentation and testing" },
|
|
||||||
255: { keyword: "Reserved", protocol: "" },
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* @param {boolean} fast
|
* @param {boolean} fast
|
||||||
* @returns {jimp}
|
* @returns {jimp}
|
||||||
*/
|
*/
|
||||||
export function gaussianBlur(input, radius) {
|
export function gaussianBlur (input, radius) {
|
||||||
try {
|
try {
|
||||||
// From http://blog.ivank.net/fastest-gaussian-blur.html
|
// From http://blog.ivank.net/fastest-gaussian-blur.html
|
||||||
const boxes = boxesForGauss(radius, 3);
|
const boxes = boxesForGauss(radius, 3);
|
||||||
|
@ -37,7 +37,7 @@ export function gaussianBlur(input, radius) {
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
function boxesForGauss(radius, numBoxes) {
|
function boxesForGauss(radius, numBoxes) {
|
||||||
const idealWidth = Math.sqrt((12 * radius * radius) / numBoxes + 1);
|
const idealWidth = Math.sqrt((12 * radius * radius / numBoxes) + 1);
|
||||||
|
|
||||||
let wl = Math.floor(idealWidth);
|
let wl = Math.floor(idealWidth);
|
||||||
|
|
||||||
|
@ -47,12 +47,7 @@ function boxesForGauss(radius, numBoxes) {
|
||||||
|
|
||||||
const wu = wl + 2;
|
const wu = wl + 2;
|
||||||
|
|
||||||
const mIdeal =
|
const mIdeal = (12 * radius * radius - numBoxes * wl * wl - 4 * numBoxes * wl - 3 * numBoxes) / (-4 * wl - 4);
|
||||||
(12 * radius * radius -
|
|
||||||
numBoxes * wl * wl -
|
|
||||||
4 * numBoxes * wl -
|
|
||||||
3 * numBoxes) /
|
|
||||||
(-4 * wl - 4);
|
|
||||||
const m = Math.round(mIdeal);
|
const m = Math.round(mIdeal);
|
||||||
|
|
||||||
const sizes = [];
|
const sizes = [];
|
||||||
|
@ -69,7 +64,7 @@ function boxesForGauss(radius, numBoxes) {
|
||||||
* @param {number} radius
|
* @param {number} radius
|
||||||
* @returns {jimp}
|
* @returns {jimp}
|
||||||
*/
|
*/
|
||||||
function boxBlur(source, radius) {
|
function boxBlur (source, radius) {
|
||||||
const width = source.bitmap.width;
|
const width = source.bitmap.width;
|
||||||
const height = source.bitmap.height;
|
const height = source.bitmap.height;
|
||||||
let output = source.clone();
|
let output = source.clone();
|
||||||
|
@ -89,7 +84,7 @@ function boxBlur(source, radius) {
|
||||||
* @param {number} radius
|
* @param {number} radius
|
||||||
* @returns {jimp}
|
* @returns {jimp}
|
||||||
*/
|
*/
|
||||||
function boxBlurH(source, output, width, height, radius) {
|
function boxBlurH (source, output, width, height, radius) {
|
||||||
const iarr = 1 / (radius + radius + 1);
|
const iarr = 1 / (radius + radius + 1);
|
||||||
for (let i = 0; i < height; i++) {
|
for (let i = 0; i < height; i++) {
|
||||||
let ti = 0,
|
let ti = 0,
|
||||||
|
@ -138,12 +133,9 @@ function boxBlurH(source, output, width, height, radius) {
|
||||||
const riIdx = source.getPixelIndex(ri++, i);
|
const riIdx = source.getPixelIndex(ri++, i);
|
||||||
const liIdx = source.getPixelIndex(li++, i);
|
const liIdx = source.getPixelIndex(li++, i);
|
||||||
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
|
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
|
||||||
green +=
|
green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
|
||||||
source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
|
blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
|
||||||
blue +=
|
alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
|
||||||
source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
|
|
||||||
alpha +=
|
|
||||||
source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(ti++, i);
|
const tiIdx = source.getPixelIndex(ti++, i);
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
||||||
|
@ -179,7 +171,7 @@ function boxBlurH(source, output, width, height, radius) {
|
||||||
* @param {number} radius
|
* @param {number} radius
|
||||||
* @returns {jimp}
|
* @returns {jimp}
|
||||||
*/
|
*/
|
||||||
function boxBlurV(source, output, width, height, radius) {
|
function boxBlurV (source, output, width, height, radius) {
|
||||||
const iarr = 1 / (radius + radius + 1);
|
const iarr = 1 / (radius + radius + 1);
|
||||||
for (let i = 0; i < width; i++) {
|
for (let i = 0; i < width; i++) {
|
||||||
let ti = 0,
|
let ti = 0,
|
||||||
|
@ -230,12 +222,9 @@ function boxBlurV(source, output, width, height, radius) {
|
||||||
const riIdx = source.getPixelIndex(i, ri++);
|
const riIdx = source.getPixelIndex(i, ri++);
|
||||||
const liIdx = source.getPixelIndex(i, li++);
|
const liIdx = source.getPixelIndex(i, li++);
|
||||||
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
|
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
|
||||||
green +=
|
green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
|
||||||
source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
|
blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
|
||||||
blue +=
|
alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
|
||||||
source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
|
|
||||||
alpha +=
|
|
||||||
source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(i, ti++);
|
const tiIdx = source.getPixelIndex(i, ti++);
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of the JWT algorithms that can be used
|
* List of the JWT algorithms that can be used
|
||||||
*/
|
*/
|
||||||
|
@ -19,5 +20,5 @@ export const JWT_ALGORITHMS = [
|
||||||
"ES256",
|
"ES256",
|
||||||
"ES384",
|
"ES384",
|
||||||
"ES512",
|
"ES512",
|
||||||
"None",
|
"None"
|
||||||
];
|
];
|
||||||
|
|
|
@ -14,7 +14,7 @@ const tiles = [];
|
||||||
*/
|
*/
|
||||||
export function initTiles() {
|
export function initTiles() {
|
||||||
for (let i = 0; i < 49; i++)
|
for (let i = 0; i < 49; i++)
|
||||||
tiles.push([letters.charAt(i), [Math.floor(i / 7), i % 7]]);
|
tiles.push([letters.charAt(i), [Math.floor(i/7), i % 7]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,19 +27,21 @@ export function initTiles() {
|
||||||
*/
|
*/
|
||||||
function rotateDown(key, col, n) {
|
function rotateDown(key, col, n) {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
for (let i = 0; i < 7; i++) lines.push(key.slice(i * 7, (i + 1) * 7));
|
for (let i = 0; i < 7; i++)
|
||||||
|
lines.push(key.slice(i*7, (i + 1) * 7));
|
||||||
const lefts = [];
|
const lefts = [];
|
||||||
let mids = [];
|
let mids = [];
|
||||||
const rights = [];
|
const rights = [];
|
||||||
lines.forEach((element) => {
|
lines.forEach((element) => {
|
||||||
lefts.push(element.slice(0, col));
|
lefts.push(element.slice(0, col));
|
||||||
mids.push(element.charAt(col));
|
mids.push(element.charAt(col));
|
||||||
rights.push(element.slice(col + 1));
|
rights.push(element.slice(col+1));
|
||||||
});
|
});
|
||||||
n = (7 - (n % 7)) % 7;
|
n = (7 - n % 7) % 7;
|
||||||
mids = mids.slice(n).concat(mids.slice(0, n));
|
mids = mids.slice(n).concat(mids.slice(0, n));
|
||||||
let result = "";
|
let result = "";
|
||||||
for (let i = 0; i < 7; i++) result += lefts[i] + mids[i] + rights[i];
|
for (let i = 0; i < 7; i++)
|
||||||
|
result += lefts[i] + mids[i] + rights[i];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +55,8 @@ function rotateDown(key, col, n) {
|
||||||
*/
|
*/
|
||||||
function rotateRight(key, row, n) {
|
function rotateRight(key, row, n) {
|
||||||
const mid = key.slice(row * 7, (row + 1) * 7);
|
const mid = key.slice(row * 7, (row + 1) * 7);
|
||||||
n = (7 - (n % 7)) % 7;
|
n = (7 - n % 7) % 7;
|
||||||
return (
|
return key.slice(0, 7 * row) + mid.slice(n) + mid.slice(0, n) + key.slice(7 * (row + 1));
|
||||||
key.slice(0, 7 * row) +
|
|
||||||
mid.slice(n) +
|
|
||||||
mid.slice(0, n) +
|
|
||||||
key.slice(7 * (row + 1))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +67,8 @@ function rotateRight(key, row, n) {
|
||||||
*/
|
*/
|
||||||
function findIx(letter) {
|
function findIx(letter) {
|
||||||
for (let i = 0; i < tiles.length; i++)
|
for (let i = 0; i < tiles.length; i++)
|
||||||
if (tiles[i][0] === letter) return tiles[i][1];
|
if (tiles[i][0] === letter)
|
||||||
|
return tiles[i][1];
|
||||||
throw new OperationError("Letter " + letter + " is not included in LS47");
|
throw new OperationError("Letter " + letter + " is not included in LS47");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +98,8 @@ function checkKey(key) {
|
||||||
if (key.length !== letters.length)
|
if (key.length !== letters.length)
|
||||||
throw new OperationError("Wrong key size");
|
throw new OperationError("Wrong key size");
|
||||||
const counts = new Array();
|
const counts = new Array();
|
||||||
for (let i = 0; i < letters.length; i++) counts[letters.charAt(i)] = 0;
|
for (let i = 0; i < letters.length; i++)
|
||||||
|
counts[letters.charAt(i)] = 0;
|
||||||
for (const elem of letters) {
|
for (const elem of letters) {
|
||||||
if (letters.indexOf(elem) === -1)
|
if (letters.indexOf(elem) === -1)
|
||||||
throw new OperationError("Letter " + elem + " not in LS47");
|
throw new OperationError("Letter " + elem + " not in LS47");
|
||||||
|
@ -117,9 +116,10 @@ function checkKey(key) {
|
||||||
* @param {string} letter
|
* @param {string} letter
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
function findPos(key, letter) {
|
function findPos (key, letter) {
|
||||||
const index = key.indexOf(letter);
|
const index = key.indexOf(letter);
|
||||||
if (index >= 0 && index < 49) return [Math.floor(index / 7), index % 7];
|
if (index >= 0 && index < 49)
|
||||||
|
return [Math.floor(index/7), index%7];
|
||||||
throw new OperationError("Letter " + letter + " is not in the key");
|
throw new OperationError("Letter " + letter + " is not in the key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ function findPos(key, letter) {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function findAtPos(key, coord) {
|
function findAtPos(key, coord) {
|
||||||
return key.charAt(coord[1] + coord[0] * 7);
|
return key.charAt(coord[1] + (coord[0] * 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,7 +157,7 @@ function addPos(a, b) {
|
||||||
function subPos(a, b) {
|
function subPos(a, b) {
|
||||||
const asub = a[0] - b[0];
|
const asub = a[0] - b[0];
|
||||||
const bsub = a[1] - b[1];
|
const bsub = a[1] - b[1];
|
||||||
return [asub - Math.floor(asub / 7) * 7, bsub - Math.floor(bsub / 7) * 7];
|
return [asub - (Math.floor(asub/7) * 7), bsub - (Math.floor(bsub/7) * 7)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,7 +226,7 @@ export function encryptPad(key, plaintext, signature, paddingSize) {
|
||||||
for (let i = 0; i < paddingSize; i++) {
|
for (let i = 0; i < paddingSize; i++) {
|
||||||
padding += letters.charAt(Math.floor(Math.random() * letters.length));
|
padding += letters.charAt(Math.floor(Math.random() * letters.length));
|
||||||
}
|
}
|
||||||
return encrypt(key, padding + plaintext + "---" + signature);
|
return encrypt(key, padding+plaintext+"---"+signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,10 +39,7 @@ export function decompress(compressed) {
|
||||||
while (coffset + 2 <= compressed.length) {
|
while (coffset + 2 <= compressed.length) {
|
||||||
const doffset = decompressed.length;
|
const doffset = decompressed.length;
|
||||||
|
|
||||||
const blockHeader = Utils.byteArrayToInt(
|
const blockHeader = Utils.byteArrayToInt(compressed.slice(coffset, coffset + 2), "little");
|
||||||
compressed.slice(coffset, coffset + 2),
|
|
||||||
"little",
|
|
||||||
);
|
|
||||||
coffset += 2;
|
coffset += 2;
|
||||||
|
|
||||||
const size = blockHeader & SIZE_MASK;
|
const size = blockHeader & SIZE_MASK;
|
||||||
|
@ -51,9 +48,7 @@ export function decompress(compressed) {
|
||||||
if (size === 0) {
|
if (size === 0) {
|
||||||
break;
|
break;
|
||||||
} else if (compressed.length < coffset + size) {
|
} else if (compressed.length < coffset + size) {
|
||||||
throw new OperationError(
|
throw new OperationError("Malformed LZNT1 stream: Block too small! Has the stream been truncated?");
|
||||||
"Malformed LZNT1 stream: Block too small! Has the stream been truncated?",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((blockHeader & COMPRESSED_MASK) !== 0) {
|
if ((blockHeader & COMPRESSED_MASK) !== 0) {
|
||||||
|
@ -64,31 +59,18 @@ export function decompress(compressed) {
|
||||||
if ((header & 1) === 0) {
|
if ((header & 1) === 0) {
|
||||||
decompressed.push(compressed[coffset++]);
|
decompressed.push(compressed[coffset++]);
|
||||||
} else {
|
} else {
|
||||||
const pointer = Utils.byteArrayToInt(
|
const pointer = Utils.byteArrayToInt(compressed.slice(coffset, coffset + 2), "little");
|
||||||
compressed.slice(coffset, coffset + 2),
|
|
||||||
"little",
|
|
||||||
);
|
|
||||||
coffset += 2;
|
coffset += 2;
|
||||||
|
|
||||||
const displacement = getDisplacement(
|
const displacement = getDisplacement(decompressed.length - doffset - 1);
|
||||||
decompressed.length - doffset - 1,
|
const symbolOffset = (pointer >> (12 - displacement)) + 1;
|
||||||
);
|
const symbolLength = (pointer & (0xFFF >> displacement)) + 2;
|
||||||
const symbolOffset =
|
|
||||||
(pointer >> (12 - displacement)) + 1;
|
|
||||||
const symbolLength =
|
|
||||||
(pointer & (0xfff >> displacement)) + 2;
|
|
||||||
const shiftOffset = decompressed.length - symbolOffset;
|
const shiftOffset = decompressed.length - symbolOffset;
|
||||||
|
|
||||||
for (
|
for (let shiftDelta = 0; shiftDelta < symbolLength + 1; shiftDelta++) {
|
||||||
let shiftDelta = 0;
|
|
||||||
shiftDelta < symbolLength + 1;
|
|
||||||
shiftDelta++
|
|
||||||
) {
|
|
||||||
const shift = shiftOffset + shiftDelta;
|
const shift = shiftOffset + shiftDelta;
|
||||||
if (shift < 0 || decompressed.length <= shift) {
|
if (shift < 0 || decompressed.length <= shift) {
|
||||||
throw new OperationError(
|
throw new OperationError("Malformed LZNT1 stream: Invalid shift!");
|
||||||
"Malformed LZNT1 stream: Invalid shift!",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
decompressed.push(decompressed[shift]);
|
decompressed.push(decompressed[shift]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ import LZString from "lz-string";
|
||||||
|
|
||||||
export const COMPRESSION_OUTPUT_FORMATS = ["default", "UTF16", "Base64"];
|
export const COMPRESSION_OUTPUT_FORMATS = ["default", "UTF16", "Base64"];
|
||||||
export const COMPRESSION_FUNCTIONS = {
|
export const COMPRESSION_FUNCTIONS = {
|
||||||
default: LZString.compress,
|
"default": LZString.compress,
|
||||||
UTF16: LZString.compressToUTF16,
|
"UTF16": LZString.compressToUTF16,
|
||||||
Base64: LZString.compressToBase64,
|
"Base64": LZString.compressToBase64,
|
||||||
};
|
};
|
||||||
export const DECOMPRESSION_FUNCTIONS = {
|
export const DECOMPRESSION_FUNCTIONS = {
|
||||||
default: LZString.decompress,
|
"default": LZString.decompress,
|
||||||
UTF16: LZString.decompressFromUTF16,
|
"UTF16": LZString.decompressFromUTF16,
|
||||||
Base64: LZString.decompressFromBase64,
|
"Base64": LZString.decompressFromBase64,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,45 +12,34 @@
|
||||||
* @param {number} length
|
* @param {number} length
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function GenerateParagraphs(length = 3) {
|
export function GenerateParagraphs(length=3) {
|
||||||
const paragraphs = [];
|
const paragraphs = [];
|
||||||
while (paragraphs.length < length) {
|
while (paragraphs.length < length) {
|
||||||
const paragraphLength = getRandomLength(
|
const paragraphLength = getRandomLength(PARAGRAPH_LENGTH_MEAN, PARAGRAPH_LENGTH_STD_DEV);
|
||||||
PARAGRAPH_LENGTH_MEAN,
|
|
||||||
PARAGRAPH_LENGTH_STD_DEV,
|
|
||||||
);
|
|
||||||
const sentences = [];
|
const sentences = [];
|
||||||
while (sentences.length < paragraphLength) {
|
while (sentences.length < paragraphLength) {
|
||||||
const sentenceLength = getRandomLength(
|
const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV);
|
||||||
SENTENCE_LENGTH_MEAN,
|
|
||||||
SENTENCE_LENGTH_STD_DEV,
|
|
||||||
);
|
|
||||||
const sentence = getWords(sentenceLength);
|
const sentence = getWords(sentenceLength);
|
||||||
sentences.push(formatSentence(sentence));
|
sentences.push(formatSentence(sentence));
|
||||||
}
|
}
|
||||||
paragraphs.push(formatParagraph(sentences));
|
paragraphs.push(formatParagraph(sentences));
|
||||||
}
|
}
|
||||||
paragraphs[paragraphs.length - 1] = paragraphs[paragraphs.length - 1].slice(
|
paragraphs[paragraphs.length-1] = paragraphs[paragraphs.length-1].slice(0, -2);
|
||||||
0,
|
|
||||||
-2,
|
|
||||||
);
|
|
||||||
paragraphs[0] = replaceStart(paragraphs[0]);
|
paragraphs[0] = replaceStart(paragraphs[0]);
|
||||||
return paragraphs.join("");
|
return paragraphs.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate lorem ipsum sentences.
|
* Generate lorem ipsum sentences.
|
||||||
*
|
*
|
||||||
* @param {number} length
|
* @param {number} length
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function GenerateSentences(length = 3) {
|
export function GenerateSentences(length=3) {
|
||||||
const sentences = [];
|
const sentences = [];
|
||||||
while (sentences.length < length) {
|
while (sentences.length < length) {
|
||||||
const sentenceLength = getRandomLength(
|
const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV);
|
||||||
SENTENCE_LENGTH_MEAN,
|
|
||||||
SENTENCE_LENGTH_STD_DEV,
|
|
||||||
);
|
|
||||||
const sentence = getWords(sentenceLength);
|
const sentence = getWords(sentenceLength);
|
||||||
sentences.push(formatSentence(sentence));
|
sentences.push(formatSentence(sentence));
|
||||||
}
|
}
|
||||||
|
@ -58,30 +47,33 @@ export function GenerateSentences(length = 3) {
|
||||||
return paragraphs.join("");
|
return paragraphs.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate lorem ipsum words.
|
* Generate lorem ipsum words.
|
||||||
*
|
*
|
||||||
* @param {number} length
|
* @param {number} length
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function GenerateWords(length = 3) {
|
export function GenerateWords(length=3) {
|
||||||
const words = getWords(length);
|
const words = getWords(length);
|
||||||
const sentences = wordsToSentences(words);
|
const sentences = wordsToSentences(words);
|
||||||
const paragraphs = sentencesToParagraphs(sentences);
|
const paragraphs = sentencesToParagraphs(sentences);
|
||||||
return paragraphs.join("");
|
return paragraphs.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate lorem ipsum bytes.
|
* Generate lorem ipsum bytes.
|
||||||
*
|
*
|
||||||
* @param {number} length
|
* @param {number} length
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function GenerateBytes(length = 3) {
|
export function GenerateBytes(length=3) {
|
||||||
const str = GenerateWords(length / 3);
|
const str = GenerateWords(length/3);
|
||||||
return str.slice(0, length);
|
return str.slice(0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get array of randomly selected words from the lorem ipsum wordList.
|
* Get array of randomly selected words from the lorem ipsum wordList.
|
||||||
*
|
*
|
||||||
|
@ -89,7 +81,7 @@ export function GenerateBytes(length = 3) {
|
||||||
* @returns {string[]}
|
* @returns {string[]}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function getWords(length = 3) {
|
function getWords(length=3) {
|
||||||
const words = [];
|
const words = [];
|
||||||
let word;
|
let word;
|
||||||
let previousWord;
|
let previousWord;
|
||||||
|
@ -103,6 +95,7 @@ function getWords(length = 3) {
|
||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an array of words into an array of sentences
|
* Convert an array of words into an array of sentences
|
||||||
*
|
*
|
||||||
|
@ -113,10 +106,7 @@ function getWords(length = 3) {
|
||||||
function wordsToSentences(words) {
|
function wordsToSentences(words) {
|
||||||
const sentences = [];
|
const sentences = [];
|
||||||
while (words.length > 0) {
|
while (words.length > 0) {
|
||||||
const sentenceLength = getRandomLength(
|
const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV);
|
||||||
SENTENCE_LENGTH_MEAN,
|
|
||||||
SENTENCE_LENGTH_STD_DEV,
|
|
||||||
);
|
|
||||||
if (sentenceLength <= words.length) {
|
if (sentenceLength <= words.length) {
|
||||||
sentences.push(formatSentence(words.splice(0, sentenceLength)));
|
sentences.push(formatSentence(words.splice(0, sentenceLength)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -126,6 +116,7 @@ function wordsToSentences(words) {
|
||||||
return sentences;
|
return sentences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an array of sentences into an array of paragraphs
|
* Convert an array of sentences into an array of paragraphs
|
||||||
*
|
*
|
||||||
|
@ -136,20 +127,15 @@ function wordsToSentences(words) {
|
||||||
function sentencesToParagraphs(sentences) {
|
function sentencesToParagraphs(sentences) {
|
||||||
const paragraphs = [];
|
const paragraphs = [];
|
||||||
while (sentences.length > 0) {
|
while (sentences.length > 0) {
|
||||||
const paragraphLength = getRandomLength(
|
const paragraphLength = getRandomLength(PARAGRAPH_LENGTH_MEAN, PARAGRAPH_LENGTH_STD_DEV);
|
||||||
PARAGRAPH_LENGTH_MEAN,
|
|
||||||
PARAGRAPH_LENGTH_STD_DEV,
|
|
||||||
);
|
|
||||||
paragraphs.push(formatParagraph(sentences.splice(0, paragraphLength)));
|
paragraphs.push(formatParagraph(sentences.splice(0, paragraphLength)));
|
||||||
}
|
}
|
||||||
paragraphs[paragraphs.length - 1] = paragraphs[paragraphs.length - 1].slice(
|
paragraphs[paragraphs.length-1] = paragraphs[paragraphs.length-1].slice(0, -1);
|
||||||
0,
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
paragraphs[0] = replaceStart(paragraphs[0]);
|
paragraphs[0] = replaceStart(paragraphs[0]);
|
||||||
return paragraphs;
|
return paragraphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format an array of words into a sentence.
|
* Format an array of words into a sentence.
|
||||||
*
|
*
|
||||||
|
@ -160,8 +146,8 @@ function sentencesToParagraphs(sentences) {
|
||||||
function formatSentence(words) {
|
function formatSentence(words) {
|
||||||
// 0.35 chance of a comma being added randomly to the sentence.
|
// 0.35 chance of a comma being added randomly to the sentence.
|
||||||
if (Math.random() < PROBABILITY_OF_A_COMMA) {
|
if (Math.random() < PROBABILITY_OF_A_COMMA) {
|
||||||
const pos = Math.round(Math.random() * (words.length - 1));
|
const pos = Math.round(Math.random()*(words.length-1));
|
||||||
words[pos] += ",";
|
words[pos] +=",";
|
||||||
}
|
}
|
||||||
let sentence = words.join(" ");
|
let sentence = words.join(" ");
|
||||||
sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1);
|
sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1);
|
||||||
|
@ -169,6 +155,7 @@ function formatSentence(words) {
|
||||||
return sentence;
|
return sentence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format an array of sentences into a paragraph.
|
* Format an array of sentences into a paragraph.
|
||||||
*
|
*
|
||||||
|
@ -182,6 +169,7 @@ function formatParagraph(sentences) {
|
||||||
return paragraph;
|
return paragraph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a random number based on a mean and standard deviation.
|
* Get a random number based on a mean and standard deviation.
|
||||||
*
|
*
|
||||||
|
@ -193,17 +181,12 @@ function formatParagraph(sentences) {
|
||||||
function getRandomLength(mean, stdDev) {
|
function getRandomLength(mean, stdDev) {
|
||||||
let length;
|
let length;
|
||||||
do {
|
do {
|
||||||
length = Math.round(
|
length = Math.round((Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1)*stdDev+mean);
|
||||||
Math.random() * 2 -
|
|
||||||
1 +
|
|
||||||
(Math.random() * 2 - 1) +
|
|
||||||
(Math.random() * 2 - 1) * stdDev +
|
|
||||||
mean,
|
|
||||||
);
|
|
||||||
} while (length <= 0);
|
} while (length <= 0);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace first 5 words with "Lorem ipsum dolor sit amet"
|
* Replace first 5 words with "Lorem ipsum dolor sit amet"
|
||||||
*
|
*
|
||||||
|
@ -225,6 +208,7 @@ function replaceStart(str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const SENTENCE_LENGTH_MEAN = 15;
|
const SENTENCE_LENGTH_MEAN = 15;
|
||||||
const SENTENCE_LENGTH_STD_DEV = 9;
|
const SENTENCE_LENGTH_STD_DEV = 9;
|
||||||
const PARAGRAPH_LENGTH_MEAN = 5;
|
const PARAGRAPH_LENGTH_MEAN = 5;
|
||||||
|
@ -232,66 +216,15 @@ const PARAGRAPH_LENGTH_STD_DEV = 2;
|
||||||
const PROBABILITY_OF_A_COMMA = 0.35;
|
const PROBABILITY_OF_A_COMMA = 0.35;
|
||||||
|
|
||||||
const wordList = [
|
const wordList = [
|
||||||
"ad",
|
"ad", "adipisicing", "aliqua", "aliquip", "amet", "anim",
|
||||||
"adipisicing",
|
"aute", "cillum", "commodo", "consectetur", "consequat", "culpa",
|
||||||
"aliqua",
|
"cupidatat", "deserunt", "do", "dolor", "dolore", "duis",
|
||||||
"aliquip",
|
"ea", "eiusmod", "elit", "enim", "esse", "est",
|
||||||
"amet",
|
"et", "eu", "ex", "excepteur", "exercitation", "fugiat",
|
||||||
"anim",
|
"id", "in", "incididunt", "ipsum", "irure", "labore",
|
||||||
"aute",
|
"laboris", "laborum", "Lorem", "magna", "minim", "mollit",
|
||||||
"cillum",
|
"nisi", "non", "nostrud", "nulla", "occaecat", "officia",
|
||||||
"commodo",
|
"pariatur", "proident", "qui", "quis", "reprehenderit", "sint",
|
||||||
"consectetur",
|
"sit", "sunt", "tempor", "ullamco", "ut", "velit",
|
||||||
"consequat",
|
"veniam", "voluptate",
|
||||||
"culpa",
|
|
||||||
"cupidatat",
|
|
||||||
"deserunt",
|
|
||||||
"do",
|
|
||||||
"dolor",
|
|
||||||
"dolore",
|
|
||||||
"duis",
|
|
||||||
"ea",
|
|
||||||
"eiusmod",
|
|
||||||
"elit",
|
|
||||||
"enim",
|
|
||||||
"esse",
|
|
||||||
"est",
|
|
||||||
"et",
|
|
||||||
"eu",
|
|
||||||
"ex",
|
|
||||||
"excepteur",
|
|
||||||
"exercitation",
|
|
||||||
"fugiat",
|
|
||||||
"id",
|
|
||||||
"in",
|
|
||||||
"incididunt",
|
|
||||||
"ipsum",
|
|
||||||
"irure",
|
|
||||||
"labore",
|
|
||||||
"laboris",
|
|
||||||
"laborum",
|
|
||||||
"Lorem",
|
|
||||||
"magna",
|
|
||||||
"minim",
|
|
||||||
"mollit",
|
|
||||||
"nisi",
|
|
||||||
"non",
|
|
||||||
"nostrud",
|
|
||||||
"nulla",
|
|
||||||
"occaecat",
|
|
||||||
"officia",
|
|
||||||
"pariatur",
|
|
||||||
"proident",
|
|
||||||
"qui",
|
|
||||||
"quis",
|
|
||||||
"reprehenderit",
|
|
||||||
"sint",
|
|
||||||
"sit",
|
|
||||||
"sunt",
|
|
||||||
"tempor",
|
|
||||||
"ullamco",
|
|
||||||
"ut",
|
|
||||||
"velit",
|
|
||||||
"veniam",
|
|
||||||
"voluptate",
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -7,50 +7,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const SWITCHES = [
|
export const SWITCHES = [
|
||||||
{ name: "Up (.)", value: "." },
|
{name: "Up (.)", value: "."},
|
||||||
{ name: "Centre", value: "" },
|
{name: "Centre", value: ""},
|
||||||
{ name: "Down (x)", value: "x" },
|
{name: "Down (x)", value: "x"}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const VALID_ITA2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ34589+-./";
|
export const VALID_ITA2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ34589+-./";
|
||||||
|
|
||||||
export const ITA2_TABLE = {
|
export const ITA2_TABLE = {
|
||||||
A: "11000",
|
"A": "11000",
|
||||||
B: "10011",
|
"B": "10011",
|
||||||
C: "01110",
|
"C": "01110",
|
||||||
D: "10010",
|
"D": "10010",
|
||||||
E: "10000",
|
"E": "10000",
|
||||||
F: "10110",
|
"F": "10110",
|
||||||
G: "01011",
|
"G": "01011",
|
||||||
H: "00101",
|
"H": "00101",
|
||||||
I: "01100",
|
"I": "01100",
|
||||||
J: "11010",
|
"J": "11010",
|
||||||
K: "11110",
|
"K": "11110",
|
||||||
L: "01001",
|
"L": "01001",
|
||||||
M: "00111",
|
"M": "00111",
|
||||||
N: "00110",
|
"N": "00110",
|
||||||
O: "00011",
|
"O": "00011",
|
||||||
P: "01101",
|
"P": "01101",
|
||||||
Q: "11101",
|
"Q": "11101",
|
||||||
R: "01010",
|
"R": "01010",
|
||||||
S: "10100",
|
"S": "10100",
|
||||||
T: "00001",
|
"T": "00001",
|
||||||
U: "11100",
|
"U": "11100",
|
||||||
V: "01111",
|
"V": "01111",
|
||||||
W: "11001",
|
"W": "11001",
|
||||||
X: "10111",
|
"X": "10111",
|
||||||
Y: "10101",
|
"Y": "10101",
|
||||||
Z: "10001",
|
"Z": "10001",
|
||||||
3: "00010",
|
"3": "00010",
|
||||||
4: "01000",
|
"4": "01000",
|
||||||
9: "00100",
|
"9": "00100",
|
||||||
"/": "00000",
|
"/": "00000",
|
||||||
" ": "00100",
|
" ": "00100",
|
||||||
".": "00100",
|
".": "00100",
|
||||||
8: "11111",
|
"8": "11111",
|
||||||
5: "11011",
|
"5": "11011",
|
||||||
"-": "11111",
|
"-": "11111",
|
||||||
"+": "11011",
|
"+": "11011"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ROTOR_SIZES = {
|
export const ROTOR_SIZES = {
|
||||||
|
@ -65,7 +65,7 @@ export const ROTOR_SIZES = {
|
||||||
X2: 31,
|
X2: 31,
|
||||||
X3: 29,
|
X3: 29,
|
||||||
X4: 26,
|
X4: 26,
|
||||||
X5: 23,
|
X5: 23
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,251 +73,84 @@ export const ROTOR_SIZES = {
|
||||||
*/
|
*/
|
||||||
export const INIT_PATTERNS = {
|
export const INIT_PATTERNS = {
|
||||||
"No Pattern": {
|
"No Pattern": {
|
||||||
X: {
|
"X": {
|
||||||
1: [
|
1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
],
|
4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
2: [
|
5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
S: {
|
"S": {
|
||||||
1: [
|
1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
0,
|
4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
],
|
5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
2: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
M: {
|
|
||||||
1: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
2: [
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
"M": {
|
||||||
|
1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
"KH Pattern": {
|
"KH Pattern": {
|
||||||
X: {
|
"X": {
|
||||||
1: [
|
1: [0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0],
|
||||||
0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1,
|
2: [1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0],
|
||||||
0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0,
|
3: [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0],
|
||||||
],
|
4: [1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0],
|
||||||
2: [
|
5: [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0]
|
||||||
1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0,
|
|
||||||
1, 0, 0, 1, 1, 0, 1, 1, 0, 0,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1,
|
|
||||||
0, 0, 1, 1, 0, 1, 1, 0,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0,
|
|
||||||
0, 0, 1, 0, 0,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1,
|
|
||||||
0, 0,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
S: {
|
"S": {
|
||||||
1: [
|
1: [0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1],
|
||||||
0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0,
|
2: [0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1],
|
||||||
1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0,
|
3: [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1],
|
||||||
1,
|
4: [0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
|
||||||
],
|
5: [1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0]
|
||||||
2: [
|
|
||||||
0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1,
|
|
||||||
1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1,
|
|
||||||
0, 1, 0, 0, 1,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1,
|
|
||||||
0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0,
|
|
||||||
1, 1, 0, 0, 1, 0, 1, 0, 1,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0,
|
|
||||||
1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1,
|
|
||||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1,
|
|
||||||
1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
M: {
|
|
||||||
1: [
|
|
||||||
0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
|
|
||||||
1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1,
|
|
||||||
1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0,
|
|
||||||
],
|
|
||||||
2: [
|
|
||||||
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0,
|
|
||||||
0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
"M": {
|
||||||
|
1: [0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0],
|
||||||
|
2: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ZMUG Pattern": {
|
"ZMUG Pattern": {
|
||||||
X: {
|
"X": {
|
||||||
1: [
|
1: [0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0],
|
||||||
0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
|
2: [1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0],
|
||||||
1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0,
|
3: [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0],
|
||||||
],
|
4: [1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1],
|
||||||
2: [
|
5: [0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1]
|
||||||
1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,
|
|
||||||
0, 1, 1, 0, 0, 1, 1, 0, 0, 0,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0,
|
|
||||||
1, 1, 0, 1, 1, 1, 1, 0,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1,
|
|
||||||
0, 0, 1, 0, 1,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1,
|
|
||||||
0, 1,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
S: {
|
"S": {
|
||||||
1: [
|
1: [1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0],
|
||||||
1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0,
|
2: [0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1],
|
||||||
1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
|
3: [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1],
|
||||||
0,
|
4: [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1],
|
||||||
],
|
5: [1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0]
|
||||||
2: [
|
|
||||||
0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0,
|
|
||||||
0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
|
|
||||||
0, 1, 0, 1, 1,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
|
|
||||||
0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0,
|
|
||||||
0, 0, 1, 1, 0, 0, 1, 1, 1,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0,
|
|
||||||
0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0,
|
|
||||||
0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
|
||||||
1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
M: {
|
|
||||||
1: [
|
|
||||||
1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1,
|
|
||||||
1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
|
|
||||||
0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1,
|
|
||||||
],
|
|
||||||
2: [
|
|
||||||
0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0,
|
|
||||||
1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
"M": {
|
||||||
|
1: [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1],
|
||||||
|
2: [0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"BREAM Pattern": {
|
"BREAM Pattern": {
|
||||||
X: {
|
"X": {
|
||||||
1: [
|
1: [0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
|
||||||
0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1,
|
2: [0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1],
|
||||||
1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
|
3: [1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0],
|
||||||
],
|
4: [1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0],
|
||||||
2: [
|
5: [0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0]
|
||||||
0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0,
|
|
||||||
1, 1, 0, 1, 1, 1, 0, 0, 1, 1,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
|
|
||||||
1, 1, 0, 1, 1, 1, 0, 0,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0,
|
|
||||||
0, 1, 1, 0, 0,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0,
|
|
||||||
1, 0,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
S: {
|
|
||||||
1: [
|
|
||||||
0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1,
|
|
||||||
1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
|
||||||
0,
|
|
||||||
],
|
|
||||||
2: [
|
|
||||||
1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0,
|
|
||||||
0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
|
|
||||||
1, 0, 1, 0, 0,
|
|
||||||
],
|
|
||||||
3: [
|
|
||||||
1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0,
|
|
||||||
0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0,
|
|
||||||
1, 0, 1, 0, 1, 0, 1, 0, 1,
|
|
||||||
],
|
|
||||||
4: [
|
|
||||||
0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0,
|
|
||||||
1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0,
|
|
||||||
1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1,
|
|
||||||
],
|
|
||||||
5: [
|
|
||||||
1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0,
|
|
||||||
0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0,
|
|
||||||
1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
M: {
|
|
||||||
1: [
|
|
||||||
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1,
|
|
||||||
0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1,
|
|
||||||
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1,
|
|
||||||
],
|
|
||||||
2: [
|
|
||||||
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
"S": {
|
||||||
|
1: [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0],
|
||||||
|
2: [1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0],
|
||||||
|
3: [1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
||||||
|
4: [0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1],
|
||||||
|
5: [1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
|
||||||
},
|
},
|
||||||
|
"M": {
|
||||||
|
1: [1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1],
|
||||||
|
2: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,15 +14,13 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import kbpgp from "kbpgp";
|
import kbpgp from "kbpgp";
|
||||||
import * as es6promisify from "es6-promisify";
|
import * as es6promisify from "es6-promisify";
|
||||||
const promisify = es6promisify.default
|
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
||||||
? es6promisify.default.promisify
|
|
||||||
: es6promisify.promisify;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Progress callback
|
* Progress callback
|
||||||
*/
|
*/
|
||||||
export const ASP = kbpgp.ASP({
|
export const ASP = kbpgp.ASP({
|
||||||
progress_hook: (info) => {
|
"progress_hook": info => {
|
||||||
let msg = "";
|
let msg = "";
|
||||||
|
|
||||||
switch (info.what) {
|
switch (info.what) {
|
||||||
|
@ -48,8 +46,9 @@ export const ASP = kbpgp.ASP({
|
||||||
msg = `Stage: ${info.what}`;
|
msg = `Stage: ${info.what}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWorkerEnvironment()) self.sendStatusMessage(msg);
|
if (isWorkerEnvironment())
|
||||||
},
|
self.sendStatusMessage(msg);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,29 +68,27 @@ export function getSubkeySize(keySize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import private key and unlock if necessary
|
* Import private key and unlock if necessary
|
||||||
*
|
*
|
||||||
* @param {string} privateKey
|
* @param {string} privateKey
|
||||||
* @param {string} [passphrase]
|
* @param {string} [passphrase]
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export async function importPrivateKey(privateKey, passphrase) {
|
export async function importPrivateKey(privateKey, passphrase) {
|
||||||
try {
|
try {
|
||||||
const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
|
const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
|
||||||
armored: privateKey,
|
armored: privateKey,
|
||||||
opts: {
|
opts: {
|
||||||
no_check_keys: true,
|
"no_check_keys": true
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
if (key.is_pgp_locked()) {
|
if (key.is_pgp_locked()) {
|
||||||
if (passphrase) {
|
if (passphrase) {
|
||||||
await promisify(key.unlock_pgp.bind(key))({
|
await promisify(key.unlock_pgp.bind(key))({
|
||||||
passphrase,
|
passphrase
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new OperationError(
|
throw new OperationError("Did not provide passphrase with locked private key.");
|
||||||
"Did not provide passphrase with locked private key.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return key;
|
return key;
|
||||||
|
@ -106,13 +103,13 @@ export async function importPrivateKey(privateKey, passphrase) {
|
||||||
* @param {string} publicKey
|
* @param {string} publicKey
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export async function importPublicKey(publicKey) {
|
export async function importPublicKey (publicKey) {
|
||||||
try {
|
try {
|
||||||
const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
|
const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
|
||||||
armored: publicKey,
|
armored: publicKey,
|
||||||
opts: {
|
opts: {
|
||||||
no_check_keys: true,
|
"no_check_keys": true
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
return key;
|
return key;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import protobuf from "protobufjs";
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
class Protobuf {
|
class Protobuf {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protobuf constructor
|
* Protobuf constructor
|
||||||
*
|
*
|
||||||
|
@ -124,8 +125,7 @@ class Protobuf {
|
||||||
try {
|
try {
|
||||||
this.parsedProto = protobuf.parse(protoText);
|
this.parsedProto = protobuf.parse(protoText);
|
||||||
if (this.parsedProto.package) {
|
if (this.parsedProto.package) {
|
||||||
this.parsedProto.root =
|
this.parsedProto.root = this.parsedProto.root.nested[this.parsedProto.package];
|
||||||
this.parsedProto.root.nested[this.parsedProto.package];
|
|
||||||
}
|
}
|
||||||
this.updateMainMessageName();
|
this.updateMainMessageName();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -140,14 +140,12 @@ class Protobuf {
|
||||||
static updateMainMessageName() {
|
static updateMainMessageName() {
|
||||||
const messageNames = [];
|
const messageNames = [];
|
||||||
const fieldTypes = [];
|
const fieldTypes = [];
|
||||||
this.parsedProto.root.nestedArray.forEach((block) => {
|
this.parsedProto.root.nestedArray.forEach(block => {
|
||||||
if (block instanceof protobuf.Type) {
|
if (block instanceof protobuf.Type) {
|
||||||
messageNames.push(block.name);
|
messageNames.push(block.name);
|
||||||
this.parsedProto.root.nested[block.name].fieldsArray.forEach(
|
this.parsedProto.root.nested[block.name].fieldsArray.forEach(field => {
|
||||||
(field) => {
|
|
||||||
fieldTypes.push(field.type);
|
fieldTypes.push(field.type);
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -177,9 +175,7 @@ class Protobuf {
|
||||||
|
|
||||||
if (this.showTypes) {
|
if (this.showTypes) {
|
||||||
rawDecode = this.showRawTypes(rawDecode, pb.fieldTypes);
|
rawDecode = this.showRawTypes(rawDecode, pb.fieldTypes);
|
||||||
this.parsedProto.root = this.appendTypesToFieldNames(
|
this.parsedProto.root = this.appendTypesToFieldNames(this.parsedProto.root);
|
||||||
this.parsedProto.root,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -188,20 +184,18 @@ class Protobuf {
|
||||||
bytes: String,
|
bytes: String,
|
||||||
longs: Number,
|
longs: Number,
|
||||||
enums: String,
|
enums: String,
|
||||||
defaults: true,
|
defaults: true
|
||||||
});
|
});
|
||||||
const output = {};
|
const output = {};
|
||||||
|
|
||||||
if (this.showUnknownFields) {
|
if (this.showUnknownFields) {
|
||||||
output[message.name] = packageDecode;
|
output[message.name] = packageDecode;
|
||||||
output["Unknown Fields"] = this.compareFields(
|
output["Unknown Fields"] = this.compareFields(rawDecode, message);
|
||||||
rawDecode,
|
|
||||||
message,
|
|
||||||
);
|
|
||||||
return output;
|
return output;
|
||||||
} else {
|
} else {
|
||||||
return packageDecode;
|
return packageDecode;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (message) {
|
if (message) {
|
||||||
throw new Error("Input " + error);
|
throw new Error("Input " + error);
|
||||||
|
@ -220,20 +214,9 @@ class Protobuf {
|
||||||
static appendTypesToFieldNames(schemaRoot) {
|
static appendTypesToFieldNames(schemaRoot) {
|
||||||
for (const block of schemaRoot.nestedArray) {
|
for (const block of schemaRoot.nestedArray) {
|
||||||
if (block instanceof protobuf.Type) {
|
if (block instanceof protobuf.Type) {
|
||||||
for (const [fieldName, fieldData] of Object.entries(
|
for (const [fieldName, fieldData] of Object.entries(block.fields)) {
|
||||||
block.fields,
|
schemaRoot.nested[block.name].remove(block.fields[fieldName]);
|
||||||
)) {
|
schemaRoot.nested[block.name].add(new protobuf.Field(`${fieldName} (${fieldData.type})`, fieldData.id, fieldData.type, fieldData.rule));
|
||||||
schemaRoot.nested[block.name].remove(
|
|
||||||
block.fields[fieldName],
|
|
||||||
);
|
|
||||||
schemaRoot.nested[block.name].add(
|
|
||||||
new protobuf.Field(
|
|
||||||
`${fieldName} (${fieldData.type})`,
|
|
||||||
fieldData.id,
|
|
||||||
fieldData.type,
|
|
||||||
fieldData.rule,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,10 +244,8 @@ class Protobuf {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const fieldInstances = [];
|
const fieldInstances = [];
|
||||||
for (const instance of Object.keys(value)) {
|
for (const instance of Object.keys(value)) {
|
||||||
if (typeof value[instance] !== "string") {
|
if (typeof(value[instance]) !== "string") {
|
||||||
fieldInstances.push(
|
fieldInstances.push(this.showRawTypes(value[instance], fieldType));
|
||||||
this.showRawTypes(value[instance], fieldType),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
fieldInstances.push(value[instance]);
|
fieldInstances.push(value[instance]);
|
||||||
}
|
}
|
||||||
|
@ -283,9 +264,7 @@ class Protobuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substitute fieldNum with field number and type
|
// Substitute fieldNum with field number and type
|
||||||
rawDecode[
|
rawDecode[`field #${fieldNum}: ${this.getTypeInfo(outputFieldType)}`] = outputFieldValue;
|
||||||
`field #${fieldNum}: ${this.getTypeInfo(outputFieldType)}`
|
|
||||||
] = outputFieldValue;
|
|
||||||
delete rawDecode[fieldNum];
|
delete rawDecode[fieldNum];
|
||||||
}
|
}
|
||||||
return rawDecode;
|
return rawDecode;
|
||||||
|
@ -302,10 +281,7 @@ class Protobuf {
|
||||||
// Define message data using raw decode output and schema
|
// Define message data using raw decode output and schema
|
||||||
const schemaFieldProperties = {};
|
const schemaFieldProperties = {};
|
||||||
const schemaFieldNames = Object.keys(schemaMessage.fields);
|
const schemaFieldNames = Object.keys(schemaMessage.fields);
|
||||||
schemaFieldNames.forEach(
|
schemaFieldNames.forEach(field => schemaFieldProperties[schemaMessage.fields[field].id] = field);
|
||||||
(field) =>
|
|
||||||
(schemaFieldProperties[schemaMessage.fields[field].id] = field),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Loop over each field present in the raw decode output
|
// Loop over each field present in the raw decode output
|
||||||
for (const fieldName in rawDecodedMessage) {
|
for (const fieldName in rawDecodedMessage) {
|
||||||
|
@ -326,26 +302,21 @@ class Protobuf {
|
||||||
|
|
||||||
// Check for repeated fields
|
// Check for repeated fields
|
||||||
if (Array.isArray(rawFieldData) && !schemaField.repeated) {
|
if (Array.isArray(rawFieldData) && !schemaField.repeated) {
|
||||||
rawDecodedMessage[
|
rawDecodedMessage[`(${schemaMessage.name}) ${schemaFieldName} is a repeated field`] = rawFieldData;
|
||||||
`(${schemaMessage.name}) ${schemaFieldName} is a repeated field`
|
|
||||||
] = rawFieldData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for submessage fields
|
// Check for submessage fields
|
||||||
if (schemaField.resolvedType instanceof protobuf.Type) {
|
if (schemaField.resolvedType instanceof protobuf.Type) {
|
||||||
const subMessageType =
|
const subMessageType = schemaMessage.fields[schemaFieldName].type;
|
||||||
schemaMessage.fields[schemaFieldName].type;
|
const schemaSubMessage = this.parsedProto.root.nested[subMessageType];
|
||||||
const schemaSubMessage =
|
|
||||||
this.parsedProto.root.nested[subMessageType];
|
|
||||||
const rawSubMessages = rawDecodedMessage[fieldName];
|
const rawSubMessages = rawDecodedMessage[fieldName];
|
||||||
let rawDecodedSubMessage = {};
|
let rawDecodedSubMessage = {};
|
||||||
|
|
||||||
// Squash multiple submessage instances into one submessage
|
// Squash multiple submessage instances into one submessage
|
||||||
if (Array.isArray(rawSubMessages)) {
|
if (Array.isArray(rawSubMessages)) {
|
||||||
rawSubMessages.forEach((subMessageInstance) => {
|
rawSubMessages.forEach(subMessageInstance => {
|
||||||
const instanceFields =
|
const instanceFields = Object.entries(subMessageInstance);
|
||||||
Object.entries(subMessageInstance);
|
instanceFields.forEach(subField => {
|
||||||
instanceFields.forEach((subField) => {
|
|
||||||
rawDecodedSubMessage[subField[0]] = subField[1];
|
rawDecodedSubMessage[subField[0]] = subField[1];
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -354,14 +325,9 @@ class Protobuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat submessage as own message and compare its fields
|
// Treat submessage as own message and compare its fields
|
||||||
rawDecodedSubMessage = Protobuf.compareFields(
|
rawDecodedSubMessage = Protobuf.compareFields(rawDecodedSubMessage, schemaSubMessage);
|
||||||
rawDecodedSubMessage,
|
|
||||||
schemaSubMessage,
|
|
||||||
);
|
|
||||||
if (Object.entries(rawDecodedSubMessage).length !== 0) {
|
if (Object.entries(rawDecodedSubMessage).length !== 0) {
|
||||||
rawDecodedMessage[
|
rawDecodedMessage[`${schemaFieldName} (${subMessageType}) has missing fields`] = rawDecodedSubMessage;
|
||||||
`${schemaFieldName} (${subMessageType}) has missing fields`
|
|
||||||
] = rawDecodedSubMessage;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete rawDecodedMessage[fieldName];
|
delete rawDecodedMessage[fieldName];
|
||||||
|
@ -426,11 +392,11 @@ class Protobuf {
|
||||||
// Get the field key/values
|
// Get the field key/values
|
||||||
const key = field.key;
|
const key = field.key;
|
||||||
const value = field.value;
|
const value = field.value;
|
||||||
object[key] = Object.prototype.hasOwnProperty.call(object, key)
|
object[key] = Object.prototype.hasOwnProperty.call(object, key) ?
|
||||||
? object[key] instanceof Array
|
object[key] instanceof Array ?
|
||||||
? object[key].concat([value])
|
object[key].concat([value]) :
|
||||||
: [object[key], value]
|
[object[key], value] :
|
||||||
: value;
|
value;
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,23 +412,23 @@ class Protobuf {
|
||||||
const type = header.type;
|
const type = header.type;
|
||||||
const key = header.key;
|
const key = header.key;
|
||||||
|
|
||||||
if (typeof this.fieldTypes[key] !== "object") {
|
if (typeof(this.fieldTypes[key]) !== "object") {
|
||||||
this.fieldTypes[key] = type;
|
this.fieldTypes[key] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// varint
|
// varint
|
||||||
case 0:
|
case 0:
|
||||||
return { key: key, value: this._varInt() };
|
return { "key": key, "value": this._varInt() };
|
||||||
// fixed 64
|
// fixed 64
|
||||||
case 1:
|
case 1:
|
||||||
return { key: key, value: this._uint64() };
|
return { "key": key, "value": this._uint64() };
|
||||||
// length delimited
|
// length delimited
|
||||||
case 2:
|
case 2:
|
||||||
return { key: key, value: this._lenDelim(key) };
|
return { "key": key, "value": this._lenDelim(key) };
|
||||||
// fixed 32
|
// fixed 32
|
||||||
case 5:
|
case 5:
|
||||||
return { key: key, value: this._uint32() };
|
return { "key": key, "value": this._uint32() };
|
||||||
// unknown type
|
// unknown type
|
||||||
default:
|
default:
|
||||||
throw new Error("Unknown type 0x" + type.toString(16));
|
throw new Error("Unknown type 0x" + type.toString(16));
|
||||||
|
@ -477,7 +443,7 @@ class Protobuf {
|
||||||
*/
|
*/
|
||||||
_fieldHeader() {
|
_fieldHeader() {
|
||||||
// Make sure we call type then number to preserve offset
|
// Make sure we call type then number to preserve offset
|
||||||
return { type: this._fieldType(), key: this._fieldNumber() };
|
return { "type": this._fieldType(), "key": this._fieldNumber() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -506,13 +472,11 @@ class Protobuf {
|
||||||
let shift = -3;
|
let shift = -3;
|
||||||
let fieldNumber = 0;
|
let fieldNumber = 0;
|
||||||
do {
|
do {
|
||||||
fieldNumber +=
|
fieldNumber += shift < 28 ?
|
||||||
shift < 28
|
shift === -3 ?
|
||||||
? shift === -3
|
(this.data[this.offset] & this.NUMBER) >> -shift :
|
||||||
? (this.data[this.offset] & this.NUMBER) >> -shift
|
(this.data[this.offset] & this.VALUE) << shift :
|
||||||
: (this.data[this.offset] & this.VALUE) << shift
|
(this.data[this.offset] & this.VALUE) * Math.pow(2, shift);
|
||||||
: (this.data[this.offset] & this.VALUE) *
|
|
||||||
Math.pow(2, shift);
|
|
||||||
shift += 7;
|
shift += 7;
|
||||||
} while ((this.data[this.offset++] & this.MSB) === this.MSB);
|
} while ((this.data[this.offset++] & this.MSB) === this.MSB);
|
||||||
return fieldNumber;
|
return fieldNumber;
|
||||||
|
@ -531,11 +495,9 @@ class Protobuf {
|
||||||
let shift = 0;
|
let shift = 0;
|
||||||
// Keep reading while upper bit set
|
// Keep reading while upper bit set
|
||||||
do {
|
do {
|
||||||
value +=
|
value += shift < 28 ?
|
||||||
shift < 28
|
(this.data[this.offset] & this.VALUE) << shift :
|
||||||
? (this.data[this.offset] & this.VALUE) << shift
|
(this.data[this.offset] & this.VALUE) * Math.pow(2, shift);
|
||||||
: (this.data[this.offset] & this.VALUE) *
|
|
||||||
Math.pow(2, shift);
|
|
||||||
shift += 7;
|
shift += 7;
|
||||||
} while ((this.data[this.offset++] & this.MSB) === this.MSB);
|
} while ((this.data[this.offset++] & this.MSB) === this.MSB);
|
||||||
return value;
|
return value;
|
||||||
|
@ -549,16 +511,8 @@ class Protobuf {
|
||||||
*/
|
*/
|
||||||
_uint64() {
|
_uint64() {
|
||||||
// Read off a Uint64 with little-endian
|
// Read off a Uint64 with little-endian
|
||||||
const lowerHalf =
|
const lowerHalf = this.data[this.offset++] + (this.data[this.offset++] * 0x100) + (this.data[this.offset++] * 0x10000) + this.data[this.offset++] * 0x1000000;
|
||||||
this.data[this.offset++] +
|
const upperHalf = this.data[this.offset++] + (this.data[this.offset++] * 0x100) + (this.data[this.offset++] * 0x10000) + this.data[this.offset++] * 0x1000000;
|
||||||
this.data[this.offset++] * 0x100 +
|
|
||||||
this.data[this.offset++] * 0x10000 +
|
|
||||||
this.data[this.offset++] * 0x1000000;
|
|
||||||
const upperHalf =
|
|
||||||
this.data[this.offset++] +
|
|
||||||
this.data[this.offset++] * 0x100 +
|
|
||||||
this.data[this.offset++] * 0x10000 +
|
|
||||||
this.data[this.offset++] * 0x1000000;
|
|
||||||
return upperHalf * 0x100000000 + lowerHalf;
|
return upperHalf * 0x100000000 + lowerHalf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,10 +533,8 @@ class Protobuf {
|
||||||
field = pbObject._parse();
|
field = pbObject._parse();
|
||||||
|
|
||||||
// Set field types object
|
// Set field types object
|
||||||
this.fieldTypes[fieldNum] = {
|
this.fieldTypes[fieldNum] = {...this.fieldTypes[fieldNum], ...pbObject.fieldTypes};
|
||||||
...this.fieldTypes[fieldNum],
|
|
||||||
...pbObject.fieldTypes,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Otherwise treat as bytes
|
// Otherwise treat as bytes
|
||||||
field = Utils.byteArrayToChars(fieldBytes);
|
field = Utils.byteArrayToChars(fieldBytes);
|
||||||
|
@ -600,10 +552,7 @@ class Protobuf {
|
||||||
*/
|
*/
|
||||||
_uint32() {
|
_uint32() {
|
||||||
// Use a dataview to read off the integer
|
// Use a dataview to read off the integer
|
||||||
const dataview = new DataView(
|
const dataview = new DataView(new Uint8Array(this.data.slice(this.offset, this.offset + 4)).buffer);
|
||||||
new Uint8Array(this.data.slice(this.offset, this.offset + 4))
|
|
||||||
.buffer,
|
|
||||||
);
|
|
||||||
const value = dataview.getUint32(0, true);
|
const value = dataview.getUint32(0, true);
|
||||||
this.offset += 4;
|
this.offset += 4;
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BigNumber from "bignumber.js";
|
import BigNumber from "bignumber.js";
|
||||||
import { toHexFast } from "../lib/Hex.mjs";
|
import {toHexFast} from "../lib/Hex.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively displays a JSON object as an HTML table
|
* Recursively displays a JSON object as an HTML table
|
||||||
|
@ -15,14 +15,10 @@ import { toHexFast } from "../lib/Hex.mjs";
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
* @returns string
|
* @returns string
|
||||||
*/
|
*/
|
||||||
export function objToTable(obj, nested = false) {
|
export function objToTable(obj, nested=false) {
|
||||||
let html = `<table
|
let html = `<table
|
||||||
class='table table-sm table-nonfluid ${
|
class='table table-sm table-nonfluid ${nested ? "mb-0 table-borderless" : "table-bordered"}'
|
||||||
nested ? "mb-0 table-borderless" : "table-bordered"
|
style='table-layout: fixed; ${nested ? "margin: -1px !important;" : ""}'>`;
|
||||||
}'
|
|
||||||
style='table-layout: fixed; ${
|
|
||||||
nested ? "margin: -1px !important;" : ""
|
|
||||||
}'>`;
|
|
||||||
if (!nested)
|
if (!nested)
|
||||||
html += `<tr>
|
html += `<tr>
|
||||||
<th>Field</th>
|
<th>Field</th>
|
||||||
|
@ -33,7 +29,8 @@ export function objToTable(obj, nested = false) {
|
||||||
html += `<tr><td style='word-wrap: break-word'>${key}</td>`;
|
html += `<tr><td style='word-wrap: break-word'>${key}</td>`;
|
||||||
if (typeof obj[key] === "object")
|
if (typeof obj[key] === "object")
|
||||||
html += `<td style='padding: 0'>${objToTable(obj[key], true)}</td>`;
|
html += `<td style='padding: 0'>${objToTable(obj[key], true)}</td>`;
|
||||||
else html += `<td>${obj[key]}</td>`;
|
else
|
||||||
|
html += `<td>${obj[key]}</td>`;
|
||||||
html += "</tr>";
|
html += "</tr>";
|
||||||
}
|
}
|
||||||
html += "</table>";
|
html += "</table>";
|
||||||
|
|
|
@ -35,6 +35,7 @@ export function formatDnObj(dnObj, indent) {
|
||||||
return output.slice(0, -1);
|
return output.slice(0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats byte strings by adding line breaks and delimiters.
|
* Formats byte strings by adding line breaks and delimiters.
|
||||||
*
|
*
|
||||||
|
@ -57,5 +58,5 @@ export function formatByteStr(byteStr, length, indent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.slice(0, output.length - 1);
|
return output.slice(0, output.length-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ export async function parseQrCode(input, normalise) {
|
||||||
try {
|
try {
|
||||||
if (normalise) {
|
if (normalise) {
|
||||||
image.rgba(false);
|
image.rgba(false);
|
||||||
image.background(0xffffffff);
|
image.background(0xFFFFFFFF);
|
||||||
image.normalize();
|
image.normalize();
|
||||||
image.greyscale();
|
image.greyscale();
|
||||||
image = await image.getBufferAsync(jimp.MIME_JPEG);
|
image = await image.getBufferAsync(jimp.MIME_JPEG);
|
||||||
|
@ -58,13 +58,7 @@ export async function parseQrCode(input, normalise) {
|
||||||
* @param {string} errorCorrection
|
* @param {string} errorCorrection
|
||||||
* @returns {ArrayBuffer}
|
* @returns {ArrayBuffer}
|
||||||
*/
|
*/
|
||||||
export function generateQrCode(
|
export function generateQrCode(input, format, moduleSize, margin, errorCorrection) {
|
||||||
input,
|
|
||||||
format,
|
|
||||||
moduleSize,
|
|
||||||
margin,
|
|
||||||
errorCorrection,
|
|
||||||
) {
|
|
||||||
const formats = ["SVG", "EPS", "PDF", "PNG"];
|
const formats = ["SVG", "EPS", "PDF", "PNG"];
|
||||||
if (!formats.includes(format.toUpperCase())) {
|
if (!formats.includes(format.toUpperCase())) {
|
||||||
throw new OperationError("Unsupported QR code format.");
|
throw new OperationError("Unsupported QR code format.");
|
||||||
|
@ -76,7 +70,7 @@ export function generateQrCode(
|
||||||
type: format,
|
type: format,
|
||||||
size: moduleSize,
|
size: moduleSize,
|
||||||
margin: margin,
|
margin: margin,
|
||||||
ec_level: errorCorrection.charAt(0).toUpperCase(),
|
"ec_level": errorCorrection.charAt(0).toUpperCase()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error generating QR code. (${err})`);
|
throw new OperationError(`Error generating QR code. (${err})`);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import forge from "node-forge";
|
||||||
|
|
||||||
export const MD_ALGORITHMS = {
|
export const MD_ALGORITHMS = {
|
||||||
"SHA-1": forge.md.sha1,
|
"SHA-1": forge.md.sha1,
|
||||||
MD5: forge.md.md5,
|
"MD5": forge.md.md5,
|
||||||
"SHA-256": forge.md.sha256,
|
"SHA-256": forge.md.sha256,
|
||||||
"SHA-384": forge.md.sha384,
|
"SHA-384": forge.md.sha384,
|
||||||
"SHA-512": forge.md.sha512,
|
"SHA-512": forge.md.sha512,
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* @todo Support for UTF16
|
* @todo Support for UTF16
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs rotation operations across the input data.
|
* Runs rotation operations across the input data.
|
||||||
*
|
*
|
||||||
|
@ -28,6 +29,7 @@ export function rot(data, amount, algo) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate right bitwise op.
|
* Rotate right bitwise op.
|
||||||
*
|
*
|
||||||
|
@ -47,9 +49,10 @@ export function rotr(b) {
|
||||||
*/
|
*/
|
||||||
export function rotl(b) {
|
export function rotl(b) {
|
||||||
const bit = (b >> 7) & 1;
|
const bit = (b >> 7) & 1;
|
||||||
return ((b << 1) | bit) & 0xff;
|
return ((b << 1) | bit) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotates a byte array to the right by a specific amount as a whole, so that bits are wrapped
|
* Rotates a byte array to the right by a specific amount as a whole, so that bits are wrapped
|
||||||
* from the end of the array to the beginning.
|
* from the end of the array to the beginning.
|
||||||
|
@ -67,13 +70,14 @@ export function rotrCarry(data, amount) {
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const oldByte = data[i] >>> 0;
|
const oldByte = data[i] >>> 0;
|
||||||
newByte = (oldByte >> amount) | carryBits;
|
newByte = (oldByte >> amount) | carryBits;
|
||||||
carryBits = (oldByte & (Math.pow(2, amount) - 1)) << (8 - amount);
|
carryBits = (oldByte & (Math.pow(2, amount)-1)) << (8-amount);
|
||||||
result.push(newByte);
|
result.push(newByte);
|
||||||
}
|
}
|
||||||
result[0] |= carryBits;
|
result[0] |= carryBits;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotates a byte array to the left by a specific amount as a whole, so that bits are wrapped
|
* Rotates a byte array to the left by a specific amount as a whole, so that bits are wrapped
|
||||||
* from the beginning of the array to the end.
|
* from the beginning of the array to the end.
|
||||||
|
@ -88,12 +92,12 @@ export function rotlCarry(data, amount) {
|
||||||
newByte;
|
newByte;
|
||||||
|
|
||||||
amount = amount % 8;
|
amount = amount % 8;
|
||||||
for (let i = data.length - 1; i >= 0; i--) {
|
for (let i = data.length-1; i >= 0; i--) {
|
||||||
const oldByte = data[i];
|
const oldByte = data[i];
|
||||||
newByte = ((oldByte << amount) | carryBits) & 0xff;
|
newByte = ((oldByte << amount) | carryBits) & 0xFF;
|
||||||
carryBits = (oldByte >> (8 - amount)) & (Math.pow(2, amount) - 1);
|
carryBits = (oldByte >> (8-amount)) & (Math.pow(2, amount)-1);
|
||||||
result[i] = newByte;
|
result[i] = (newByte);
|
||||||
}
|
}
|
||||||
result[data.length - 1] = result[data.length - 1] | carryBits;
|
result[data.length-1] = result[data.length-1] | carryBits;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,27 +10,27 @@
|
||||||
* A set of randomised example SIGABA cipher/control rotors (these rotors are interchangeable). Cipher and control rotors can be referred to as C and R rotors respectively.
|
* A set of randomised example SIGABA cipher/control rotors (these rotors are interchangeable). Cipher and control rotors can be referred to as C and R rotors respectively.
|
||||||
*/
|
*/
|
||||||
export const CR_ROTORS = [
|
export const CR_ROTORS = [
|
||||||
{ name: "Example 1", value: "SRGWANHPJZFXVIDQCEUKBYOLMT" },
|
{name: "Example 1", value: "SRGWANHPJZFXVIDQCEUKBYOLMT"},
|
||||||
{ name: "Example 2", value: "THQEFSAZVKJYULBODCPXNIMWRG" },
|
{name: "Example 2", value: "THQEFSAZVKJYULBODCPXNIMWRG"},
|
||||||
{ name: "Example 3", value: "XDTUYLEVFNQZBPOGIRCSMHWKAJ" },
|
{name: "Example 3", value: "XDTUYLEVFNQZBPOGIRCSMHWKAJ"},
|
||||||
{ name: "Example 4", value: "LOHDMCWUPSTNGVXYFJREQIKBZA" },
|
{name: "Example 4", value: "LOHDMCWUPSTNGVXYFJREQIKBZA"},
|
||||||
{ name: "Example 5", value: "ERXWNZQIJYLVOFUMSGHTCKPBDA" },
|
{name: "Example 5", value: "ERXWNZQIJYLVOFUMSGHTCKPBDA"},
|
||||||
{ name: "Example 6", value: "FQECYHJIOUMDZVPSLKRTGWXBAN" },
|
{name: "Example 6", value: "FQECYHJIOUMDZVPSLKRTGWXBAN"},
|
||||||
{ name: "Example 7", value: "TBYIUMKZDJSOPEWXVANHLCFQGR" },
|
{name: "Example 7", value: "TBYIUMKZDJSOPEWXVANHLCFQGR"},
|
||||||
{ name: "Example 8", value: "QZUPDTFNYIAOMLEBWJXCGHKRSV" },
|
{name: "Example 8", value: "QZUPDTFNYIAOMLEBWJXCGHKRSV"},
|
||||||
{ name: "Example 9", value: "CZWNHEMPOVXLKRSIDGJFYBTQAU" },
|
{name: "Example 9", value: "CZWNHEMPOVXLKRSIDGJFYBTQAU"},
|
||||||
{ name: "Example 10", value: "ENPXJVKYQBFZTICAGMOHWRLDUS" },
|
{name: "Example 10", value: "ENPXJVKYQBFZTICAGMOHWRLDUS"}
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of randomised example SIGABA index rotors (may be referred to as I rotors).
|
* A set of randomised example SIGABA index rotors (may be referred to as I rotors).
|
||||||
*/
|
*/
|
||||||
export const I_ROTORS = [
|
export const I_ROTORS = [
|
||||||
{ name: "Example 1", value: "6201348957" },
|
{name: "Example 1", value: "6201348957"},
|
||||||
{ name: "Example 2", value: "6147253089" },
|
{name: "Example 2", value: "6147253089"},
|
||||||
{ name: "Example 3", value: "8239647510" },
|
{name: "Example 3", value: "8239647510"},
|
||||||
{ name: "Example 4", value: "7194835260" },
|
{name: "Example 4", value: "7194835260"},
|
||||||
{ name: "Example 5", value: "4873205916" },
|
{name: "Example 5", value: "4873205916"}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const NUMBERS = "0123456789".split("");
|
export const NUMBERS = "0123456789".split("");
|
||||||
|
@ -43,8 +43,8 @@ export const NUMBERS = "0123456789".split("");
|
||||||
*/
|
*/
|
||||||
export function convToUpperCase(letter) {
|
export function convToUpperCase(letter) {
|
||||||
const charCode = letter.charCodeAt();
|
const charCode = letter.charCodeAt();
|
||||||
if (97 <= charCode && charCode <= 122) {
|
if (97<=charCode && charCode<=122) {
|
||||||
return String.fromCharCode(charCode - 32);
|
return String.fromCharCode(charCode-32);
|
||||||
}
|
}
|
||||||
return letter;
|
return letter;
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ export function convToUpperCase(letter) {
|
||||||
* The SIGABA machine consisting of the 3 rotor banks: cipher, control and index banks.
|
* The SIGABA machine consisting of the 3 rotor banks: cipher, control and index banks.
|
||||||
*/
|
*/
|
||||||
export class SigabaMachine {
|
export class SigabaMachine {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SigabaMachine constructor
|
* SigabaMachine constructor
|
||||||
*
|
*
|
||||||
|
@ -136,12 +137,14 @@ export class SigabaMachine {
|
||||||
}
|
}
|
||||||
return plaintext;
|
return plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cipher rotor bank consists of 5 cipher rotors in either a forward or reversed orientation.
|
* The cipher rotor bank consists of 5 cipher rotors in either a forward or reversed orientation.
|
||||||
*/
|
*/
|
||||||
export class CipherBank {
|
export class CipherBank {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CipherBank constructor
|
* CipherBank constructor
|
||||||
*
|
*
|
||||||
|
@ -184,13 +187,7 @@ export class CipherBank {
|
||||||
* @param {number[]} indexInputs - the inputs from the index rotors
|
* @param {number[]} indexInputs - the inputs from the index rotors
|
||||||
*/
|
*/
|
||||||
step(indexInputs) {
|
step(indexInputs) {
|
||||||
const logicDict = {
|
const logicDict = {0: [0, 9], 1: [7, 8], 2: [5, 6], 3: [3, 4], 4: [1, 2]};
|
||||||
0: [0, 9],
|
|
||||||
1: [7, 8],
|
|
||||||
2: [5, 6],
|
|
||||||
3: [3, 4],
|
|
||||||
4: [1, 2],
|
|
||||||
};
|
|
||||||
const rotorsToMove = [];
|
const rotorsToMove = [];
|
||||||
for (const key in logicDict) {
|
for (const key in logicDict) {
|
||||||
const item = logicDict[key];
|
const item = logicDict[key];
|
||||||
|
@ -205,12 +202,14 @@ export class CipherBank {
|
||||||
rotor.step();
|
rotor.step();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The control rotor bank consists of 5 control rotors in either a forward or reversed orientation. Signals to the control rotor bank always go from right-to-left.
|
* The control rotor bank consists of 5 control rotors in either a forward or reversed orientation. Signals to the control rotor bank always go from right-to-left.
|
||||||
*/
|
*/
|
||||||
export class ControlBank {
|
export class ControlBank {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ControlBank constructor. The rotors have been reversed as signals go from right-to-left through the control rotors.
|
* ControlBank constructor. The rotors have been reversed as signals go from right-to-left through the control rotors.
|
||||||
*
|
*
|
||||||
|
@ -239,23 +238,8 @@ export class ControlBank {
|
||||||
* @returns {number[]}
|
* @returns {number[]}
|
||||||
*/
|
*/
|
||||||
getOutputs() {
|
getOutputs() {
|
||||||
const outputs = [
|
const outputs = [this.crypt("F"), this.crypt("G"), this.crypt("H"), this.crypt("I")];
|
||||||
this.crypt("F"),
|
const logicDict = {1: "B", 2: "C", 3: "DE", 4: "FGH", 5: "IJK", 6: "LMNO", 7: "PQRST", 8: "UVWXYZ", 9: "A"};
|
||||||
this.crypt("G"),
|
|
||||||
this.crypt("H"),
|
|
||||||
this.crypt("I"),
|
|
||||||
];
|
|
||||||
const logicDict = {
|
|
||||||
1: "B",
|
|
||||||
2: "C",
|
|
||||||
3: "DE",
|
|
||||||
4: "FGH",
|
|
||||||
5: "IJK",
|
|
||||||
6: "LMNO",
|
|
||||||
7: "PQRST",
|
|
||||||
8: "UVWXYZ",
|
|
||||||
9: "A",
|
|
||||||
};
|
|
||||||
const numberOutputs = [];
|
const numberOutputs = [];
|
||||||
for (const key in logicDict) {
|
for (const key in logicDict) {
|
||||||
const item = logicDict[key];
|
const item = logicDict[key];
|
||||||
|
@ -273,9 +257,7 @@ export class ControlBank {
|
||||||
* Steps the control rotors. Only 3 of the control rotors step: one after every encryption, one after every 26, and one after every 26 squared.
|
* Steps the control rotors. Only 3 of the control rotors step: one after every encryption, one after every 26, and one after every 26 squared.
|
||||||
*/
|
*/
|
||||||
step() {
|
step() {
|
||||||
const MRotor = this.rotors[1],
|
const MRotor = this.rotors[1], FRotor = this.rotors[2], SRotor = this.rotors[3];
|
||||||
FRotor = this.rotors[2],
|
|
||||||
SRotor = this.rotors[3];
|
|
||||||
// 14 is the offset of "O" from "A" - the next rotor steps once the previous rotor reaches "O"
|
// 14 is the offset of "O" from "A" - the next rotor steps once the previous rotor reaches "O"
|
||||||
if (FRotor.state === 14) {
|
if (FRotor.state === 14) {
|
||||||
if (MRotor.state === 14) {
|
if (MRotor.state === 14) {
|
||||||
|
@ -296,12 +278,14 @@ export class ControlBank {
|
||||||
this.step();
|
this.step();
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index rotor bank consists of 5 index rotors all placed in the forwards orientation.
|
* The index rotor bank consists of 5 index rotors all placed in the forwards orientation.
|
||||||
*/
|
*/
|
||||||
export class IndexBank {
|
export class IndexBank {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IndexBank constructor
|
* IndexBank constructor
|
||||||
*
|
*
|
||||||
|
@ -337,12 +321,14 @@ export class IndexBank {
|
||||||
}
|
}
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotor class
|
* Rotor class
|
||||||
*/
|
*/
|
||||||
export class Rotor {
|
export class Rotor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotor constructor
|
* Rotor constructor
|
||||||
*
|
*
|
||||||
|
@ -364,12 +350,12 @@ export class Rotor {
|
||||||
* @returns {number[]}
|
* @returns {number[]}
|
||||||
*/
|
*/
|
||||||
getNumMapping(wireSetting, rev) {
|
getNumMapping(wireSetting, rev) {
|
||||||
if (rev === false) {
|
if (rev===false) {
|
||||||
return wireSetting;
|
return wireSetting;
|
||||||
} else {
|
} else {
|
||||||
const length = wireSetting.length;
|
const length = wireSetting.length;
|
||||||
const tempMapping = new Array(length);
|
const tempMapping = new Array(length);
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i=0; i<length; i++) {
|
||||||
tempMapping[wireSetting[i]] = i;
|
tempMapping[wireSetting[i]] = i;
|
||||||
}
|
}
|
||||||
return tempMapping;
|
return tempMapping;
|
||||||
|
@ -385,18 +371,18 @@ export class Rotor {
|
||||||
getPosMapping(rev) {
|
getPosMapping(rev) {
|
||||||
const length = this.numMapping.length;
|
const length = this.numMapping.length;
|
||||||
const posMapping = [];
|
const posMapping = [];
|
||||||
if (rev === false) {
|
if (rev===false) {
|
||||||
for (let i = this.state; i < this.state + length; i++) {
|
for (let i = this.state; i < this.state+length; i++) {
|
||||||
let res = i % length;
|
let res = i%length;
|
||||||
if (res < 0) {
|
if (res<0) {
|
||||||
res += length;
|
res += length;
|
||||||
}
|
}
|
||||||
posMapping.push(res);
|
posMapping.push(res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let i = this.state; i > this.state - length; i--) {
|
for (let i = this.state; i > this.state-length; i--) {
|
||||||
let res = i % length;
|
let res = i%length;
|
||||||
if (res < 0) {
|
if (res<0) {
|
||||||
res += length;
|
res += length;
|
||||||
}
|
}
|
||||||
posMapping.push(res);
|
posMapping.push(res);
|
||||||
|
@ -432,12 +418,14 @@ export class Rotor {
|
||||||
this.posMapping.splice(0, 0, lastNum);
|
this.posMapping.splice(0, 0, lastNum);
|
||||||
this.state = this.posMapping[0];
|
this.state = this.posMapping[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CRRotor is a cipher (C) or control (R) rotor. These rotors are identical and interchangeable. A C or R rotor consists of 26 contacts, one for each letter, and may be put into either a forwards of reversed orientation.
|
* A CRRotor is a cipher (C) or control (R) rotor. These rotors are identical and interchangeable. A C or R rotor consists of 26 contacts, one for each letter, and may be put into either a forwards of reversed orientation.
|
||||||
*/
|
*/
|
||||||
export class CRRotor extends Rotor {
|
export class CRRotor extends Rotor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CRRotor constructor
|
* CRRotor constructor
|
||||||
*
|
*
|
||||||
|
@ -445,7 +433,7 @@ export class CRRotor extends Rotor {
|
||||||
* @param {char} key - initial state of rotor
|
* @param {char} key - initial state of rotor
|
||||||
* @param {bool} rev - true if reversed, false if not
|
* @param {bool} rev - true if reversed, false if not
|
||||||
*/
|
*/
|
||||||
constructor(wireSetting, key, rev = false) {
|
constructor(wireSetting, key, rev=false) {
|
||||||
wireSetting = wireSetting.split("").map(CRRotor.letterToNum);
|
wireSetting = wireSetting.split("").map(CRRotor.letterToNum);
|
||||||
super(wireSetting, CRRotor.letterToNum(key), rev);
|
super(wireSetting, CRRotor.letterToNum(key), rev);
|
||||||
}
|
}
|
||||||
|
@ -457,7 +445,7 @@ export class CRRotor extends Rotor {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
static letterToNum(letter) {
|
static letterToNum(letter) {
|
||||||
return letter.charCodeAt() - 65;
|
return letter.charCodeAt()-65;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -467,7 +455,7 @@ export class CRRotor extends Rotor {
|
||||||
* @returns {char}
|
* @returns {char}
|
||||||
*/
|
*/
|
||||||
static numToLetter(num) {
|
static numToLetter(num) {
|
||||||
return String.fromCharCode(num + 65);
|
return String.fromCharCode(num+65);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -482,12 +470,14 @@ export class CRRotor extends Rotor {
|
||||||
const outPos = this.cryptNum(inputPos, direction);
|
const outPos = this.cryptNum(inputPos, direction);
|
||||||
return CRRotor.numToLetter(outPos);
|
return CRRotor.numToLetter(outPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An IRotor is an index rotor, which consists of 10 contacts each numbered from 0 to 9. Unlike C and R rotors, they cannot be put in the reversed orientation. The index rotors do not step at any point during encryption or decryption.
|
* An IRotor is an index rotor, which consists of 10 contacts each numbered from 0 to 9. Unlike C and R rotors, they cannot be put in the reversed orientation. The index rotors do not step at any point during encryption or decryption.
|
||||||
*/
|
*/
|
||||||
export class IRotor extends Rotor {
|
export class IRotor extends Rotor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IRotor constructor
|
* IRotor constructor
|
||||||
*
|
*
|
||||||
|
@ -508,4 +498,5 @@ export class IRotor extends Rotor {
|
||||||
crypt(inputPos) {
|
crypt(inputPos) {
|
||||||
return this.cryptNum(inputPos, "leftToRight");
|
return this.cryptNum(inputPos, "leftToRight");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,38 +23,34 @@ const BLOCKSIZE = 16;
|
||||||
|
|
||||||
/** The S box, 256 8-bit values */
|
/** The S box, 256 8-bit values */
|
||||||
const Sbox = [
|
const Sbox = [
|
||||||
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2,
|
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
|
||||||
0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
|
0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
|
||||||
0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4,
|
0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
|
||||||
0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
|
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
|
||||||
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa,
|
0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
|
||||||
0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
|
0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
|
||||||
0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2,
|
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
|
||||||
0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
|
0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
|
||||||
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b,
|
0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
|
||||||
0x01, 0x21, 0x78, 0x87, 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
|
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
|
||||||
0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2,
|
0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
|
||||||
0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
|
0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
|
||||||
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30,
|
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
|
||||||
0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
|
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
|
||||||
0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45,
|
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
|
||||||
0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
|
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
|
||||||
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41,
|
|
||||||
0x1f, 0x10, 0x5a, 0xd8, 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
|
|
||||||
0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a,
|
|
||||||
0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
|
|
||||||
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e,
|
|
||||||
0xd7, 0xcb, 0x39, 0x48,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** "Fixed parameter CK" used in key expansion */
|
/** "Fixed parameter CK" used in key expansion */
|
||||||
const CK = [
|
const CK = [
|
||||||
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1,
|
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
|
||||||
0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
|
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
|
||||||
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1,
|
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
|
||||||
0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
|
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
|
||||||
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41,
|
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
|
||||||
0x484f565d, 0x646b7279,
|
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
|
||||||
|
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
|
||||||
|
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
|
||||||
];
|
];
|
||||||
|
|
||||||
/** "System parameter FK" */
|
/** "System parameter FK" */
|
||||||
|
@ -77,11 +73,8 @@ function ROL(i, n) {
|
||||||
*/
|
*/
|
||||||
function transformL(b) {
|
function transformL(b) {
|
||||||
/* Replace each of the 4 bytes in b with the value at its offset in the Sbox */
|
/* Replace each of the 4 bytes in b with the value at its offset in the Sbox */
|
||||||
b =
|
b = (Sbox[(b >>> 24) & 0xFF] << 24) | (Sbox[(b >>> 16) & 0xFF] << 16) |
|
||||||
(Sbox[(b >>> 24) & 0xff] << 24) |
|
(Sbox[(b >>> 8) & 0xFF] << 8) | Sbox[b & 0xFF];
|
||||||
(Sbox[(b >>> 16) & 0xff] << 16) |
|
|
||||||
(Sbox[(b >>> 8) & 0xff] << 8) |
|
|
||||||
Sbox[b & 0xff];
|
|
||||||
/* circular rotate and xor */
|
/* circular rotate and xor */
|
||||||
return b ^ ROL(b, 2) ^ ROL(b, 10) ^ ROL(b, 18) ^ ROL(b, 24);
|
return b ^ ROL(b, 2) ^ ROL(b, 10) ^ ROL(b, 18) ^ ROL(b, 24);
|
||||||
}
|
}
|
||||||
|
@ -93,11 +86,8 @@ function transformL(b) {
|
||||||
*/
|
*/
|
||||||
function transformLprime(b) {
|
function transformLprime(b) {
|
||||||
/* Replace each of the 4 bytes in b with the value at its offset in the Sbox */
|
/* Replace each of the 4 bytes in b with the value at its offset in the Sbox */
|
||||||
b =
|
b = (Sbox[(b >>> 24) & 0xFF] << 24) | (Sbox[(b >>> 16) & 0xFF] << 16) |
|
||||||
(Sbox[(b >>> 24) & 0xff] << 24) |
|
(Sbox[(b >>> 8) & 0xFF] << 8) | Sbox[b & 0xFF];
|
||||||
(Sbox[(b >>> 16) & 0xff] << 16) |
|
|
||||||
(Sbox[(b >>> 8) & 0xff] << 8) |
|
|
||||||
Sbox[b & 0xff];
|
|
||||||
return b ^ ROL(b, 13) ^ ROL(b, 23); /* circular rotate and XOR */
|
return b ^ ROL(b, 13) ^ ROL(b, 23); /* circular rotate and XOR */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +98,7 @@ function initSM4RoundKey(rawkey) {
|
||||||
const K = rawkey.map((a, i) => a ^ FK[i]); /* K = rawkey ^ FK */
|
const K = rawkey.map((a, i) => a ^ FK[i]); /* K = rawkey ^ FK */
|
||||||
const roundKey = [];
|
const roundKey = [];
|
||||||
for (let i = 0; i < 32; i++)
|
for (let i = 0; i < 32; i++)
|
||||||
roundKey[i] = K[i + 4] =
|
roundKey[i] = K[i + 4] = K[i] ^ transformLprime(K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i]);
|
||||||
K[i] ^ transformLprime(K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i]);
|
|
||||||
return roundKey;
|
return roundKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,8 +111,7 @@ function initSM4RoundKey(rawkey) {
|
||||||
*/
|
*/
|
||||||
function encryptBlockSM4(X, roundKey) {
|
function encryptBlockSM4(X, roundKey) {
|
||||||
for (let i = 0; i < NROUNDS; i++)
|
for (let i = 0; i < NROUNDS; i++)
|
||||||
X[i + 4] =
|
X[i + 4] = X[i] ^ transformL(X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ roundKey[i]);
|
||||||
X[i] ^ transformL(X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ roundKey[i]);
|
|
||||||
return [X[35], X[34], X[33], X[32]];
|
return [X[35], X[34], X[33], X[32]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,31 +122,15 @@ function encryptBlockSM4(X, roundKey) {
|
||||||
* @param {byteArray} bArray - the array of bytes
|
* @param {byteArray} bArray - the array of bytes
|
||||||
* @param {integer} offset - starting offset in the array; 15 bytes must follow it.
|
* @param {integer} offset - starting offset in the array; 15 bytes must follow it.
|
||||||
*/
|
*/
|
||||||
function bytesToInts(bArray, offs = 0) {
|
function bytesToInts(bArray, offs=0) {
|
||||||
let offset = offs;
|
let offset = offs;
|
||||||
const A =
|
const A = (bArray[offset] << 24) | (bArray[offset + 1] << 16) | (bArray[offset + 2] << 8) | bArray[offset + 3];
|
||||||
(bArray[offset] << 24) |
|
|
||||||
(bArray[offset + 1] << 16) |
|
|
||||||
(bArray[offset + 2] << 8) |
|
|
||||||
bArray[offset + 3];
|
|
||||||
offset += 4;
|
offset += 4;
|
||||||
const B =
|
const B = (bArray[offset] << 24) | (bArray[offset + 1] << 16) | (bArray[offset + 2] << 8) | bArray[offset + 3];
|
||||||
(bArray[offset] << 24) |
|
|
||||||
(bArray[offset + 1] << 16) |
|
|
||||||
(bArray[offset + 2] << 8) |
|
|
||||||
bArray[offset + 3];
|
|
||||||
offset += 4;
|
offset += 4;
|
||||||
const C =
|
const C = (bArray[offset] << 24) | (bArray[offset + 1] << 16) | (bArray[offset + 2] << 8) | bArray[offset + 3];
|
||||||
(bArray[offset] << 24) |
|
|
||||||
(bArray[offset + 1] << 16) |
|
|
||||||
(bArray[offset + 2] << 8) |
|
|
||||||
bArray[offset + 3];
|
|
||||||
offset += 4;
|
offset += 4;
|
||||||
const D =
|
const D = (bArray[offset] << 24) | (bArray[offset + 1] << 16) | (bArray[offset + 2] << 8) | bArray[offset + 3];
|
||||||
(bArray[offset] << 24) |
|
|
||||||
(bArray[offset + 1] << 16) |
|
|
||||||
(bArray[offset + 2] << 8) |
|
|
||||||
bArray[offset + 3];
|
|
||||||
return [A, B, C, D];
|
return [A, B, C, D];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,10 +141,10 @@ function bytesToInts(bArray, offs = 0) {
|
||||||
function intsToBytes(ints) {
|
function intsToBytes(ints) {
|
||||||
const bArr = [];
|
const bArr = [];
|
||||||
for (let i = 0; i < ints.length; i++) {
|
for (let i = 0; i < ints.length; i++) {
|
||||||
bArr.push((ints[i] >> 24) & 0xff);
|
bArr.push((ints[i] >> 24) & 0xFF);
|
||||||
bArr.push((ints[i] >> 16) & 0xff);
|
bArr.push((ints[i] >> 16) & 0xFF);
|
||||||
bArr.push((ints[i] >> 8) & 0xff);
|
bArr.push((ints[i] >> 8) & 0xFF);
|
||||||
bArr.push(ints[i] & 0xff);
|
bArr.push(ints[i] & 0xFF);
|
||||||
}
|
}
|
||||||
return bArr;
|
return bArr;
|
||||||
}
|
}
|
||||||
|
@ -187,44 +159,38 @@ function intsToBytes(ints) {
|
||||||
* @param {boolean} noPadding - Don't add PKCS#7 padding if set.
|
* @param {boolean} noPadding - Don't add PKCS#7 padding if set.
|
||||||
* @returns {byteArray} - The cipher text.
|
* @returns {byteArray} - The cipher text.
|
||||||
*/
|
*/
|
||||||
export function encryptSM4(message, key, iv, mode = "ECB", noPadding = false) {
|
export function encryptSM4(message, key, iv, mode="ECB", noPadding=false) {
|
||||||
const messageLength = message.length;
|
const messageLength = message.length;
|
||||||
if (messageLength === 0) return [];
|
if (messageLength === 0)
|
||||||
|
return [];
|
||||||
const roundKey = initSM4RoundKey(bytesToInts(key, 0));
|
const roundKey = initSM4RoundKey(bytesToInts(key, 0));
|
||||||
|
|
||||||
/* Pad with PKCS#7 if requested for ECB/CBC else add zeroes (which are sliced off at the end) */
|
/* Pad with PKCS#7 if requested for ECB/CBC else add zeroes (which are sliced off at the end) */
|
||||||
let padByte = 0;
|
let padByte = 0;
|
||||||
let nPadding = 16 - (message.length & 0xf);
|
let nPadding = 16 - (message.length & 0xF);
|
||||||
if (mode === "ECB" || mode === "CBC") {
|
if (mode === "ECB" || mode === "CBC") {
|
||||||
if (noPadding) {
|
if (noPadding) {
|
||||||
if (nPadding !== 16)
|
if (nPadding !== 16)
|
||||||
throw new OperationError(
|
throw new OperationError(`No padding requested in ${mode} mode but input is not a 16-byte multiple.`);
|
||||||
`No padding requested in ${mode} mode but input is not a 16-byte multiple.`,
|
|
||||||
);
|
|
||||||
nPadding = 0;
|
nPadding = 0;
|
||||||
} else padByte = nPadding;
|
} else
|
||||||
|
padByte = nPadding;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < nPadding; i++) message.push(padByte);
|
for (let i = 0; i < nPadding; i++)
|
||||||
|
message.push(padByte);
|
||||||
|
|
||||||
const cipherText = [];
|
const cipherText = [];
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "ECB":
|
case "ECB":
|
||||||
for (let i = 0; i < message.length; i += BLOCKSIZE)
|
for (let i = 0; i < message.length; i += BLOCKSIZE)
|
||||||
Array.prototype.push.apply(
|
Array.prototype.push.apply(cipherText, intsToBytes(encryptBlockSM4(bytesToInts(message, i), roundKey)));
|
||||||
cipherText,
|
|
||||||
intsToBytes(
|
|
||||||
encryptBlockSM4(bytesToInts(message, i), roundKey),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "CBC":
|
case "CBC":
|
||||||
iv = bytesToInts(iv, 0);
|
iv = bytesToInts(iv, 0);
|
||||||
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
||||||
const block = bytesToInts(message, i);
|
const block = bytesToInts(message, i);
|
||||||
block[0] ^= iv[0];
|
block[0] ^= iv[0]; block[1] ^= iv[1];
|
||||||
block[1] ^= iv[1];
|
block[2] ^= iv[2]; block[3] ^= iv[3];
|
||||||
block[2] ^= iv[2];
|
|
||||||
block[3] ^= iv[3];
|
|
||||||
iv = encryptBlockSM4(block, roundKey);
|
iv = encryptBlockSM4(block, roundKey);
|
||||||
Array.prototype.push.apply(cipherText, intsToBytes(iv));
|
Array.prototype.push.apply(cipherText, intsToBytes(iv));
|
||||||
}
|
}
|
||||||
|
@ -234,10 +200,8 @@ export function encryptSM4(message, key, iv, mode = "ECB", noPadding = false) {
|
||||||
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
||||||
iv = encryptBlockSM4(iv, roundKey);
|
iv = encryptBlockSM4(iv, roundKey);
|
||||||
const block = bytesToInts(message, i);
|
const block = bytesToInts(message, i);
|
||||||
block[0] ^= iv[0];
|
block[0] ^= iv[0]; block[1] ^= iv[1];
|
||||||
block[1] ^= iv[1];
|
block[2] ^= iv[2]; block[3] ^= iv[3];
|
||||||
block[2] ^= iv[2];
|
|
||||||
block[3] ^= iv[3];
|
|
||||||
Array.prototype.push.apply(cipherText, intsToBytes(block));
|
Array.prototype.push.apply(cipherText, intsToBytes(block));
|
||||||
iv = block;
|
iv = block;
|
||||||
}
|
}
|
||||||
|
@ -247,10 +211,8 @@ export function encryptSM4(message, key, iv, mode = "ECB", noPadding = false) {
|
||||||
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
||||||
iv = encryptBlockSM4(iv, roundKey);
|
iv = encryptBlockSM4(iv, roundKey);
|
||||||
const block = bytesToInts(message, i);
|
const block = bytesToInts(message, i);
|
||||||
block[0] ^= iv[0];
|
block[0] ^= iv[0]; block[1] ^= iv[1];
|
||||||
block[1] ^= iv[1];
|
block[2] ^= iv[2]; block[3] ^= iv[3];
|
||||||
block[2] ^= iv[2];
|
|
||||||
block[3] ^= iv[3];
|
|
||||||
Array.prototype.push.apply(cipherText, intsToBytes(block));
|
Array.prototype.push.apply(cipherText, intsToBytes(block));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -258,20 +220,16 @@ export function encryptSM4(message, key, iv, mode = "ECB", noPadding = false) {
|
||||||
iv = bytesToInts(iv, 0);
|
iv = bytesToInts(iv, 0);
|
||||||
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
for (let i = 0; i < message.length; i += BLOCKSIZE) {
|
||||||
let iv2 = [...iv]; /* containing the IV + counter */
|
let iv2 = [...iv]; /* containing the IV + counter */
|
||||||
iv2[3] +=
|
iv2[3] += (i >> 4);/* Using a 32 bit counter here. 64 Gb encrypts should be enough for everyone. */
|
||||||
i >>
|
|
||||||
4; /* Using a 32 bit counter here. 64 Gb encrypts should be enough for everyone. */
|
|
||||||
iv2 = encryptBlockSM4(iv2, roundKey);
|
iv2 = encryptBlockSM4(iv2, roundKey);
|
||||||
const block = bytesToInts(message, i);
|
const block = bytesToInts(message, i);
|
||||||
block[0] ^= iv2[0];
|
block[0] ^= iv2[0]; block[1] ^= iv2[1];
|
||||||
block[1] ^= iv2[1];
|
block[2] ^= iv2[2]; block[3] ^= iv2[3];
|
||||||
block[2] ^= iv2[2];
|
|
||||||
block[3] ^= iv2[3];
|
|
||||||
Array.prototype.push.apply(cipherText, intsToBytes(block));
|
Array.prototype.push.apply(cipherText, intsToBytes(block));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new OperationError("Invalid block cipher mode: " + mode);
|
throw new OperationError("Invalid block cipher mode: "+mode);
|
||||||
}
|
}
|
||||||
if (mode !== "ECB" && mode !== "CBC")
|
if (mode !== "ECB" && mode !== "CBC")
|
||||||
return cipherText.slice(0, messageLength);
|
return cipherText.slice(0, messageLength);
|
||||||
|
@ -288,53 +246,34 @@ export function encryptSM4(message, key, iv, mode = "ECB", noPadding = false) {
|
||||||
* @param {boolean] ignorePadding - If true, ignore padding issues in ECB/CBC mode.
|
* @param {boolean] ignorePadding - If true, ignore padding issues in ECB/CBC mode.
|
||||||
* @returns {byteArray} - The cipher text.
|
* @returns {byteArray} - The cipher text.
|
||||||
*/
|
*/
|
||||||
export function decryptSM4(
|
export function decryptSM4(cipherText, key, iv, mode="ECB", ignorePadding=false) {
|
||||||
cipherText,
|
|
||||||
key,
|
|
||||||
iv,
|
|
||||||
mode = "ECB",
|
|
||||||
ignorePadding = false,
|
|
||||||
) {
|
|
||||||
const originalLength = cipherText.length;
|
const originalLength = cipherText.length;
|
||||||
if (originalLength === 0) return [];
|
if (originalLength === 0)
|
||||||
|
return [];
|
||||||
let roundKey = initSM4RoundKey(bytesToInts(key, 0));
|
let roundKey = initSM4RoundKey(bytesToInts(key, 0));
|
||||||
|
|
||||||
if (mode === "ECB" || mode === "CBC") {
|
if (mode === "ECB" || mode === "CBC") {
|
||||||
/* Init decryption key */
|
/* Init decryption key */
|
||||||
roundKey = roundKey.reverse();
|
roundKey = roundKey.reverse();
|
||||||
if ((originalLength & 0xf) !== 0 && !ignorePadding)
|
if ((originalLength & 0xF) !== 0 && !ignorePadding)
|
||||||
throw new OperationError(
|
throw new OperationError(`With ECB or CBC modes, the input must be divisible into 16 byte blocks. (${cipherText.length & 0xF} bytes extra)`);
|
||||||
`With ECB or CBC modes, the input must be divisible into 16 byte blocks. (${
|
} else { /* Pad dummy bytes for other modes, chop them off at the end */
|
||||||
cipherText.length & 0xf
|
while ((cipherText.length & 0xF) !== 0)
|
||||||
} bytes extra)`,
|
cipherText.push(0);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
/* Pad dummy bytes for other modes, chop them off at the end */
|
|
||||||
while ((cipherText.length & 0xf) !== 0) cipherText.push(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearText = [];
|
const clearText = [];
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "ECB":
|
case "ECB":
|
||||||
for (let i = 0; i < cipherText.length; i += BLOCKSIZE)
|
for (let i = 0; i < cipherText.length; i += BLOCKSIZE)
|
||||||
Array.prototype.push.apply(
|
Array.prototype.push.apply(clearText, intsToBytes(encryptBlockSM4(bytesToInts(cipherText, i), roundKey)));
|
||||||
clearText,
|
|
||||||
intsToBytes(
|
|
||||||
encryptBlockSM4(bytesToInts(cipherText, i), roundKey),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "CBC":
|
case "CBC":
|
||||||
iv = bytesToInts(iv, 0);
|
iv = bytesToInts(iv, 0);
|
||||||
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
||||||
const block = encryptBlockSM4(
|
const block = encryptBlockSM4(bytesToInts(cipherText, i), roundKey);
|
||||||
bytesToInts(cipherText, i),
|
block[0] ^= iv[0]; block[1] ^= iv[1];
|
||||||
roundKey,
|
block[2] ^= iv[2]; block[3] ^= iv[3];
|
||||||
);
|
|
||||||
block[0] ^= iv[0];
|
|
||||||
block[1] ^= iv[1];
|
|
||||||
block[2] ^= iv[2];
|
|
||||||
block[3] ^= iv[3];
|
|
||||||
Array.prototype.push.apply(clearText, intsToBytes(block));
|
Array.prototype.push.apply(clearText, intsToBytes(block));
|
||||||
iv = bytesToInts(cipherText, i);
|
iv = bytesToInts(cipherText, i);
|
||||||
}
|
}
|
||||||
|
@ -344,10 +283,8 @@ export function decryptSM4(
|
||||||
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
||||||
iv = encryptBlockSM4(iv, roundKey);
|
iv = encryptBlockSM4(iv, roundKey);
|
||||||
const block = bytesToInts(cipherText, i);
|
const block = bytesToInts(cipherText, i);
|
||||||
block[0] ^= iv[0];
|
block[0] ^= iv[0]; block[1] ^= iv[1];
|
||||||
block[1] ^= iv[1];
|
block[2] ^= iv[2]; block[3] ^= iv[3];
|
||||||
block[2] ^= iv[2];
|
|
||||||
block[3] ^= iv[3];
|
|
||||||
Array.prototype.push.apply(clearText, intsToBytes(block));
|
Array.prototype.push.apply(clearText, intsToBytes(block));
|
||||||
iv = bytesToInts(cipherText, i);
|
iv = bytesToInts(cipherText, i);
|
||||||
}
|
}
|
||||||
|
@ -357,10 +294,8 @@ export function decryptSM4(
|
||||||
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
||||||
iv = encryptBlockSM4(iv, roundKey);
|
iv = encryptBlockSM4(iv, roundKey);
|
||||||
const block = bytesToInts(cipherText, i);
|
const block = bytesToInts(cipherText, i);
|
||||||
block[0] ^= iv[0];
|
block[0] ^= iv[0]; block[1] ^= iv[1];
|
||||||
block[1] ^= iv[1];
|
block[2] ^= iv[2]; block[3] ^= iv[3];
|
||||||
block[2] ^= iv[2];
|
|
||||||
block[3] ^= iv[3];
|
|
||||||
Array.prototype.push.apply(clearText, intsToBytes(block));
|
Array.prototype.push.apply(clearText, intsToBytes(block));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -368,15 +303,11 @@ export function decryptSM4(
|
||||||
iv = bytesToInts(iv, 0);
|
iv = bytesToInts(iv, 0);
|
||||||
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
for (let i = 0; i < cipherText.length; i += BLOCKSIZE) {
|
||||||
let iv2 = [...iv]; /* containing the IV + counter */
|
let iv2 = [...iv]; /* containing the IV + counter */
|
||||||
iv2[3] +=
|
iv2[3] += (i >> 4);/* Using a 32 bit counter here. 64 Gb encrypts should be enough for everyone. */
|
||||||
i >>
|
|
||||||
4; /* Using a 32 bit counter here. 64 Gb encrypts should be enough for everyone. */
|
|
||||||
iv2 = encryptBlockSM4(iv2, roundKey);
|
iv2 = encryptBlockSM4(iv2, roundKey);
|
||||||
const block = bytesToInts(cipherText, i);
|
const block = bytesToInts(cipherText, i);
|
||||||
block[0] ^= iv2[0];
|
block[0] ^= iv2[0]; block[1] ^= iv2[1];
|
||||||
block[1] ^= iv2[1];
|
block[2] ^= iv2[2]; block[3] ^= iv2[3];
|
||||||
block[2] ^= iv2[2];
|
|
||||||
block[3] ^= iv2[3];
|
|
||||||
Array.prototype.push.apply(clearText, intsToBytes(block));
|
Array.prototype.push.apply(clearText, intsToBytes(block));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -385,13 +316,16 @@ export function decryptSM4(
|
||||||
}
|
}
|
||||||
/* Check PKCS#7 padding */
|
/* Check PKCS#7 padding */
|
||||||
if (mode === "ECB" || mode === "CBC") {
|
if (mode === "ECB" || mode === "CBC") {
|
||||||
if (ignorePadding) return clearText;
|
if (ignorePadding)
|
||||||
|
return clearText;
|
||||||
const padByte = clearText[clearText.length - 1];
|
const padByte = clearText[clearText.length - 1];
|
||||||
if (padByte > 16) throw new OperationError("Invalid PKCS#7 padding.");
|
if (padByte > 16)
|
||||||
|
throw new OperationError("Invalid PKCS#7 padding.");
|
||||||
for (let i = 0; i < padByte; i++)
|
for (let i = 0; i < padByte; i++)
|
||||||
if (clearText[clearText.length - i - 1] !== padByte)
|
if (clearText[clearText.length -i - 1] !== padByte)
|
||||||
throw new OperationError("Invalid PKCS#7 padding.");
|
throw new OperationError("Invalid PKCS#7 padding.");
|
||||||
return clearText.slice(0, clearText.length - padByte);
|
return clearText.slice(0, clearText.length - padByte);
|
||||||
}
|
}
|
||||||
return clearText.slice(0, originalLength);
|
return clearText.slice(0, originalLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ export function caseInsensitiveSort(a, b) {
|
||||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparison operation for sorting of IPv4 addresses.
|
* Comparison operation for sorting of IPv4 addresses.
|
||||||
*
|
*
|
||||||
|
@ -58,8 +59,7 @@ export function numericSort(a, b) {
|
||||||
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
||||||
if (ret !== 0) return ret;
|
if (ret !== 0) return ret;
|
||||||
}
|
}
|
||||||
if (!isNaN(a_[i]) && !isNaN(b_[i])) {
|
if (!isNaN(a_[i]) && !isNaN(b_[i])) { // Compare numbers
|
||||||
// Compare numbers
|
|
||||||
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,12 +79,12 @@ export function hexadecimalSort(a, b) {
|
||||||
let a_ = a.split(/([^\da-f]+)/i),
|
let a_ = a.split(/([^\da-f]+)/i),
|
||||||
b_ = b.split(/([^\da-f]+)/i);
|
b_ = b.split(/([^\da-f]+)/i);
|
||||||
|
|
||||||
a_ = a_.map((v) => {
|
a_ = a_.map(v => {
|
||||||
const t = parseInt(v, 16);
|
const t = parseInt(v, 16);
|
||||||
return isNaN(t) ? v : t;
|
return isNaN(t) ? v : t;
|
||||||
});
|
});
|
||||||
|
|
||||||
b_ = b_.map((v) => {
|
b_ = b_.map(v => {
|
||||||
const t = parseInt(v, 16);
|
const t = parseInt(v, 16);
|
||||||
return isNaN(t) ? v : t;
|
return isNaN(t) ? v : t;
|
||||||
});
|
});
|
||||||
|
@ -96,8 +96,7 @@ export function hexadecimalSort(a, b) {
|
||||||
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
||||||
if (ret !== 0) return ret;
|
if (ret !== 0) return ret;
|
||||||
}
|
}
|
||||||
if (!isNaN(a_[i]) && !isNaN(b_[i])) {
|
if (!isNaN(a_[i]) && !isNaN(b_[i])) { // Compare numbers
|
||||||
// Compare numbers
|
|
||||||
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,3 +114,4 @@ export function hexadecimalSort(a, b) {
|
||||||
export function lengthSort(a, b) {
|
export function lengthSort(a, b) {
|
||||||
return a.length - b.length;
|
return a.length - b.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* as various data types.
|
* as various data types.
|
||||||
*/
|
*/
|
||||||
export default class Stream {
|
export default class Stream {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream constructor.
|
* Stream constructor.
|
||||||
*
|
*
|
||||||
|
@ -31,11 +32,12 @@ export default class Stream {
|
||||||
* @param {number} [numBytes=null]
|
* @param {number} [numBytes=null]
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
getBytes(numBytes = null) {
|
getBytes(numBytes=null) {
|
||||||
if (this.position > this.length) return undefined;
|
if (this.position > this.length) return undefined;
|
||||||
|
|
||||||
const newPosition =
|
const newPosition = numBytes !== null ?
|
||||||
numBytes !== null ? this.position + numBytes : this.length;
|
this.position + numBytes :
|
||||||
|
this.length;
|
||||||
const bytes = this.bytes.slice(this.position, newPosition);
|
const bytes = this.bytes.slice(this.position, newPosition);
|
||||||
this.position = newPosition;
|
this.position = newPosition;
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
|
@ -49,7 +51,7 @@ export default class Stream {
|
||||||
* @param {number} [numBytes=-1]
|
* @param {number} [numBytes=-1]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
readString(numBytes = -1) {
|
readString(numBytes=-1) {
|
||||||
if (this.position > this.length) return undefined;
|
if (this.position > this.length) return undefined;
|
||||||
|
|
||||||
if (numBytes === -1) numBytes = this.length - this.position;
|
if (numBytes === -1) numBytes = this.length - this.position;
|
||||||
|
@ -72,7 +74,7 @@ export default class Stream {
|
||||||
* @param {string} [endianness="be"]
|
* @param {string} [endianness="be"]
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
readInt(numBytes, endianness = "be") {
|
readInt(numBytes, endianness="be") {
|
||||||
if (this.position > this.length) return undefined;
|
if (this.position > this.length) return undefined;
|
||||||
|
|
||||||
let val = 0;
|
let val = 0;
|
||||||
|
@ -82,11 +84,7 @@ export default class Stream {
|
||||||
val |= this.bytes[i];
|
val |= this.bytes[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (
|
for (let i = this.position + numBytes - 1; i >= this.position; i--) {
|
||||||
let i = this.position + numBytes - 1;
|
|
||||||
i >= this.position;
|
|
||||||
i--
|
|
||||||
) {
|
|
||||||
val = val << 8;
|
val = val << 8;
|
||||||
val |= this.bytes[i];
|
val |= this.bytes[i];
|
||||||
}
|
}
|
||||||
|
@ -103,7 +101,7 @@ export default class Stream {
|
||||||
* @param {string} [endianness="be"]
|
* @param {string} [endianness="be"]
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
readBits(numBits, endianness = "be") {
|
readBits(numBits, endianness="be") {
|
||||||
if (this.position > this.length) return undefined;
|
if (this.position > this.length) return undefined;
|
||||||
|
|
||||||
let bitBuf = 0,
|
let bitBuf = 0,
|
||||||
|
@ -119,15 +117,18 @@ export default class Stream {
|
||||||
while (bitBufLen < numBits) {
|
while (bitBufLen < numBits) {
|
||||||
if (endianness === "be")
|
if (endianness === "be")
|
||||||
bitBuf = (bitBuf << bitBufLen) | this.bytes[this.position++];
|
bitBuf = (bitBuf << bitBufLen) | this.bytes[this.position++];
|
||||||
else bitBuf |= this.bytes[this.position++] << bitBufLen;
|
else
|
||||||
|
bitBuf |= this.bytes[this.position++] << bitBufLen;
|
||||||
bitBufLen += 8;
|
bitBufLen += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse back to numBits
|
// Reverse back to numBits
|
||||||
if (bitBufLen > numBits) {
|
if (bitBufLen > numBits) {
|
||||||
const excess = bitBufLen - numBits;
|
const excess = bitBufLen - numBits;
|
||||||
if (endianness === "be") bitBuf >>>= excess;
|
if (endianness === "be")
|
||||||
else bitBuf &= (1 << numBits) - 1;
|
bitBuf >>>= excess;
|
||||||
|
else
|
||||||
|
bitBuf &= (1 << numBits) - 1;
|
||||||
bitBufLen -= excess;
|
bitBufLen -= excess;
|
||||||
this.position--;
|
this.position--;
|
||||||
this.bitPos = 8 - excess;
|
this.bitPos = 8 - excess;
|
||||||
|
@ -142,9 +143,9 @@ export default class Stream {
|
||||||
* @returns {number} The bit mask
|
* @returns {number} The bit mask
|
||||||
*/
|
*/
|
||||||
function bitMask(bitPos) {
|
function bitMask(bitPos) {
|
||||||
return endianness === "be"
|
return endianness === "be" ?
|
||||||
? (1 << (8 - bitPos)) - 1
|
(1 << (8 - bitPos)) - 1 :
|
||||||
: 256 - (1 << bitPos);
|
256 - (1 << bitPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,10 +160,7 @@ export default class Stream {
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
|
|
||||||
if (typeof val === "number") {
|
if (typeof val === "number") {
|
||||||
while (
|
while (++this.position < this.length && this.bytes[this.position] !== val) {
|
||||||
++this.position < this.length &&
|
|
||||||
this.bytes[this.position] !== val
|
|
||||||
) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -186,7 +184,7 @@ export default class Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
const length = val.length;
|
const length = val.length;
|
||||||
const initial = val[length - 1];
|
const initial = val[length-1];
|
||||||
this.position = length;
|
this.position = length;
|
||||||
|
|
||||||
// Get the skip table.
|
// Get the skip table.
|
||||||
|
@ -195,15 +193,12 @@ export default class Stream {
|
||||||
|
|
||||||
while (this.position < this.length) {
|
while (this.position < this.length) {
|
||||||
// Until we hit the final element of val in the stream.
|
// Until we hit the final element of val in the stream.
|
||||||
while (
|
while ((this.position < this.length) && (this.bytes[this.position++] !== initial));
|
||||||
this.position < this.length &&
|
|
||||||
this.bytes[this.position++] !== initial
|
|
||||||
);
|
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
// Loop through the elements comparing them to val.
|
// Loop through the elements comparing them to val.
|
||||||
for (let x = length - 1; x >= 0; x--) {
|
for (let x = length-1; x >= 0; x--) {
|
||||||
if (this.bytes[this.position - length + x] !== val[x]) {
|
if (this.bytes[this.position - length + x] !== val[x]) {
|
||||||
found = false;
|
found = false;
|
||||||
|
|
||||||
|
@ -219,6 +214,7 @@ export default class Stream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consume bytes if they match the supplied value.
|
* Consume bytes if they match the supplied value.
|
||||||
*
|
*
|
||||||
|
@ -254,9 +250,7 @@ export default class Stream {
|
||||||
moveForwardsBy(numBytes) {
|
moveForwardsBy(numBytes) {
|
||||||
const pos = this.position + numBytes;
|
const pos = this.position + numBytes;
|
||||||
if (pos < 0 || pos > this.length)
|
if (pos < 0 || pos > this.length)
|
||||||
throw new Error(
|
throw new Error("Cannot move to position " + pos + " in stream. Out of bounds.");
|
||||||
"Cannot move to position " + pos + " in stream. Out of bounds.",
|
|
||||||
);
|
|
||||||
this.position = pos;
|
this.position = pos;
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
}
|
}
|
||||||
|
@ -269,9 +263,7 @@ export default class Stream {
|
||||||
moveBackwardsBy(numBytes) {
|
moveBackwardsBy(numBytes) {
|
||||||
const pos = this.position - numBytes;
|
const pos = this.position - numBytes;
|
||||||
if (pos < 0 || pos > this.length)
|
if (pos < 0 || pos > this.length)
|
||||||
throw new Error(
|
throw new Error("Cannot move to position " + pos + " in stream. Out of bounds.");
|
||||||
"Cannot move to position " + pos + " in stream. Out of bounds.",
|
|
||||||
);
|
|
||||||
this.position = pos;
|
this.position = pos;
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
}
|
}
|
||||||
|
@ -306,9 +298,7 @@ export default class Stream {
|
||||||
*/
|
*/
|
||||||
moveTo(pos) {
|
moveTo(pos) {
|
||||||
if (pos < 0 || pos > this.length)
|
if (pos < 0 || pos > this.length)
|
||||||
throw new Error(
|
throw new Error("Cannot move to position " + pos + " in stream. Out of bounds.");
|
||||||
"Cannot move to position " + pos + " in stream. Out of bounds.",
|
|
||||||
);
|
|
||||||
this.position = pos;
|
this.position = pos;
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
}
|
}
|
||||||
|
@ -329,8 +319,9 @@ export default class Stream {
|
||||||
* @param {number} [finish=this.position]
|
* @param {number} [finish=this.position]
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
carve(start = 0, finish = this.position) {
|
carve(start=0, finish=this.position) {
|
||||||
if (this.bitPos > 0) finish++;
|
if (this.bitPos > 0) finish++;
|
||||||
return this.bytes.slice(start, finish);
|
return this.bytes.slice(start, finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,14 @@
|
||||||
const defaults = {
|
const defaults = {
|
||||||
location: 0,
|
location: 0,
|
||||||
bytesInLength: 1,
|
bytesInLength: 1,
|
||||||
basicEncodingRules: false,
|
basicEncodingRules: false
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLVParser library
|
* TLVParser library
|
||||||
*/
|
*/
|
||||||
export default class TLVParser {
|
export default class TLVParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLVParser constructor
|
* TLVParser constructor
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,47 +15,28 @@ import Utils from "../Utils.mjs";
|
||||||
* randomised.
|
* randomised.
|
||||||
*/
|
*/
|
||||||
export const ROTORS = [
|
export const ROTORS = [
|
||||||
{ name: "Example 1", value: "MCYLPQUVRXGSAOWNBJEZDTFKHI<BFHNQUW" },
|
{name: "Example 1", value: "MCYLPQUVRXGSAOWNBJEZDTFKHI<BFHNQUW"},
|
||||||
{ name: "Example 2", value: "KHWENRCBISXJQGOFMAPVYZDLTU<BFHNQUW" },
|
{name: "Example 2", value: "KHWENRCBISXJQGOFMAPVYZDLTU<BFHNQUW"},
|
||||||
{ name: "Example 3", value: "BYPDZMGIKQCUSATREHOJNLFWXV<BFHNQUW" },
|
{name: "Example 3", value: "BYPDZMGIKQCUSATREHOJNLFWXV<BFHNQUW"},
|
||||||
{ name: "Example 4", value: "ZANJCGDLVHIXOBRPMSWQUKFYET<BFHNQUW" },
|
{name: "Example 4", value: "ZANJCGDLVHIXOBRPMSWQUKFYET<BFHNQUW"},
|
||||||
{ name: "Example 5", value: "QXBGUTOVFCZPJIHSWERYNDAMLK<BFHNQUW" },
|
{name: "Example 5", value: "QXBGUTOVFCZPJIHSWERYNDAMLK<BFHNQUW"},
|
||||||
{ name: "Example 6", value: "BDCNWUEIQVFTSXALOGZJYMHKPR<BFHNQUW" },
|
{name: "Example 6", value: "BDCNWUEIQVFTSXALOGZJYMHKPR<BFHNQUW"},
|
||||||
{ name: "Example 7", value: "WJUKEIABMSGFTQZVCNPHORDXYL<BFHNQUW" },
|
{name: "Example 7", value: "WJUKEIABMSGFTQZVCNPHORDXYL<BFHNQUW"},
|
||||||
{ name: "Example 8", value: "TNVCZXDIPFWQKHSJMAOYLEURGB<BFHNQUW" },
|
{name: "Example 8", value: "TNVCZXDIPFWQKHSJMAOYLEURGB<BFHNQUW"},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An example Typex reflector. Again, randomised.
|
* An example Typex reflector. Again, randomised.
|
||||||
*/
|
*/
|
||||||
export const REFLECTORS = [
|
export const REFLECTORS = [
|
||||||
{ name: "Example", value: "AN BC FG IE KD LU MH OR TS VZ WQ XJ YP" },
|
{name: "Example", value: "AN BC FG IE KD LU MH OR TS VZ WQ XJ YP"},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Special character handling on Typex keyboard
|
// Special character handling on Typex keyboard
|
||||||
const KEYBOARD = {
|
const KEYBOARD = {
|
||||||
Q: "1",
|
"Q": "1", "W": "2", "E": "3", "R": "4", "T": "5", "Y": "6", "U": "7", "I": "8", "O": "9", "P": "0",
|
||||||
W: "2",
|
"A": "-", "S": "/", "D": "Z", "F": "%", "G": "X", "H": "£", "K": "(", "L": ")",
|
||||||
E: "3",
|
"C": "V", "B": "'", "N": ",", "M": "."
|
||||||
R: "4",
|
|
||||||
T: "5",
|
|
||||||
Y: "6",
|
|
||||||
U: "7",
|
|
||||||
I: "8",
|
|
||||||
O: "9",
|
|
||||||
P: "0",
|
|
||||||
A: "-",
|
|
||||||
S: "/",
|
|
||||||
D: "Z",
|
|
||||||
F: "%",
|
|
||||||
G: "X",
|
|
||||||
H: "£",
|
|
||||||
K: "(",
|
|
||||||
L: ")",
|
|
||||||
C: "V",
|
|
||||||
B: "'",
|
|
||||||
N: ",",
|
|
||||||
M: ".",
|
|
||||||
};
|
};
|
||||||
const KEYBOARD_REV = {};
|
const KEYBOARD_REV = {};
|
||||||
for (const i of Object.keys(KEYBOARD)) {
|
for (const i of Object.keys(KEYBOARD)) {
|
||||||
|
@ -175,13 +156,11 @@ export class Rotor extends Enigma.Rotor {
|
||||||
let wiringMod = wiring;
|
let wiringMod = wiring;
|
||||||
if (reversed) {
|
if (reversed) {
|
||||||
const outMap = new Array(26);
|
const outMap = new Array(26);
|
||||||
for (let i = 0; i < 26; i++) {
|
for (let i=0; i<26; i++) {
|
||||||
// wiring[i] is the original output
|
// wiring[i] is the original output
|
||||||
// Enigma.LETTERS[i] is the original input
|
// Enigma.LETTERS[i] is the original input
|
||||||
const input = Utils.mod(26 - Enigma.a2i(wiring[i]), 26);
|
const input = Utils.mod(26 - Enigma.a2i(wiring[i]), 26);
|
||||||
const output = Enigma.i2a(
|
const output = Enigma.i2a(Utils.mod(26 - Enigma.a2i(Enigma.LETTERS[i]), 26));
|
||||||
Utils.mod(26 - Enigma.a2i(Enigma.LETTERS[i]), 26),
|
|
||||||
);
|
|
||||||
outMap[input] = output;
|
outMap[input] = output;
|
||||||
}
|
}
|
||||||
wiringMod = outMap.join("");
|
wiringMod = outMap.join("");
|
||||||
|
@ -213,12 +192,10 @@ export class Plugboard extends Enigma.Rotor {
|
||||||
// We're going to achieve this by mapping the plugboard settings through an additional
|
// We're going to achieve this by mapping the plugboard settings through an additional
|
||||||
// transform that mirrors the alphabet before we pass it to the superclass.
|
// transform that mirrors the alphabet before we pass it to the superclass.
|
||||||
if (!/^[A-Z]{26}$/.test(wiring)) {
|
if (!/^[A-Z]{26}$/.test(wiring)) {
|
||||||
throw new OperationError(
|
throw new OperationError("Plugboard wiring must be 26 unique uppercase letters");
|
||||||
"Plugboard wiring must be 26 unique uppercase letters",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const reversed = "AZYXWVUTSRQPONMLKJIHGFEDCB";
|
const reversed = "AZYXWVUTSRQPONMLKJIHGFEDCB";
|
||||||
wiring = wiring.replace(/./g, (x) => {
|
wiring = wiring.replace(/./g, x => {
|
||||||
return reversed[Enigma.a2i(x)];
|
return reversed[Enigma.a2i(x)];
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
@ -245,9 +222,6 @@ export class Plugboard extends Enigma.Rotor {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
revTransform(c) {
|
revTransform(c) {
|
||||||
return Utils.mod(
|
return Utils.mod(this.revMap[Utils.mod(c + this.pos, 26)] - this.pos, 26);
|
||||||
this.revMap[Utils.mod(c + this.pos, 26)] - this.pos,
|
|
||||||
26,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@ import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js";
|
||||||
|
|
||||||
const Zlib = zlibAndGzip.Zlib;
|
const Zlib = zlibAndGzip.Zlib;
|
||||||
|
|
||||||
export const COMPRESSION_TYPE = [
|
export const COMPRESSION_TYPE = ["Dynamic Huffman Coding", "Fixed Huffman Coding", "None (Store)"];
|
||||||
"Dynamic Huffman Coding",
|
|
||||||
"Fixed Huffman Coding",
|
|
||||||
"None (Store)",
|
|
||||||
];
|
|
||||||
export const INFLATE_BUFFER_TYPE = ["Adaptive", "Block"];
|
export const INFLATE_BUFFER_TYPE = ["Adaptive", "Block"];
|
||||||
export const ZLIB_COMPRESSION_TYPE_LOOKUP = {
|
export const ZLIB_COMPRESSION_TYPE_LOOKUP = {
|
||||||
"Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED,
|
"Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED,
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import { DELIM_OPTIONS } from "../lib/Delim.mjs";
|
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A1Z26 Cipher Decode operation
|
* A1Z26 Cipher Decode operation
|
||||||
*/
|
*/
|
||||||
class A1Z26CipherDecode extends Operation {
|
class A1Z26CipherDecode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A1Z26CipherDecode constructor
|
* A1Z26CipherDecode constructor
|
||||||
*/
|
*/
|
||||||
|
@ -21,8 +22,7 @@ class A1Z26CipherDecode extends Operation {
|
||||||
|
|
||||||
this.name = "A1Z26 Cipher Decode";
|
this.name = "A1Z26 Cipher Decode";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "Converts alphabet order numbers into their corresponding alphabet character.<br><br>e.g. <code>1</code> becomes <code>a</code> and <code>2</code> becomes <code>b</code>.";
|
||||||
"Converts alphabet order numbers into their corresponding alphabet character.<br><br>e.g. <code>1</code> becomes <code>a</code> and <code>2</code> becomes <code>b</code>.";
|
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -30,40 +30,40 @@ class A1Z26CipherDecode extends Operation {
|
||||||
{
|
{
|
||||||
name: "Delimiter",
|
name: "Delimiter",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: DELIM_OPTIONS,
|
value: DELIM_OPTIONS
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
this.checks = [
|
this.checks = [
|
||||||
{
|
{
|
||||||
pattern: "^\\s*([12]?[0-9] )+[12]?[0-9]\\s*$",
|
pattern: "^\\s*([12]?[0-9] )+[12]?[0-9]\\s*$",
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["Space"],
|
args: ["Space"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "^\\s*([12]?[0-9],)+[12]?[0-9]\\s*$",
|
pattern: "^\\s*([12]?[0-9],)+[12]?[0-9]\\s*$",
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["Comma"],
|
args: ["Comma"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "^\\s*([12]?[0-9];)+[12]?[0-9]\\s*$",
|
pattern: "^\\s*([12]?[0-9];)+[12]?[0-9]\\s*$",
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["Semi-colon"],
|
args: ["Semi-colon"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "^\\s*([12]?[0-9]:)+[12]?[0-9]\\s*$",
|
pattern: "^\\s*([12]?[0-9]:)+[12]?[0-9]\\s*$",
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["Colon"],
|
args: ["Colon"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "^\\s*([12]?[0-9]\\n)+[12]?[0-9]\\s*$",
|
pattern: "^\\s*([12]?[0-9]\\n)+[12]?[0-9]\\s*$",
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["Line feed"],
|
args: ["Line feed"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "^\\s*([12]?[0-9]\\r\\n)+[12]?[0-9]\\s*$",
|
pattern: "^\\s*([12]?[0-9]\\r\\n)+[12]?[0-9]\\s*$",
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["CRLF"],
|
args: ["CRLF"]
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +83,13 @@ class A1Z26CipherDecode extends Operation {
|
||||||
let latin1 = "";
|
let latin1 = "";
|
||||||
for (let i = 0; i < bites.length; i++) {
|
for (let i = 0; i < bites.length; i++) {
|
||||||
if (bites[i] < 1 || bites[i] > 26) {
|
if (bites[i] < 1 || bites[i] > 26) {
|
||||||
throw new OperationError(
|
throw new OperationError("Error: all numbers must be between 1 and 26.");
|
||||||
"Error: all numbers must be between 1 and 26.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
|
latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
|
||||||
}
|
}
|
||||||
return latin1;
|
return latin1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default A1Z26CipherDecode;
|
export default A1Z26CipherDecode;
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import { DELIM_OPTIONS } from "../lib/Delim.mjs";
|
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A1Z26 Cipher Encode operation
|
* A1Z26 Cipher Encode operation
|
||||||
*/
|
*/
|
||||||
class A1Z26CipherEncode extends Operation {
|
class A1Z26CipherEncode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A1Z26CipherEncode constructor
|
* A1Z26CipherEncode constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,8 +21,7 @@ class A1Z26CipherEncode extends Operation {
|
||||||
|
|
||||||
this.name = "A1Z26 Cipher Encode";
|
this.name = "A1Z26 Cipher Encode";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "Converts alphabet characters into their corresponding alphabet order number.<br><br>e.g. <code>a</code> becomes <code>1</code> and <code>b</code> becomes <code>2</code>.<br><br>Non-alphabet characters are dropped.";
|
||||||
"Converts alphabet characters into their corresponding alphabet order number.<br><br>e.g. <code>a</code> becomes <code>1</code> and <code>b</code> becomes <code>2</code>.<br><br>Non-alphabet characters are dropped.";
|
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -29,8 +29,8 @@ class A1Z26CipherEncode extends Operation {
|
||||||
{
|
{
|
||||||
name: "Delimiter",
|
name: "Delimiter",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: DELIM_OPTIONS,
|
value: DELIM_OPTIONS
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ class A1Z26CipherEncode extends Operation {
|
||||||
}
|
}
|
||||||
return output.slice(0, -delim.length);
|
return output.slice(0, -delim.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default A1Z26CipherEncode;
|
export default A1Z26CipherEncode;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { bitOp, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs";
|
||||||
* ADD operation
|
* ADD operation
|
||||||
*/
|
*/
|
||||||
class ADD extends Operation {
|
class ADD extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ADD constructor
|
* ADD constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,19 +21,17 @@ class ADD extends Operation {
|
||||||
|
|
||||||
this.name = "ADD";
|
this.name = "ADD";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description =
|
this.description = "ADD the input with the given key (e.g. <code>fe023da5</code>), MOD 255";
|
||||||
"ADD the input with the given key (e.g. <code>fe023da5</code>), MOD 255";
|
this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#Bitwise_operators";
|
||||||
this.infoURL =
|
|
||||||
"https://wikipedia.org/wiki/Bitwise_operation#Bitwise_operators";
|
|
||||||
this.inputType = "byteArray";
|
this.inputType = "byteArray";
|
||||||
this.outputType = "byteArray";
|
this.outputType = "byteArray";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Key",
|
"name": "Key",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: BITWISE_OP_DELIMS,
|
"toggleValues": BITWISE_OP_DELIMS
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +41,7 @@ class ADD extends Operation {
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const key = Utils.convertToByteArray(
|
const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
|
||||||
args[0].string || "",
|
|
||||||
args[0].option,
|
|
||||||
);
|
|
||||||
|
|
||||||
return bitOp(input, key, add);
|
return bitOp(input, key, add);
|
||||||
}
|
}
|
||||||
|
@ -75,6 +71,7 @@ class ADD extends Operation {
|
||||||
highlightReverse(pos, args) {
|
highlightReverse(pos, args) {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ADD;
|
export default ADD;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* AES Decrypt operation
|
* AES Decrypt operation
|
||||||
*/
|
*/
|
||||||
class AESDecrypt extends Operation {
|
class AESDecrypt extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AESDecrypt constructor
|
* AESDecrypt constructor
|
||||||
*/
|
*/
|
||||||
|
@ -21,85 +22,83 @@ class AESDecrypt extends Operation {
|
||||||
|
|
||||||
this.name = "AES Decrypt";
|
this.name = "AES Decrypt";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul><br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.<br><br><b>GCM Tag:</b> This field is ignored unless 'GCM' mode is used.";
|
||||||
"Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul><br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.<br><br><b>GCM Tag:</b> This field is ignored unless 'GCM' mode is used.";
|
this.infoURL = "https://wikipedia.org/wiki/Advanced_Encryption_Standard";
|
||||||
this.infoURL =
|
|
||||||
"https://wikipedia.org/wiki/Advanced_Encryption_Standard";
|
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Key",
|
"name": "Key",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "IV",
|
"name": "IV",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mode",
|
"name": "Mode",
|
||||||
type: "argSelector",
|
"type": "argSelector",
|
||||||
value: [
|
"value": [
|
||||||
{
|
{
|
||||||
name: "CBC",
|
name: "CBC",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CFB",
|
name: "CFB",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OFB",
|
name: "OFB",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CTR",
|
name: "CTR",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GCM",
|
name: "GCM",
|
||||||
on: [5, 6],
|
on: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ECB",
|
name: "ECB",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CBC/NoPadding",
|
name: "CBC/NoPadding",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ECB/NoPadding",
|
name: "ECB/NoPadding",
|
||||||
off: [5, 6],
|
off: [5, 6]
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Input",
|
"name": "Input",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Hex", "Raw"],
|
"value": ["Hex", "Raw"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Output",
|
"name": "Output",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Raw", "Hex"],
|
"value": ["Raw", "Hex"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GCM Tag",
|
"name": "GCM Tag",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Additional Authenticated Data",
|
"name": "Additional Authenticated Data",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +134,7 @@ The following algorithms will be used based on the size of the key:
|
||||||
|
|
||||||
/* Allow for a "no padding" mode */
|
/* Allow for a "no padding" mode */
|
||||||
if (noPadding) {
|
if (noPadding) {
|
||||||
decipher.mode.unpad = function (output, options) {
|
decipher.mode.unpad = function(output, options) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -143,21 +142,18 @@ The following algorithms will be used based on the size of the key:
|
||||||
decipher.start({
|
decipher.start({
|
||||||
iv: iv.length === 0 ? "" : iv,
|
iv: iv.length === 0 ? "" : iv,
|
||||||
tag: mode === "GCM" ? gcmTag : undefined,
|
tag: mode === "GCM" ? gcmTag : undefined,
|
||||||
additionalData: mode === "GCM" ? aad : undefined,
|
additionalData: mode === "GCM" ? aad : undefined
|
||||||
});
|
});
|
||||||
decipher.update(forge.util.createBuffer(input));
|
decipher.update(forge.util.createBuffer(input));
|
||||||
const result = decipher.finish();
|
const result = decipher.finish();
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return outputType === "Hex"
|
return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes();
|
||||||
? decipher.output.toHex()
|
|
||||||
: decipher.output.getBytes();
|
|
||||||
} else {
|
} else {
|
||||||
throw new OperationError(
|
throw new OperationError("Unable to decrypt input with these parameters.");
|
||||||
"Unable to decrypt input with these parameters.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AESDecrypt;
|
export default AESDecrypt;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* AES Encrypt operation
|
* AES Encrypt operation
|
||||||
*/
|
*/
|
||||||
class AESEncrypt extends Operation {
|
class AESEncrypt extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AESEncrypt constructor
|
* AESEncrypt constructor
|
||||||
*/
|
*/
|
||||||
|
@ -21,71 +22,69 @@ class AESEncrypt extends Operation {
|
||||||
|
|
||||||
this.name = "AES Encrypt";
|
this.name = "AES Encrypt";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
|
||||||
"Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
|
this.infoURL = "https://wikipedia.org/wiki/Advanced_Encryption_Standard";
|
||||||
this.infoURL =
|
|
||||||
"https://wikipedia.org/wiki/Advanced_Encryption_Standard";
|
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Key",
|
"name": "Key",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "IV",
|
"name": "IV",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mode",
|
"name": "Mode",
|
||||||
type: "argSelector",
|
"type": "argSelector",
|
||||||
value: [
|
"value": [
|
||||||
{
|
{
|
||||||
name: "CBC",
|
name: "CBC",
|
||||||
off: [5],
|
off: [5]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CFB",
|
name: "CFB",
|
||||||
off: [5],
|
off: [5]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OFB",
|
name: "OFB",
|
||||||
off: [5],
|
off: [5]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CTR",
|
name: "CTR",
|
||||||
off: [5],
|
off: [5]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GCM",
|
name: "GCM",
|
||||||
on: [5],
|
on: [5]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ECB",
|
name: "ECB",
|
||||||
off: [5],
|
off: [5]
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Input",
|
"name": "Input",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Raw", "Hex"],
|
"value": ["Raw", "Hex"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Output",
|
"name": "Output",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Hex", "Raw"],
|
"value": ["Hex", "Raw"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Additional Authenticated Data",
|
"name": "Additional Authenticated Data",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,33 +117,26 @@ The following algorithms will be used based on the size of the key:
|
||||||
const cipher = forge.cipher.createCipher("AES-" + mode, key);
|
const cipher = forge.cipher.createCipher("AES-" + mode, key);
|
||||||
cipher.start({
|
cipher.start({
|
||||||
iv: iv,
|
iv: iv,
|
||||||
additionalData: mode === "GCM" ? aad : undefined,
|
additionalData: mode === "GCM" ? aad : undefined
|
||||||
});
|
});
|
||||||
cipher.update(forge.util.createBuffer(input));
|
cipher.update(forge.util.createBuffer(input));
|
||||||
cipher.finish();
|
cipher.finish();
|
||||||
|
|
||||||
if (outputType === "Hex") {
|
if (outputType === "Hex") {
|
||||||
if (mode === "GCM") {
|
if (mode === "GCM") {
|
||||||
return (
|
return cipher.output.toHex() + "\n\n" +
|
||||||
cipher.output.toHex() +
|
"Tag: " + cipher.mode.tag.toHex();
|
||||||
"\n\n" +
|
|
||||||
"Tag: " +
|
|
||||||
cipher.mode.tag.toHex()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return cipher.output.toHex();
|
return cipher.output.toHex();
|
||||||
} else {
|
} else {
|
||||||
if (mode === "GCM") {
|
if (mode === "GCM") {
|
||||||
return (
|
return cipher.output.getBytes() + "\n\n" +
|
||||||
cipher.output.getBytes() +
|
"Tag: " + cipher.mode.tag.getBytes();
|
||||||
"\n\n" +
|
|
||||||
"Tag: " +
|
|
||||||
cipher.mode.tag.getBytes()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return cipher.output.getBytes();
|
return cipher.output.getBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AESEncrypt;
|
export default AESEncrypt;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* AES Key Unwrap operation
|
* AES Key Unwrap operation
|
||||||
*/
|
*/
|
||||||
class AESKeyUnwrap extends Operation {
|
class AESKeyUnwrap extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AESKeyUnwrap constructor
|
* AESKeyUnwrap constructor
|
||||||
*/
|
*/
|
||||||
|
@ -22,33 +23,32 @@ class AESKeyUnwrap extends Operation {
|
||||||
|
|
||||||
this.name = "AES Key Unwrap";
|
this.name = "AES Key Unwrap";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "Decryptor for a key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to decrypt 64-bit blocks.";
|
||||||
"Decryptor for a key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to decrypt 64-bit blocks.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Key (KEK)",
|
"name": "Key (KEK)",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "IV",
|
"name": "IV",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "a6a6a6a6a6a6a6a6",
|
"value": "a6a6a6a6a6a6a6a6",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Input",
|
"name": "Input",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Hex", "Raw"],
|
"value": ["Hex", "Raw"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Output",
|
"name": "Output",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Hex", "Raw"],
|
"value": ["Hex", "Raw"]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -65,24 +65,14 @@ class AESKeyUnwrap extends Operation {
|
||||||
outputType = args[3];
|
outputType = args[3];
|
||||||
|
|
||||||
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||||
throw new OperationError(
|
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||||
"KEK must be either 16, 24, or 32 bytes (currently " +
|
|
||||||
kek.length +
|
|
||||||
" bytes)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (iv.length !== 8) {
|
if (iv.length !== 8) {
|
||||||
throw new OperationError(
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
"IV must be 8 bytes (currently " + iv.length + " bytes)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const inputData = Utils.convertToByteString(input, inputType);
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
if (inputData.length % 8 !== 0 || inputData.length < 24) {
|
if (inputData.length % 8 !== 0 || inputData.length < 24) {
|
||||||
throw new OperationError(
|
throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
|
||||||
"input must be 8n (n>=3) bytes (currently " +
|
|
||||||
inputData.length +
|
|
||||||
" bytes)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
@ -100,8 +90,8 @@ class AESKeyUnwrap extends Operation {
|
||||||
}
|
}
|
||||||
let cntLower = R.length >>> 0;
|
let cntLower = R.length >>> 0;
|
||||||
let cntUpper = (R.length / ((1 << 30) * 4)) >>> 0;
|
let cntUpper = (R.length / ((1 << 30) * 4)) >>> 0;
|
||||||
cntUpper = cntUpper * 6 + (((cntLower * 6) / ((1 << 30) * 4)) >>> 0);
|
cntUpper = cntUpper * 6 + ((cntLower * 6 / ((1 << 30) * 4)) >>> 0);
|
||||||
cntLower = (cntLower * 6) >>> 0;
|
cntLower = cntLower * 6 >>> 0;
|
||||||
for (let j = 5; j >= 0; j--) {
|
for (let j = 5; j >= 0; j--) {
|
||||||
for (let i = R.length - 1; i >= 0; i--) {
|
for (let i = R.length - 1; i >= 0; i--) {
|
||||||
const aBuffer = Utils.strToArrayBuffer(A);
|
const aBuffer = Utils.strToArrayBuffer(A);
|
||||||
|
@ -110,9 +100,7 @@ class AESKeyUnwrap extends Operation {
|
||||||
aView.setUint32(4, aView.getUint32(4) ^ cntLower);
|
aView.setUint32(4, aView.getUint32(4) ^ cntLower);
|
||||||
A = Utils.arrayBufferToStr(aBuffer, false);
|
A = Utils.arrayBufferToStr(aBuffer, false);
|
||||||
decipher.start();
|
decipher.start();
|
||||||
decipher.update(
|
decipher.update(forge.util.createBuffer(A + R[i] + paddingBlock));
|
||||||
forge.util.createBuffer(A + R[i] + paddingBlock),
|
|
||||||
);
|
|
||||||
decipher.finish();
|
decipher.finish();
|
||||||
const B = decipher.output.getBytes();
|
const B = decipher.output.getBytes();
|
||||||
A = B.substring(0, 8);
|
A = B.substring(0, 8);
|
||||||
|
@ -134,6 +122,7 @@ class AESKeyUnwrap extends Operation {
|
||||||
}
|
}
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AESKeyUnwrap;
|
export default AESKeyUnwrap;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* AES Key Wrap operation
|
* AES Key Wrap operation
|
||||||
*/
|
*/
|
||||||
class AESKeyWrap extends Operation {
|
class AESKeyWrap extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AESKeyWrap constructor
|
* AESKeyWrap constructor
|
||||||
*/
|
*/
|
||||||
|
@ -22,33 +23,32 @@ class AESKeyWrap extends Operation {
|
||||||
|
|
||||||
this.name = "AES Key Wrap";
|
this.name = "AES Key Wrap";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "A key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to encrypt 64-bit blocks.";
|
||||||
"A key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to encrypt 64-bit blocks.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Key (KEK)",
|
"name": "Key (KEK)",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "IV",
|
"name": "IV",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "a6a6a6a6a6a6a6a6",
|
"value": "a6a6a6a6a6a6a6a6",
|
||||||
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"],
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Input",
|
"name": "Input",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Hex", "Raw"],
|
"value": ["Hex", "Raw"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Output",
|
"name": "Output",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Hex", "Raw"],
|
"value": ["Hex", "Raw"]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -65,24 +65,14 @@ class AESKeyWrap extends Operation {
|
||||||
outputType = args[3];
|
outputType = args[3];
|
||||||
|
|
||||||
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||||
throw new OperationError(
|
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||||
"KEK must be either 16, 24, or 32 bytes (currently " +
|
|
||||||
kek.length +
|
|
||||||
" bytes)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (iv.length !== 8) {
|
if (iv.length !== 8) {
|
||||||
throw new OperationError(
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
"IV must be 8 bytes (currently " + iv.length + " bytes)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const inputData = Utils.convertToByteString(input, inputType);
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
||||||
throw new OperationError(
|
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
|
||||||
"input must be 8n (n>=2) bytes (currently " +
|
|
||||||
inputData.length +
|
|
||||||
" bytes)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
@ -92,8 +82,7 @@ class AESKeyWrap extends Operation {
|
||||||
for (let i = 0; i < inputData.length; i += 8) {
|
for (let i = 0; i < inputData.length; i += 8) {
|
||||||
R.push(inputData.substring(i, i + 8));
|
R.push(inputData.substring(i, i + 8));
|
||||||
}
|
}
|
||||||
let cntLower = 1,
|
let cntLower = 1, cntUpper = 0;
|
||||||
cntUpper = 0;
|
|
||||||
for (let j = 0; j < 6; j++) {
|
for (let j = 0; j < 6; j++) {
|
||||||
for (let i = 0; i < R.length; i++) {
|
for (let i = 0; i < R.length; i++) {
|
||||||
cipher.start();
|
cipher.start();
|
||||||
|
@ -120,6 +109,7 @@ class AESKeyWrap extends Operation {
|
||||||
}
|
}
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AESKeyWrap;
|
export default AESKeyWrap;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { AMF0, AMF3 } from "@astronautlabs/amf";
|
||||||
* AMF Decode operation
|
* AMF Decode operation
|
||||||
*/
|
*/
|
||||||
class AMFDecode extends Operation {
|
class AMFDecode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AMFDecode constructor
|
* AMFDecode constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,8 +21,7 @@ class AMFDecode extends Operation {
|
||||||
|
|
||||||
this.name = "AMF Decode";
|
this.name = "AMF Decode";
|
||||||
this.module = "Encodings";
|
this.module = "Encodings";
|
||||||
this.description =
|
this.description = "Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
||||||
"Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "JSON";
|
this.outputType = "JSON";
|
||||||
|
@ -30,8 +30,8 @@ class AMFDecode extends Operation {
|
||||||
name: "Format",
|
name: "Format",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["AMF0", "AMF3"],
|
value: ["AMF0", "AMF3"],
|
||||||
defaultIndex: 1,
|
defaultIndex: 1
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ class AMFDecode extends Operation {
|
||||||
const encoded = new Uint8Array(input);
|
const encoded = new Uint8Array(input);
|
||||||
return handler.Value.deserialize(encoded);
|
return handler.Value.deserialize(encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AMFDecode;
|
export default AMFDecode;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { AMF0, AMF3 } from "@astronautlabs/amf";
|
||||||
* AMF Encode operation
|
* AMF Encode operation
|
||||||
*/
|
*/
|
||||||
class AMFEncode extends Operation {
|
class AMFEncode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AMFEncode constructor
|
* AMFEncode constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,8 +21,7 @@ class AMFEncode extends Operation {
|
||||||
|
|
||||||
this.name = "AMF Encode";
|
this.name = "AMF Encode";
|
||||||
this.module = "Encodings";
|
this.module = "Encodings";
|
||||||
this.description =
|
this.description = "Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
||||||
"Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
||||||
this.inputType = "JSON";
|
this.inputType = "JSON";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
|
@ -30,8 +30,8 @@ class AMFEncode extends Operation {
|
||||||
name: "Format",
|
name: "Format",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["AMF0", "AMF3"],
|
value: ["AMF0", "AMF3"],
|
||||||
defaultIndex: 1,
|
defaultIndex: 1
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ class AMFEncode extends Operation {
|
||||||
const output = handler.Value.any(input).serialize();
|
const output = handler.Value.any(input).serialize();
|
||||||
return output.buffer;
|
return output.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AMFEncode;
|
export default AMFEncode;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { bitOp, and, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs";
|
||||||
* AND operation
|
* AND operation
|
||||||
*/
|
*/
|
||||||
class AND extends Operation {
|
class AND extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AND constructor
|
* AND constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,18 +21,17 @@ class AND extends Operation {
|
||||||
|
|
||||||
this.name = "AND";
|
this.name = "AND";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description =
|
this.description = "AND the input with the given key.<br>e.g. <code>fe023da5</code>";
|
||||||
"AND the input with the given key.<br>e.g. <code>fe023da5</code>";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#AND";
|
this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#AND";
|
||||||
this.inputType = "byteArray";
|
this.inputType = "byteArray";
|
||||||
this.outputType = "byteArray";
|
this.outputType = "byteArray";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Key",
|
"name": "Key",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "",
|
"value": "",
|
||||||
toggleValues: BITWISE_OP_DELIMS,
|
"toggleValues": BITWISE_OP_DELIMS
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +41,7 @@ class AND extends Operation {
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const key = Utils.convertToByteArray(
|
const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
|
||||||
args[0].string || "",
|
|
||||||
args[0].option,
|
|
||||||
);
|
|
||||||
|
|
||||||
return bitOp(input, key, and);
|
return bitOp(input, key, and);
|
||||||
}
|
}
|
||||||
|
@ -74,6 +71,7 @@ class AND extends Operation {
|
||||||
highlightReverse(pos, args) {
|
highlightReverse(pos, args) {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AND;
|
export default AND;
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Operation from "../Operation.mjs";
|
||||||
* Add line numbers operation
|
* Add line numbers operation
|
||||||
*/
|
*/
|
||||||
class AddLineNumbers extends Operation {
|
class AddLineNumbers extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AddLineNumbers constructor
|
* AddLineNumbers constructor
|
||||||
*/
|
*/
|
||||||
|
@ -35,11 +36,11 @@ class AddLineNumbers extends Operation {
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
for (let n = 0; n < lines.length; n++) {
|
for (let n = 0; n < lines.length; n++) {
|
||||||
output +=
|
output += (n+1).toString().padStart(width, " ") + " " + lines[n] + "\n";
|
||||||
(n + 1).toString().padStart(width, " ") + " " + lines[n] + "\n";
|
|
||||||
}
|
}
|
||||||
return output.slice(0, output.length - 1);
|
return output.slice(0, output.length-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddLineNumbers;
|
export default AddLineNumbers;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import jimp from "jimp";
|
||||||
* Add Text To Image operation
|
* Add Text To Image operation
|
||||||
*/
|
*/
|
||||||
class AddTextToImage extends Operation {
|
class AddTextToImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AddTextToImage constructor
|
* AddTextToImage constructor
|
||||||
*/
|
*/
|
||||||
|
@ -23,8 +24,7 @@ class AddTextToImage extends Operation {
|
||||||
|
|
||||||
this.name = "Add Text To Image";
|
this.name = "Add Text To Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description =
|
this.description = "Adds text onto an image.<br><br>Text can be horizontally or vertically aligned, or the position can be manually specified.<br>Variants of the Roboto font face are available in any size or colour.";
|
||||||
"Adds text onto an image.<br><br>Text can be horizontally or vertically aligned, or the position can be manually specified.<br>Variants of the Roboto font face are available in any size or colour.";
|
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
|
@ -33,67 +33,72 @@ class AddTextToImage extends Operation {
|
||||||
{
|
{
|
||||||
name: "Text",
|
name: "Text",
|
||||||
type: "string",
|
type: "string",
|
||||||
value: "",
|
value: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Horizontal align",
|
name: "Horizontal align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["None", "Left", "Center", "Right"],
|
value: ["None", "Left", "Center", "Right"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Vertical align",
|
name: "Vertical align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["None", "Top", "Middle", "Bottom"],
|
value: ["None", "Top", "Middle", "Bottom"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "X position",
|
name: "X position",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Y position",
|
name: "Y position",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Size",
|
name: "Size",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 32,
|
value: 32,
|
||||||
min: 8,
|
min: 8
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Font face",
|
name: "Font face",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["Roboto", "Roboto Black", "Roboto Mono", "Roboto Slab"],
|
value: [
|
||||||
|
"Roboto",
|
||||||
|
"Roboto Black",
|
||||||
|
"Roboto Mono",
|
||||||
|
"Roboto Slab"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Red",
|
name: "Red",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255,
|
max: 255
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Green",
|
name: "Green",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255,
|
max: 255
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Blue",
|
name: "Blue",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255,
|
max: 255
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Alpha",
|
name: "Alpha",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255,
|
max: 255
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,51 +137,35 @@ class AddTextToImage extends Operation {
|
||||||
|
|
||||||
const fontsMap = {};
|
const fontsMap = {};
|
||||||
const fonts = [
|
const fonts = [
|
||||||
import(
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.fnt"),
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.fnt"
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.fnt"),
|
||||||
),
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.fnt"),
|
||||||
import(
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.fnt")
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.fnt"
|
|
||||||
),
|
|
||||||
import(
|
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.fnt"
|
|
||||||
),
|
|
||||||
import(
|
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.fnt"
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(fonts).then((fonts) => {
|
await Promise.all(fonts)
|
||||||
|
.then(fonts => {
|
||||||
fontsMap.Roboto = fonts[0];
|
fontsMap.Roboto = fonts[0];
|
||||||
fontsMap["Roboto Black"] = fonts[1];
|
fontsMap["Roboto Black"] = fonts[1];
|
||||||
fontsMap["Roboto Mono"] = fonts[2];
|
fontsMap["Roboto Mono"] = fonts[2];
|
||||||
fontsMap["Roboto Slab"] = fonts[3];
|
fontsMap["Roboto Slab"] = fonts[3];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Make Webpack load the png font images
|
// Make Webpack load the png font images
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
import(
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.png"),
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.png"
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.png"),
|
||||||
),
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.png"),
|
||||||
import(
|
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.png")
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.png"
|
|
||||||
),
|
|
||||||
import(
|
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.png"
|
|
||||||
),
|
|
||||||
import(
|
|
||||||
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.png"
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const font = fontsMap[fontFace];
|
const font = fontsMap[fontFace];
|
||||||
|
|
||||||
// LoadFont needs an absolute url, so append the font name to self.docURL
|
// LoadFont needs an absolute url, so append the font name to self.docURL
|
||||||
const jimpFont = await jimp.loadFont(
|
const jimpFont = await jimp.loadFont(self.docURL + "/" + font.default);
|
||||||
self.docURL + "/" + font.default,
|
|
||||||
);
|
|
||||||
|
|
||||||
jimpFont.pages.forEach(function (page) {
|
jimpFont.pages.forEach(function(page) {
|
||||||
if (page.bitmap) {
|
if (page.bitmap) {
|
||||||
// Adjust the RGB values of the image pages to change the font colour.
|
// Adjust the RGB values of the image pages to change the font colour.
|
||||||
const pageWidth = page.bitmap.width;
|
const pageWidth = page.bitmap.width;
|
||||||
|
@ -186,31 +175,22 @@ class AddTextToImage extends Operation {
|
||||||
const idx = (iy * pageWidth + ix) << 2;
|
const idx = (iy * pageWidth + ix) << 2;
|
||||||
|
|
||||||
const newRed = page.bitmap.data[idx] - (255 - red);
|
const newRed = page.bitmap.data[idx] - (255 - red);
|
||||||
const newGreen =
|
const newGreen = page.bitmap.data[idx + 1] - (255 - green);
|
||||||
page.bitmap.data[idx + 1] - (255 - green);
|
const newBlue = page.bitmap.data[idx + 2] - (255 - blue);
|
||||||
const newBlue =
|
const newAlpha = page.bitmap.data[idx + 3] - (255 - alpha);
|
||||||
page.bitmap.data[idx + 2] - (255 - blue);
|
|
||||||
const newAlpha =
|
|
||||||
page.bitmap.data[idx + 3] - (255 - alpha);
|
|
||||||
|
|
||||||
// Make sure the bitmap values don't go below 0 as that makes jimp very unhappy
|
// Make sure the bitmap values don't go below 0 as that makes jimp very unhappy
|
||||||
page.bitmap.data[idx] = newRed > 0 ? newRed : 0;
|
page.bitmap.data[idx] = (newRed > 0) ? newRed : 0;
|
||||||
page.bitmap.data[idx + 1] =
|
page.bitmap.data[idx + 1] = (newGreen > 0) ? newGreen : 0;
|
||||||
newGreen > 0 ? newGreen : 0;
|
page.bitmap.data[idx + 2] = (newBlue > 0) ? newBlue : 0;
|
||||||
page.bitmap.data[idx + 2] =
|
page.bitmap.data[idx + 3] = (newAlpha > 0) ? newAlpha : 0;
|
||||||
newBlue > 0 ? newBlue : 0;
|
|
||||||
page.bitmap.data[idx + 3] =
|
|
||||||
newAlpha > 0 ? newAlpha : 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a temporary image to hold the rendered text
|
// Create a temporary image to hold the rendered text
|
||||||
const textImage = new jimp(
|
const textImage = new jimp(jimp.measureText(jimpFont, text), jimp.measureTextHeight(jimpFont, text));
|
||||||
jimp.measureText(jimpFont, text),
|
|
||||||
jimp.measureTextHeight(jimpFont, text),
|
|
||||||
);
|
|
||||||
textImage.print(jimpFont, 0, 0, text);
|
textImage.print(jimpFont, 0, 0, text);
|
||||||
|
|
||||||
// Scale the rendered text image to the correct size
|
// Scale the rendered text image to the correct size
|
||||||
|
@ -230,7 +210,7 @@ class AddTextToImage extends Operation {
|
||||||
xPos = 0;
|
xPos = 0;
|
||||||
break;
|
break;
|
||||||
case "Center":
|
case "Center":
|
||||||
xPos = image.getWidth() / 2 - textImage.getWidth() / 2;
|
xPos = (image.getWidth() / 2) - (textImage.getWidth() / 2);
|
||||||
break;
|
break;
|
||||||
case "Right":
|
case "Right":
|
||||||
xPos = image.getWidth() - textImage.getWidth();
|
xPos = image.getWidth() - textImage.getWidth();
|
||||||
|
@ -242,7 +222,7 @@ class AddTextToImage extends Operation {
|
||||||
yPos = 0;
|
yPos = 0;
|
||||||
break;
|
break;
|
||||||
case "Middle":
|
case "Middle":
|
||||||
yPos = image.getHeight() / 2 - textImage.getHeight() / 2;
|
yPos = (image.getHeight() / 2) - (textImage.getHeight() / 2);
|
||||||
break;
|
break;
|
||||||
case "Bottom":
|
case "Bottom":
|
||||||
yPos = image.getHeight() - textImage.getHeight();
|
yPos = image.getHeight() - textImage.getHeight();
|
||||||
|
@ -281,6 +261,7 @@ class AddTextToImage extends Operation {
|
||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddTextToImage;
|
export default AddTextToImage;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Utils from "../Utils.mjs";
|
||||||
* Adler-32 Checksum operation
|
* Adler-32 Checksum operation
|
||||||
*/
|
*/
|
||||||
class Adler32Checksum extends Operation {
|
class Adler32Checksum extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adler32Checksum constructor
|
* Adler32Checksum constructor
|
||||||
*/
|
*/
|
||||||
|
@ -19,8 +20,7 @@ class Adler32Checksum extends Operation {
|
||||||
|
|
||||||
this.name = "Adler-32 Checksum";
|
this.name = "Adler-32 Checksum";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description =
|
this.description = "Adler-32 is a checksum algorithm which was invented by Mark Adler in 1995, and is a modification of the Fletcher checksum. Compared to a cyclic redundancy check of the same length, it trades reliability for speed (preferring the latter).<br><br>Adler-32 is more reliable than Fletcher-16, and slightly less reliable than Fletcher-32.";
|
||||||
"Adler-32 is a checksum algorithm which was invented by Mark Adler in 1995, and is a modification of the Fletcher checksum. Compared to a cyclic redundancy check of the same length, it trades reliability for speed (preferring the latter).<br><br>Adler-32 is more reliable than Fletcher-16, and slightly less reliable than Fletcher-32.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Adler-32";
|
this.infoURL = "https://wikipedia.org/wiki/Adler-32";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -48,6 +48,7 @@ class Adler32Checksum extends Operation {
|
||||||
|
|
||||||
return Utils.hex(((b << 16) | a) >>> 0, 8);
|
return Utils.hex(((b << 16) | a) >>> 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Adler32Checksum;
|
export default Adler32Checksum;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* Affine Cipher Decode operation
|
* Affine Cipher Decode operation
|
||||||
*/
|
*/
|
||||||
class AffineCipherDecode extends Operation {
|
class AffineCipherDecode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AffineCipherDecode constructor
|
* AffineCipherDecode constructor
|
||||||
*/
|
*/
|
||||||
|
@ -20,22 +21,21 @@ class AffineCipherDecode extends Operation {
|
||||||
|
|
||||||
this.name = "Affine Cipher Decode";
|
this.name = "Affine Cipher Decode";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "The Affine cipher is a type of monoalphabetic substitution cipher. To decrypt, each letter in an alphabet is mapped to its numeric equivalent, decrypted by a mathematical function, and converted back to a letter.";
|
||||||
"The Affine cipher is a type of monoalphabetic substitution cipher. To decrypt, each letter in an alphabet is mapped to its numeric equivalent, decrypted by a mathematical function, and converted back to a letter.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Affine_cipher";
|
this.infoURL = "https://wikipedia.org/wiki/Affine_cipher";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "a",
|
"name": "a",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 1,
|
"value": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "b",
|
"name": "b",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 0,
|
"value": 0
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,9 +53,7 @@ class AffineCipherDecode extends Operation {
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
|
if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
|
||||||
throw new OperationError(
|
throw new OperationError("The values of a and b can only be integers.");
|
||||||
"The values of a and b can only be integers.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.gcd(a, 26) !== 1) {
|
if (Utils.gcd(a, 26) !== 1) {
|
||||||
|
@ -65,23 +63,10 @@ class AffineCipherDecode extends Operation {
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
if (alphabet.indexOf(input[i]) >= 0) {
|
if (alphabet.indexOf(input[i]) >= 0) {
|
||||||
// Uses the affine decode function (y-b * A') % m = x (where m is length of the alphabet and A' is modular inverse)
|
// Uses the affine decode function (y-b * A') % m = x (where m is length of the alphabet and A' is modular inverse)
|
||||||
output +=
|
output += alphabet[Utils.mod((alphabet.indexOf(input[i]) - b) * aModInv, 26)];
|
||||||
alphabet[
|
|
||||||
Utils.mod(
|
|
||||||
(alphabet.indexOf(input[i]) - b) * aModInv,
|
|
||||||
26,
|
|
||||||
)
|
|
||||||
];
|
|
||||||
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
|
||||||
// Same as above, accounting for uppercase
|
// Same as above, accounting for uppercase
|
||||||
output +=
|
output += alphabet[Utils.mod((alphabet.indexOf(input[i].toLowerCase()) - b) * aModInv, 26)].toUpperCase();
|
||||||
alphabet[
|
|
||||||
Utils.mod(
|
|
||||||
(alphabet.indexOf(input[i].toLowerCase()) - b) *
|
|
||||||
aModInv,
|
|
||||||
26,
|
|
||||||
)
|
|
||||||
].toUpperCase();
|
|
||||||
} else {
|
} else {
|
||||||
// Non-alphabetic characters
|
// Non-alphabetic characters
|
||||||
output += input[i];
|
output += input[i];
|
||||||
|
@ -115,6 +100,7 @@ class AffineCipherDecode extends Operation {
|
||||||
highlightReverse(pos, args) {
|
highlightReverse(pos, args) {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AffineCipherDecode;
|
export default AffineCipherDecode;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { affineEncode } from "../lib/Ciphers.mjs";
|
||||||
* Affine Cipher Encode operation
|
* Affine Cipher Encode operation
|
||||||
*/
|
*/
|
||||||
class AffineCipherEncode extends Operation {
|
class AffineCipherEncode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AffineCipherEncode constructor
|
* AffineCipherEncode constructor
|
||||||
*/
|
*/
|
||||||
|
@ -19,22 +20,21 @@ class AffineCipherEncode extends Operation {
|
||||||
|
|
||||||
this.name = "Affine Cipher Encode";
|
this.name = "Affine Cipher Encode";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description =
|
this.description = "The Affine cipher is a type of monoalphabetic substitution cipher, wherein each letter in an alphabet is mapped to its numeric equivalent, encrypted using simple mathematical function, <code>(ax + b) % 26</code>, and converted back to a letter.";
|
||||||
"The Affine cipher is a type of monoalphabetic substitution cipher, wherein each letter in an alphabet is mapped to its numeric equivalent, encrypted using simple mathematical function, <code>(ax + b) % 26</code>, and converted back to a letter.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Affine_cipher";
|
this.infoURL = "https://wikipedia.org/wiki/Affine_cipher";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "a",
|
"name": "a",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 1,
|
"value": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "b",
|
"name": "b",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 0,
|
"value": 0
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ class AffineCipherEncode extends Operation {
|
||||||
highlightReverse(pos, args) {
|
highlightReverse(pos, args) {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AffineCipherEncode;
|
export default AffineCipherEncode;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import OperationError from "../errors/OperationError.mjs";
|
||||||
* Analyse hash operation
|
* Analyse hash operation
|
||||||
*/
|
*/
|
||||||
class AnalyseHash extends Operation {
|
class AnalyseHash extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AnalyseHash constructor
|
* AnalyseHash constructor
|
||||||
*/
|
*/
|
||||||
|
@ -19,10 +20,8 @@ class AnalyseHash extends Operation {
|
||||||
|
|
||||||
this.name = "Analyse hash";
|
this.name = "Analyse hash";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description =
|
this.description = "Tries to determine information about a given hash and suggests which algorithm may have been used to generate it based on its length.";
|
||||||
"Tries to determine information about a given hash and suggests which algorithm may have been used to generate it based on its length.";
|
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
|
||||||
this.infoURL =
|
|
||||||
"https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
|
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [];
|
this.args = [];
|
||||||
|
@ -45,16 +44,9 @@ class AnalyseHash extends Operation {
|
||||||
throw new OperationError("Invalid hash");
|
throw new OperationError("Invalid hash");
|
||||||
}
|
}
|
||||||
|
|
||||||
output +=
|
output += "Hash length: " + input.length + "\n" +
|
||||||
"Hash length: " +
|
"Byte length: " + byteLength + "\n" +
|
||||||
input.length +
|
"Bit length: " + bitLength + "\n\n" +
|
||||||
"\n" +
|
|
||||||
"Byte length: " +
|
|
||||||
byteLength +
|
|
||||||
"\n" +
|
|
||||||
"Bit length: " +
|
|
||||||
bitLength +
|
|
||||||
"\n\n" +
|
|
||||||
"Based on the length, this hash could have been generated by one of the following hashing functions:\n";
|
"Based on the length, this hash could have been generated by one of the following hashing functions:\n";
|
||||||
|
|
||||||
switch (bitLength) {
|
switch (bitLength) {
|
||||||
|
@ -66,21 +58,31 @@ class AnalyseHash extends Operation {
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
possibleHashFunctions = ["Fletcher-8"];
|
possibleHashFunctions = [
|
||||||
|
"Fletcher-8",
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
possibleHashFunctions = [
|
possibleHashFunctions = [
|
||||||
"BSD checksum",
|
"BSD checksum",
|
||||||
"CRC-16",
|
"CRC-16",
|
||||||
"SYSV checksum",
|
"SYSV checksum",
|
||||||
"Fletcher-16",
|
"Fletcher-16"
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
possibleHashFunctions = ["CRC-32", "Fletcher-32", "Adler-32"];
|
possibleHashFunctions = [
|
||||||
|
"CRC-32",
|
||||||
|
"Fletcher-32",
|
||||||
|
"Adler-32",
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
possibleHashFunctions = ["CRC-64", "RIPEMD-64", "SipHash"];
|
possibleHashFunctions = [
|
||||||
|
"CRC-64",
|
||||||
|
"RIPEMD-64",
|
||||||
|
"SipHash",
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
case 128:
|
case 128:
|
||||||
possibleHashFunctions = [
|
possibleHashFunctions = [
|
||||||
|
@ -105,7 +107,10 @@ class AnalyseHash extends Operation {
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case 192:
|
case 192:
|
||||||
possibleHashFunctions = ["Tiger", "HAVAL-192"];
|
possibleHashFunctions = [
|
||||||
|
"Tiger",
|
||||||
|
"HAVAL-192",
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
case 224:
|
case 224:
|
||||||
possibleHashFunctions = [
|
possibleHashFunctions = [
|
||||||
|
@ -132,7 +137,9 @@ class AnalyseHash extends Operation {
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case 320:
|
case 320:
|
||||||
possibleHashFunctions = ["RIPEMD-320"];
|
possibleHashFunctions = [
|
||||||
|
"RIPEMD-320",
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
case 384:
|
case 384:
|
||||||
possibleHashFunctions = [
|
possibleHashFunctions = [
|
||||||
|
@ -158,15 +165,20 @@ class AnalyseHash extends Operation {
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case 1024:
|
case 1024:
|
||||||
possibleHashFunctions = ["Fowler-Noll-Vo"];
|
possibleHashFunctions = [
|
||||||
|
"Fowler-Noll-Vo",
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
possibleHashFunctions = ["Unknown"];
|
possibleHashFunctions = [
|
||||||
|
"Unknown"
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output + possibleHashFunctions.join("\n");
|
return output + possibleHashFunctions.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AnalyseHash;
|
export default AnalyseHash;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import argon2 from "argon2-browser";
|
||||||
* Argon2 operation
|
* Argon2 operation
|
||||||
*/
|
*/
|
||||||
class Argon2 extends Operation {
|
class Argon2 extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argon2 constructor
|
* Argon2 constructor
|
||||||
*/
|
*/
|
||||||
|
@ -21,49 +22,48 @@ class Argon2 extends Operation {
|
||||||
|
|
||||||
this.name = "Argon2";
|
this.name = "Argon2";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description =
|
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.";
|
||||||
"Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Argon2";
|
this.infoURL = "https://wikipedia.org/wiki/Argon2";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Salt",
|
"name": "Salt",
|
||||||
type: "toggleString",
|
"type": "toggleString",
|
||||||
value: "somesalt",
|
"value": "somesalt",
|
||||||
toggleValues: ["UTF8", "Hex", "Base64", "Latin1"],
|
"toggleValues": ["UTF8", "Hex", "Base64", "Latin1"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Iterations",
|
"name": "Iterations",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 3,
|
"value": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Memory (KiB)",
|
"name": "Memory (KiB)",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 4096,
|
"value": 4096
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Parallelism",
|
"name": "Parallelism",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 1,
|
"value": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Hash length (bytes)",
|
"name": "Hash length (bytes)",
|
||||||
type: "number",
|
"type": "number",
|
||||||
value: 32,
|
"value": 32
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Type",
|
"name": "Type",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Argon2i", "Argon2d", "Argon2id"],
|
"value": ["Argon2i", "Argon2d", "Argon2id"],
|
||||||
defaultIndex: 0,
|
"defaultIndex": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Output format",
|
"name": "Output format",
|
||||||
type: "option",
|
"type": "option",
|
||||||
value: ["Encoded hash", "Hex hash", "Raw hash"],
|
"value": ["Encoded hash", "Hex hash", "Raw hash"]
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,15 +74,12 @@ class Argon2 extends Operation {
|
||||||
*/
|
*/
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
const argon2Types = {
|
const argon2Types = {
|
||||||
Argon2i: argon2.ArgonType.Argon2i,
|
"Argon2i": argon2.ArgonType.Argon2i,
|
||||||
Argon2d: argon2.ArgonType.Argon2d,
|
"Argon2d": argon2.ArgonType.Argon2d,
|
||||||
Argon2id: argon2.ArgonType.Argon2id,
|
"Argon2id": argon2.ArgonType.Argon2id
|
||||||
};
|
};
|
||||||
|
|
||||||
const salt = Utils.convertToByteString(
|
const salt = Utils.convertToByteString(args[0].string || "", args[0].option),
|
||||||
args[0].string || "",
|
|
||||||
args[0].option,
|
|
||||||
),
|
|
||||||
time = args[1],
|
time = args[1],
|
||||||
mem = args[2],
|
mem = args[2],
|
||||||
parallelism = args[3],
|
parallelism = args[3],
|
||||||
|
@ -114,6 +111,7 @@ class Argon2 extends Operation {
|
||||||
throw new OperationError(`Error: ${err.message}`);
|
throw new OperationError(`Error: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Argon2;
|
export default Argon2;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import argon2 from "argon2-browser";
|
||||||
* Argon2 compare operation
|
* Argon2 compare operation
|
||||||
*/
|
*/
|
||||||
class Argon2Compare extends Operation {
|
class Argon2Compare extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argon2Compare constructor
|
* Argon2Compare constructor
|
||||||
*/
|
*/
|
||||||
|
@ -19,17 +20,16 @@ class Argon2Compare extends Operation {
|
||||||
|
|
||||||
this.name = "Argon2 compare";
|
this.name = "Argon2 compare";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description =
|
this.description = "Tests whether the input matches the given Argon2 hash. To test multiple possible passwords, use the 'Fork' operation.";
|
||||||
"Tests whether the input matches the given Argon2 hash. To test multiple possible passwords, use the 'Fork' operation.";
|
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Argon2";
|
this.infoURL = "https://wikipedia.org/wiki/Argon2";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Encoded hash",
|
"name": "Encoded hash",
|
||||||
type: "string",
|
"type": "string",
|
||||||
value: "",
|
"value": ""
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class Argon2Compare extends Operation {
|
||||||
try {
|
try {
|
||||||
await argon2.verify({
|
await argon2.verify({
|
||||||
pass: input,
|
pass: input,
|
||||||
encoded,
|
encoded
|
||||||
});
|
});
|
||||||
|
|
||||||
return `Match: ${input}`;
|
return `Match: ${input}`;
|
||||||
|
@ -52,6 +52,7 @@ class Argon2Compare extends Operation {
|
||||||
return "No match";
|
return "No match";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Argon2Compare;
|
export default Argon2Compare;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue