diff --git a/.eslintignore b/.eslintignore index 4277ae0f..1034aa8a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ src/core/lib/** +src/core/config/MetaConfig.js \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index d1d31b73..58dcc8b3 100755 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -97,6 +97,9 @@ "COMPILE_TIME": false, "COMPILE_MSG": false, - "PKG_VERSION": false + "PKG_VERSION": false, + "ENVIRONMENT_IS_WORKER": false, + "ENVIRONMENT_IS_NODE": false, + "ENVIRONMENT_IS_WEB": false } } diff --git a/.gitignore b/.gitignore index deafd4da..79c28325 100755 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ docs/* !docs/*.conf.json !docs/*.ico .vscode +src/core/config/MetaConfig.js \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js index fbb650e2..93e58857 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,8 +1,16 @@ const webpack = require("webpack"); -const ExtractTextPlugin = require("extract-text-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const NodeExternals = require("webpack-node-externals"); const Inliner = require("web-resource-inliner"); +const fs = require("fs"); + +/** + * Grunt configuration for building the app in various formats. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ module.exports = function (grunt) { grunt.file.defaultEncoding = "utf8"; @@ -11,15 +19,15 @@ module.exports = function (grunt) { // Tasks grunt.registerTask("dev", "A persistent task which creates a development build whenever source files are modified.", - ["clean:dev", "webpack:webDev"]); + ["clean:dev", "concurrent:dev"]); grunt.registerTask("node", "Compiles CyberChef into a single NodeJS module.", - ["clean:node", "webpack:node", "chmod:build"]); + ["clean:node", "webpack:metaConf", "webpack:node", "chmod:build"]); grunt.registerTask("test", "A task which runs all the tests in test/tests.", - ["clean:test", "webpack:tests", "execute:test"]); + ["clean:test", "webpack:metaConf", "webpack:tests", "execute:test"]); grunt.registerTask("docs", "Compiles documentation in the /docs directory.", @@ -27,7 +35,7 @@ module.exports = function (grunt) { grunt.registerTask("prod", "Creates a production-ready build. Use the --msg flag to add a compile message.", - ["eslint", "clean:prod", "webpack:webProd", "inline", "chmod"]); + ["eslint", "clean:prod", "webpack:metaConf", "webpack:web", "inline", "chmod"]); grunt.registerTask("default", "Lints the code base", @@ -35,8 +43,10 @@ module.exports = function (grunt) { grunt.registerTask("inline", "Compiles a production build of CyberChef into a single, portable web page.", - runInliner); + ["webpack:webInline", "runInliner", "clean:inlineScripts"]); + + grunt.registerTask("runInliner", runInliner); grunt.registerTask("doc", "docs"); grunt.registerTask("tests", "test"); grunt.registerTask("lint", "eslint"); @@ -52,31 +62,28 @@ module.exports = function (grunt) { grunt.loadNpmTasks("grunt-exec"); grunt.loadNpmTasks("grunt-execute"); grunt.loadNpmTasks("grunt-accessibility"); + grunt.loadNpmTasks("grunt-concurrent"); // Project configuration const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC", - banner = "/**\n" + - "* CyberChef - The Cyber Swiss Army Knife\n" + - "*\n" + - "* @copyright Crown Copyright 2016\n" + - "* @license Apache-2.0\n" + - "*\n" + - "* Copyright 2016 Crown Copyright\n" + - "*\n" + - '* Licensed under the Apache License, Version 2.0 (the "License");\n' + - "* you may not use this file except in compliance with the License.\n" + - "* You may obtain a copy of the License at\n" + - "*\n" + - "* http://www.apache.org/licenses/LICENSE-2.0\n" + - "*\n" + - "* Unless required by applicable law or agreed to in writing, software\n" + - '* distributed under the License is distributed on an "AS IS" BASIS,\n' + - "* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + - "* See the License for the specific language governing permissions and\n" + - "* limitations under the License.\n" + - "*/\n", - pkg = grunt.file.readJSON("package.json"); + pkg = grunt.file.readJSON("package.json"), + webpackConfig = require("./webpack.config.js"), + BUILD_CONSTANTS = { + COMPILE_TIME: JSON.stringify(compileTime), + COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""), + PKG_VERSION: JSON.stringify(pkg.version), + ENVIRONMENT_IS_WORKER: function() { + return typeof importScripts === "function"; + }, + ENVIRONMENT_IS_NODE: function() { + return typeof process === "object" && typeof require === "function"; + }, + ENVIRONMENT_IS_WEB: function() { + return typeof window === "object"; + } + }, + moduleEntryPoints = listEntryModules(); /** * Compiles a production build of CyberChef into a single, portable web page. @@ -105,20 +112,36 @@ module.exports = function (grunt) { }); } + /** + * Generates an entry list for all the modules. + */ + function listEntryModules() { + const path = "./src/core/config/modules/"; + let entryModules = {}; + + fs.readdirSync(path).forEach(file => { + if (file !== "Default.js" && file !== "OpModules.js") + entryModules[file.split(".js")[0]] = path + file; + }); + + return entryModules; + } + grunt.initConfig({ clean: { - dev: ["build/dev/*"], - prod: ["build/prod/*"], - test: ["build/test/*"], - node: ["build/node/*"], + dev: ["build/dev/*", "src/core/config/MetaConfig.js"], + prod: ["build/prod/*", "src/core/config/MetaConfig.js"], + test: ["build/test/*", "src/core/config/MetaConfig.js"], + node: ["build/node/*", "src/core/config/MetaConfig.js"], docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico", "!docs/*.png"], + inlineScripts: ["build/prod/scripts.js"], }, eslint: { options: { configFile: "./.eslintrc.json" }, configs: ["Gruntfile.js"], - core: ["src/core/**/*.js", "!src/core/lib/**/*"], + core: ["src/core/**/*.js", "!src/core/lib/**/*", "!src/core/config/MetaConfig.js"], web: ["src/web/**/*.js"], node: ["src/node/**/*.js"], tests: ["test/**/*.js"], @@ -135,9 +158,16 @@ module.exports = function (grunt) { src: [ "src/**/*.js", "!src/core/lib/**/*", + "!src/core/config/MetaConfig.js" ], } }, + concurrent: { + options: { + logConcurrentOutput: true + }, + dev: ["webpack:metaConfDev", "webpack-dev-server:start"] + }, accessibility: { options: { accessibilityLevel: "WCAG2A", @@ -151,114 +181,47 @@ module.exports = function (grunt) { } }, webpack: { - options: { - plugins: [ - new webpack.ProvidePlugin({ - $: "jquery", - jQuery: "jquery", - moment: "moment-timezone" - }), - new webpack.BannerPlugin({ - banner: banner, - raw: true, - entryOnly: true - }), - new webpack.DefinePlugin({ - COMPILE_TIME: JSON.stringify(compileTime), - COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""), - PKG_VERSION: JSON.stringify(pkg.version) - }), - new ExtractTextPlugin("styles.css"), - ], - resolve: { - alias: { - jquery: "jquery/src/jquery" - } - }, - module: { - rules: [ - { - test: /\.js$/, - exclude: /node_modules/, - loader: "babel-loader?compact=false" - }, - { - test: /\.css$/, - use: ExtractTextPlugin.extract({ - use: [ - { loader: "css-loader?minimize" }, - { loader: "postcss-loader" }, - ] - }) - }, - { - test: /\.less$/, - use: ExtractTextPlugin.extract({ - use: [ - { loader: "css-loader?minimize" }, - { loader: "postcss-loader" }, - { loader: "less-loader" } - ] - }) - }, - { - test: /\.(ico|eot|ttf|woff|woff2)$/, - loader: "url-loader", - options: { - limit: 10000 - } - }, - { // First party images are saved as files to be cached - test: /\.(png|jpg|gif|svg)$/, - exclude: /node_modules/, - loader: "file-loader", - options: { - name: "images/[name].[ext]" - } - }, - { // Third party images are inlined - test: /\.(png|jpg|gif|svg)$/, - exclude: /web\/static/, - loader: "url-loader", - options: { - limit: 10000 - } - }, - ] - }, - stats: { - children: false, - warningsFilter: /source-map/ - }, - node: { - fs: "empty" - } - }, - webDev: { - target: "web", - entry: "./src/web/index.js", + options: webpackConfig, + metaConf: { + target: "node", + entry: "./src/core/config/OperationConfig.js", output: { - filename: "scripts.js", - path: __dirname + "/build/dev" + filename: "MetaConfig.js", + path: __dirname + "/src/core/config/", + library: "MetaConfig", + libraryTarget: "commonjs2", + libraryExport: "default" }, - plugins: [ - new HtmlWebpackPlugin({ - filename: "index.html", - template: "./src/web/html/index.html", - compileTime: compileTime, - version: pkg.version, - }) - ], + externals: [NodeExternals()], + }, + metaConfDev: { + target: "node", + entry: "./src/core/config/OperationConfig.js", + output: { + filename: "MetaConfig.js", + path: __dirname + "/src/core/config/", + library: "MetaConfig", + libraryTarget: "commonjs2", + libraryExport: "default" + }, + externals: [NodeExternals()], watch: true }, - webProd: { + web: { target: "web", - entry: "./src/web/index.js", + entry: Object.assign({ + main: "./src/web/index.js" + }, moduleEntryPoints), output: { - filename: "scripts.js", path: __dirname + "/build/prod" }, + resolve: { + alias: { + "./config/modules/OpModules.js": "./config/modules/Default.js" + } + }, plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS), new webpack.optimize.UglifyJsPlugin({ compress: { "screw_ie8": true, @@ -268,9 +231,10 @@ module.exports = function (grunt) { }, comments: false, }), - new HtmlWebpackPlugin({ // Main version + new HtmlWebpackPlugin({ filename: "index.html", template: "./src/web/html/index.html", + chunks: ["main"], compileTime: compileTime, version: pkg.version, minify: { @@ -280,7 +244,27 @@ module.exports = function (grunt) { minifyCSS: true } }), - new HtmlWebpackPlugin({ // Inline version + ] + }, + webInline: { + target: "web", + entry: "./src/web/index.js", + output: { + filename: "scripts.js", + path: __dirname + "/build/prod" + }, + plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS), + new webpack.optimize.UglifyJsPlugin({ + compress: { + "screw_ie8": true, + "dead_code": true, + "unused": true, + "warnings": false + }, + comments: false, + }), + new HtmlWebpackPlugin({ filename: "cyberchef.htm", template: "./src/web/html/index.html", compileTime: compileTime, @@ -302,7 +286,10 @@ module.exports = function (grunt) { output: { filename: "index.js", path: __dirname + "/build/test" - } + }, + plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS) + ] }, node: { target: "node", @@ -313,6 +300,45 @@ module.exports = function (grunt) { path: __dirname + "/build/node", library: "CyberChef", libraryTarget: "commonjs2" + }, + plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS) + ] + } + }, + "webpack-dev-server": { + options: { + webpack: webpackConfig, + overlay: true, + clientLogLevel: "error", + stats: { + children: false, + chunks: false, + modules: false, + warningsFilter: /source-map/, + } + }, + start: { + webpack: { + target: "web", + entry: Object.assign({ + main: "./src/web/index.js" + }, moduleEntryPoints), + resolve: { + alias: { + "./config/modules/OpModules.js": "./config/modules/Default.js" + } + }, + plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS), + new HtmlWebpackPlugin({ + filename: "index.html", + template: "./src/web/html/index.html", + chunks: ["main"], + compileTime: compileTime, + version: pkg.version, + }) + ] } } }, diff --git a/package-lock.json b/package-lock.json index 3672783c..d3501a44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,15 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "HTML_CodeSniffer": { + "version": "github:squizlabs/HTML_CodeSniffer#d209ce54876657858a8a01528ad812cd234f37f0", + "dev": true + }, + "JSONSelect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", + "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" + }, "abab": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", @@ -16,18 +25,28 @@ "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", "dev": true }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, "access-sniff": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/access-sniff/-/access-sniff-3.0.1.tgz", "integrity": "sha1-IJ4W63DAlaA79/yCnsrLfHeS9e4=", "dev": true, "requires": { + "HTML_CodeSniffer": "github:squizlabs/HTML_CodeSniffer#d209ce54876657858a8a01528ad812cd234f37f0", "axios": "0.9.1", "bluebird": "3.5.0", "chalk": "1.1.3", "commander": "2.11.0", "glob": "7.1.2", - "HTML_CodeSniffer": "github:squizlabs/HTML_CodeSniffer#d209ce54876657858a8a01528ad812cd234f37f0", "jsdom": "9.12.0", "mkdirp": "0.5.1", "phantomjs-prebuilt": "2.1.15", @@ -146,6 +165,12 @@ "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", "dev": true }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -204,6 +229,22 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.8.2" + } + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -298,7 +339,7 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000726", + "caniuse-db": "1.0.30000732", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "5.2.17", @@ -311,8 +352,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000726", - "electron-to-chromium": "1.3.20" + "caniuse-db": "1.0.30000732", + "electron-to-chromium": "1.3.21" } } } @@ -374,14 +415,6 @@ "private": "0.1.7", "slash": "1.0.0", "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "babel-generator": { @@ -398,14 +431,6 @@ "lodash": "4.17.4", "source-map": "0.5.7", "trim-right": "1.0.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "babel-helper-builder-binary-assignment-operator-visitor": { @@ -927,7 +952,7 @@ "home-or-tmp": "2.0.0", "lodash": "4.17.4", "mkdirp": "0.5.1", - "source-map-support": "0.4.17" + "source-map-support": "0.4.18" } }, "babel-runtime": { @@ -1006,6 +1031,12 @@ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", "dev": true }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, "bcrypt-pbkdf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", @@ -1017,9 +1048,9 @@ } }, "big.js": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz", - "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, "binary-extensions": { @@ -1040,6 +1071,20 @@ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "2.1.1", + "deep-equal": "1.0.1", + "dns-equal": "1.0.0", + "dns-txt": "2.0.2", + "multicast-dns": "6.1.1", + "multicast-dns-service-types": "1.1.0" + } + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -1176,8 +1221,8 @@ "integrity": "sha512-aM2Gt4x9bVlCUteADBS6JP0F+2tMWKM1jQzUulVROtdFWFIcIVvY76AJbr7GDqy0eDhn+PcnpzzivGxY4qiaKQ==", "dev": true, "requires": { - "caniuse-lite": "1.0.30000726", - "electron-to-chromium": "1.3.20" + "caniuse-lite": "1.0.30000732", + "electron-to-chromium": "1.3.21" } }, "buffer": { @@ -1191,6 +1236,12 @@ "isarray": "1.0.0" } }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -1209,6 +1260,12 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "bytes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.5.0.tgz", + "integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=", + "dev": true + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -1230,7 +1287,7 @@ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", "dev": true, "requires": { - "no-case": "2.3.1", + "no-case": "2.3.2", "upper-case": "1.1.3" } }, @@ -1257,7 +1314,7 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000726", + "caniuse-db": "1.0.30000732", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" }, @@ -1268,22 +1325,22 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000726", - "electron-to-chromium": "1.3.20" + "caniuse-db": "1.0.30000732", + "electron-to-chromium": "1.3.21" } } } }, "caniuse-db": { - "version": "1.0.30000726", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000726.tgz", - "integrity": "sha1-m7dC+NAmpi34c7wDwGhD0iVbYNc=", + "version": "1.0.30000732", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000732.tgz", + "integrity": "sha1-3bPIheiMr3eccIDuCWU/uF0b0ks=", "dev": true }, "caniuse-lite": { - "version": "1.0.30000726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000726.tgz", - "integrity": "sha1-lmp1P6EHoJ1BMc+LPWFnI6Bsz34=", + "version": "1.0.30000732", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000732.tgz", + "integrity": "sha1-fPnKVl9NMaSz36bia3LsIukCfaE=", "dev": true }, "caseless": { @@ -1377,14 +1434,6 @@ "dev": true, "requires": { "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "cli-cursor": { @@ -1526,6 +1575,30 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compressible": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.11.tgz", + "integrity": "sha1-FnGKdd4oPtjmBAQWJaIGRYZ5fYo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "compression": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.0.tgz", + "integrity": "sha1-AwyfGY8WQ6BX13anOOki2kNzAS0=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "bytes": "2.5.0", + "compressible": "2.0.11", + "debug": "2.6.8", + "on-headers": "1.0.1", + "safe-buffer": "5.1.1", + "vary": "1.1.1" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1543,6 +1616,12 @@ "typedarray": "0.0.6" } }, + "connect-history-api-fallback": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz", + "integrity": "sha1-5R0X+PDvDbkKZP20feMFFVbp8Wk=", + "dev": true + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -1558,6 +1637,18 @@ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, "content-type-parser": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz", @@ -1570,6 +1661,18 @@ "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", "dev": true }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, "core-js": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", @@ -1812,14 +1915,6 @@ "requires": { "clap": "1.2.0", "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "cssom": { @@ -1922,6 +2017,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", @@ -1942,6 +2043,26 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, + "default-gateway": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.4.0.tgz", + "integrity": "sha512-jtdtfL2MWLLHMASg/XlDBHnVPVX+s5IEHRxyNvy/AaWyyf9XZr+ClAAPITevY7k8IdOYZvx1BcrjSyeU6e5W8w==", + "dev": true, + "requires": { + "execa": "0.7.0", + "ip-regex": "2.1.0" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", @@ -1969,6 +2090,12 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -1979,6 +2106,12 @@ "minimalistic-assert": "1.0.0" } }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -1988,6 +2121,12 @@ "repeating": "2.0.1" } }, + "detect-node": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", + "dev": true + }, "diff": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", @@ -2004,6 +2143,31 @@ "randombytes": "2.0.5" } }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.2.2.tgz", + "integrity": "sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==", + "dev": true, + "requires": { + "ip": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "1.1.1" + } + }, "doctrine": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", @@ -2080,6 +2244,18 @@ "domelementtype": "1.3.0" } }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, "ebnf-parser": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", @@ -2104,10 +2280,16 @@ } } }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, "electron-to-chromium": { - "version": "1.3.20", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz", - "integrity": "sha1-Lu3VzLrn3cVX9orR/OnBcukV5OU=", + "version": "1.3.21", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.21.tgz", + "integrity": "sha1-qWfr3P6O0Ag/wkTRiUAiqOgRPqI=", "dev": true }, "elliptic": { @@ -2131,6 +2313,21 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", @@ -2167,6 +2364,30 @@ "is-arrayish": "0.2.1" } }, + "es-abstract": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.2.tgz", + "integrity": "sha512-dvhwFL3yjQxNNsOWx6exMlaDrRHCRGMQlnx5lsXDCZ/J7G/frgIIl94zhZSp/galVAYp7VzPi1OrAHta89/yGQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, "es5-ext": { "version": "0.10.30", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", @@ -2243,6 +2464,12 @@ "es6-symbol": "3.1.1" } }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2265,12 +2492,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "optional": true } } }, @@ -2290,9 +2511,9 @@ } }, "eslint": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.6.1.tgz", - "integrity": "sha1-3cf8f9cL+TIFsLNEm7FqHp59SVA=", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.7.0.tgz", + "integrity": "sha1-01/AfEclIL496Fs9oR6ZxXav1RU=", "dev": true, "requires": { "ajv": "5.2.2", @@ -2300,10 +2521,10 @@ "chalk": "2.1.0", "concat-stream": "1.6.0", "cross-spawn": "5.1.0", - "debug": "2.6.8", + "debug": "3.0.1", "doctrine": "2.0.0", "eslint-scope": "3.7.1", - "espree": "3.5.0", + "espree": "3.5.1", "esquery": "1.0.0", "estraverse": "4.2.0", "esutils": "2.0.2", @@ -2315,7 +2536,7 @@ "imurmurhash": "0.1.4", "inquirer": "3.2.3", "is-resolvable": "1.0.0", - "js-yaml": "3.9.1", + "js-yaml": "3.10.0", "json-stable-stringify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", @@ -2324,7 +2545,7 @@ "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "4.0.0", + "pluralize": "7.0.0", "progress": "2.0.0", "require-uncached": "1.0.3", "semver": "5.4.1", @@ -2360,11 +2581,14 @@ "supports-color": "4.4.0" } }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "debug": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.0.1.tgz", + "integrity": "sha512-6nVc6S36qbt/mutyt+UGMnawAMrPDZUPQjRZI3FS9tCtDRhvxJbK79unYBLPi+z5SLXQ3ftoVBFCblQtNSls8w==", + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "glob": { "version": "7.1.2", @@ -2387,9 +2611,9 @@ "dev": true }, "js-yaml": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { "argparse": "1.0.9", @@ -2430,14 +2654,6 @@ "requires": { "esrecurse": "4.2.0", "estraverse": "4.2.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "esmangle": { @@ -2524,9 +2740,9 @@ } }, "espree": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz", - "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", + "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", "dev": true, "requires": { "acorn": "5.1.2", @@ -2553,14 +2769,6 @@ "dev": true, "requires": { "estraverse": "4.2.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "esrecurse": { @@ -2571,14 +2779,6 @@ "requires": { "estraverse": "4.2.0", "object-assign": "4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "esshorten": { @@ -2608,6 +2808,12 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", @@ -2624,12 +2830,27 @@ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": "1.0.0" + } + }, "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -2692,12 +2913,54 @@ "requires": { "loader-utils": "1.1.0", "source-map": "0.5.7" + } + }, + "express": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", + "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.8", + "depd": "1.1.1", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.0.5", + "fresh": "0.5.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.1.5", + "qs": "6.5.0", + "range-parser": "1.2.0", + "send": "0.15.4", + "serve-static": "1.12.4", + "setprototypeof": "1.0.3", + "statuses": "1.3.1", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vary": "1.1.1" }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "qs": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==", "dev": true } } @@ -2714,7 +2977,7 @@ "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", "dev": true, "requires": { - "iconv-lite": "0.4.18", + "iconv-lite": "0.4.19", "jschardet": "1.5.1", "tmp": "0.0.31" } @@ -2801,6 +3064,15 @@ "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", "dev": true }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -2874,6 +3146,21 @@ } } }, + "finalhandler": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.5.tgz", + "integrity": "sha1-pwEwPSV6G8gv6lR6M+WuiVMXI98=", + "dev": true, + "requires": { + "debug": "2.6.8", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, "find-cache-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", @@ -2961,6 +3248,12 @@ "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2978,6 +3271,18 @@ "mime-types": "2.1.17" } }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fresh": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", + "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=", + "dev": true + }, "fs-extra": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", @@ -3128,7 +3433,7 @@ "grunt-known-options": "1.1.0", "grunt-legacy-log": "1.0.0", "grunt-legacy-util": "1.0.0", - "iconv-lite": "0.4.18", + "iconv-lite": "0.4.19", "js-yaml": "3.5.5", "minimatch": "3.0.4", "nopt": "3.0.6", @@ -3184,6 +3489,26 @@ "shelljs": "0.5.3" } }, + "grunt-concurrent": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/grunt-concurrent/-/grunt-concurrent-2.3.1.tgz", + "integrity": "sha1-Hj2zjM71o9oRleYdYx/n4yE0TSM=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "async": "1.5.2", + "indent-string": "2.1.0", + "pad-stream": "1.2.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, "grunt-contrib-clean": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", @@ -3191,7 +3516,7 @@ "dev": true, "requires": { "async": "1.5.2", - "rimraf": "2.6.1" + "rimraf": "2.6.2" }, "dependencies": { "async": { @@ -3201,9 +3526,9 @@ "dev": true }, "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "7.0.6" @@ -3228,7 +3553,7 @@ "dev": true, "requires": { "chalk": "2.1.0", - "eslint": "4.6.1" + "eslint": "4.7.0" }, "dependencies": { "ansi-styles": { @@ -3392,6 +3717,12 @@ "lodash": "4.17.4" } }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true + }, "har-schema": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", @@ -3530,9 +3861,17 @@ "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, - "HTML_CodeSniffer": { - "version": "github:squizlabs/HTML_CodeSniffer#d209ce54876657858a8a01528ad812cd234f37f0", - "dev": true + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "obuf": "1.1.1", + "readable-stream": "2.3.3", + "wbuf": "1.7.2" + } }, "html-comment-regex": { "version": "1.1.1", @@ -3549,10 +3888,16 @@ "whatwg-encoding": "1.0.1" } }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, "html-minifier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.3.tgz", - "integrity": "sha512-iKRzQQDuTCsq0Ultbi/mfJJnR0D3AdZKTq966Gsp92xkmAPCV4Xi08qhJ0Dl3ZAWemSgJ7qZK+UsZc0gFqK6wg==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.5.tgz", + "integrity": "sha512-g+1+NBycQI0fGnggd52JM8TRUweG7+9W2wrtjGitMAqc4G7maweAHvVAAjz9veHseIH3tYKE2lk2USGSoewIrQ==", "dev": true, "requires": { "camel-case": "3.0.0", @@ -3562,7 +3907,7 @@ "ncname": "1.0.0", "param-case": "2.1.1", "relateurl": "0.2.7", - "uglify-js": "3.0.28" + "uglify-js": "3.1.1" } }, "html-webpack-plugin": { @@ -3572,7 +3917,7 @@ "dev": true, "requires": { "bluebird": "3.5.0", - "html-minifier": "3.5.3", + "html-minifier": "3.5.5", "loader-utils": "0.2.17", "lodash": "4.17.4", "pretty-error": "2.1.1", @@ -3585,7 +3930,7 @@ "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "requires": { - "big.js": "3.1.3", + "big.js": "3.2.0", "emojis-list": "2.1.0", "json5": "0.5.1", "object-assign": "4.1.1" @@ -3640,6 +3985,69 @@ } } }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + } + }, + "http-parser-js": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.6.tgz", + "integrity": "sha1-GVJz9YcExFLWcQdr4gEyndNB3FU=", + "dev": true + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", + "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "dev": true, + "requires": { + "http-proxy": "1.16.2", + "is-glob": "3.1.0", + "lodash": "4.17.4", + "micromatch": "2.3.11" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, "http-signature": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", @@ -3658,9 +4066,9 @@ "dev": true }, "iconv-lite": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", "dev": true }, "icss-replace-symbols": { @@ -3715,12 +4123,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3759,14 +4161,6 @@ "requires": { "loader-utils": "1.1.0", "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "imurmurhash": { @@ -3902,10 +4296,28 @@ } } }, + "internal-ip": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-2.0.3.tgz", + "integrity": "sha512-XxJMiJOjXbb9LlwH6SVTsnUPymYACunXzKg3dqU+HIC+xYIkUhMyTiT/H6xxPmhlE4zHq50lKlx0CZlyN2C76Q==", + "dev": true, + "requires": { + "default-gateway": "2.4.0", + "ipaddr.js": "1.5.2" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", + "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", + "dev": true + } + } + }, "interpret": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", "dev": true }, "invariant": { @@ -3923,6 +4335,24 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=", + "dev": true + }, "is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", @@ -3959,6 +4389,18 @@ "builtin-modules": "1.1.1" } }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, "is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", @@ -4082,6 +4524,15 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + }, "is-resolvable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", @@ -4106,6 +4557,12 @@ "html-comment-regex": "1.1.1" } }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -4118,6 +4575,12 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -4147,12 +4610,12 @@ "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz", "integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=", "requires": { + "JSONSelect": "0.4.0", "cjson": "0.2.1", "ebnf-parser": "0.1.10", "escodegen": "0.0.21", "esprima": "1.0.4", "jison-lex": "0.2.1", - "JSONSelect": "0.4.0", "lex-parser": "0.1.4", "nomnom": "1.5.2" }, @@ -4164,7 +4627,7 @@ "requires": { "esprima": "1.0.4", "estraverse": "0.0.4", - "source-map": "0.2.0" + "source-map": "0.5.7" } }, "esprima": { @@ -4194,9 +4657,9 @@ "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=" }, "js-base64": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", - "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", + "integrity": "sha512-Y2/+DnfJJXT1/FCwUebUhLWb3QihxiSC42+ctHLGogmW2jPY6LCapMdFZXRvVP2z6qyKW7s6qncE/9gSqZiArw==", "dev": true }, "js-crc": { @@ -4375,6 +4838,12 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", @@ -4414,11 +4883,6 @@ } } }, - "JSONSelect": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", - "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4497,15 +4961,6 @@ "promise": "7.3.1", "request": "2.81.0", "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } } }, "less-loader": { @@ -4566,7 +5021,7 @@ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "3.1.3", + "big.js": "3.2.0", "emojis-list": "2.1.0", "json5": "0.5.1" } @@ -4610,6 +5065,12 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "loglevel": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.5.0.tgz", + "integrity": "sha512-OQ2jhWI5G2qsvO0UFNyCQWgKl/tFiwuPIXxELzACeUO2FqstN/R7mmL09+nhv6xOWVPPojQO1A90sCEoJSgBcQ==", + "dev": true + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -4706,6 +5167,12 @@ } } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", @@ -4751,6 +5218,18 @@ } } }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", @@ -4786,8 +5265,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.0.tgz", "integrity": "sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ==", - "dev": true, - "optional": true + "dev": true }, "mime-db": { "version": "1.30.0", @@ -4871,6 +5349,22 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "multicast-dns": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.1.1.tgz", + "integrity": "sha1-bn3oalcIcqsXBYrepxYLvsqBTd4=", + "dev": true, + "requires": { + "dns-packet": "1.2.2", + "thunky": "0.1.0" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -4892,15 +5386,27 @@ "xml-char-classes": "1.0.0" } }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, "no-case": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz", - "integrity": "sha1-euuhxzpSGEJlVUt9wDuvcg34AIE=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { "lower-case": "1.1.4" } }, + "node-forge": { + "version": "0.6.33", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz", + "integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=", + "dev": true + }, "node-libs-browser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.0.0.tgz", @@ -5057,6 +5563,12 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -5067,6 +5579,27 @@ "is-extendable": "0.1.1" } }, + "obuf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz", + "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5085,6 +5618,15 @@ "mimic-fn": "1.1.0" } }, + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -5098,6 +5640,27 @@ "wordwrap": "1.0.0" } }, + "original": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", + "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "dev": true, + "requires": { + "url-parse": "1.0.5" + }, + "dependencies": { + "url-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", + "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "dev": true, + "requires": { + "querystringify": "0.0.4", + "requires-port": "1.0.0" + } + } + } + }, "os-browserify": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", @@ -5156,6 +5719,25 @@ "p-limit": "1.1.0" } }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "pad-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pad-stream/-/pad-stream-1.2.0.tgz", + "integrity": "sha1-Yx3Mn3mBC3BZZeid7eps/w/B38k=", + "dev": true, + "requires": { + "meow": "3.7.0", + "pumpify": "1.3.5", + "repeating": "2.0.1", + "split2": "1.1.1", + "through2": "2.0.3" + } + }, "pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -5168,7 +5750,7 @@ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", "dev": true, "requires": { - "no-case": "2.3.1" + "no-case": "2.3.2" } }, "parse-asn1": { @@ -5211,6 +5793,12 @@ "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", "dev": true }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", @@ -5241,6 +5829,12 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", @@ -5325,11 +5919,30 @@ } }, "pluralize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", - "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.8", + "mkdirp": "0.5.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, "postcss": { "version": "5.2.17", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", @@ -5337,17 +5950,11 @@ "dev": true, "requires": { "chalk": "1.1.3", - "js-base64": "2.1.9", + "js-base64": "2.3.2", "source-map": "0.5.7", "supports-color": "3.2.3" }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", @@ -5439,12 +6046,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5562,12 +6163,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5660,12 +6255,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5716,8 +6305,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000726", - "electron-to-chromium": "1.3.20" + "caniuse-db": "1.0.30000732", + "electron-to-chromium": "1.3.21" } } } @@ -5819,12 +6408,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5883,12 +6466,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5947,12 +6524,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -6011,12 +6582,6 @@ "supports-color": "4.4.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -6201,6 +6766,16 @@ "asap": "2.0.6" } }, + "proxy-addr": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "dev": true, + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.4.0" + } + }, "prr": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", @@ -6226,6 +6801,27 @@ "randombytes": "2.0.5" } }, + "pump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", + "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", + "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "inherits": "2.0.3", + "pump": "1.0.2" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -6266,6 +6862,12 @@ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, + "querystringify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "dev": true + }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", @@ -6316,6 +6918,12 @@ "safe-buffer": "5.1.1" } }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, "rc": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", @@ -6652,6 +7260,12 @@ "resolve-from": "1.0.1" } }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "requizzle": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", @@ -6797,12 +7411,83 @@ "ajv": "5.2.2" } }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz", + "integrity": "sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=", + "dev": true, + "requires": { + "node-forge": "0.6.33" + } + }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "send": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz", + "integrity": "sha1-mF+qPihLAnPHkzZKNcZze9k5Bbk=", + "dev": true, + "requires": { + "debug": "2.6.8", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.0", + "http-errors": "1.6.2", + "mime": "1.3.4", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.0.tgz", + "integrity": "sha1-0rKA/FYNYW7oG0i/D6gqvtJIXOc=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "batch": "0.6.1", + "debug": "2.6.8", + "escape-html": "1.0.3", + "http-errors": "1.6.2", + "mime-types": "2.1.17", + "parseurl": "1.3.2" + } + }, + "serve-static": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz", + "integrity": "sha1-m2qpjutyU8Tu3Ewfb9vKYJkBqWE=", + "dev": true, + "requires": { + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.15.4" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -6821,6 +7506,12 @@ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + }, "sha.js": { "version": "2.4.8", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", @@ -6883,6 +7574,49 @@ "hoek": "2.16.3" } }, + "sockjs": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", + "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=", + "dev": true, + "requires": { + "faye-websocket": "0.10.0", + "uuid": "2.0.3" + }, + "dependencies": { + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "sockjs-client": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", + "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", + "dev": true, + "requires": { + "debug": "2.6.8", + "eventsource": "0.1.6", + "faye-websocket": "0.11.1", + "inherits": "2.0.3", + "json3": "3.3.2", + "url-parse": "1.1.9" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + } + } + }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -6904,29 +7638,17 @@ "dev": true }, "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "optional": true, - "requires": { - "amdefine": "1.0.1" - } + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-support": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.17.tgz", - "integrity": "sha512-30c1Ch8FSjV0FwC253iftbbj0dU/OXoSg1LAEGZJUlGgjTNj6cu+DVqJWWIZJY5RXLWV4eFtR+4ouo0VIOYOTg==", + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "spdx-correct": { @@ -6950,11 +7672,49 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, + "requires": { + "debug": "2.6.8", + "handle-thing": "1.2.5", + "http-deceiver": "1.2.7", + "safe-buffer": "5.1.1", + "select-hose": "2.0.0", + "spdy-transport": "2.0.20" + } + }, + "spdy-transport": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz", + "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=", + "dev": true, + "requires": { + "debug": "2.6.8", + "detect-node": "2.0.3", + "hpack.js": "2.1.6", + "obuf": "1.1.1", + "readable-stream": "2.3.3", + "safe-buffer": "5.1.1", + "wbuf": "1.7.2" + } + }, "split.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/split.js/-/split.js-1.3.5.tgz", "integrity": "sha1-YuLOZtLPkcx3SqXwdJ/yUTgDn1A=" }, + "split2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.1.1.tgz", + "integrity": "sha1-Fi2bGIZfAqsvKtlYVSLbm1TEgfk=", + "dev": true, + "requires": { + "through2": "2.0.3" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -7007,7 +7767,7 @@ "requires": { "esprima": "1.0.4", "estraverse": "1.3.2", - "source-map": "0.2.0" + "source-map": "0.5.7" } }, "esprima": { @@ -7022,6 +7782,12 @@ } } }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", @@ -7051,21 +7817,18 @@ "xtend": "4.0.1" } }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -7093,6 +7856,15 @@ } } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -7244,6 +8016,28 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "thunky": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", + "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=", + "dev": true + }, + "time-stamp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + }, "timers-browserify": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", @@ -7343,6 +8137,16 @@ "prelude-ls": "1.1.2" } }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.17" + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -7350,21 +8154,13 @@ "dev": true }, "uglify-js": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.28.tgz", - "integrity": "sha512-0h/qGay016GG2lVav3Kz174F3T2Vjlz2v6HCt+WDQpoXfco0hWwF5gHK9yh88mUYvIC+N7Z8NT8WpjSp1yoqGA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.1.1.tgz", + "integrity": "sha512-f7DpmEgt/RYAKzQzcfahn3JYZHobDwTZCa8oixC7pweVGEIizTX2kTYdNWcdk00xsMJqUhI8RDAa9HXHXGhNxA==", "dev": true, "requires": { "commander": "2.11.0", "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "uglify-to-browserify": { @@ -7391,12 +8187,6 @@ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", @@ -7480,6 +8270,12 @@ "normalize-path": "2.1.1" } }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, "upper-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", @@ -7522,6 +8318,24 @@ } } }, + "url-parse": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", + "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=", + "dev": true, + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + }, + "dependencies": { + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "dev": true + } + } + }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -7551,12 +8365,27 @@ "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", "dev": true }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", "dev": true }, + "val-loader": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/val-loader/-/val-loader-1.0.2.tgz", + "integrity": "sha1-eQkZgJOzfLoKlr9PbSnelw0JnT0=", + "dev": true, + "requires": { + "loader-utils": "1.1.0" + } + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", @@ -7573,6 +8402,12 @@ "integrity": "sha1-eoelgUa2laxIYHEUHAxJ1n2gXlw=", "dev": true }, + "vary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", + "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", + "dev": true + }, "vendors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", @@ -7623,6 +8458,15 @@ "graceful-fs": "4.1.11" } }, + "wbuf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz", + "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=", + "dev": true, + "requires": { + "minimalistic-assert": "1.0.0" + } + }, "web-resource-inliner": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-4.1.1.tgz", @@ -7670,9 +8514,9 @@ "dev": true }, "webpack": { - "version": "3.5.6", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.5.6.tgz", - "integrity": "sha512-sXnxfx6KoZVrFAGLjdhCCwDtDwkYMfwm8mJjkQv3thr5pjTlbxopVlr/kJwc9Bz317gL+gNjvz++ir9TgG1MDg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.6.0.tgz", + "integrity": "sha512-OsHT3D0W0KmPPh60tC7asNnOmST6bKTiR90UyEdT9QYoaJ4OYN4Gg7WK1k3VxHK07ZoiYWPsKvlS/gAjwL/vRA==", "dev": true, "requires": { "acorn": "5.1.2", @@ -7682,7 +8526,7 @@ "async": "2.5.0", "enhanced-resolve": "3.4.1", "escope": "3.6.0", - "interpret": "1.0.3", + "interpret": "1.0.4", "json-loader": "0.5.7", "json5": "0.5.1", "loader-runner": "2.3.0", @@ -7729,12 +8573,155 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz", + "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=", + "dev": true, + "requires": { + "memory-fs": "0.4.1", + "mime": "1.4.0", + "path-is-absolute": "1.0.1", + "range-parser": "1.2.0", + "time-stamp": "2.0.0" + } + }, + "webpack-dev-server": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.8.2.tgz", + "integrity": "sha512-wD9bs+Z1uwvf3Jc+8ZkyMI0Xi+aJJYjC2UZplOWoo/vStelK5Mv62X2uXYEYIQEjy9wJQMzC0fEFqQsg7vVEIg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "array-includes": "3.0.3", + "bonjour": "3.5.0", + "chokidar": "1.7.0", + "compression": "1.7.0", + "connect-history-api-fallback": "1.3.0", + "del": "3.0.0", + "express": "4.15.4", + "html-entities": "1.2.1", + "http-proxy-middleware": "0.17.4", + "internal-ip": "2.0.3", + "ip": "1.1.5", + "loglevel": "1.5.0", + "opn": "5.1.0", + "portfinder": "1.0.13", + "selfsigned": "1.10.1", + "serve-index": "1.9.0", + "sockjs": "0.3.18", + "sockjs-client": "1.1.4", + "spdy": "3.4.7", + "strip-ansi": "3.0.1", + "supports-color": "4.4.0", + "webpack-dev-middleware": "1.12.0", + "yargs": "6.6.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.2.8" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.0.6", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -7743,6 +8730,42 @@ "requires": { "has-flag": "2.0.0" } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } } } }, @@ -7760,16 +8783,24 @@ "requires": { "source-list-map": "2.0.0", "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.6", + "websocket-extensions": "0.1.2" + } + }, + "websocket-extensions": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.2.tgz", + "integrity": "sha1-Dhh4HeYpoYMIzhSBZQ9n/6JpOl0=", + "dev": true + }, "whatwg-encoding": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz", @@ -7837,6 +8868,16 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, + "worker-loader": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-0.8.1.tgz", + "integrity": "sha1-6OmVMx6jTfW/aCloJL+38K1XjUM=", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index 208f0f5e..325d1241 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "grunt": ">=1.0.1", "grunt-accessibility": "~5.0.0", "grunt-chmod": "~1.1.1", + "grunt-concurrent": "^2.3.1", "grunt-contrib-clean": "~1.1.0", "grunt-contrib-copy": "~1.0.0", "grunt-eslint": "^20.1.0", @@ -58,9 +59,12 @@ "postcss-loader": "^2.0.6", "style-loader": "^0.18.2", "url-loader": "^0.5.9", + "val-loader": "^1.0.2", "web-resource-inliner": "^4.1.1", "webpack": "^3.5.6", - "webpack-node-externals": "^1.6.0" + "webpack-dev-server": "^2.5.0", + "webpack-node-externals": "^1.6.0", + "worker-loader": "^0.8.0" }, "dependencies": { "babel-polyfill": "^6.26.0", @@ -95,6 +99,7 @@ "zlibjs": "^0.3.1" }, "scripts": { + "start": "grunt dev", "build": "grunt prod", "test": "grunt test", "docs": "grunt docs" diff --git a/src/core/Chef.js b/src/core/Chef.js index 9fa23d22..7c9817df 100755 --- a/src/core/Chef.js +++ b/src/core/Chef.js @@ -30,7 +30,6 @@ const Chef = function() { * @returns {string} response.result - The output of the recipe * @returns {string} response.type - The data type of the result * @returns {number} response.progress - The position that we have got to in the recipe - * @returns {number} response.options - The app options object (which may have been changed) * @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) */ @@ -40,12 +39,7 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress, containsFc = recipe.containsFlowControl(), error = false; - // Reset attemptHighlight flag - if (options.hasOwnProperty("attemptHighlight")) { - options.attemptHighlight = true; - } - - if (containsFc) options.attemptHighlight = false; + if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); // Clean up progress if (progress >= recipeConfig.length) { @@ -86,7 +80,6 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress, this.dish.get(Dish.STRING), type: Dish.enumLookup(this.dish.type), progress: progress, - options: options, duration: new Date().getTime() - startTime, error: error }; @@ -123,4 +116,38 @@ Chef.prototype.silentBake = function(recipeConfig) { return new Date().getTime() - startTime; }; + +/** + * Calculates highlight offsets if possible. + * + * @param {Object[]} recipeConfig + * @param {string} direction + * @param {Object} pos - The position object for the highlight. + * @param {number} pos.start - The start offset. + * @param {number} pos.end - The end offset. + * @returns {Object} + */ +Chef.prototype.calculateHighlights = function(recipeConfig, direction, pos) { + const recipe = new Recipe(recipeConfig); + const highlights = recipe.generateHighlightList(); + + if (!highlights) return false; + + for (let i = 0; i < highlights.length; i++) { + // Remove multiple highlights before processing again + pos = [pos[0]]; + + const func = direction === "forward" ? highlights[i].f : highlights[i].b; + + if (typeof func == "function") { + pos = func(pos, highlights[i].args); + } + } + + return { + pos: pos, + direction: direction + }; +}; + export default Chef; diff --git a/src/core/ChefWorker.js b/src/core/ChefWorker.js new file mode 100644 index 00000000..d3f0c032 --- /dev/null +++ b/src/core/ChefWorker.js @@ -0,0 +1,178 @@ +/** + * Web Worker to handle communications between the front-end and the core. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import "babel-polyfill"; +import Chef from "./Chef.js"; +import OperationConfig from "./config/MetaConfig.js"; +import OpModules from "./config/modules/Default.js"; + + +// Set up Chef instance +self.chef = new Chef(); + +self.OpModules = OpModules; +self.OperationConfig = OperationConfig; + +// Tell the app that the worker has loaded and is ready to operate +self.postMessage({ + action: "workerLoaded", + data: {} +}); + +/** + * Respond to message from parent thread. + * + * Messages should have the following format: + * { + * action: "bake" | "silentBake", + * data: { + * input: {string}, + * recipeConfig: {[Object]}, + * options: {Object}, + * progress: {number}, + * step: {boolean} + * } | undefined + * } + */ +self.addEventListener("message", function(e) { + // Handle message + const r = e.data; + switch (r.action) { + case "bake": + bake(r.data); + break; + case "silentBake": + silentBake(r.data); + break; + case "docURL": + // Used to set the URL of the current document so that scripts can be + // imported into an inline worker. + self.docURL = r.data; + break; + case "highlight": + calculateHighlights( + r.data.recipeConfig, + r.data.direction, + r.data.pos + ); + break; + default: + break; + } +}); + + +/** + * Baking handler + * + * @param {Object} data + */ +async function bake(data) { + // Ensure the relevant modules are loaded + loadRequiredModules(data.recipeConfig); + + try { + const response = await self.chef.bake( + data.input, // The user's input + data.recipeConfig, // The configuration of the recipe + data.options, // Options set by the user + data.progress, // The current position in the recipe + data.step // Whether or not to take one step or execute the whole recipe + ); + + self.postMessage({ + action: "bakeSuccess", + data: response + }); + } catch (err) { + self.postMessage({ + action: "bakeError", + data: err.message + }); + } +} + + +/** + * Silent baking handler + */ +function silentBake(data) { + const duration = self.chef.silentBake(data.recipeConfig); + + self.postMessage({ + action: "silentBakeComplete", + data: duration + }); +} + + +/** + * Checks that all required modules are loaded and loads them if not. + * + * @param {Object} recipeConfig + */ +function loadRequiredModules(recipeConfig) { + recipeConfig.forEach(op => { + let module = self.OperationConfig[op.op].module; + + if (!OpModules.hasOwnProperty(module)) { + console.log("Loading module " + module); + self.sendStatusMessage("Loading module " + module); + self.importScripts(self.docURL + "/" + module + ".js"); + } + }); +} + + +/** + * Calculates highlight offsets if possible. + * + * @param {Object[]} recipeConfig + * @param {string} direction + * @param {Object} pos - The position object for the highlight. + * @param {number} pos.start - The start offset. + * @param {number} pos.end - The end offset. + */ +function calculateHighlights(recipeConfig, direction, pos) { + pos = self.chef.calculateHighlights(recipeConfig, direction, pos); + + self.postMessage({ + action: "highlightsCalculated", + data: pos + }); +} + + +/** + * Send status update to the app. + * + * @param {string} msg + */ +self.sendStatusMessage = function(msg) { + self.postMessage({ + action: "statusMessage", + data: msg + }); +}; + + +/** + * Send an option value update to the app. + * + * @param {string} option + * @param {*} value + */ +self.setOption = function(option, value) { + self.postMessage({ + action: "optionUpdate", + data: { + option: option, + value: value + } + }); +}; diff --git a/src/core/FlowControl.js b/src/core/FlowControl.js index 8585a160..9e01ef0a 100755 --- a/src/core/FlowControl.js +++ b/src/core/FlowControl.js @@ -13,22 +13,6 @@ import Dish from "./Dish.js"; */ const FlowControl = { - /** - * @constant - * @default - */ - FORK_DELIM: "\\n", - /** - * @constant - * @default - */ - MERGE_DELIM: "\\n", - /** - * @constant - * @default - */ - FORK_IGNORE_ERRORS: false, - /** * Fork operation. * @@ -106,17 +90,6 @@ const FlowControl = { }, - /** - * @constant - * @default - */ - JUMP_NUM: 0, - /** - * @constant - * @default - */ - MAX_JUMPS: 10, - /** * Jump operation. * diff --git a/src/core/Operation.js b/src/core/Operation.js index d2493718..d4ee21d3 100755 --- a/src/core/Operation.js +++ b/src/core/Operation.js @@ -1,5 +1,7 @@ import Dish from "./Dish.js"; import Ingredient from "./Ingredient.js"; +import OperationConfig from "./config/MetaConfig.js"; +import OpModules from "./config/modules/OpModules.js"; /** @@ -11,10 +13,10 @@ import Ingredient from "./Ingredient.js"; * * @class * @param {string} operationName - * @param {Object} operationConfig */ -const Operation = function(operationName, operationConfig) { +const Operation = function(operationName) { this.name = operationName; + this.module = ""; this.description = ""; this.inputType = -1; this.outputType = -1; @@ -25,8 +27,8 @@ const Operation = function(operationName, operationConfig) { this.disabled = false; this.ingList = []; - if (operationConfig) { - this._parseConfig(operationConfig); + if (OperationConfig.hasOwnProperty(this.name)) { + this._parseConfig(OperationConfig[this.name]); } }; @@ -38,19 +40,28 @@ const Operation = function(operationName, operationConfig) { * @param {Object} operationConfig */ Operation.prototype._parseConfig = function(operationConfig) { + this.module = operationConfig.module; this.description = operationConfig.description; this.inputType = Dish.typeEnum(operationConfig.inputType); this.outputType = Dish.typeEnum(operationConfig.outputType); - this.run = operationConfig.run; this.highlight = operationConfig.highlight; this.highlightReverse = operationConfig.highlightReverse; this.flowControl = operationConfig.flowControl; + this.run = OpModules[this.module][this.name]; for (let a = 0; a < operationConfig.args.length; a++) { const ingredientConfig = operationConfig.args[a]; const ingredient = new Ingredient(ingredientConfig); this.addIngredient(ingredient); } + + if (this.highlight === "func") { + this.highlight = OpModules[this.module][`${this.name}-highlight`]; + } + + if (this.highlightReverse === "func") { + this.highlightReverse = OpModules[this.module][`${this.name}-highlightReverse`]; + } }; diff --git a/src/core/Recipe.js b/src/core/Recipe.js index e7e5625a..d703ac1e 100755 --- a/src/core/Recipe.js +++ b/src/core/Recipe.js @@ -1,5 +1,4 @@ import Operation from "./Operation.js"; -import OperationConfig from "./config/OperationConfig.js"; /** @@ -30,8 +29,7 @@ const Recipe = function(recipeConfig) { Recipe.prototype._parseConfig = function(recipeConfig) { for (let c = 0; c < recipeConfig.length; c++) { const operationName = recipeConfig[c].op; - const operationConfig = OperationConfig[operationName]; - const operation = new Operation(operationName, operationConfig); + const operation = new Operation(operationName); operation.setIngValues(recipeConfig[c].args); operation.setBreakpoint(recipeConfig[c].breakpoint); operation.setDisabled(recipeConfig[c].disabled); @@ -217,4 +215,37 @@ Recipe.prototype.fromString = function(recipeStr) { this._parseConfig(recipeConfig); }; + +/** + * Generates a list of all the highlight functions assigned to operations in the recipe, if the + * entire recipe supports highlighting. + * + * @returns {Object[]} highlights + * @returns {function} highlights[].f + * @returns {function} highlights[].b + * @returns {Object[]} highlights[].args + */ +Recipe.prototype.generateHighlightList = function() { + const highlights = []; + + for (let i = 0; i < this.opList.length; i++) { + let op = this.opList[i]; + if (op.isDisabled()) continue; + + // If any breakpoints are set, do not attempt to highlight + if (op.isBreakpoint()) return false; + + // If any of the operations do not support highlighting, fail immediately. + if (op.highlight === false || op.highlight === undefined) return false; + + highlights.push({ + f: op.highlight, + b: op.highlightReverse, + args: op.getIngValues() + }); + } + + return highlights; +}; + export default Recipe; diff --git a/src/core/Utils.js b/src/core/Utils.js index 508c8e07..375c451d 100755 --- a/src/core/Utils.js +++ b/src/core/Utils.js @@ -234,7 +234,7 @@ const Utils = { * @returns {string} */ printable: function(str, preserveWs) { - if (typeof window !== "undefined" && window.app && !window.app.options.treatAsUtf8) { + if (ENVIRONMENT_IS_WEB() && window.app && !window.app.options.treatAsUtf8) { str = Utils.byteArrayToChars(Utils.strToByteArray(str)); } @@ -384,8 +384,12 @@ const Utils = { let wordArray = CryptoJS.enc.Utf8.parse(str), byteArray = Utils.wordArrayToByteArray(wordArray); - if (typeof window !== "undefined" && str.length !== wordArray.sigBytes) { - window.app.options.attemptHighlight = false; + if (str.length !== wordArray.sigBytes) { + if (ENVIRONMENT_IS_WORKER()) { + self.setOption("attemptHighlight", false); + } else if (ENVIRONMENT_IS_WEB()) { + window.app.options.attemptHighlight = false; + } } return byteArray; }, @@ -448,8 +452,13 @@ const Utils = { let wordArray = new CryptoJS.lib.WordArray.init(words, byteArray.length), str = CryptoJS.enc.Utf8.stringify(wordArray); - if (typeof window !== "undefined" && str.length !== wordArray.sigBytes) - window.app.options.attemptHighlight = false; + if (str.length !== wordArray.sigBytes) { + if (ENVIRONMENT_IS_WORKER()) { + self.setOption("attemptHighlight", false); + } else if (ENVIRONMENT_IS_WEB()) { + window.app.options.attemptHighlight = false; + } + } return str; } catch (err) { // If it fails, treat it as ANSI diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 1bb2a6ef..d8b75ca5 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -1,4 +1,3 @@ -import FlowControl from "../FlowControl.js"; import Base from "../operations/Base.js"; import Base58 from "../operations/Base58.js"; import Base64 from "../operations/Base64.js"; @@ -12,9 +11,11 @@ import Code from "../operations/Code.js"; import Compress from "../operations/Compress.js"; import Convert from "../operations/Convert.js"; import DateTime from "../operations/DateTime.js"; +import Diff from "../operations/Diff.js"; import Endian from "../operations/Endian.js"; import Entropy from "../operations/Entropy.js"; import Extract from "../operations/Extract.js"; +import Filetime from "../operations/Filetime.js"; import FileType from "../operations/FileType.js"; import Image from "../operations/Image.js"; import Hash from "../operations/Hash.js"; @@ -46,8 +47,8 @@ import UUID from "../operations/UUID.js"; * Type definition for an OpConf. * * @typedef {Object} OpConf + * @property {string} module - The module to which the operation belongs * @property {html} description - A description of the operation with optional HTML tags - * @property {Function} run - The function which can be called the run the operation * @property {string} inputType * @property {string} outputType * @property {Function|boolean} [highlight] - A function to calculate the highlight offset, or true @@ -84,8 +85,8 @@ import UUID from "../operations/UUID.js"; */ const OperationConfig = { "Fork": { + module: "Default", description: "Split the input data up based on the specified delimiter and run all subsequent operations on each branch separately.

For example, to decode multiple Base64 strings, enter them all on separate lines then add the 'Fork' and 'From Base64' operations to the recipe. Each string will be decoded separately.", - run: FlowControl.runFork, inputType: "string", outputType: "string", flowControl: true, @@ -93,31 +94,31 @@ const OperationConfig = { { name: "Split delimiter", type: "binaryShortString", - value: FlowControl.FORK_DELIM + value: "\\n" }, { name: "Merge delimiter", type: "binaryShortString", - value: FlowControl.MERGE_DELIM + value: "\\n" }, { name: "Ignore errors", type: "boolean", - value: FlowControl.FORK_IGNORE_ERRORS + value: false } ] }, "Merge": { + module: "Default", description: "Consolidate all branches back into a single trunk. The opposite of Fork.", - run: FlowControl.runMerge, inputType: "string", outputType: "string", flowControl: true, args: [] }, "Jump": { + module: "Default", description: "Jump forwards or backwards over the specified number of operations.", - run: FlowControl.runJump, inputType: "string", outputType: "string", flowControl: true, @@ -125,18 +126,18 @@ const OperationConfig = { { name: "Number of operations to jump over", type: "number", - value: FlowControl.JUMP_NUM + value: 0 }, { name: "Maximum jumps (if jumping backwards)", type: "number", - value: FlowControl.MAX_JUMPS + value: 10 } ] }, "Conditional Jump": { + module: "Default", description: "Conditionally jump forwards or backwards over the specified number of operations based on whether the data matches the specified regular expression.", - run: FlowControl.runCondJump, inputType: "string", outputType: "string", flowControl: true, @@ -149,26 +150,26 @@ const OperationConfig = { { name: "Number of operations to jump over if match found", type: "number", - value: FlowControl.JUMP_NUM + value: 0 }, { name: "Maximum jumps (if jumping backwards)", type: "number", - value: FlowControl.MAX_JUMPS + value: 10 } ] }, "Return": { + module: "Default", description: "End execution of operations at this point in the recipe.", - run: FlowControl.runReturn, inputType: "string", outputType: "string", flowControl: true, args: [] }, "Comment": { + module: "Default", description: "Provides a place to write comments within the flow of the recipe. This operation has no computational effect.", - run: FlowControl.runComment, inputType: "string", outputType: "string", flowControl: true, @@ -181,10 +182,10 @@ const OperationConfig = { ] }, "From Base64": { + module: "Default", description: "Base64 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers.

This operation decodes data from an ASCII Base64 string back into its raw format.

e.g. aGVsbG8= becomes hello", - run: Base64.runFrom, - highlight: Base64.highlightFrom, - highlightReverse: Base64.highlightTo, + highlight: "func", + highlightReverse: "func", inputType: "string", outputType: "byteArray", args: [ @@ -194,17 +195,17 @@ const OperationConfig = { value: Base64.ALPHABET_OPTIONS }, { - name: "Remove non‑alphabet chars", + name: "Remove non-alphabet chars", type: "boolean", value: Base64.REMOVE_NON_ALPH_CHARS } ] }, "To Base64": { + module: "Default", description: "Base64 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers.

This operation encodes data in an ASCII Base64 string.

e.g. hello becomes aGVsbG8=", - run: Base64.runTo, - highlight: Base64.highlightTo, - highlightReverse: Base64.highlightFrom, + highlight: "func", + highlightReverse: "func", inputType: "byteArray", outputType: "string", args: [ @@ -216,8 +217,8 @@ const OperationConfig = { ] }, "From Base58": { + module: "Default", description: "Base58 (similar to Base64) is a notation for encoding arbitrary byte data. It differs from Base64 by removing easily misread characters (i.e. l, I, 0 and O) to improve human readability.

This operation decodes data from an ASCII string (with an alphabet of your choosing, presets included) back into its raw form.

e.g. StV1DL6CwTryKyV becomes hello world

Base58 is commonly used in cryptocurrencies (Bitcoin, Ripple, etc).", - run: Base58.runFrom, inputType: "string", outputType: "byteArray", args: [ @@ -227,15 +228,15 @@ const OperationConfig = { value: Base58.ALPHABET_OPTIONS }, { - name: "Remove non‑alphabet chars", + name: "Remove non-alphabet chars", type: "boolean", value: Base58.REMOVE_NON_ALPH_CHARS } ] }, "To Base58": { + module: "Default", description: "Base58 (similar to Base64) is a notation for encoding arbitrary byte data. It differs from Base64 by removing easily misread characters (i.e. l, I, 0 and O) to improve human readability.

This operation encodes data in an ASCII string (with an alphabet of your choosing, presets included).

e.g. hello world becomes StV1DL6CwTryKyV

Base58 is commonly used in cryptocurrencies (Bitcoin, Ripple, etc).", - run: Base58.runTo, inputType: "byteArray", outputType: "string", args: [ @@ -247,8 +248,8 @@ const OperationConfig = { ] }, "From Base32": { + module: "Default", description: "Base32 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. It uses a smaller set of characters than Base64, usually the uppercase alphabet and the numbers 2 to 7.", - run: Base64.runFrom32, inputType: "string", outputType: "byteArray", args: [ @@ -258,15 +259,15 @@ const OperationConfig = { value: Base64.BASE32_ALPHABET }, { - name: "Remove non‑alphabet chars", + name: "Remove non-alphabet chars", type: "boolean", value: Base64.REMOVE_NON_ALPH_CHARS } ] }, "To Base32": { + module: "Default", description: "Base32 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. It uses a smaller set of characters than Base64, usually the uppercase alphabet and the numbers 2 to 7.", - run: Base64.runTo32, inputType: "byteArray", outputType: "string", args: [ @@ -278,8 +279,8 @@ const OperationConfig = { ] }, "Show Base64 offsets": { + module: "Default", description: "When a string is within a block of data and the whole block is Base64'd, the string itself could be represented in Base64 in three distinct ways depending on its offset within the block.

This operation shows all possible offsets for a given string so that each possible encoding can be considered.", - run: Base64.runOffsets, inputType: "byteArray", outputType: "html", args: [ @@ -296,8 +297,8 @@ const OperationConfig = { ] }, "XOR": { + module: "Default", description: "XOR the input with the given key.
e.g. fe023da5

Options
Null preserving: If the current byte is 0x00 or the same as the key, skip it.

Scheme:", - run: BitwiseOp.runXor, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -322,14 +323,14 @@ const OperationConfig = { ] }, "XOR Brute Force": { - description: "Enumerate all possible XOR solutions. Current maximum key length is 2 due to browser performance.

Optionally enter a regex string that you expect to find in the plaintext to filter results (crib).", - run: BitwiseOp.runXorBrute, + module: "Default", + description: "Enumerate all possible XOR solutions. Current maximum key length is 2 due to browser performance.

Optionally enter a string that you expect to find in the plaintext to filter results (crib).", inputType: "byteArray", outputType: "string", args: [ { name: "Key length", - type: "option", + type: "number", value: BitwiseOp.XOR_BRUTE_KEY_LENGTH }, { @@ -370,8 +371,8 @@ const OperationConfig = { ] }, "NOT": { + module: "Default", description: "Returns the inverse of each byte.", - run: BitwiseOp.runNot, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -379,8 +380,8 @@ const OperationConfig = { args: [] }, "AND": { + module: "Default", description: "AND the input with the given key.
e.g. fe023da5", - run: BitwiseOp.runAnd, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -395,8 +396,8 @@ const OperationConfig = { ] }, "OR": { + module: "Default", description: "OR the input with the given key.
e.g. fe023da5", - run: BitwiseOp.runOr, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -411,8 +412,8 @@ const OperationConfig = { ] }, "ADD": { + module: "Default", description: "ADD the input with the given key (e.g. fe023da5), MOD 255", - run: BitwiseOp.runAdd, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -427,8 +428,8 @@ const OperationConfig = { ] }, "SUB": { + module: "Default", description: "SUB the input with the given key (e.g. fe023da5), MOD 255", - run: BitwiseOp.runSub, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -443,10 +444,10 @@ const OperationConfig = { ] }, "From Hex": { + module: "Default", description: "Converts a hexadecimal byte string back into its raw value.

e.g. ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a becomes the UTF-8 encoded string Γειά σου", - run: ByteRepr.runFromHex, - highlight: ByteRepr.highlightFrom, - highlightReverse: ByteRepr.highlightTo, + highlight: "func", + highlightReverse: "func", inputType: "string", outputType: "byteArray", args: [ @@ -458,10 +459,10 @@ const OperationConfig = { ] }, "To Hex": { + module: "Default", description: "Converts the input string to hexadecimal bytes separated by the specified delimiter.

e.g. The UTF-8 encoded string Γειά σου becomes ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a", - run: ByteRepr.runToHex, - highlight: ByteRepr.highlightTo, - highlightReverse: ByteRepr.highlightFrom, + highlight: "func", + highlightReverse: "func", inputType: "byteArray", outputType: "string", args: [ @@ -473,8 +474,8 @@ const OperationConfig = { ] }, "From Octal": { + module: "Default", description: "Converts an octal byte string back into its raw value.

e.g. 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205 becomes the UTF-8 encoded string Γειά σου", - run: ByteRepr.runFromOct, highlight: false, highlightReverse: false, inputType: "string", @@ -488,8 +489,8 @@ const OperationConfig = { ] }, "To Octal": { + module: "Default", description: "Converts the input string to octal bytes separated by the specified delimiter.

e.g. The UTF-8 encoded string Γειά σου becomes 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205", - run: ByteRepr.runToOct, highlight: false, highlightReverse: false, inputType: "byteArray", @@ -503,10 +504,10 @@ const OperationConfig = { ] }, "From Charcode": { + module: "Default", description: "Converts unicode character codes back into text.

e.g. 0393 03b5 03b9 03ac 20 03c3 03bf 03c5 becomes Γειά σου", - run: ByteRepr.runFromCharcode, - highlight: ByteRepr.highlightFrom, - highlightReverse: ByteRepr.highlightTo, + highlight: "func", + highlightReverse: "func", inputType: "string", outputType: "byteArray", args: [ @@ -524,10 +525,10 @@ const OperationConfig = { }, "To Charcode": { + module: "Default", description: "Converts text to its unicode character code equivalent.

e.g. Γειά σου becomes 0393 03b5 03b9 03ac 20 03c3 03bf 03c5", - run: ByteRepr.runToCharcode, - highlight: ByteRepr.highlightTo, - highlightReverse: ByteRepr.highlightFrom, + highlight: "func", + highlightReverse: "func", inputType: "string", outputType: "string", args: [ @@ -544,10 +545,10 @@ const OperationConfig = { ] }, "From Binary": { + module: "Default", description: "Converts a binary string back into its raw form.

e.g. 01001000 01101001 becomes Hi", - run: ByteRepr.runFromBinary, - highlight: ByteRepr.highlightFromBinary, - highlightReverse: ByteRepr.highlightToBinary, + highlight: "func", + highlightReverse: "func", inputType: "string", outputType: "byteArray", args: [ @@ -559,10 +560,10 @@ const OperationConfig = { ] }, "To Binary": { + module: "Default", description: "Displays the input data as a binary string.

e.g. Hi becomes 01001000 01101001", - run: ByteRepr.runToBinary, - highlight: ByteRepr.highlightToBinary, - highlightReverse: ByteRepr.highlightFromBinary, + highlight: "func", + highlightReverse: "func", inputType: "byteArray", outputType: "string", args: [ @@ -574,8 +575,8 @@ const OperationConfig = { ] }, "From Decimal": { + module: "Default", description: "Converts the data from an ordinal integer array back into its raw form.

e.g. 72 101 108 108 111 becomes Hello", - run: ByteRepr.runFromDecimal, inputType: "string", outputType: "byteArray", args: [ @@ -587,8 +588,8 @@ const OperationConfig = { ] }, "To Decimal": { + module: "Default", description: "Converts the input data to an ordinal integer array.

e.g. Hello becomes 72 101 108 108 111", - run: ByteRepr.runToDecimal, inputType: "byteArray", outputType: "string", args: [ @@ -600,19 +601,19 @@ const OperationConfig = { ] }, "From Hexdump": { + module: "Default", description: "Attempts to convert a hexdump back into raw data. This operation supports many different hexdump variations, but probably not all. Make sure you verify that the data it gives you is correct before continuing analysis.", - run: Hexdump.runFrom, - highlight: Hexdump.highlightFrom, - highlightReverse: Hexdump.highlightTo, + highlight: "func", + highlightReverse: "func", inputType: "string", outputType: "byteArray", args: [] }, "To Hexdump": { + module: "Default", description: "Creates a hexdump of the input data, displaying both the hexadecimal values of each byte and an ASCII representation alongside.", - run: Hexdump.runTo, - highlight: Hexdump.highlightTo, - highlightReverse: Hexdump.highlightFrom, + highlight: "func", + highlightReverse: "func", inputType: "byteArray", outputType: "string", args: [ @@ -634,8 +635,8 @@ const OperationConfig = { ] }, "From Base": { + module: "Default", description: "Converts a number to decimal from a given numerical base.", - run: Base.runFrom, inputType: "string", outputType: "number", args: [ @@ -647,8 +648,8 @@ const OperationConfig = { ] }, "To Base": { + module: "Default", description: "Converts a decimal number to a given numerical base.", - run: Base.runTo, inputType: "number", outputType: "string", args: [ @@ -660,15 +661,15 @@ const OperationConfig = { ] }, "From HTML Entity": { + module: "Default", description: "Converts HTML entities back to characters

e.g. &amp; becomes &", // tags required to stop the browser just printing & - run: HTML.runFromEntity, inputType: "string", outputType: "string", args: [] }, "To HTML Entity": { + module: "Default", description: "Converts characters to HTML entities

e.g. & becomes &amp;", // tags required to stop the browser just printing & - run: HTML.runToEntity, inputType: "string", outputType: "string", args: [ @@ -685,8 +686,8 @@ const OperationConfig = { ] }, "Strip HTML tags": { + module: "Default", description: "Removes all HTML tags from the input.", - run: HTML.runStripTags, inputType: "string", outputType: "string", args: [ @@ -703,15 +704,15 @@ const OperationConfig = { ] }, "URL Decode": { + module: "Default", description: "Converts URI/URL percent-encoded characters back to their raw values.

e.g. %3d becomes =", - run: URL_.runFrom, inputType: "string", outputType: "string", args: [] }, "URL Encode": { + module: "Default", description: "Encodes problematic characters into percent-encoding, a format supported by URIs/URLs.

e.g. = becomes %3d", - run: URL_.runTo, inputType: "string", outputType: "string", args: [ @@ -723,15 +724,15 @@ const OperationConfig = { ] }, "Parse URI": { + module: "Default", description: "Pretty prints complicated Uniform Resource Identifier (URI) strings for ease of reading. Particularly useful for Uniform Resource Locators (URLs) with a lot of arguments.", - run: URL_.runParse, inputType: "string", outputType: "string", args: [] }, "Unescape Unicode Characters": { + module: "Default", description: "Converts unicode-escaped character notation back into raw characters.

Supports the prefixes:e.g. \\u03c3\\u03bf\\u03c5 becomes σου", - run: Unicode.runUnescape, inputType: "string", outputType: "string", args: [ @@ -743,22 +744,22 @@ const OperationConfig = { ] }, "From Quoted Printable": { + module: "Default", description: "Converts QP-encoded text back to standard text.", - run: QuotedPrintable.runFrom, inputType: "string", outputType: "byteArray", args: [] }, "To Quoted Printable": { + module: "Default", description: "Quoted-Printable, or QP encoding, is an encoding using printable ASCII characters (alphanumeric and the equals sign '=') to transmit 8-bit data over a 7-bit data path or, generally, over a medium which is not 8-bit clean. It is defined as a MIME content transfer encoding for use in e-mail.

QP works by using the equals sign '=' as an escape character. It also limits line length to 76, as some software has limits on line length.", - run: QuotedPrintable.runTo, inputType: "byteArray", outputType: "string", args: [] }, "From Punycode": { + module: "Encodings", description: "Punycode is a way to represent Unicode with the limited character subset of ASCII supported by the Domain Name System.

e.g. mnchen-3ya decodes to münchen", - run: Punycode.runToUnicode, inputType: "string", outputType: "string", args: [ @@ -770,8 +771,8 @@ const OperationConfig = { ] }, "To Punycode": { + module: "Encodings", description: "Punycode is a way to represent Unicode with the limited character subset of ASCII supported by the Domain Name System.

e.g. münchen encodes to mnchen-3ya", - run: Punycode.runToAscii, inputType: "string", outputType: "string", args: [ @@ -783,15 +784,15 @@ const OperationConfig = { ] }, "From Hex Content": { + module: "Default", description: "Translates hexadecimal bytes in text back to raw bytes.

e.g. foo|3d|bar becomes foo=bar.", - run: ByteRepr.runFromHexContent, inputType: "string", outputType: "byteArray", args: [] }, "To Hex Content": { + module: "Default", description: "Converts special characters in a string to hexadecimal.

e.g. foo=bar becomes foo|3d|bar.", - run: ByteRepr.runToHexContent, inputType: "byteArray", outputType: "string", args: [ @@ -808,8 +809,8 @@ const OperationConfig = { ] }, "Change IP format": { + module: "JSBN", description: "Convert an IP address from one format to another, e.g. 172.20.23.54 to ac141736", - run: IP.runChangeIpFormat, inputType: "string", outputType: "string", args: [ @@ -826,8 +827,8 @@ const OperationConfig = { ] }, "Parse IP range": { + module: "JSBN", description: "Given a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated.", - run: IP.runParseIpRange, inputType: "string", outputType: "string", args: [ @@ -849,8 +850,8 @@ const OperationConfig = { ] }, "Group IP addresses": { + module: "JSBN", description: "Groups a list of IP addresses into subnets. Supports both IPv4 and IPv6 addresses.", - run: IP.runGroupIps, inputType: "string", outputType: "string", args: [ @@ -872,15 +873,15 @@ const OperationConfig = { ] }, "Parse IPv6 address": { + module: "JSBN", description: "Displays the longhand and shorthand versions of a valid IPv6 address.

Recognises all reserved ranges and parses encapsulated or tunnelled addresses including Teredo and 6to4.", - run: IP.runParseIPv6, inputType: "string", outputType: "string", args: [] }, "Parse IPv4 header": { + module: "JSBN", description: "Given an IPv4 header, this operations parses and displays each field in an easily readable format.", - run: IP.runParseIPv4Header, inputType: "string", outputType: "html", args: [ @@ -892,6 +893,7 @@ const OperationConfig = { ] }, "Encode text": { + module: "CharEnc", description: [ "Encodes text into the chosen character encoding.", "

", @@ -900,7 +902,6 @@ const OperationConfig = { Object.keys(CharEnc.IO_FORMAT).map(e => `
  • ${e}
  • `).join("\n"), "", ].join("\n"), - run: CharEnc.runEncode, inputType: "string", outputType: "byteArray", args: [ @@ -912,6 +913,7 @@ const OperationConfig = { ] }, "Decode text": { + module: "CharEnc", description: [ "Decodes text from the chosen character encoding.", "

    ", @@ -920,7 +922,6 @@ const OperationConfig = { Object.keys(CharEnc.IO_FORMAT).map(e => `
  • ${e}
  • `).join("\n"), "", ].join("\n"), - run: CharEnc.runDecode, inputType: "byteArray", outputType: "string", args: [ @@ -932,8 +933,8 @@ const OperationConfig = { ] }, "AES Decrypt": { + module: "Ciphers", description: "To successfully decrypt AES, you need either:The IV should be the first 16 bytes of encrypted material.", - run: Cipher.runAesDec, inputType: "string", outputType: "string", args: [ @@ -978,8 +979,8 @@ const OperationConfig = { ] }, "AES Encrypt": { + module: "Ciphers", description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

    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.

    AES-128, AES-192, and AES-256 are supported. The variant will be chosen based on the size of the key passed in. If a passphrase is used, a 256-bit key will be generated.", - run: Cipher.runAesEnc, inputType: "string", outputType: "string", args: [ @@ -1024,8 +1025,8 @@ const OperationConfig = { ] }, "DES Decrypt": { + module: "Ciphers", description: "To successfully decrypt DES, you need either:The IV should be the first 8 bytes of encrypted material.", - run: Cipher.runDesDec, inputType: "string", outputType: "string", args: [ @@ -1071,8 +1072,8 @@ const OperationConfig = { ] }, "DES Encrypt": { + module: "Ciphers", description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

    DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.", - run: Cipher.runDesEnc, inputType: "string", outputType: "string", args: [ @@ -1118,8 +1119,8 @@ const OperationConfig = { ] }, "Triple DES Decrypt": { + module: "Ciphers", description: "To successfully decrypt Triple DES, you need either:The IV should be the first 8 bytes of encrypted material.", - run: Cipher.runTripleDesDec, inputType: "string", outputType: "string", args: [ @@ -1165,8 +1166,8 @@ const OperationConfig = { ] }, "Triple DES Encrypt": { + module: "Ciphers", description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

    Triple DES applies DES three times to each block to increase key size.", - run: Cipher.runTripleDesEnc, inputType: "string", outputType: "string", args: [ @@ -1212,8 +1213,8 @@ const OperationConfig = { ] }, "Blowfish Decrypt": { + module: "Ciphers", description: "Blowfish is a symmetric-key block cipher designed in 1993 by Bruce Schneier and included in a large number of cipher suites and encryption products. AES now receives more attention.", - run: Cipher.runBlowfishDec, inputType: "string", outputType: "string", args: [ @@ -1236,8 +1237,8 @@ const OperationConfig = { ] }, "Blowfish Encrypt": { + module: "Ciphers", description: "Blowfish is a symmetric-key block cipher designed in 1993 by Bruce Schneier and included in a large number of cipher suites and encryption products. AES now receives more attention.", - run: Cipher.runBlowfishEnc, inputType: "string", outputType: "string", args: [ @@ -1260,8 +1261,8 @@ const OperationConfig = { ] }, "Rabbit Decrypt": { + module: "Ciphers", description: "To successfully decrypt Rabbit, you need either:The IV should be the first 8 bytes of encrypted material.", - run: Cipher.runRabbitDec, inputType: "string", outputType: "string", args: [ @@ -1307,8 +1308,8 @@ const OperationConfig = { ] }, "Rabbit Encrypt": { + module: "Ciphers", description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

    Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2 year process where 22 designs were evaluated.", - run: Cipher.runRabbitEnc, inputType: "string", outputType: "string", args: [ @@ -1354,8 +1355,8 @@ const OperationConfig = { ] }, "RC4": { + module: "Ciphers", description: "RC4 is a widely-used stream cipher. It is used in popular protocols such as SSL and WEP. Although remarkable for its simplicity and speed, the algorithm's history doesn't inspire confidence in its security.", - run: Cipher.runRc4, highlight: true, highlightReverse: true, inputType: "string", @@ -1380,8 +1381,8 @@ const OperationConfig = { ] }, "RC4 Drop": { + module: "Ciphers", description: "It was discovered that the first few bytes of the RC4 keystream are strongly non-random and leak information about the key. We can defend against this attack by discarding the initial portion of the keystream. This modified algorithm is traditionally called RC4-drop.", - run: Cipher.runRc4drop, highlight: true, highlightReverse: true, inputType: "string", @@ -1411,8 +1412,8 @@ const OperationConfig = { ] }, "Derive PBKDF2 key": { + module: "Ciphers", description: "PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.

    A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.

    Enter your passphrase as the input and then set the relevant options to generate a key.", - run: Cipher.runPbkdf2, inputType: "string", outputType: "string", args: [ @@ -1449,8 +1450,8 @@ const OperationConfig = { ] }, "Derive EVP key": { + module: "Ciphers", description: "EVP is a password-based key derivation function used extensively in OpenSSL. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.

    A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.

    Enter your passphrase as the input and then set the relevant options to generate a key.", - run: Cipher.runEvpkdf, inputType: "string", outputType: "string", args: [ @@ -1487,8 +1488,8 @@ const OperationConfig = { ] }, "Vigenère Encode": { + module: "Ciphers", description: "The Vigenere cipher is a method of encrypting alphabetic text by using a series of different Caesar ciphers based on the letters of a keyword. It is a simple form of polyalphabetic substitution.", - run: Cipher.runVigenereEnc, highlight: true, highlightReverse: true, inputType: "string", @@ -1502,8 +1503,8 @@ const OperationConfig = { ] }, "Vigenère Decode": { + module: "Ciphers", description: "The Vigenere cipher is a method of encrypting alphabetic text by using a series of different Caesar ciphers based on the letters of a keyword. It is a simple form of polyalphabetic substitution.", - run: Cipher.runVigenereDec, highlight: true, highlightReverse: true, inputType: "string", @@ -1517,8 +1518,8 @@ const OperationConfig = { ] }, "Bifid Cipher Encode": { + module: "Ciphers", description: "The Bifid cipher is a cipher which uses a Polybius square in conjunction with transposition, which can be fairly difficult to decipher without knowing the alphabet keyword.", - run: Cipher.runBifidEnc, highlight: true, highlightReverse: true, inputType: "string", @@ -1532,8 +1533,8 @@ const OperationConfig = { ] }, "Bifid Cipher Decode": { + module: "Ciphers", description: "The Bifid cipher is a cipher which uses a Polybius square in conjunction with transposition, which can be fairly difficult to decipher without knowing the alphabet keyword.", - run: Cipher.runBifidDec, highlight: true, highlightReverse: true, inputType: "string", @@ -1547,8 +1548,8 @@ const OperationConfig = { ] }, "Affine Cipher Encode": { + module: "Ciphers", 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, (ax + b) % 26, and converted back to a letter.", - run: Cipher.runAffineEnc, highlight: true, highlightReverse: true, inputType: "string", @@ -1567,8 +1568,8 @@ const OperationConfig = { ] }, "Affine Cipher Decode": { + module: "Ciphers", 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.", - run: Cipher.runAffineDec, highlight: true, highlightReverse: true, inputType: "string", @@ -1587,8 +1588,8 @@ const OperationConfig = { ] }, "Atbash Cipher": { + module: "Ciphers", description: "Atbash is a mono-alphabetic substitution cipher originally used to encode the Hebrew alphabet. It has been modified here for use with the Latin alphabet.", - run: Cipher.runAtbash, highlight: true, highlightReverse: true, inputType: "string", @@ -1596,8 +1597,8 @@ const OperationConfig = { args: [] }, "Rotate right": { + module: "Default", description: "Rotates each byte to the right by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.", - run: Rotate.runRotr, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -1616,8 +1617,8 @@ const OperationConfig = { ] }, "Rotate left": { + module: "Default", description: "Rotates each byte to the left by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.", - run: Rotate.runRotl, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -1636,8 +1637,8 @@ const OperationConfig = { ] }, "ROT13": { + module: "Default", description: "A simple caesar substitution cipher which rotates alphabet characters by the specified amount (default 13).", - run: Rotate.runRot13, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -1661,8 +1662,8 @@ const OperationConfig = { ] }, "ROT47": { + module: "Default", description: "A slightly more complex variation of a caesar cipher, which includes ASCII characters from 33 '!' to 126 '~'. Default rotation: 47.", - run: Rotate.runRot47, highlight: true, highlightReverse: true, inputType: "byteArray", @@ -1676,22 +1677,22 @@ const OperationConfig = { ] }, "Strip HTTP headers": { + module: "HTTP", description: "Removes HTTP headers from a request or response by looking for the first instance of a double newline.", - run: HTTP.runStripHeaders, inputType: "string", outputType: "string", args: [] }, "Parse User Agent": { + module: "HTTP", description: "Attempts to identify and categorise information contained in a user-agent string.", - run: HTTP.runParseUserAgent, inputType: "string", outputType: "string", args: [] }, "Format MAC addresses": { + module: "Default", description: "Displays given MAC addresses in multiple different formats.

    Expects addresses in a list separated by newlines, spaces or commas.

    WARNING: There are no validity checks.", - run: MAC.runFormat, inputType: "string", outputType: "string", args: [ @@ -1723,8 +1724,8 @@ const OperationConfig = { ] }, "Encode NetBIOS Name": { + module: "Default", description: "NetBIOS names as seen across the client interface to NetBIOS are exactly 16 bytes long. Within the NetBIOS-over-TCP protocols, a longer representation is used.

    There are two levels of encoding. The first level maps a NetBIOS name into a domain system name. The second level maps the domain system name into the 'compressed' representation required for interaction with the domain name system.

    This operation carries out the first level of encoding. See RFC 1001 for full details.", - run: NetBIOS.runEncodeName, inputType: "byteArray", outputType: "byteArray", args: [ @@ -1736,8 +1737,8 @@ const OperationConfig = { ] }, "Decode NetBIOS Name": { + module: "Default", description: "NetBIOS names as seen across the client interface to NetBIOS are exactly 16 bytes long. Within the NetBIOS-over-TCP protocols, a longer representation is used.

    There are two levels of encoding. The first level maps a NetBIOS name into a domain system name. The second level maps the domain system name into the 'compressed' representation required for interaction with the domain name system.

    This operation decodes the first level of encoding. See RFC 1001 for full details.", - run: NetBIOS.runDecodeName, inputType: "byteArray", outputType: "byteArray", args: [ @@ -1749,8 +1750,8 @@ const OperationConfig = { ] }, "Offset checker": { + module: "Default", description: "Compares multiple inputs (separated by the specified delimiter) and highlights matching characters which appear at the same position in all samples.", - run: StrUtils.runOffsetChecker, inputType: "string", outputType: "html", args: [ @@ -1762,8 +1763,8 @@ const OperationConfig = { ] }, "Remove whitespace": { + module: "Default", description: "Optionally removes all spaces, carriage returns, line feeds, tabs and form feeds from the input data.

    This operation also supports the removal of full stops which are sometimes used to represent non-printable bytes in ASCII output.", - run: Tidy.runRemoveWhitespace, inputType: "string", outputType: "string", args: [ @@ -1800,15 +1801,15 @@ const OperationConfig = { ] }, "Remove null bytes": { + module: "Default", description: "Removes all null bytes (0x00) from the input.", - run: Tidy.runRemoveNulls, inputType: "byteArray", outputType: "byteArray", args: [] }, "Drop bytes": { + module: "Default", description: "Cuts the specified number of bytes out of the data.", - run: Tidy.runDropBytes, inputType: "byteArray", outputType: "byteArray", args: [ @@ -1830,8 +1831,8 @@ const OperationConfig = { ] }, "Take bytes": { + module: "Default", description: "Takes a slice of the specified number of bytes from the data.", - run: Tidy.runTakeBytes, inputType: "byteArray", outputType: "byteArray", args: [ @@ -1853,8 +1854,8 @@ const OperationConfig = { ] }, "Pad lines": { + module: "Default", description: "Add the specified number of the specified character to the beginning or end of each line", - run: Tidy.runPad, inputType: "string", outputType: "string", args: [ @@ -1876,8 +1877,8 @@ const OperationConfig = { ] }, "Reverse": { + module: "Default", description: "Reverses the input string.", - run: SeqUtils.runReverse, inputType: "byteArray", outputType: "byteArray", args: [ @@ -1889,8 +1890,8 @@ const OperationConfig = { ] }, "Sort": { + module: "Default", description: "Alphabetically sorts strings separated by the specified delimiter.

    The IP address option supports IPv4 only.", - run: SeqUtils.runSort, inputType: "string", outputType: "string", args: [ @@ -1912,8 +1913,8 @@ const OperationConfig = { ] }, "Unique": { + module: "Default", description: "Removes duplicate strings from the input.", - run: SeqUtils.runUnique, inputType: "string", outputType: "string", args: [ @@ -1925,8 +1926,8 @@ const OperationConfig = { ] }, "Count occurrences": { + module: "Default", description: "Counts the number of times the provided string occurs in the input.", - run: SeqUtils.runCount, inputType: "string", outputType: "number", args: [ @@ -1939,22 +1940,22 @@ const OperationConfig = { ] }, "Add line numbers": { + module: "Default", description: "Adds line numbers to the output.", - run: SeqUtils.runAddLineNumbers, inputType: "string", outputType: "string", args: [] }, "Remove line numbers": { + module: "Default", description: "Removes line numbers from the output if they can be trivially detected.", - run: SeqUtils.runRemoveLineNumbers, inputType: "string", outputType: "string", args: [] }, "Find / Replace": { + module: "Default", description: "Replaces all occurrences of the first string with the second.

    Includes support for regular expressions (regex), simple strings and extended strings (which support \\n, \\r, \\t, \\b, \\f and escaped hex bytes using \\x notation, e.g. \\x00 for a null byte).", - run: StrUtils.runFindReplace, manualBake: true, inputType: "string", outputType: "string", @@ -1989,8 +1990,8 @@ const OperationConfig = { ] }, "To Upper case": { + module: "Default", description: "Converts the input string to upper case, optionally limiting scope to only the first character in each word, sentence or paragraph.", - run: StrUtils.runUpper, highlight: true, highlightReverse: true, inputType: "string", @@ -2004,8 +2005,8 @@ const OperationConfig = { ] }, "To Lower case": { + module: "Default", description: "Converts every character in the input to lower case.", - run: StrUtils.runLower, highlight: true, highlightReverse: true, inputType: "string", @@ -2013,8 +2014,8 @@ const OperationConfig = { args: [] }, "Split": { + module: "Default", description: "Splits a string into sections around a given delimiter.", - run: StrUtils.runSplit, inputType: "string", outputType: "string", args: [ @@ -2031,8 +2032,8 @@ const OperationConfig = { ] }, "Filter": { + module: "Default", description: "Splits up the input using the specified delimiter and then filters each branch based on a regular expression.", - run: StrUtils.runFilter, manualBake: true, inputType: "string", outputType: "string", @@ -2055,8 +2056,8 @@ const OperationConfig = { ] }, "Strings": { + module: "Default", description: "Extracts all strings from the input.", - run: Extract.runStrings, inputType: "string", outputType: "string", args: [ @@ -2073,8 +2074,8 @@ const OperationConfig = { ] }, "Extract IP addresses": { + module: "Default", description: "Extracts all IPv4 and IPv6 addresses.

    Warning: Given a string 710.65.0.456, this will match 10.65.0.45 so always check the original input!", - run: Extract.runIp, inputType: "string", outputType: "string", args: [ @@ -2101,8 +2102,8 @@ const OperationConfig = { ] }, "Extract email addresses": { + module: "Default", description: "Extracts all email addresses from the input.", - run: Extract.runEmail, inputType: "string", outputType: "string", args: [ @@ -2114,8 +2115,8 @@ const OperationConfig = { ] }, "Extract MAC addresses": { + module: "Default", description: "Extracts all Media Access Control (MAC) addresses from the input.", - run: Extract.runMac, inputType: "string", outputType: "string", args: [ @@ -2127,8 +2128,8 @@ const OperationConfig = { ] }, "Extract URLs": { + module: "Default", description: "Extracts Uniform Resource Locators (URLs) from the input. The protocol (http, ftp etc.) is required otherwise there will be far too many false positives.", - run: Extract.runUrls, inputType: "string", outputType: "string", args: [ @@ -2140,8 +2141,8 @@ const OperationConfig = { ] }, "Extract domains": { + module: "Default", description: "Extracts domain names.
    Note that this will not include paths. Use Extract URLs to find entire URLs.", - run: Extract.runDomains, inputType: "string", outputType: "string", args: [ @@ -2153,8 +2154,8 @@ const OperationConfig = { ] }, "Extract file paths": { + module: "Default", description: "Extracts anything that looks like a Windows or UNIX file path.

    Note that if UNIX is selected, there will likely be a lot of false positives.", - run: Extract.runFilePaths, inputType: "string", outputType: "string", args: [ @@ -2176,8 +2177,8 @@ const OperationConfig = { ] }, "Extract dates": { + module: "Default", description: "Extracts dates in the following formatsDividers can be any of /, -, . or space", - run: Extract.runDates, inputType: "string", outputType: "string", args: [ @@ -2189,8 +2190,8 @@ const OperationConfig = { ] }, "Regular expression": { + module: "Default", description: "Define your own regular expression (regex) to search the input data with, optionally choosing from a list of pre-defined patterns.", - run: StrUtils.runRegex, manualBake: true, inputType: "string", outputType: "html", @@ -2229,8 +2230,8 @@ const OperationConfig = { ] }, "XPath expression": { + module: "Code", description: "Extract information from an XML document with an XPath query", - run: Code.runXpath, inputType: "string", outputType: "string", args: [ @@ -2247,8 +2248,8 @@ const OperationConfig = { ] }, "JPath expression": { + module: "Code", description: "Extract information from a JSON object with a JPath query.", - run: Code.runJpath, inputType: "string", outputType: "string", args: [ @@ -2265,8 +2266,8 @@ const OperationConfig = { ] }, "CSS selector": { + module: "Code", description: "Extract information from an HTML document with a CSS selector", - run: Code.runCSSQuery, inputType: "string", outputType: "string", args: [ @@ -2283,8 +2284,8 @@ const OperationConfig = { ] }, "From UNIX Timestamp": { + module: "Default", description: "Converts a UNIX timestamp to a datetime string.

    e.g. 978346800 becomes Mon 1 January 2001 11:00:00 UTC

    A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).", - run: DateTime.runFromUnixTimestamp, inputType: "number", outputType: "string", args: [ @@ -2296,8 +2297,8 @@ const OperationConfig = { ] }, "To UNIX Timestamp": { + module: "Default", description: "Parses a datetime string in UTC and returns the corresponding UNIX timestamp.

    e.g. Mon 1 January 2001 11:00:00 becomes 978346800

    A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).", - run: DateTime.runToUnixTimestamp, inputType: "string", outputType: "number", args: [ @@ -2314,44 +2315,44 @@ const OperationConfig = { ] }, "Windows Filetime to UNIX Timestamp": { + module: "JSBN", description: "Converts a Windows Filetime value to a UNIX timestamp.

    A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.

    A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).

    This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.", - run: DateTime.runFromFiletimeToUnix, inputType: "string", outputType: "string", args: [ { name: "Output units", type: "option", - value: DateTime.UNITS + value: Filetime.UNITS }, { name: "Input format", type: "option", - value: DateTime.FILETIME_FORMATS + value: Filetime.FILETIME_FORMATS } ] }, "UNIX Timestamp to Windows Filetime": { + module: "JSBN", description: "Converts a UNIX timestamp to a Windows Filetime value.

    A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.

    A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).

    This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.", - run: DateTime.runToFiletimeFromUnix, inputType: "string", outputType: "string", args: [ { name: "Input units", type: "option", - value: DateTime.UNITS + value: Filetime.UNITS }, { name: "Output format", type: "option", - value: DateTime.FILETIME_FORMATS + value: Filetime.FILETIME_FORMATS } ] }, "Translate DateTime Format": { + module: "Default", description: "Parses a datetime string in one format and re-writes it in another.

    Run with no input to see the relevant format string examples.", - run: DateTime.runTranslateFormat, inputType: "string", outputType: "html", args: [ @@ -2384,8 +2385,8 @@ const OperationConfig = { ] }, "Parse DateTime": { + module: "Default", description: "Parses a DateTime string in your specified format and displays it in whichever timezone you choose with the following information:Run with no input to see format string examples if required.", - run: DateTime.runParse, inputType: "string", outputType: "html", args: [ @@ -2408,8 +2409,8 @@ const OperationConfig = { ] }, "Convert distance": { + module: "Default", description: "Converts a unit of distance to another format.", - run: Convert.runDistance, inputType: "number", outputType: "number", args: [ @@ -2426,8 +2427,8 @@ const OperationConfig = { ] }, "Convert area": { + module: "Default", description: "Converts a unit of area to another format.", - run: Convert.runArea, inputType: "number", outputType: "number", args: [ @@ -2444,8 +2445,8 @@ const OperationConfig = { ] }, "Convert mass": { + module: "Default", description: "Converts a unit of mass to another format.", - run: Convert.runMass, inputType: "number", outputType: "number", args: [ @@ -2462,8 +2463,8 @@ const OperationConfig = { ] }, "Convert speed": { + module: "Default", description: "Converts a unit of speed to another format.", - run: Convert.runSpeed, inputType: "number", outputType: "number", args: [ @@ -2480,8 +2481,8 @@ const OperationConfig = { ] }, "Convert data units": { + module: "Default", description: "Converts a unit of data to another format.", - run: Convert.runDataSize, inputType: "number", outputType: "number", args: [ @@ -2498,8 +2499,8 @@ const OperationConfig = { ] }, "Raw Deflate": { + module: "Compression", description: "Compresses data using the deflate algorithm with no headers.", - run: Compress.runRawDeflate, inputType: "byteArray", outputType: "byteArray", args: [ @@ -2511,8 +2512,8 @@ const OperationConfig = { ] }, "Raw Inflate": { + module: "Compression", description: "Decompresses data which has been compressed using the deflate algorithm with no headers.", - run: Compress.runRawInflate, inputType: "byteArray", outputType: "byteArray", args: [ @@ -2544,8 +2545,8 @@ const OperationConfig = { ] }, "Zlib Deflate": { + module: "Compression", description: "Compresses data using the deflate algorithm adding zlib headers.", - run: Compress.runZlibDeflate, inputType: "byteArray", outputType: "byteArray", args: [ @@ -2557,8 +2558,8 @@ const OperationConfig = { ] }, "Zlib Inflate": { + module: "Compression", description: "Decompresses data which has been compressed using the deflate algorithm with zlib headers.", - run: Compress.runZlibInflate, inputType: "byteArray", outputType: "byteArray", args: [ @@ -2590,8 +2591,8 @@ const OperationConfig = { ] }, "Gzip": { + module: "Compression", description: "Compresses data using the deflate algorithm with gzip headers.", - run: Compress.runGzip, inputType: "byteArray", outputType: "byteArray", args: [ @@ -2618,15 +2619,15 @@ const OperationConfig = { ] }, "Gunzip": { + module: "Compression", description: "Decompresses data which has been compressed using the deflate algorithm with gzip headers.", - run: Compress.runGunzip, inputType: "byteArray", outputType: "byteArray", args: [] }, "Zip": { + module: "Compression", description: "Compresses data using the PKZIP algorithm with the given filename.

    No support for multiple files at this time.", - run: Compress.runPkzip, inputType: "byteArray", outputType: "byteArray", args: [ @@ -2663,8 +2664,8 @@ const OperationConfig = { ] }, "Unzip": { + module: "Compression", description: "Decompresses data using the PKZIP algorithm and displays it per file, with support for passwords.", - run: Compress.runPkunzip, inputType: "byteArray", outputType: "html", args: [ @@ -2681,22 +2682,22 @@ const OperationConfig = { ] }, "Bzip2 Decompress": { + module: "Compression", description: "Decompresses data using the Bzip2 algorithm.", - run: Compress.runBzip2Decompress, inputType: "byteArray", outputType: "string", args: [] }, "Generic Code Beautify": { + module: "Code", description: "Attempts to pretty print C-style languages such as C, C++, C#, Java, PHP, JavaScript etc.

    This will not do a perfect job, and the resulting code may not work any more. This operation is designed purely to make obfuscated or minified code more easy to read and understand.

    Things which will not work properly:", - run: Code.runGenericBeautify, inputType: "string", outputType: "string", args: [] }, "JavaScript Parser": { + module: "Code", description: "Returns an Abstract Syntax Tree for valid JavaScript code.", - run: JS.runParse, inputType: "string", outputType: "string", args: [ @@ -2728,8 +2729,8 @@ const OperationConfig = { ] }, "JavaScript Beautify": { + module: "Code", description: "Parses and pretty prints valid JavaScript code. Also works with JavaScript Object Notation (JSON).", - run: JS.runBeautify, inputType: "string", outputType: "string", args: [ @@ -2756,15 +2757,15 @@ const OperationConfig = { ] }, "JavaScript Minify": { + module: "Code", description: "Compresses JavaScript code.", - run: JS.runMinify, inputType: "string", outputType: "string", args: [] }, "XML Beautify": { + module: "Code", description: "Indents and prettifies eXtensible Markup Language (XML) code.", - run: Code.runXmlBeautify, inputType: "string", outputType: "string", args: [ @@ -2776,8 +2777,8 @@ const OperationConfig = { ] }, "JSON Beautify": { + module: "Code", description: "Indents and prettifies JavaScript Object Notation (JSON) code.", - run: Code.runJsonBeautify, inputType: "string", outputType: "string", args: [ @@ -2789,8 +2790,8 @@ const OperationConfig = { ] }, "CSS Beautify": { + module: "Code", description: "Indents and prettifies Cascading Style Sheets (CSS) code.", - run: Code.runCssBeautify, inputType: "string", outputType: "string", args: [ @@ -2802,8 +2803,8 @@ const OperationConfig = { ] }, "SQL Beautify": { + module: "Code", description: "Indents and prettifies Structured Query Language (SQL) code.", - run: Code.runSqlBeautify, inputType: "string", outputType: "string", args: [ @@ -2815,8 +2816,8 @@ const OperationConfig = { ] }, "XML Minify": { + module: "Code", description: "Compresses eXtensible Markup Language (XML) code.", - run: Code.runXmlMinify, inputType: "string", outputType: "string", args: [ @@ -2828,15 +2829,15 @@ const OperationConfig = { ] }, "JSON Minify": { + module: "Code", description: "Compresses JavaScript Object Notation (JSON) code.", - run: Code.runJsonMinify, inputType: "string", outputType: "string", args: [] }, "CSS Minify": { + module: "Code", description: "Compresses Cascading Style Sheets (CSS) code.", - run: Code.runCssMinify, inputType: "string", outputType: "string", args: [ @@ -2848,43 +2849,43 @@ const OperationConfig = { ] }, "SQL Minify": { + module: "Code", description: "Compresses Structured Query Language (SQL) code.", - run: Code.runSqlMinify, inputType: "string", outputType: "string", args: [] }, "Analyse hash": { + module: "Hashing", description: "Tries to determine information about a given hash and suggests which algorithm may have been used to generate it based on its length.", - run: Hash.runAnalyse, inputType: "string", outputType: "string", args: [] }, "MD2": { + module: "Hashing", description: "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.

    Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA.", - run: Hash.runMD2, inputType: "string", outputType: "string", args: [] }, "MD4": { + module: "Hashing", description: "The MD4 (Message-Digest 4) algorithm is a cryptographic hash function developed by Ronald Rivest in 1990. The digest length is 128 bits. The algorithm has influenced later designs, such as the MD5, SHA-1 and RIPEMD algorithms.

    The security of MD4 has been severely compromised.", - run: Hash.runMD4, inputType: "string", outputType: "string", args: [] }, "MD5": { + module: "Hashing", description: "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.

    However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property.", - run: Hash.runMD5, inputType: "string", outputType: "string", args: [] }, "MD6": { + module: "Hashing", description: "The MD6 (Message-Digest 6) algorithm is a cryptographic hash function. It uses a Merkle tree-like structure to allow for immense parallel computation of hashes for very long inputs.", - run: Hash.runMD6, inputType: "string", outputType: "string", args: [ @@ -2906,22 +2907,22 @@ const OperationConfig = { ] }, "SHA0": { + module: "Hashing", description: "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.", - run: Hash.runSHA0, inputType: "string", outputType: "string", args: [] }, "SHA1": { + module: "Hashing", description: "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.

    However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.", - run: Hash.runSHA1, inputType: "string", outputType: "string", args: [] }, "SHA2": { + module: "Hashing", description: "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.

    ", - run: Hash.runSHA2, inputType: "string", outputType: "string", args: [ @@ -2933,8 +2934,8 @@ const OperationConfig = { ] }, "SHA3": { + module: "Hashing", description: "The SHA-3 (Secure Hash Algorithm 3) hash functions were released by NIST on August 5, 2015. Although part of the same series of standards, SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.

    SHA-3 is a subset of the broader cryptographic primitive family Keccak designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún.", - run: Hash.runSHA3, inputType: "string", outputType: "string", args: [ @@ -2946,8 +2947,8 @@ const OperationConfig = { ] }, "Keccak": { + module: "Hashing", description: "The Keccak hash algorithm was designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún. It was selected as the winner of the SHA-3 design competition.

    This version of the algorithm is Keccak[c=2d] and differs from the SHA-3 specification.", - run: Hash.runKeccak, inputType: "string", outputType: "string", args: [ @@ -2959,8 +2960,8 @@ const OperationConfig = { ] }, "Shake": { + module: "Hashing", description: "Shake is an Extendable Output Function (XOF) of the SHA-3 hash algorithm, part of the Keccak family, allowing for variable output length/size.", - run: Hash.runShake, inputType: "string", outputType: "string", args: [ @@ -2978,8 +2979,8 @@ const OperationConfig = { }, "RIPEMD": { + module: "Hashing", description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.

    RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.

    ", - run: Hash.runRIPEMD, inputType: "string", outputType: "string", args: [ @@ -2991,8 +2992,8 @@ const OperationConfig = { ] }, "HMAC": { + module: "Hashing", description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.", - run: Hash.runHMAC, inputType: "string", outputType: "string", args: [ @@ -3009,64 +3010,64 @@ const OperationConfig = { ] }, "Fletcher-8 Checksum": { + module: "Hashing", description: "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.

    The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.", - run: Checksum.runFletcher8, inputType: "byteArray", outputType: "string", args: [] }, "Fletcher-16 Checksum": { + module: "Hashing", description: "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.

    The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.", - run: Checksum.runFletcher16, inputType: "byteArray", outputType: "string", args: [] }, "Fletcher-32 Checksum": { + module: "Hashing", description: "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.

    The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.", - run: Checksum.runFletcher32, inputType: "byteArray", outputType: "string", args: [] }, "Fletcher-64 Checksum": { + module: "Hashing", description: "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.

    The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.", - run: Checksum.runFletcher64, inputType: "byteArray", outputType: "string", args: [] }, "Adler-32 Checksum": { + module: "Hashing", 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).

    Adler-32 is more reliable than Fletcher-16, and slightly less reliable than Fletcher-32.", - run: Checksum.runAdler32, inputType: "byteArray", outputType: "string", args: [] }, "CRC-32 Checksum": { + module: "Hashing", description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.

    The CRC was invented by W. Wesley Peterson in 1961; the 32-bit CRC function of Ethernet and many other standards is the work of several researchers and was published in 1975.", - run: Checksum.runCRC32, inputType: "string", outputType: "string", args: [] }, "CRC-16 Checksum": { + module: "Hashing", description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.

    The CRC was invented by W. Wesley Peterson in 1961.", - run: Checksum.runCRC16, inputType: "string", outputType: "string", args: [] }, "Generate all hashes": { + module: "Hashing", description: "Generates all available hashes and checksums for the input.", - run: Hash.runAll, inputType: "string", outputType: "string", args: [] }, "Entropy": { + module: "Default", description: "Calculates the Shannon entropy of the input data which gives an idea of its randomness. 8 is the maximum.", - run: Entropy.runEntropy, inputType: "byteArray", outputType: "html", args: [ @@ -3078,8 +3079,8 @@ const OperationConfig = { ] }, "Frequency distribution": { + module: "Default", description: "Displays the distribution of bytes in the data as a graph.", - run: Entropy.runFreqDistrib, inputType: "byteArray", outputType: "html", args: [ @@ -3091,15 +3092,15 @@ const OperationConfig = { ] }, "Numberwang": { + module: "Default", description: "Based on the popular gameshow by Mitchell and Webb.", - run: Numberwang.run, inputType: "string", outputType: "string", args: [] }, "Parse X.509 certificate": { + module: "PublicKey", description: "X.509 is an ITU-T standard for a public key infrastructure (PKI) and Privilege Management Infrastructure (PMI). It is commonly involved with SSL/TLS security.

    This operation displays the contents of a certificate in a human readable format, similar to the openssl command line tool.", - run: PublicKey.runParseX509, inputType: "string", outputType: "string", args: [ @@ -3111,15 +3112,15 @@ const OperationConfig = { ] }, "PEM to Hex": { + module: "PublicKey", description: "Converts PEM (Privacy Enhanced Mail) format to a hexadecimal DER (Distinguished Encoding Rules) string.", - run: PublicKey.runPemToHex, inputType: "string", outputType: "string", args: [] }, "Hex to PEM": { + module: "PublicKey", description: "Converts a hexadecimal DER (Distinguished Encoding Rules) string into PEM (Privacy Enhanced Mail) format.", - run: PublicKey.runHexToPem, inputType: "string", outputType: "string", args: [ @@ -3131,22 +3132,22 @@ const OperationConfig = { ] }, "Hex to Object Identifier": { + module: "PublicKey", description: "Converts a hexadecimal string into an object identifier (OID).", - run: PublicKey.runHexToObjectIdentifier, inputType: "string", outputType: "string", args: [] }, "Object Identifier to Hex": { + module: "PublicKey", description: "Converts an object identifier (OID) into a hexadecimal string.", - run: PublicKey.runObjectIdentifierToHex, inputType: "string", outputType: "string", args: [] }, "Parse ASN.1 hex string": { + module: "PublicKey", description: "Abstract Syntax Notation One (ASN.1) is a standard and notation that describes rules and structures for representing, encoding, transmitting, and decoding data in telecommunications and computer networking.

    This operation parses arbitrary ASN.1 data and presents the resulting tree.", - run: PublicKey.runParseAsn1HexString, inputType: "string", outputType: "string", args: [ @@ -3163,15 +3164,15 @@ const OperationConfig = { ] }, "Detect File Type": { + module: "Default", description: "Attempts to guess the MIME (Multipurpose Internet Mail Extensions) type of the data based on 'magic bytes'.

    Currently supports the following file types: 7z, amr, avi, bmp, bz2, class, cr2, crx, dex, dmg, doc, elf, eot, epub, exe, flac, flv, gif, gz, ico, iso, jpg, jxr, m4a, m4v, mid, mkv, mov, mp3, mp4, mpg, ogg, otf, pdf, png, ppt, ps, psd, rar, rtf, sqlite, swf, tar, tar.z, tif, ttf, utf8, vmdk, wav, webm, webp, wmv, woff, woff2, xls, xz, zip.", - run: FileType.runDetect, inputType: "byteArray", outputType: "string", args: [] }, "Scan for Embedded Files": { + module: "Default", description: "Scans the data for potential embedded files by looking for magic bytes at all offsets. This operation is prone to false positives.

    WARNING: Files over about 100KB in size will take a VERY long time to process.", - run: FileType.runScanForEmbeddedFiles, inputType: "byteArray", outputType: "string", args: [ @@ -3183,8 +3184,8 @@ const OperationConfig = { ] }, "Expand alphabet range": { + module: "Default", description: "Expand an alphabet range string into a list of the characters in that range.

    e.g. a-z becomes abcdefghijklmnopqrstuvwxyz.", - run: SeqUtils.runExpandAlphRange, inputType: "string", outputType: "string", args: [ @@ -3196,20 +3197,20 @@ const OperationConfig = { ] }, "Diff": { + module: "Diff", description: "Compares two inputs (separated by the specified delimiter) and highlights the differences between them.", - run: StrUtils.runDiff, inputType: "string", outputType: "html", args: [ { name: "Sample delimiter", type: "binaryString", - value: StrUtils.DIFF_SAMPLE_DELIMITER + value: Diff.DIFF_SAMPLE_DELIMITER }, { name: "Diff by", type: "option", - value: StrUtils.DIFF_BY + value: Diff.DIFF_BY }, { name: "Show added", @@ -3229,15 +3230,15 @@ const OperationConfig = { ] }, "Parse UNIX file permissions": { + module: "Default", description: "Given a UNIX/Linux file permission string in octal or textual format, this operation explains which permissions are granted to which user groups.

    Input should be in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.", - run: OS.runParseUnixPerms, inputType: "string", outputType: "string", args: [] }, "Swap endianness": { + module: "Default", description: "Switches the data from big-endian to little-endian or vice-versa. Data can be read in as hexadecimal or raw bytes. It will be returned in the same format as it is entered.", - run: Endian.runSwapEndianness, highlight: true, highlightReverse: true, inputType: "string", @@ -3261,15 +3262,15 @@ const OperationConfig = { ] }, "Microsoft Script Decoder": { + module: "Default", description: "Decodes Microsoft Encoded Script files that have been encoded with Microsoft's custom encoding. These are often VBS (Visual Basic Script) files that are encoded and renamed with a '.vbe' extention or JS (JScript) files renamed with a '.jse' extention.

    Sample

    Encoded:
    #@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&@*eEI@#@&@#@&.jm.raY 214Wv:zms/obI0xEAAA==^#~@

    Decoded:
    var my_msg = "Testing <1><2><3>!";\n\nVScript.Echo(my_msg);", - run: MS.runDecodeScript, inputType: "string", outputType: "string", args: [] }, "Syntax highlighter": { + module: "Code", description: "Adds syntax highlighting to a range of source code languages. Note that this will not indent the code. Use one of the 'Beautify' operations for that.", - run: Code.runSyntaxHighlight, highlight: true, highlightReverse: true, inputType: "string", @@ -3288,29 +3289,29 @@ const OperationConfig = { ] }, "TCP/IP Checksum": { + module: "Hashing", description: "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes.", - run: Checksum.runTCPIP, inputType: "byteArray", outputType: "string", args: [] }, "Parse colour code": { + module: "Default", description: "Converts a colour code in a standard format to other standard formats and displays the colour itself.

    Example inputs", - run: HTML.runParseColourCode, inputType: "string", outputType: "html", args: [] }, "Generate UUID": { + module: "Default", description: "Generates an RFC 4122 version 4 compliant Universally Unique Identifier (UUID), also known as a Globally Unique Identifier (GUID).

    A version 4 UUID relies on random numbers, in this case generated using window.crypto if available and falling back to Math.random if not.", - run: UUID.runGenerateV4, inputType: "string", outputType: "string", args: [] }, "Substitute": { + module: "Ciphers", description: "A substitution cipher allowing you to specify bytes to replace with other byte values. This can be used to create Caesar ciphers but is more powerful as any byte value can be substituted, not just letters, and the substitution values need not be in order.

    Enter the bytes you want to replace in the Plaintext field and the bytes to replace them with in the Ciphertext field.

    Non-printable bytes can be specified using string escape notation. For example, a line feed character can be written as either \\n or \\x0a.

    Byte ranges can be specified using a hyphen. For example, the sequence 0123456789 can be written as 0-9.", - run: Cipher.runSubstitute, inputType: "string", outputType: "string", args: [ @@ -3327,22 +3328,22 @@ const OperationConfig = { ] }, "Escape string": { + module: "Default", description: "Escapes special characters in a string so that they do not cause conflicts. For example, Don't stop me now becomes Don\\'t stop me now.", - run: StrUtils.runEscape, inputType: "string", outputType: "string", args: [] }, "Unescape string": { + module: "Default", description: "Unescapes characters in a string that have been escaped. For example, Don\\'t stop me now becomes Don't stop me now.", - run: StrUtils.runUnescape, inputType: "string", outputType: "string", args: [] }, "To Morse Code": { + module: "Default", description: "Translates alphanumeric characters into International Morse Code.

    Ignores non-Morse characters.

    e.g. SOS becomes ... --- ...", - run: MorseCode.runTo, inputType: "string", outputType: "string", args: [ @@ -3364,8 +3365,8 @@ const OperationConfig = { ] }, "From Morse Code": { + module: "Default", description: "Translates Morse Code into (upper case) alphanumeric characters.", - run: MorseCode.runFrom, inputType: "string", outputType: "string", args: [ @@ -3382,8 +3383,8 @@ const OperationConfig = { ] }, "Tar": { + module: "Compression", description: "Packs the input into a tarball.

    No support for multiple files at this time.", - run: Compress.runTar, inputType: "byteArray", outputType: "byteArray", args: [ @@ -3395,14 +3396,15 @@ const OperationConfig = { ] }, "Untar": { + module: "Compression", description: "Unpacks a tarball and displays it per file.", - run: Compress.runUntar, inputType: "byteArray", outputType: "html", args: [ ] }, "Head": { + module: "Default", description: [ "Like the UNIX head utility.", "
    ", @@ -3412,7 +3414,6 @@ const OperationConfig = { "
    ", "The delimiter can be changed so that instead of lines, fields (i.e. commas) are selected instead.", ].join("\n"), - run: StrUtils.runHead, inputType: "string", outputType: "string", args: [ @@ -3429,6 +3430,7 @@ const OperationConfig = { ] }, "Tail": { + module: "Default", description: [ "Like the UNIX tail utility.", "
    ", @@ -3438,7 +3440,6 @@ const OperationConfig = { "
    ", "The delimiter can be changed so that instead of lines, fields (i.e. commas) are selected instead.", ].join("\n"), - run: StrUtils.runTail, inputType: "string", outputType: "string", args: [ @@ -3455,6 +3456,7 @@ const OperationConfig = { ] }, "To Snake case": { + module: "Code", description: [ "Converts the input string to snake case.", "

    ", @@ -3464,7 +3466,6 @@ const OperationConfig = { "

    ", "'Attempt to be context aware' will make the operation attempt to nicely transform variable and function names.", ].join("\n"), - run: Code.runToSnakeCase, inputType: "string", outputType: "string", args: [ @@ -3476,6 +3477,7 @@ const OperationConfig = { ] }, "To Camel case": { + module: "Code", description: [ "Converts the input string to camel case.", "

    ", @@ -3485,7 +3487,6 @@ const OperationConfig = { "

    ", "'Attempt to be context aware' will make the operation attempt to nicely transform variable and function names.", ].join("\n"), - run: Code.runToCamelCase, inputType: "string", outputType: "string", args: [ @@ -3497,6 +3498,7 @@ const OperationConfig = { ] }, "To Kebab case": { + module: "Code", description: [ "Converts the input string to kebab case.", "

    ", @@ -3506,7 +3508,6 @@ const OperationConfig = { "

    ", "'Attempt to be context aware' will make the operation attempt to nicely transform variable and function names.", ].join("\n"), - run: Code.runToKebabCase, inputType: "string", outputType: "string", args: [ @@ -3518,6 +3519,7 @@ const OperationConfig = { ] }, "Extract EXIF": { + module: "Image", description: [ "Extracts EXIF data from an image.", "

    ", @@ -3525,14 +3527,13 @@ const OperationConfig = { "

    ", "EXIF data from photos usually contains information about the image file itself as well as the device used to create it.", ].join("\n"), - run: Image.runExtractEXIF, inputType: "byteArray", outputType: "string", args: [], }, "Render Image": { + module: "Image", description: "Displays the input as an image. Supports the following formats:

    ", - run: Image.runRenderImage, inputType: "string", outputType: "html", args: [ @@ -3544,17 +3545,18 @@ const OperationConfig = { ] }, "Remove EXIF": { + module: "Image", description: [ "Removes EXIF data from a JPEG image.", "

    ", "EXIF data embedded in photos usually contains information about the image file itself as well as the device used to create it.", ].join("\n"), - run: Image.runRemoveEXIF, inputType: "byteArray", outputType: "byteArray", args: [] }, "HTTP request": { + module: "HTTP", description: [ "Makes an HTTP request and returns the response.", "

    ", @@ -3564,7 +3566,6 @@ const OperationConfig = { "

    ", "The status code of the response, along with a limited selection of exposed headers, can be viewed by checking the 'Show response metadata' option. Only a limited set of response headers are exposed by the browser for security reasons.", ].join("\n"), - run: HTTP.runHTTPRequest, inputType: "string", outputType: "string", manualBake: true, @@ -3597,8 +3598,8 @@ const OperationConfig = { ] }, "From BCD": { + module: "Default", description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign.", - run: BCD.runFromBCD, inputType: "string", outputType: "number", args: [ @@ -3626,8 +3627,8 @@ const OperationConfig = { }, "To BCD": { + module: "Default", description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign", - run: BCD.runToBCD, inputType: "number", outputType: "string", args: [ @@ -3655,8 +3656,8 @@ const OperationConfig = { }, "Bit shift left": { + module: "Default", description: "Shifts the bits in each byte towards the left by the specified amount.", - run: BitwiseOp.runBitShiftLeft, inputType: "byteArray", outputType: "byteArray", highlight: true, @@ -3670,8 +3671,8 @@ const OperationConfig = { ] }, "Bit shift right": { + module: "Default", description: "Shifts the bits in each byte towards the right by the specified amount.

    Logical shifts replace the leftmost bits with zeros.
    Arithmetic shifts preserve the most significant bit (MSB) of the original byte keeping the sign the same (positive or negative).", - run: BitwiseOp.runBitShiftRight, inputType: "byteArray", outputType: "byteArray", highlight: true, @@ -3690,8 +3691,8 @@ const OperationConfig = { ] }, "Generate TOTP": { + module: "Default", description: "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.

    Enter the secret as the input or leave it blank for a random secret to be generated. T0 and T1 are in seconds.", - run: OTP.runTOTP, inputType: "byteArray", outputType: "string", args: [ @@ -3723,8 +3724,8 @@ const OperationConfig = { ] }, "Generate HOTP": { + module: "Default", description: "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems.

    Enter the secret as the input or leave it blank for a random secret to be generated.", - run: OTP.runHOTP, inputType: "string", outputType: "string", args: [ @@ -3752,4 +3753,19 @@ const OperationConfig = { }, }; -export default OperationConfig; + +/** + * Exports the OperationConfig JSON object in val-loader format so that it can be loaded + * into the app without also importing all the dependencies. + * + * See https://github.com/webpack-contrib/val-loader + * + * @returns {Object} + */ +function valExport() { + return { + code: "module.exports = " + JSON.stringify(OperationConfig) + ";" + }; +} + +export default valExport; diff --git a/src/core/config/modules/CharEnc.js b/src/core/config/modules/CharEnc.js new file mode 100644 index 00000000..4c27ebed --- /dev/null +++ b/src/core/config/modules/CharEnc.js @@ -0,0 +1,22 @@ +import CharEnc from "../../operations/CharEnc.js"; + + +/** + * CharEnc module. + * + * Libraries: + * - cptable + * - CryptoJS + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.CharEnc = { + "Encode text": CharEnc.runEncode, + "Decode text": CharEnc.runDecode, +}; + +export default OpModules; diff --git a/src/core/config/modules/Ciphers.js b/src/core/config/modules/Ciphers.js new file mode 100644 index 00000000..de7e1f20 --- /dev/null +++ b/src/core/config/modules/Ciphers.js @@ -0,0 +1,42 @@ +import Cipher from "../../operations/Cipher.js"; + + +/** + * Ciphers module. + * + * Libraries: + * - CryptoJS + * - Blowfish + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Ciphers = { + "AES Encrypt": Cipher.runAesEnc, + "AES Decrypt": Cipher.runAesDec, + "Blowfish Encrypt": Cipher.runBlowfishEnc, + "Blowfish Decrypt": Cipher.runBlowfishDec, + "DES Encrypt": Cipher.runDesEnc, + "DES Decrypt": Cipher.runDesDec, + "Triple DES Encrypt": Cipher.runTripleDesEnc, + "Triple DES Decrypt": Cipher.runTripleDesDec, + "Rabbit Encrypt": Cipher.runRabbitEnc, + "Rabbit Decrypt": Cipher.runRabbitDec, + "Derive PBKDF2 key": Cipher.runPbkdf2, + "Derive EVP key": Cipher.runEvpkdf, + "RC4": Cipher.runRc4, + "RC4 Drop": Cipher.runRc4drop, + "Vigenère Encode": Cipher.runVigenereEnc, + "Vigenère Decode": Cipher.runVigenereDec, + "Bifid Cipher Encode": Cipher.runBifidEnc, + "Bifid Cipher Decode": Cipher.runBifidDec, + "Affine Cipher Encode": Cipher.runAffineEnc, + "Affine Cipher Decode": Cipher.runAffineDec, + "Atbash Cipher": Cipher.runAtbash, + "Substitute": Cipher.runSubstitute, +}; + +export default OpModules; diff --git a/src/core/config/modules/Code.js b/src/core/config/modules/Code.js new file mode 100644 index 00000000..c4807240 --- /dev/null +++ b/src/core/config/modules/Code.js @@ -0,0 +1,44 @@ +import JS from "../../operations/JS.js"; +import Code from "../../operations/Code.js"; + + +/** + * Code module. + * + * Libraries: + * - lodash + * - vkbeautify + * - xmldom + * - xpath + * - jpath + * - googlecodeprettify + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Code = { + "JavaScript Parser": JS.runParse, + "JavaScript Beautify": JS.runBeautify, + "JavaScript Minify": JS.runMinify, + "Syntax highlighter": Code.runSyntaxHighlight, + "Generic Code Beautify": Code.runGenericBeautify, + "JSON Beautify": Code.runJsonBeautify, + "JSON Minify": Code.runJsonMinify, + "XML Beautify": Code.runXmlBeautify, + "XML Minify": Code.runXmlMinify, + "SQL Beautify": Code.runSqlBeautify, + "SQL Minify": Code.runSqlMinify, + "CSS Beautify": Code.runCssBeautify, + "CSS Minify": Code.runCssMinify, + "XPath expression": Code.runXpath, + "CSS selector": Code.runCSSQuery, + "To Snake case": Code.runToSnakeCase, + "To Camel case": Code.runToCamelCase, + "To Kebab case": Code.runToKebabCase, + "JPath expression": Code.runJpath, +}; + +export default OpModules; diff --git a/src/core/config/modules/Compression.js b/src/core/config/modules/Compression.js new file mode 100644 index 00000000..aa8d074f --- /dev/null +++ b/src/core/config/modules/Compression.js @@ -0,0 +1,32 @@ +import Compress from "../../operations/Compress.js"; + + +/** + * Compression module. + * + * Libraries: + * - zlib.js + * - bzip2.js + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Compression = { + "Raw Deflate": Compress.runRawDeflate, + "Raw Inflate": Compress.runRawInflate, + "Zlib Deflate": Compress.runZlibDeflate, + "Zlib Inflate": Compress.runZlibInflate, + "Gzip": Compress.runGzip, + "Gunzip": Compress.runGunzip, + "Zip": Compress.runPkzip, + "Unzip": Compress.runPkunzip, + "Bzip2 Decompress": Compress.runBzip2Decompress, + "Tar": Compress.runTar, + "Untar": Compress.runUntar, + +}; + +export default OpModules; diff --git a/src/core/config/modules/Default.js b/src/core/config/modules/Default.js new file mode 100644 index 00000000..9af165d0 --- /dev/null +++ b/src/core/config/modules/Default.js @@ -0,0 +1,191 @@ +import FlowControl from "../../FlowControl.js"; +import Base from "../../operations/Base.js"; +import Base58 from "../../operations/Base58.js"; +import Base64 from "../../operations/Base64.js"; +import BCD from "../../operations/BCD.js"; +import BitwiseOp from "../../operations/BitwiseOp.js"; +import ByteRepr from "../../operations/ByteRepr.js"; +import Convert from "../../operations/Convert.js"; +import DateTime from "../../operations/DateTime.js"; +import Endian from "../../operations/Endian.js"; +import Entropy from "../../operations/Entropy.js"; +import Extract from "../../operations/Extract.js"; +import FileType from "../../operations/FileType.js"; +import Hexdump from "../../operations/Hexdump.js"; +import HTML from "../../operations/HTML.js"; +import MAC from "../../operations/MAC.js"; +import MorseCode from "../../operations/MorseCode.js"; +import MS from "../../operations/MS.js"; +import NetBIOS from "../../operations/NetBIOS.js"; +import Numberwang from "../../operations/Numberwang.js"; +import OS from "../../operations/OS.js"; +import OTP from "../../operations/OTP.js"; +import QuotedPrintable from "../../operations/QuotedPrintable.js"; +import Rotate from "../../operations/Rotate.js"; +import SeqUtils from "../../operations/SeqUtils.js"; +import StrUtils from "../../operations/StrUtils.js"; +import Tidy from "../../operations/Tidy.js"; +import Unicode from "../../operations/Unicode.js"; +import URL_ from "../../operations/URL.js"; +import UUID from "../../operations/UUID.js"; + + +/** + * Default module. + * + * The Default module is for operations that are expected to be very commonly used or + * do not require any libraries. This module is loaded into the app at compile time. + * + * Libraries: + * - Utils.js + * - CryptoJS + * - otp + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Default = { + "To Hexdump": Hexdump.runTo, + "From Hexdump": Hexdump.runFrom, + "To Hex": ByteRepr.runToHex, + "From Hex": ByteRepr.runFromHex, + "To Octal": ByteRepr.runToOct, + "From Octal": ByteRepr.runFromOct, + "To Charcode": ByteRepr.runToCharcode, + "From Charcode": ByteRepr.runFromCharcode, + "To Decimal": ByteRepr.runToDecimal, + "From Decimal": ByteRepr.runFromDecimal, + "To Binary": ByteRepr.runToBinary, + "From Binary": ByteRepr.runFromBinary, + "To Hex Content": ByteRepr.runToHexContent, + "From Hex Content": ByteRepr.runFromHexContent, + "To Base64": Base64.runTo, + "From Base64": Base64.runFrom, + "Show Base64 offsets": Base64.runOffsets, + "To Base32": Base64.runTo32, + "From Base32": Base64.runFrom32, + "To Base58": Base58.runTo, + "From Base58": Base58.runFrom, + "To Base": Base.runTo, + "From Base": Base.runFrom, + "To BCD": BCD.runToBCD, + "From BCD": BCD.runFromBCD, + "To HTML Entity": HTML.runToEntity, + "From HTML Entity": HTML.runFromEntity, + "Strip HTML tags": HTML.runStripTags, + "Parse colour code": HTML.runParseColourCode, + "URL Encode": URL_.runTo, + "URL Decode": URL_.runFrom, + "Parse URI": URL_.runParse, + "Unescape Unicode Characters": Unicode.runUnescape, + "To Quoted Printable": QuotedPrintable.runTo, + "From Quoted Printable": QuotedPrintable.runFrom, + "Swap endianness": Endian.runSwapEndianness, + "ROT13": Rotate.runRot13, + "ROT47": Rotate.runRot47, + "Rotate left": Rotate.runRotl, + "Rotate right": Rotate.runRotr, + "Bit shift left": BitwiseOp.runBitShiftLeft, + "Bit shift right": BitwiseOp.runBitShiftRight, + "XOR": BitwiseOp.runXor, + "XOR Brute Force": BitwiseOp.runXorBrute, + "OR": BitwiseOp.runXor, + "NOT": BitwiseOp.runNot, + "AND": BitwiseOp.runAnd, + "ADD": BitwiseOp.runAdd, + "SUB": BitwiseOp.runSub, + "To Morse Code": MorseCode.runTo, + "From Morse Code": MorseCode.runFrom, + "Format MAC addresses": MAC.runFormat, + "Encode NetBIOS Name": NetBIOS.runEncodeName, + "Decode NetBIOS Name": NetBIOS.runDecodeName, + "Regular expression": StrUtils.runRegex, + "Offset checker": StrUtils.runOffsetChecker, + "To Upper case": StrUtils.runUpper, + "To Lower case": StrUtils.runLower, + "Find / Replace": StrUtils.runFindReplace, + "Split": StrUtils.runSplit, + "Filter": StrUtils.runFilter, + "Escape string": StrUtils.runEscape, + "Unescape string": StrUtils.runUnescape, + "Head": StrUtils.runHead, + "Tail": StrUtils.runTail, + "Remove whitespace": Tidy.runRemoveWhitespace, + "Remove null bytes": Tidy.runRemoveNulls, + "Drop bytes": Tidy.runDropBytes, + "Take bytes": Tidy.runTakeBytes, + "Pad lines": Tidy.runPad, + "Reverse": SeqUtils.runReverse, + "Sort": SeqUtils.runSort, + "Unique": SeqUtils.runUnique, + "Count occurrences": SeqUtils.runCount, + "Add line numbers": SeqUtils.runAddLineNumbers, + "Remove line numbers": SeqUtils.runRemoveLineNumbers, + "Expand alphabet range": SeqUtils.runExpandAlphRange, + "Convert distance": Convert.runDistance, + "Convert area": Convert.runArea, + "Convert mass": Convert.runMass, + "Convert speed": Convert.runSpeed, + "Convert data units": Convert.runDataSize, + "Parse UNIX file permissions": OS.runParseUnixPerms, + "Parse DateTime": DateTime.runParse, + "Translate DateTime Format": DateTime.runTranslateFormat, + "From UNIX Timestamp": DateTime.runFromUnixTimestamp, + "To UNIX Timestamp": DateTime.runToUnixTimestamp, + "Strings": Extract.runStrings, + "Extract IP addresses": Extract.runIp, + "Extract email addresses": Extract.runEmail, + "Extract MAC addresses": Extract.runMac, + "Extract URLs": Extract.runUrls, + "Extract domains": Extract.runDomains, + "Extract file paths": Extract.runFilePaths, + "Extract dates": Extract.runDates, + "Microsoft Script Decoder": MS.runDecodeScript, + "Entropy": Entropy.runEntropy, + "Frequency distribution": Entropy.runFreqDistrib, + "Detect File Type": FileType.runDetect, + "Scan for Embedded Files": FileType.runScanForEmbeddedFiles, + "Generate UUID": UUID.runGenerateV4, + "Numberwang": Numberwang.run, + "Generate TOTP": OTP.runTOTP, + "Generate HOTP": OTP.runHOTP, + "Fork": FlowControl.runFork, + "Merge": FlowControl.runMerge, + "Jump": FlowControl.runJump, + "Conditional Jump": FlowControl.runCondJump, + "Return": FlowControl.runReturn, + "Comment": FlowControl.runComment, + + + /* + Highlighting functions. + + This is a temporary solution as highlighting should be entirely + overhauled at some point. + */ + "From Base64-highlight": Base64.highlightFrom, + "From Base64-highlightReverse": Base64.highlightTo, + "To Base64-highlight": Base64.highlightTo, + "To Base64-highlightReverse": Base64.highlightFrom, + "From Hex-highlight": ByteRepr.highlightFrom, + "From Hex-highlightReverse": ByteRepr.highlightTo, + "To Hex-highlight": ByteRepr.highlightTo, + "To Hex-highlightReverse": ByteRepr.highlightFrom, + "From Charcode-highlight": ByteRepr.highlightFrom, + "From Charcode-highlightReverse": ByteRepr.highlightTo, + "To Charcode-highlight": ByteRepr.highlightTo, + "To Charcode-highlightReverse": ByteRepr.highlightFrom, + "From Binary-highlight": ByteRepr.highlightFromBinary, + "From Binary-highlightReverse": ByteRepr.highlightToBinary, + "To Binary-highlight": ByteRepr.highlightToBinary, + "To Binary-highlightReverse": ByteRepr.highlightFromBinary, + "From Hexdump-highlight": Hexdump.highlightFrom, + "From Hexdump-highlightReverse": Hexdump.highlightTo, + "To Hexdump-highlight": Hexdump.highlightTo, + "To Hexdump-highlightReverse": Hexdump.highlightFrom, +}; + +export default OpModules; diff --git a/src/core/config/modules/Diff.js b/src/core/config/modules/Diff.js new file mode 100644 index 00000000..e6888a3a --- /dev/null +++ b/src/core/config/modules/Diff.js @@ -0,0 +1,20 @@ +import Diff from "../../operations/Diff.js"; + + +/** + * Diff module. + * + * Libraries: + * - JsDIff + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Diff = { + "Diff": Diff.runDiff, +}; + +export default OpModules; diff --git a/src/core/config/modules/Encodings.js b/src/core/config/modules/Encodings.js new file mode 100644 index 00000000..c029117c --- /dev/null +++ b/src/core/config/modules/Encodings.js @@ -0,0 +1,21 @@ +import Punycode from "../../operations/Punycode.js"; + + +/** + * Encodings module. + * + * Libraries: + * - punycode + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Encodings = { + "To Punycode": Punycode.runToAscii, + "From Punycode": Punycode.runToUnicode, +}; + +export default OpModules; diff --git a/src/core/config/modules/HTTP.js b/src/core/config/modules/HTTP.js new file mode 100644 index 00000000..8972a3e6 --- /dev/null +++ b/src/core/config/modules/HTTP.js @@ -0,0 +1,22 @@ +import HTTP from "../../operations/HTTP.js"; + + +/** + * HTTP module. + * + * Libraries: + * - UAS_parser + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.HTTP = { + "HTTP request": HTTP.runHTTPRequest, + "Strip HTTP headers": HTTP.runStripHeaders, + "Parse User Agent": HTTP.runParseUserAgent, +}; + +export default OpModules; diff --git a/src/core/config/modules/Hashing.js b/src/core/config/modules/Hashing.js new file mode 100644 index 00000000..a04b87e3 --- /dev/null +++ b/src/core/config/modules/Hashing.js @@ -0,0 +1,45 @@ +import Checksum from "../../operations/Checksum.js"; +import Hash from "../../operations/Hash.js"; + + +/** + * Hashing module. + * + * Libraries: + * - CryptoApi + * - node-md6 + * - js-sha3 + * - ./Checksum.js + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Hashing = { + "Analyse hash": Hash.runAnalyse, + "Generate all hashes": Hash.runAll, + "MD2": Hash.runMD2, + "MD4": Hash.runMD4, + "MD5": Hash.runMD5, + "MD6": Hash.runMD6, + "SHA0": Hash.runSHA0, + "SHA1": Hash.runSHA1, + "SHA2": Hash.runSHA2, + "SHA3": Hash.runSHA3, + "Keccak": Hash.runKeccak, + "Shake": Hash.runShake, + "RIPEMD": Hash.runRIPEMD, + "HMAC": Hash.runHMAC, + "Fletcher-8 Checksum": Checksum.runFletcher8, + "Fletcher-16 Checksum": Checksum.runFletcher16, + "Fletcher-32 Checksum": Checksum.runFletcher32, + "Fletcher-64 Checksum": Checksum.runFletcher64, + "Adler-32 Checksum": Checksum.runAdler32, + "CRC-16 Checksum": Checksum.runCRC16, + "CRC-32 Checksum": Checksum.runCRC32, + "TCP/IP Checksum": Checksum.runTCPIP, +}; + +export default OpModules; diff --git a/src/core/config/modules/Image.js b/src/core/config/modules/Image.js new file mode 100644 index 00000000..7ce03cba --- /dev/null +++ b/src/core/config/modules/Image.js @@ -0,0 +1,25 @@ +import Image from "../../operations/Image.js"; + + +/** + * Image module. + * + * Libraries: + * - exif-parser + * - remove-exif + * - ./FileType.js + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Image = { + "Extract EXIF": Image.runExtractEXIF, + "Remove EXIF": Image.runRemoveEXIF, + "Render Image": Image.runRenderImage, + +}; + +export default OpModules; diff --git a/src/core/config/modules/JSBN.js b/src/core/config/modules/JSBN.js new file mode 100644 index 00000000..53718924 --- /dev/null +++ b/src/core/config/modules/JSBN.js @@ -0,0 +1,28 @@ +import IP from "../../operations/IP.js"; +import Filetime from "../../operations/Filetime.js"; + + +/** + * JSBN module. + * + * Libraries: + * - jsbn + * - ./Checksum.js + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.JSBN = { + "Parse IP range": IP.runParseIpRange, + "Parse IPv6 address": IP.runParseIPv6, + "Parse IPv4 header": IP.runParseIPv4Header, + "Change IP format": IP.runChangeIpFormat, + "Group IP addresses": IP.runGroupIps, + "Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix, + "UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix, +}; + +export default OpModules; diff --git a/src/core/config/modules/OpModules.js b/src/core/config/modules/OpModules.js new file mode 100644 index 00000000..831a0e27 --- /dev/null +++ b/src/core/config/modules/OpModules.js @@ -0,0 +1,37 @@ +/** + * Imports all modules for builds which do not load modules separately. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import OpModules from "./Default.js"; +import CharEncModule from "./CharEnc.js"; +import CipherModule from "./Ciphers.js"; +import CodeModule from "./Code.js"; +import CompressionModule from "./Compression.js"; +import DiffModule from "./Diff.js"; +import EncodingModule from "./Encodings.js"; +import HashingModule from "./Hashing.js"; +import HTTPModule from "./HTTP.js"; +import ImageModule from "./Image.js"; +import JSBNModule from "./JSBN.js"; +import PublicKeyModule from "./PublicKey.js"; + +Object.assign( + OpModules, + CharEncModule, + CipherModule, + CodeModule, + CompressionModule, + DiffModule, + EncodingModule, + HashingModule, + HTTPModule, + ImageModule, + JSBNModule, + PublicKeyModule +); + +export default OpModules; diff --git a/src/core/config/modules/PublicKey.js b/src/core/config/modules/PublicKey.js new file mode 100644 index 00000000..cbf46ccc --- /dev/null +++ b/src/core/config/modules/PublicKey.js @@ -0,0 +1,25 @@ +import PublicKey from "../../operations/PublicKey.js"; + + +/** + * PublicKey module. + * + * Libraries: + * - jsrsasign + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.PublicKey = { + "Parse X.509 certificate": PublicKey.runParseX509, + "Parse ASN.1 hex string": PublicKey.runParseAsn1HexString, + "PEM to Hex": PublicKey.runPemToHex, + "Hex to PEM": PublicKey.runHexToPem, + "Hex to Object Identifier": PublicKey.runHexToObjectIdentifier, + "Object Identifier to Hex": PublicKey.runObjectIdentifierToHex, +}; + +export default OpModules; diff --git a/src/core/operations/BitwiseOp.js b/src/core/operations/BitwiseOp.js index bc971136..7512aa32 100755 --- a/src/core/operations/BitwiseOp.js +++ b/src/core/operations/BitwiseOp.js @@ -1,5 +1,4 @@ import Utils from "../Utils.js"; -import CryptoJS from "crypto-js"; /** @@ -92,7 +91,7 @@ const BitwiseOp = { * @constant * @default */ - XOR_BRUTE_KEY_LENGTH: ["1", "2"], + XOR_BRUTE_KEY_LENGTH: 1, /** * @constant * @default @@ -122,37 +121,62 @@ const BitwiseOp = { * @returns {string} */ runXorBrute: function (input, args) { - const keyLength = parseInt(args[0], 10), + const keyLength = args[0], sampleLength = args[1], sampleOffset = args[2], scheme = args[3], nullPreserving = args[4], printKey = args[5], outputHex = args[6], - crib = args[7]; + crib = args[7].toLowerCase(); - let output = "", + let output = [], result, resultUtf8, - regex; + record = ""; input = input.slice(sampleOffset, sampleOffset + sampleLength); - if (crib !== "") { - regex = new RegExp(crib, "im"); - } + if (ENVIRONMENT_IS_WORKER()) + self.sendStatusMessage("Calculating " + Math.pow(256, keyLength) + " values..."); + /** + * Converts an integer to an array of bytes expressing that number. + * + * @param {number} int + * @param {number} len - Length of the resulting array + * @returns {array} + */ + const intToByteArray = (int, len) => { + let res = Array(len).fill(0); + for (let i = len - 1; i >= 0; i--) { + res[i] = int & 0xff; + int = int >>> 8; + } + return res; + }; for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) { - result = BitwiseOp._bitOp(input, Utils.fromHex(key.toString(16)), BitwiseOp._xor, nullPreserving, scheme); + if (key % 10000 === 0 && ENVIRONMENT_IS_WORKER()) { + self.sendStatusMessage("Calculating " + l + " values... " + Math.floor(key / l * 100) + "%"); + } + + result = BitwiseOp._bitOp(input, intToByteArray(key, keyLength), BitwiseOp._xor, nullPreserving, scheme); resultUtf8 = Utils.byteArrayToUtf8(result); - if (crib !== "" && resultUtf8.search(regex) === -1) continue; - if (printKey) output += "Key = " + Utils.hex(key, (2*keyLength)) + ": "; - if (outputHex) output += Utils.toHex(result) + "\n"; - else output += Utils.printable(resultUtf8, false) + "\n"; - if (printKey) output += "\n"; + record = ""; + + if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue; + if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": "; + if (outputHex) { + record += Utils.toHex(result); + } else { + record += Utils.printable(resultUtf8, false); + } + + output.push(record); } - return output; + + return output.join("\n"); }, diff --git a/src/core/operations/ByteRepr.js b/src/core/operations/ByteRepr.js index 5a845c70..3564e5d6 100755 --- a/src/core/operations/ByteRepr.js +++ b/src/core/operations/ByteRepr.js @@ -119,11 +119,11 @@ const ByteRepr = { else if (ordinal < 4294967296) padding = 8; else padding = 2; - if (padding > 2 && app) app.options.attemptHighlight = false; + if (padding > 2 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); output += Utils.hex(ordinal, padding) + delim; } else { - if (app) app.options.attemptHighlight = false; + if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); output += ordinal.toString(base) + delim; } } @@ -149,9 +149,7 @@ const ByteRepr = { throw "Error: Base argument must be between 2 and 36"; } - if (base !== 16 && app) { - app.options.attemptHighlight = false; - } + if (base !== 16 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); // Split into groups of 2 if the whole string is concatenated and // too long to be a single character diff --git a/src/core/operations/DateTime.js b/src/core/operations/DateTime.js index b665a2b5..523206b2 100755 --- a/src/core/operations/DateTime.js +++ b/src/core/operations/DateTime.js @@ -1,5 +1,3 @@ -import {BigInteger} from "jsbn"; - /** * Date and time operations. * @@ -80,85 +78,6 @@ const DateTime = { }, - /** - * Windows Filetime to Unix Timestamp operation. - * - * @author bwhitn [brian.m.whitney@outlook.com] - * @param {string} input - * @param {Object[]} args - * @returns {string} - */ - runFromFiletimeToUnix: function(input, args) { - let units = args[0], - format = args[1]; - - if (format === "Hex") { - input = new BigInteger(input, 16); - } else { - input = new BigInteger(input); - } - - input = input.subtract(new BigInteger("116444736000000000")); - - if (units === "Seconds (s)"){ - input = input.divide(new BigInteger("10000000")); - } else if (units === "Milliseconds (ms)") { - input = input.divide(new BigInteger("10000")); - } else if (units === "Microseconds (μs)") { - input = input.divide(new BigInteger("10")); - } else if (units === "Nanoseconds (ns)") { - input = input.multiply(new BigInteger("100")); - } else { - throw "Unrecognised unit"; - } - - return input.toString(); - }, - - - /** - * Unix Timestamp to Windows Filetime operation. - * - * @author bwhitn [brian.m.whitney@outlook.com] - * @param {string} input - * @param {Object[]} args - * @returns {string} - */ - runToFiletimeFromUnix: function(input, args) { - let units = args[0], - format = args[1]; - - input = new BigInteger(input); - - if (units === "Seconds (s)"){ - input = input.multiply(new BigInteger("10000000")); - } else if (units === "Milliseconds (ms)") { - input = input.multiply(new BigInteger("10000")); - } else if (units === "Microseconds (μs)") { - input = input.multiply(new BigInteger("10")); - } else if (units === "Nanoseconds (ns)") { - input = input.divide(new BigInteger("100")); - } else { - throw "Unrecognised unit"; - } - - input = input.add(new BigInteger("116444736000000000")); - - if (format === "Hex"){ - return input.toString(16); - } else { - return input.toString(); - } - }, - - - /** - * @constant - * @default - */ - FILETIME_FORMATS: ["Decimal", "Hex"], - - /** * @constant * @default diff --git a/src/core/operations/Diff.js b/src/core/operations/Diff.js new file mode 100644 index 00000000..afa00c37 --- /dev/null +++ b/src/core/operations/Diff.js @@ -0,0 +1,94 @@ +import Utils from "../Utils.js"; +import * as JsDiff from "diff"; + + +/** + * Diff operations. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @namespace + */ +const Diff = { + + /** + * @constant + * @default + */ + DIFF_SAMPLE_DELIMITER: "\\n\\n", + /** + * @constant + * @default + */ + DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"], + + /** + * Diff operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + runDiff: function(input, args) { + let sampleDelim = args[0], + diffBy = args[1], + showAdded = args[2], + showRemoved = args[3], + ignoreWhitespace = args[4], + samples = input.split(sampleDelim), + output = "", + diff; + + if (!samples || samples.length !== 2) { + return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?"; + } + + switch (diffBy) { + case "Character": + diff = JsDiff.diffChars(samples[0], samples[1]); + break; + case "Word": + if (ignoreWhitespace) { + diff = JsDiff.diffWords(samples[0], samples[1]); + } else { + diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]); + } + break; + case "Line": + if (ignoreWhitespace) { + diff = JsDiff.diffTrimmedLines(samples[0], samples[1]); + } else { + diff = JsDiff.diffLines(samples[0], samples[1]); + } + break; + case "Sentence": + diff = JsDiff.diffSentences(samples[0], samples[1]); + break; + case "CSS": + diff = JsDiff.diffCss(samples[0], samples[1]); + break; + case "JSON": + diff = JsDiff.diffJson(samples[0], samples[1]); + break; + default: + return "Invalid 'Diff by' option."; + } + + for (let i = 0; i < diff.length; i++) { + if (diff[i].added) { + if (showAdded) output += "" + Utils.escapeHtml(diff[i].value) + ""; + } else if (diff[i].removed) { + if (showRemoved) output += "" + Utils.escapeHtml(diff[i].value) + ""; + } else { + output += Utils.escapeHtml(diff[i].value); + } + } + + return output; + }, + +}; + +export default Diff; diff --git a/src/core/operations/Extract.js b/src/core/operations/Extract.js index d822830a..54b25b32 100755 --- a/src/core/operations/Extract.js +++ b/src/core/operations/Extract.js @@ -258,39 +258,6 @@ const Extract = { return Extract._search(input, regex, null, displayTotal); }, - - /** - * Extract all identifiers operation. - * - * @param {string} input - * @param {Object[]} args - * @returns {string} - */ - runAllIdents: function(input, args) { - let output = ""; - output += "IP addresses\n"; - output += Extract.runIp(input, [true, true, false]); - - output += "\nEmail addresses\n"; - output += Extract.runEmail(input, []); - - output += "\nMAC addresses\n"; - output += Extract.runMac(input, []); - - output += "\nURLs\n"; - output += Extract.runUrls(input, []); - - output += "\nDomain names\n"; - output += Extract.runDomains(input, []); - - output += "\nFile paths\n"; - output += Extract.runFilePaths(input, [true, true]); - - output += "\nDates\n"; - output += Extract.runDates(input, []); - return output; - }, - }; export default Extract; diff --git a/src/core/operations/Filetime.js b/src/core/operations/Filetime.js new file mode 100644 index 00000000..5b419d28 --- /dev/null +++ b/src/core/operations/Filetime.js @@ -0,0 +1,99 @@ +import {BigInteger} from "jsbn"; + +/** + * Windows Filetime operations. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * @namespace + */ +const Filetime = { + + /** + * @constant + * @default + */ + UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"], + + /** + * @constant + * @default + */ + FILETIME_FORMATS: ["Decimal", "Hex"], + + /** + * Windows Filetime to Unix Timestamp operation. + * + * @author bwhitn [brian.m.whitney@outlook.com] + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runFromFiletimeToUnix: function(input, args) { + let units = args[0], + format = args[1]; + + if (format === "Hex") { + input = new BigInteger(input, 16); + } else { + input = new BigInteger(input); + } + + input = input.subtract(new BigInteger("116444736000000000")); + + if (units === "Seconds (s)"){ + input = input.divide(new BigInteger("10000000")); + } else if (units === "Milliseconds (ms)") { + input = input.divide(new BigInteger("10000")); + } else if (units === "Microseconds (μs)") { + input = input.divide(new BigInteger("10")); + } else if (units === "Nanoseconds (ns)") { + input = input.multiply(new BigInteger("100")); + } else { + throw "Unrecognised unit"; + } + + return input.toString(); + }, + + + /** + * Unix Timestamp to Windows Filetime operation. + * + * @author bwhitn [brian.m.whitney@outlook.com] + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runToFiletimeFromUnix: function(input, args) { + let units = args[0], + format = args[1]; + + input = new BigInteger(input); + + if (units === "Seconds (s)"){ + input = input.multiply(new BigInteger("10000000")); + } else if (units === "Milliseconds (ms)") { + input = input.multiply(new BigInteger("10000")); + } else if (units === "Microseconds (μs)") { + input = input.multiply(new BigInteger("10")); + } else if (units === "Nanoseconds (ns)") { + input = input.divide(new BigInteger("100")); + } else { + throw "Unrecognised unit"; + } + + input = input.add(new BigInteger("116444736000000000")); + + if (format === "Hex"){ + return input.toString(16); + } else { + return input.toString(); + } + }, + +}; + +export default Filetime; diff --git a/src/core/operations/Hexdump.js b/src/core/operations/Hexdump.js index 94014fed..7bb08728 100755 --- a/src/core/operations/Hexdump.js +++ b/src/core/operations/Hexdump.js @@ -92,7 +92,7 @@ const Hexdump = { const w = (width - 13) / 4; // w should be the specified width of the hexdump and therefore a round number if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) { - if (app) app.options.attemptHighlight = false; + if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); } return output; }, diff --git a/src/core/operations/PublicKey.js b/src/core/operations/PublicKey.js index 8731dfcd..295a5bf4 100755 --- a/src/core/operations/PublicKey.js +++ b/src/core/operations/PublicKey.js @@ -341,702 +341,3 @@ ${extensions}`; }; export default PublicKey; - - -/** - * Overwrite DN attribute lookup in jsrasign library with a much more complete version from - * https://github.com/nfephp-org/nfephp/blob/master/libs/Common/Certificate/Oids.php - * - * Various duplicates commented out. - * - * @constant - */ -r.X509.DN_ATTRHEX = { - "0603550403": "commonName", - "0603550404": "surname", - "0603550406": "countryName", - "0603550407": "localityName", - "0603550408": "stateOrProvinceName", - "0603550409": "streetAddress", - "060355040a": "organizationName", - "060355040b": "organizationalUnitName", - "060355040c": "title", - "0603550414": "telephoneNumber", - "060355042a": "givenName", - // "0603551d0e" : "id-ce-subjectKeyIdentifier", - // "0603551d0f" : "id-ce-keyUsage", - // "0603551d11" : "id-ce-subjectAltName", - // "0603551d13" : "id-ce-basicConstraints", - // "0603551d14" : "id-ce-cRLNumber", - // "0603551d1f" : "id-ce-CRLDistributionPoints", - // "0603551d20" : "id-ce-certificatePolicies", - // "0603551d23" : "id-ce-authorityKeyIdentifier", - // "0603551d25" : "id-ce-extKeyUsage", - // "06032a864886f70d010901" : "Email", - // "06032a864886f70d010101" : "RSAEncryption", - // "06032a864886f70d010102" : "md2WithRSAEncryption", - // "06032a864886f70d010104" : "md5withRSAEncryption", - // "06032a864886f70d010105" : "SHA-1WithRSAEncryption", - // "06032a8648ce380403" : "id-dsa-with-sha-1", - // "06032b06010505070302" : "idKpClientAuth", - // "06032b06010505070304" : "idKpSecurityemail", - "06032b06010505070201": "idCertificatePolicies", - "06036086480186f8420101": "netscape-cert-type", - "06036086480186f8420102": "netscape-base-url", - "06036086480186f8420103": "netscape-revocation-url", - "06036086480186f8420104": "netscape-ca-revocation-url", - "06036086480186f8420107": "netscape-cert-renewal-url", - "06036086480186f8420108": "netscape-ca-policy-url", - "06036086480186f842010c": "netscape-ssl-server-name", - "06036086480186f842010d": "netscape-comment", - "0603604c010201": "A1", - "0603604c010203": "A3", - "0603604c01020110": "Certification Practice Statement pointer", - "0603604c010301": "Dados do cert parte 1", - "0603604c010305": "Dados do cert parte 2", - "0603604c010306": "Dados do cert parte 3", - "06030992268993f22c640119": "domainComponent", - "06032a24a0f2a07d01010a": "Signet pilot", - "06032a24a0f2a07d01010b": "Signet intraNet", - "06032a24a0f2a07d010102": "Signet personal", - "06032a24a0f2a07d010114": "Signet securityPolicy", - "06032a24a0f2a07d010103": "Signet business", - "06032a24a0f2a07d010104": "Signet legal", - "06032a24a497a35301640101": "Certificates Australia policyIdentifier", - "06032a85702201": "seis-cp", - "06032a8570220101": "SEIS certificatePolicy-s10", - "06032a85702202": "SEIS pe", - "06032a85702203": "SEIS at", - "06032a8570220301": "SEIS at-personalIdentifier", - "06032a8648ce380201": "holdinstruction-none", - "06032a8648ce380202": "holdinstruction-callissuer", - "06032a8648ce380203": "holdinstruction-reject", - "06032a8648ce380401": "dsa", - "06032a8648ce380403": "dsaWithSha1", - "06032a8648ce3d01": "fieldType", - "06032a8648ce3d0101": "prime-field", - "06032a8648ce3d0102": "characteristic-two-field", - "06032a8648ce3d010201": "ecPublicKey", - "06032a8648ce3d010203": "characteristic-two-basis", - "06032a8648ce3d01020301": "onBasis", - "06032a8648ce3d01020302": "tpBasis", - "06032a8648ce3d01020303": "ppBasis", - "06032a8648ce3d02": "publicKeyType", - "06032a8648ce3d0201": "ecPublicKey", - "06032a8648ce3e0201": "dhPublicNumber", - "06032a864886f67d07": "nsn", - "06032a864886f67d0741": "nsn-ce", - "06032a864886f67d074100": "entrustVersInfo", - "06032a864886f67d0742": "nsn-alg", - "06032a864886f67d07420a": "cast5CBC", - "06032a864886f67d07420b": "cast5MAC", - "06032a864886f67d07420c": "pbeWithMD5AndCAST5-CBC", - "06032a864886f67d07420d": "passwordBasedMac", - "06032a864886f67d074203": "cast3CBC", - "06032a864886f67d0743": "nsn-oc", - "06032a864886f67d074300": "entrustUser", - "06032a864886f67d0744": "nsn-at", - "06032a864886f67d074400": "entrustCAInfo", - "06032a864886f67d07440a": "attributeCertificate", - "06032a864886f70d0101": "pkcs-1", - "06032a864886f70d010101": "rsaEncryption", - "06032a864886f70d010102": "md2withRSAEncryption", - "06032a864886f70d010103": "md4withRSAEncryption", - "06032a864886f70d010104": "md5withRSAEncryption", - "06032a864886f70d010105": "sha1withRSAEncryption", - "06032a864886f70d010106": "rsaOAEPEncryptionSET", - "06032a864886f70d010910020b": "SMIMEEncryptionKeyPreference", - "06032a864886f70d010c": "pkcs-12", - "06032a864886f70d010c01": "pkcs-12-PbeIds", - "06032a864886f70d010c0101": "pbeWithSHAAnd128BitRC4", - "06032a864886f70d010c0102": "pbeWithSHAAnd40BitRC4", - "06032a864886f70d010c0103": "pbeWithSHAAnd3-KeyTripleDES-CBC", - "06032a864886f70d010c0104": "pbeWithSHAAnd2-KeyTripleDES-CBC", - "06032a864886f70d010c0105": "pbeWithSHAAnd128BitRC2-CBC", - "06032a864886f70d010c0106": "pbeWithSHAAnd40BitRC2-CBC", - "06032a864886f70d010c0a": "pkcs-12Version1", - "06032a864886f70d010c0a01": "pkcs-12BadIds", - "06032a864886f70d010c0a0101": "pkcs-12-keyBag", - "06032a864886f70d010c0a0102": "pkcs-12-pkcs-8ShroudedKeyBag", - "06032a864886f70d010c0a0103": "pkcs-12-certBag", - "06032a864886f70d010c0a0104": "pkcs-12-crlBag", - "06032a864886f70d010c0a0105": "pkcs-12-secretBag", - "06032a864886f70d010c0a0106": "pkcs-12-safeContentsBag", - "06032a864886f70d010c02": "pkcs-12-ESPVKID", - "06032a864886f70d010c0201": "pkcs-12-PKCS8KeyShrouding", - "06032a864886f70d010c03": "pkcs-12-BagIds", - "06032a864886f70d010c0301": "pkcs-12-keyBagId", - "06032a864886f70d010c0302": "pkcs-12-certAndCRLBagId", - "06032a864886f70d010c0303": "pkcs-12-secretBagId", - "06032a864886f70d010c0304": "pkcs-12-safeContentsId", - "06032a864886f70d010c0305": "pkcs-12-pkcs-8ShroudedKeyBagId", - "06032a864886f70d010c04": "pkcs-12-CertBagID", - "06032a864886f70d010c0401": "pkcs-12-X509CertCRLBagID", - "06032a864886f70d010c0402": "pkcs-12-SDSICertBagID", - "06032a864886f70d010c05": "pkcs-12-OID", - "06032a864886f70d010c0501": "pkcs-12-PBEID", - "06032a864886f70d010c050101": "pkcs-12-PBEWithSha1And128BitRC4", - "06032a864886f70d010c050102": "pkcs-12-PBEWithSha1And40BitRC4", - "06032a864886f70d010c050103": "pkcs-12-PBEWithSha1AndTripleDESCBC", - "06032a864886f70d010c050104": "pkcs-12-PBEWithSha1And128BitRC2CBC", - "06032a864886f70d010c050105": "pkcs-12-PBEWithSha1And40BitRC2CBC", - "06032a864886f70d010c050106": "pkcs-12-PBEWithSha1AndRC4", - "06032a864886f70d010c050107": "pkcs-12-PBEWithSha1AndRC2CBC", - "06032a864886f70d010c0502": "pkcs-12-EnvelopingID", - "06032a864886f70d010c050201": "pkcs-12-RSAEncryptionWith128BitRC4", - "06032a864886f70d010c050202": "pkcs-12-RSAEncryptionWith40BitRC4", - "06032a864886f70d010c050203": "pkcs-12-RSAEncryptionWithTripleDES", - "06032a864886f70d010c0503": "pkcs-12-SignatureID", - "06032a864886f70d010c050301": "pkcs-12-RSASignatureWithSHA1Digest", - "06032a864886f70d0103": "pkcs-3", - "06032a864886f70d010301": "dhKeyAgreement", - "06032a864886f70d0105": "pkcs-5", - "06032a864886f70d010501": "pbeWithMD2AndDES-CBC", - "06032a864886f70d01050a": "pbeWithSHAAndDES-CBC", - "06032a864886f70d010503": "pbeWithMD5AndDES-CBC", - "06032a864886f70d010504": "pbeWithMD2AndRC2-CBC", - "06032a864886f70d010506": "pbeWithMD5AndRC2-CBC", - "06032a864886f70d010509": "pbeWithMD5AndXOR", - "06032a864886f70d0107": "pkcs-7", - "06032a864886f70d010701": "data", - "06032a864886f70d010702": "signedData", - "06032a864886f70d010703": "envelopedData", - "06032a864886f70d010704": "signedAndEnvelopedData", - "06032a864886f70d010705": "digestData", - "06032a864886f70d010706": "encryptedData", - "06032a864886f70d010707": "dataWithAttributes", - "06032a864886f70d010708": "encryptedPrivateKeyInfo", - "06032a864886f70d0109": "pkcs-9", - "06032a864886f70d010901": "emailAddress", - "06032a864886f70d01090a": "issuerAndSerialNumber", - "06032a864886f70d01090b": "passwordCheck", - "06032a864886f70d01090c": "publicKey", - "06032a864886f70d01090d": "signingDescription", - "06032a864886f70d01090e": "extensionReq", - "06032a864886f70d01090f": "sMIMECapabilities", - "06032a864886f70d01090f01": "preferSignedData", - "06032a864886f70d01090f02": "canNotDecryptAny", - "06032a864886f70d01090f03": "receiptRequest", - "06032a864886f70d01090f04": "receipt", - "06032a864886f70d01090f05": "contentHints", - "06032a864886f70d01090f06": "mlExpansionHistory", - "06032a864886f70d010910": "id-sMIME", - "06032a864886f70d01091000": "id-mod", - "06032a864886f70d0109100001": "id-mod-cms", - "06032a864886f70d0109100002": "id-mod-ess", - "06032a864886f70d01091001": "id-ct", - "06032a864886f70d0109100101": "id-ct-receipt", - "06032a864886f70d01091002": "id-aa", - "06032a864886f70d0109100201": "id-aa-receiptRequest", - "06032a864886f70d0109100202": "id-aa-securityLabel", - "06032a864886f70d0109100203": "id-aa-mlExpandHistory", - "06032a864886f70d0109100204": "id-aa-contentHint", - "06032a864886f70d010902": "unstructuredName", - "06032a864886f70d010914": "friendlyName", - "06032a864886f70d010915": "localKeyID", - "06032a864886f70d010916": "certTypes", - "06032a864886f70d01091601": "x509Certificate", - "06032a864886f70d01091602": "sdsiCertificate", - "06032a864886f70d010917": "crlTypes", - "06032a864886f70d01091701": "x509Crl", - "06032a864886f70d010903": "contentType", - "06032a864886f70d010904": "messageDigest", - "06032a864886f70d010905": "signingTime", - "06032a864886f70d010906": "countersignature", - "06032a864886f70d010907": "challengePassword", - "06032a864886f70d010908": "unstructuredAddress", - "06032a864886f70d010909": "extendedCertificateAttributes", - "06032a864886f70d02": "digestAlgorithm", - "06032a864886f70d0202": "md2", - "06032a864886f70d0204": "md4", - "06032a864886f70d0205": "md5", - "06032a864886f70d03": "encryptionAlgorithm", - "06032a864886f70d030a": "desCDMF", - "06032a864886f70d0302": "rc2CBC", - "06032a864886f70d0303": "rc2ECB", - "06032a864886f70d0304": "rc4", - "06032a864886f70d0305": "rc4WithMAC", - "06032a864886f70d0306": "DESX-CBC", - "06032a864886f70d0307": "DES-EDE3-CBC", - "06032a864886f70d0308": "RC5CBC", - "06032a864886f70d0309": "RC5-CBCPad", - "06032a864886f7140403": "microsoftExcel", - "06032a864886f7140404": "titledWithOID", - "06032a864886f7140405": "microsoftPowerPoint", - "06032b81051086480954": "x9-84", - "06032b8105108648095400": "x9-84-Module", - "06032b810510864809540001": "x9-84-Biometrics", - "06032b810510864809540002": "x9-84-CMS", - "06032b810510864809540003": "x9-84-Identifiers", - "06032b8105108648095401": "biometric", - "06032b810510864809540100": "id-unknown-Type", - "06032b810510864809540101": "id-body-Odor", - "06032b81051086480954010a": "id-palm", - "06032b81051086480954010b": "id-retina", - "06032b81051086480954010c": "id-signature", - "06032b81051086480954010d": "id-speech-Pattern", - "06032b81051086480954010e": "id-thermal-Image", - "06032b81051086480954010f": "id-vein-Pattern", - "06032b810510864809540110": "id-thermal-Face-Image", - "06032b810510864809540111": "id-thermal-Hand-Image", - "06032b810510864809540112": "id-lip-Movement", - "06032b810510864809540113": "id-gait", - "06032b810510864809540102": "id-dna", - "06032b810510864809540103": "id-ear-Shape", - "06032b810510864809540104": "id-facial-Features", - "06032b810510864809540105": "id-finger-Image", - "06032b810510864809540106": "id-finger-Geometry", - "06032b810510864809540107": "id-hand-Geometry", - "06032b810510864809540108": "id-iris-Features", - "06032b810510864809540109": "id-keystroke-Dynamics", - "06032b8105108648095402": "processing-algorithm", - "06032b8105108648095403": "matching-method", - "06032b8105108648095404": "format-Owner", - "06032b810510864809540400": "cbeff-Owner", - "06032b810510864809540401": "ibia-Owner", - "06032b81051086480954040101": "id-ibia-SAFLINK", - "06032b8105108648095404010a": "id-ibia-SecuGen", - "06032b8105108648095404010b": "id-ibia-PreciseBiometric", - "06032b8105108648095404010c": "id-ibia-Identix", - "06032b8105108648095404010d": "id-ibia-DERMALOG", - "06032b8105108648095404010e": "id-ibia-LOGICO", - "06032b8105108648095404010f": "id-ibia-NIST", - "06032b81051086480954040110": "id-ibia-A3Vision", - "06032b81051086480954040111": "id-ibia-NEC", - "06032b81051086480954040112": "id-ibia-STMicroelectronics", - "06032b81051086480954040102": "id-ibia-Bioscrypt", - "06032b81051086480954040103": "id-ibia-Visionics", - "06032b81051086480954040104": "id-ibia-InfineonTechnologiesAG", - "06032b81051086480954040105": "id-ibia-IridianTechnologies", - "06032b81051086480954040106": "id-ibia-Veridicom", - "06032b81051086480954040107": "id-ibia-CyberSIGN", - "06032b81051086480954040108": "id-ibia-eCryp.", - "06032b81051086480954040109": "id-ibia-FingerprintCardsAB", - "06032b810510864809540402": "x9-Owner", - "06032b0e021a05": "sha", - "06032b0e03020101": "rsa", - "06032b0e03020a": "desMAC", - "06032b0e03020b": "rsaSignature", - "06032b0e03020c": "dsa", - "06032b0e03020d": "dsaWithSHA", - "06032b0e03020e": "mdc2WithRSASignature", - "06032b0e03020f": "shaWithRSASignature", - "06032b0e030210": "dhWithCommonModulus", - "06032b0e030211": "desEDE", - "06032b0e030212": "sha", - "06032b0e030213": "mdc-2", - "06032b0e030202": "md4WitRSA", - "06032b0e03020201": "sqmod-N", - "06032b0e030214": "dsaCommon", - "06032b0e030215": "dsaCommonWithSHA", - "06032b0e030216": "rsaKeyTransport", - "06032b0e030217": "keyed-hash-seal", - "06032b0e030218": "md2WithRSASignature", - "06032b0e030219": "md5WithRSASignature", - "06032b0e03021a": "sha1", - "06032b0e03021b": "dsaWithSHA1", - "06032b0e03021c": "dsaWithCommonSHA1", - "06032b0e03021d": "sha-1WithRSAEncryption", - "06032b0e030203": "md5WithRSA", - "06032b0e03020301": "sqmod-NwithRSA", - "06032b0e030204": "md4WithRSAEncryption", - "06032b0e030206": "desECB", - "06032b0e030207": "desCBC", - "06032b0e030208": "desOFB", - "06032b0e030209": "desCFB", - "06032b0e030301": "simple-strong-auth-mechanism", - "06032b0e07020101": "ElGamal", - "06032b0e07020301": "md2WithRSA", - "06032b0e07020302": "md2WithElGamal", - "06032b2403": "algorithm", - "06032b240301": "encryptionAlgorithm", - "06032b24030101": "des", - "06032b240301010101": "desECBPad", - "06032b24030101010101": "desECBPadISO", - "06032b240301010201": "desCBCPad", - "06032b24030101020101": "desCBCPadISO", - "06032b24030102": "idea", - "06032b2403010201": "ideaECB", - "06032b240301020101": "ideaECBPad", - "06032b24030102010101": "ideaECBPadISO", - "06032b2403010202": "ideaCBC", - "06032b240301020201": "ideaCBCPad", - "06032b24030102020101": "ideaCBCPadISO", - "06032b2403010203": "ideaOFB", - "06032b2403010204": "ideaCFB", - "06032b24030103": "des-3", - "06032b240301030101": "des-3ECBPad", - "06032b24030103010101": "des-3ECBPadISO", - "06032b240301030201": "des-3CBCPad", - "06032b24030103020101": "des-3CBCPadISO", - "06032b240302": "hashAlgorithm", - "06032b24030201": "ripemd160", - "06032b24030202": "ripemd128", - "06032b24030203": "ripemd256", - "06032b24030204": "mdc2singleLength", - "06032b24030205": "mdc2doubleLength", - "06032b240303": "signatureAlgorithm", - "06032b24030301": "rsa", - "06032b2403030101": "rsaMitSHA-1", - "06032b2403030102": "rsaMitRIPEMD160", - "06032b24030302": "ellipticCurve", - "06032b240304": "signatureScheme", - "06032b24030401": "iso9796-1", - "06032b2403040201": "iso9796-2", - "06032b2403040202": "iso9796-2rsa", - "06032b2404": "attribute", - "06032b2405": "policy", - "06032b2406": "api", - "06032b240601": "manufacturerSpecific", - "06032b240602": "functionalitySpecific", - "06032b2407": "api", - "06032b240701": "keyAgreement", - "06032b240702": "keyTransport", - "06032b06010401927c0a0101": "UNINETT policyIdentifier", - "06032b0601040195180a": "ICE-TEL policyIdentifier", - "06032b0601040197552001": "cryptlibEnvelope", - "06032b0601040197552002": "cryptlibPrivateKey", - "060a2b060104018237": "Microsoft OID", - "060a2b0601040182370a": "Crypto 2.0", - "060a2b0601040182370a01": "certTrustList", - "060a2b0601040182370a0101": "szOID_SORTED_CTL", - "060a2b0601040182370a0a": "Microsoft CMC OIDs", - "060a2b0601040182370a0a01": "szOID_CMC_ADD_ATTRIBUTES", - "060a2b0601040182370a0b": "Microsoft certificate property OIDs", - "060a2b0601040182370a0b01": "szOID_CERT_PROP_ID_PREFIX", - "060a2b0601040182370a0c": "CryptUI", - "060a2b0601040182370a0c01": "szOID_ANY_APPLICATION_POLICY", - "060a2b0601040182370a02": "nextUpdateLocation", - "060a2b0601040182370a0301": "certTrustListSigning", - "060a2b0601040182370a030a": "szOID_KP_QUALIFIED_SUBORDINATION", - "060a2b0601040182370a030b": "szOID_KP_KEY_RECOVERY", - "060a2b0601040182370a030c": "szOID_KP_DOCUMENT_SIGNING", - "060a2b0601040182370a0302": "timeStampSigning", - "060a2b0601040182370a0303": "serverGatedCrypto", - "060a2b0601040182370a030301": "szOID_SERIALIZED", - "060a2b0601040182370a0304": "encryptedFileSystem", - "060a2b0601040182370a030401": "szOID_EFS_RECOVERY", - "060a2b0601040182370a0305": "szOID_WHQL_CRYPTO", - "060a2b0601040182370a0306": "szOID_NT5_CRYPTO", - "060a2b0601040182370a0307": "szOID_OEM_WHQL_CRYPTO", - "060a2b0601040182370a0308": "szOID_EMBEDDED_NT_CRYPTO", - "060a2b0601040182370a0309": "szOID_ROOT_LIST_SIGNER", - "060a2b0601040182370a0401": "yesnoTrustAttr", - "060a2b0601040182370a0501": "szOID_DRM", - "060a2b0601040182370a0502": "szOID_DRM_INDIVIDUALIZATION", - "060a2b0601040182370a0601": "szOID_LICENSES", - "060a2b0601040182370a0602": "szOID_LICENSE_SERVER", - "060a2b0601040182370a07": "szOID_MICROSOFT_RDN_PREFIX", - "060a2b0601040182370a0701": "szOID_KEYID_RDN", - "060a2b0601040182370a0801": "szOID_REMOVE_CERTIFICATE", - "060a2b0601040182370a0901": "szOID_CROSS_CERT_DIST_POINTS", - "060a2b0601040182370c": "Catalog", - "060a2b0601040182370c0101": "szOID_CATALOG_LIST", - "060a2b0601040182370c0102": "szOID_CATALOG_LIST_MEMBER", - "060a2b0601040182370c0201": "CAT_NAMEVALUE_OBJID", - "060a2b0601040182370c0202": "CAT_MEMBERINFO_OBJID", - "060a2b0601040182370d": "Microsoft PKCS10 OIDs", - "060a2b0601040182370d01": "szOID_RENEWAL_CERTIFICATE", - "060a2b0601040182370d0201": "szOID_ENROLLMENT_NAME_VALUE_PAIR", - "060a2b0601040182370d0202": "szOID_ENROLLMENT_CSP_PROVIDER", - "060a2b0601040182370d0203": "OS Version", - "060a2b0601040182370f": "Microsoft Java", - "060a2b06010401823710": "Microsoft Outlook/Exchange", - "060a2b0601040182371004": "Outlook Express", - "060a2b06010401823711": "Microsoft PKCS12 attributes", - "060a2b0601040182371101": "szOID_LOCAL_MACHINE_KEYSET", - "060a2b06010401823712": "Microsoft Hydra", - "060a2b06010401823713": "Microsoft ISPU Test", - "060a2b06010401823702": "Authenticode", - "060a2b06010401823702010a": "spcAgencyInfo", - "060a2b06010401823702010b": "spcStatementType", - "060a2b06010401823702010c": "spcSpOpusInfo", - "060a2b06010401823702010e": "certExtensions", - "060a2b06010401823702010f": "spcPelmageData", - "060a2b060104018237020112": "SPC_RAW_FILE_DATA_OBJID", - "060a2b060104018237020113": "SPC_STRUCTURED_STORAGE_DATA_OBJID", - "060a2b060104018237020114": "spcLink", - "060a2b060104018237020115": "individualCodeSigning", - "060a2b060104018237020116": "commercialCodeSigning", - "060a2b060104018237020119": "spcLink", - "060a2b06010401823702011a": "spcMinimalCriteriaInfo", - "060a2b06010401823702011b": "spcFinancialCriteriaInfo", - "060a2b06010401823702011c": "spcLink", - "060a2b06010401823702011d": "SPC_HASH_INFO_OBJID", - "060a2b06010401823702011e": "SPC_SIPINFO_OBJID", - "060a2b060104018237020104": "spcIndirectDataContext", - "060a2b0601040182370202": "CTL for Software Publishers Trusted CAs", - "060a2b060104018237020201": "szOID_TRUSTED_CODESIGNING_CA_LIST", - "060a2b060104018237020202": "szOID_TRUSTED_CLIENT_AUTH_CA_LIST", - "060a2b060104018237020203": "szOID_TRUSTED_SERVER_AUTH_CA_LIST", - "060a2b06010401823714": "Microsoft Enrollment Infrastructure", - "060a2b0601040182371401": "szOID_AUTO_ENROLL_CTL_USAGE", - "060a2b0601040182371402": "szOID_ENROLL_CERTTYPE_EXTENSION", - "060a2b060104018237140201": "szOID_ENROLLMENT_AGENT", - "060a2b060104018237140202": "szOID_KP_SMARTCARD_LOGON", - "060a2b060104018237140203": "szOID_NT_PRINCIPAL_NAME", - "060a2b0601040182371403": "szOID_CERT_MANIFOLD", - "06092b06010401823715": "Microsoft CertSrv Infrastructure", - "06092b0601040182371501": "szOID_CERTSRV_CA_VERSION", - "06092b0601040182371514": "Client Information", - "060a2b06010401823719": "Microsoft Directory Service", - "060a2b0601040182371901": "szOID_NTDS_REPLICATION", - "060a2b06010401823703": "Time Stamping", - "060a2b060104018237030201": "SPC_TIME_STAMP_REQUEST_OBJID", - "060a2b0601040182371e": "IIS", - "060a2b0601040182371f": "Windows updates and service packs", - "060a2b0601040182371f01": "szOID_PRODUCT_UPDATE", - "060a2b06010401823704": "Permissions", - "060a2b06010401823728": "Fonts", - "060a2b06010401823729": "Microsoft Licensing and Registration", - "060a2b0601040182372a": "Microsoft Corporate PKI (ITG)", - "060a2b06010401823758": "CAPICOM", - "060a2b0601040182375801": "szOID_CAPICOM_VERSION", - "060a2b0601040182375802": "szOID_CAPICOM_ATTRIBUTE", - "060a2b060104018237580201": "szOID_CAPICOM_DOCUMENT_NAME", - "060a2b060104018237580202": "szOID_CAPICOM_DOCUMENT_DESCRIPTION", - "060a2b0601040182375803": "szOID_CAPICOM_ENCRYPTED_DATA", - "060a2b060104018237580301": "szOID_CAPICOM_ENCRYPTED_CONTENT", - "06032b0601050507": "pkix", - "06032b060105050701": "privateExtension", - "06032b06010505070101": "authorityInfoAccess", - "06032b06010505070c02": "CMC Data", - "06032b060105050702": "policyQualifierIds", - // "06032b06010505070201" : "cps", - "06032b06010505070202": "unotice", - "06032b060105050703": "keyPurpose", - "06032b06010505070301": "serverAuth", - "06032b06010505070302": "clientAuth", - "06032b06010505070303": "codeSigning", - "06032b06010505070304": "emailProtection", - "06032b06010505070305": "ipsecEndSystem", - "06032b06010505070306": "ipsecTunnel", - "06032b06010505070307": "ipsecUser", - "06032b06010505070308": "timeStamping", - "06032b060105050704": "cmpInformationTypes", - "06032b06010505070401": "caProtEncCert", - "06032b06010505070402": "signKeyPairTypes", - "06032b06010505070403": "encKeyPairTypes", - "06032b06010505070404": "preferredSymmAlg", - "06032b06010505070405": "caKeyUpdateInfo", - "06032b06010505070406": "currentCRL", - "06032b06010505073001": "ocsp", - "06032b06010505073002": "caIssuers", - "06032b06010505080101": "HMAC-MD5", - "06032b06010505080102": "HMAC-SHA", - "060360864801650201010a": "mosaicKeyManagementAlgorithm", - "060360864801650201010b": "sdnsKMandSigAlgorithm", - "060360864801650201010c": "mosaicKMandSigAlgorithm", - "060360864801650201010d": "SuiteASignatureAlgorithm", - "060360864801650201010e": "SuiteAConfidentialityAlgorithm", - "060360864801650201010f": "SuiteAIntegrityAlgorithm", - "06036086480186f84201": "cert-extension", - // "06036086480186f8420101" : "netscape-cert-type", - "06036086480186f842010a": "EntityLogo", - "06036086480186f842010b": "UserPicture", - // "06036086480186f842010c" : "netscape-ssl-server-name", - // "06036086480186f842010d" : "netscape-comment", - // "06036086480186f8420102" : "netscape-base-url", - // "06036086480186f8420103" : "netscape-revocation-url", - // "06036086480186f8420104" : "netscape-ca-revocation-url", - // "06036086480186f8420107" : "netscape-cert-renewal-url", - // "06036086480186f8420108" : "netscape-ca-policy-url", - "06036086480186f8420109": "HomePage-url", - "06036086480186f84202": "data-type", - "06036086480186f8420201": "GIF", - "06036086480186f8420202": "JPEG", - "06036086480186f8420203": "URL", - "06036086480186f8420204": "HTML", - "06036086480186f8420205": "netscape-cert-sequence", - "06036086480186f8420206": "netscape-cert-url", - "06036086480186f84203": "directory", - "06036086480186f8420401": "serverGatedCrypto", - "06036086480186f845010603": "Unknown Verisign extension", - "06036086480186f845010606": "Unknown Verisign extension", - "06036086480186f84501070101": "Verisign certificatePolicy", - "06036086480186f8450107010101": "Unknown Verisign policy qualifier", - "06036086480186f8450107010102": "Unknown Verisign policy qualifier", - "0603678105": "TCPA", - "060367810501": "tcpaSpecVersion", - "060367810502": "tcpaAttribute", - "06036781050201": "tcpaAtTpmManufacturer", - "0603678105020a": "tcpaAtSecurityQualities", - "0603678105020b": "tcpaAtTpmProtectionProfile", - "0603678105020c": "tcpaAtTpmSecurityTarget", - "0603678105020d": "tcpaAtFoundationProtectionProfile", - "0603678105020e": "tcpaAtFoundationSecurityTarget", - "0603678105020f": "tcpaAtTpmIdLabel", - "06036781050202": "tcpaAtTpmModel", - "06036781050203": "tcpaAtTpmVersion", - "06036781050204": "tcpaAtPlatformManufacturer", - "06036781050205": "tcpaAtPlatformModel", - "06036781050206": "tcpaAtPlatformVersion", - "06036781050207": "tcpaAtComponentManufacturer", - "06036781050208": "tcpaAtComponentModel", - "06036781050209": "tcpaAtComponentVersion", - "060367810503": "tcpaProtocol", - "06036781050301": "tcpaPrttTpmIdProtocol", - "0603672a00": "contentType", - "0603672a0000": "PANData", - "0603672a0001": "PANToken", - "0603672a0002": "PANOnly", - "0603672a01": "msgExt", - "0603672a0a": "national", - "0603672a0a8140": "Japan", - "0603672a02": "field", - "0603672a0200": "fullName", - "0603672a0201": "givenName", - "0603672a020a": "amount", - "0603672a0202": "familyName", - "0603672a0203": "birthFamilyName", - "0603672a0204": "placeName", - "0603672a0205": "identificationNumber", - "0603672a0206": "month", - "0603672a0207": "date", - "0603672a02070b": "accountNumber", - "0603672a02070c": "passPhrase", - "0603672a0208": "address", - "0603672a0209": "telephone", - "0603672a03": "attribute", - "0603672a0300": "cert", - "0603672a030000": "rootKeyThumb", - "0603672a030001": "additionalPolicy", - "0603672a04": "algorithm", - "0603672a05": "policy", - "0603672a0500": "root", - "0603672a06": "module", - "0603672a07": "certExt", - "0603672a0700": "hashedRootKey", - "0603672a0701": "certificateType", - "0603672a0702": "merchantData", - "0603672a0703": "cardCertRequired", - "0603672a0704": "tunneling", - "0603672a0705": "setExtensions", - "0603672a0706": "setQualifier", - "0603672a08": "brand", - "0603672a0801": "IATA-ATA", - "0603672a081e": "Diners", - "0603672a0822": "AmericanExpress", - "0603672a0804": "VISA", - "0603672a0805": "MasterCard", - "0603672a08ae7b": "Novus", - "0603672a09": "vendor", - "0603672a0900": "GlobeSet", - "0603672a0901": "IBM", - "0603672a090a": "Griffin", - "0603672a090b": "Certicom", - "0603672a090c": "OSS", - "0603672a090d": "TenthMountain", - "0603672a090e": "Antares", - "0603672a090f": "ECC", - "0603672a0910": "Maithean", - "0603672a0911": "Netscape", - "0603672a0912": "Verisign", - "0603672a0913": "BlueMoney", - "0603672a0902": "CyberCash", - "0603672a0914": "Lacerte", - "0603672a0915": "Fujitsu", - "0603672a0916": "eLab", - "0603672a0917": "Entrust", - "0603672a0918": "VIAnet", - "0603672a0919": "III", - "0603672a091a": "OpenMarket", - "0603672a091b": "Lexem", - "0603672a091c": "Intertrader", - "0603672a091d": "Persimmon", - "0603672a0903": "Terisa", - "0603672a091e": "NABLE", - "0603672a091f": "espace-net", - "0603672a0920": "Hitachi", - "0603672a0921": "Microsoft", - "0603672a0922": "NEC", - "0603672a0923": "Mitsubishi", - "0603672a0924": "NCR", - "0603672a0925": "e-COMM", - "0603672a0926": "Gemplus", - "0603672a0904": "RSADSI", - "0603672a0905": "VeriFone", - "0603672a0906": "TrinTech", - "0603672a0907": "BankGate", - "0603672a0908": "GTE", - "0603672a0909": "CompuSource", - "0603551d01": "authorityKeyIdentifier", - "0603551d0a": "basicConstraints", - "0603551d0b": "nameConstraints", - "0603551d0c": "policyConstraints", - "0603551d0d": "basicConstraints", - "0603551d0e": "subjectKeyIdentifier", - "0603551d0f": "keyUsage", - "0603551d10": "privateKeyUsagePeriod", - "0603551d11": "subjectAltName", - "0603551d12": "issuerAltName", - "0603551d13": "basicConstraints", - "0603551d02": "keyAttributes", - "0603551d14": "cRLNumber", - "0603551d15": "cRLReason", - "0603551d16": "expirationDate", - "0603551d17": "instructionCode", - "0603551d18": "invalidityDate", - "0603551d1a": "issuingDistributionPoint", - "0603551d1b": "deltaCRLIndicator", - "0603551d1c": "issuingDistributionPoint", - "0603551d1d": "certificateIssuer", - "0603551d03": "certificatePolicies", - "0603551d1e": "nameConstraints", - "0603551d1f": "cRLDistributionPoints", - "0603551d20": "certificatePolicies", - "0603551d21": "policyMappings", - "0603551d22": "policyConstraints", - "0603551d23": "authorityKeyIdentifier", - "0603551d24": "policyConstraints", - "0603551d25": "extKeyUsage", - "0603551d04": "keyUsageRestriction", - "0603551d05": "policyMapping", - "0603551d06": "subtreesConstraint", - "0603551d07": "subjectAltName", - "0603551d08": "issuerAltName", - "0603551d09": "subjectDirectoryAttributes", - "0603550400": "objectClass", - "0603550401": "aliasObjectName", - // "060355040c" : "title", - "060355040d": "description", - "060355040e": "searchGuide", - "060355040f": "businessCategory", - "0603550410": "postalAddress", - "0603550411": "postalCode", - "0603550412": "postOfficeBox", - "0603550413": "physicalDeliveryOfficeName", - "0603550402": "knowledgeInformation", - // "0603550414" : "telephoneNumber", - "0603550415": "telexNumber", - "0603550416": "teletexTerminalIdentifier", - "0603550417": "facsimileTelephoneNumber", - "0603550418": "x121Address", - "0603550419": "internationalISDNNumber", - "060355041a": "registeredAddress", - "060355041b": "destinationIndicator", - "060355041c": "preferredDeliveryMehtod", - "060355041d": "presentationAddress", - "060355041e": "supportedApplicationContext", - "060355041f": "member", - "0603550420": "owner", - "0603550421": "roleOccupant", - "0603550422": "seeAlso", - "0603550423": "userPassword", - "0603550424": "userCertificate", - "0603550425": "caCertificate", - "0603550426": "authorityRevocationList", - "0603550427": "certificateRevocationList", - "0603550428": "crossCertificatePair", - "0603550429": "givenName", - // "060355042a" : "givenName", - "0603550405": "serialNumber", - "0603550434": "supportedAlgorithms", - "0603550435": "deltaRevocationList", - "060355043a": "crossCertificatePair", - // "0603550409" : "streetAddress", - "06035508": "X.500-Algorithms", - "0603550801": "X.500-Alg-Encryption", - "060355080101": "rsa", - "0603604c0101": "DPC" -}; diff --git a/src/core/operations/StrUtils.js b/src/core/operations/StrUtils.js index 71823053..23b5eb26 100755 --- a/src/core/operations/StrUtils.js +++ b/src/core/operations/StrUtils.js @@ -1,5 +1,4 @@ import Utils from "../Utils.js"; -import * as JsDiff from "diff"; /** @@ -294,83 +293,6 @@ const StrUtils = { }, - /** - * @constant - * @default - */ - DIFF_SAMPLE_DELIMITER: "\\n\\n", - /** - * @constant - * @default - */ - DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"], - - /** - * Diff operation. - * - * @param {string} input - * @param {Object[]} args - * @returns {html} - */ - runDiff: function(input, args) { - let sampleDelim = args[0], - diffBy = args[1], - showAdded = args[2], - showRemoved = args[3], - ignoreWhitespace = args[4], - samples = input.split(sampleDelim), - output = "", - diff; - - if (!samples || samples.length !== 2) { - return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?"; - } - - switch (diffBy) { - case "Character": - diff = JsDiff.diffChars(samples[0], samples[1]); - break; - case "Word": - if (ignoreWhitespace) { - diff = JsDiff.diffWords(samples[0], samples[1]); - } else { - diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]); - } - break; - case "Line": - if (ignoreWhitespace) { - diff = JsDiff.diffTrimmedLines(samples[0], samples[1]); - } else { - diff = JsDiff.diffLines(samples[0], samples[1]); - } - break; - case "Sentence": - diff = JsDiff.diffSentences(samples[0], samples[1]); - break; - case "CSS": - diff = JsDiff.diffCss(samples[0], samples[1]); - break; - case "JSON": - diff = JsDiff.diffJson(samples[0], samples[1]); - break; - default: - return "Invalid 'Diff by' option."; - } - - for (let i = 0; i < diff.length; i++) { - if (diff[i].added) { - if (showAdded) output += "" + Utils.escapeHtml(diff[i].value) + ""; - } else if (diff[i].removed) { - if (showRemoved) output += "" + Utils.escapeHtml(diff[i].value) + ""; - } else { - output += Utils.escapeHtml(diff[i].value); - } - } - - return output; - }, - - /** * @constant * @default diff --git a/src/web/App.js b/src/web/App.js index 8c209814..7dade878 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -1,5 +1,4 @@ import Utils from "../core/Utils.js"; -import Chef from "../core/Chef.js"; import Manager from "./Manager.js"; import HTMLCategory from "./HTMLCategory.js"; import HTMLOperation from "./HTMLOperation.js"; @@ -27,7 +26,6 @@ const App = function(categories, operations, defaultFavourites, defaultOptions) this.doptions = defaultOptions; this.options = Utils.extend({}, defaultOptions); - this.chef = new Chef(); this.manager = new Manager(this); this.baking = false; @@ -35,8 +33,6 @@ const App = function(categories, operations, defaultFavourites, defaultOptions) this.autoBakePause = false; this.progress = 0; this.ingId = 0; - - window.chef = this.chef; }; @@ -54,6 +50,8 @@ App.prototype.setup = function() { this.resetLayout(); this.setCompileMessage(); this.loadURIParams(); + + this.appLoaded = true; this.loaded(); }; @@ -64,6 +62,11 @@ App.prototype.setup = function() { * @fires Manager#apploaded */ App.prototype.loaded = function() { + // Check that both the app and the worker have loaded successfully, and that + // we haven't already loaded before attempting to remove the loading screen. + if (!this.workerLoaded || !this.appLoaded || + !document.getElementById("loader-wrapper")) return; + // Trigger CSS animations to remove preloader document.body.classList.add("loaded"); @@ -94,76 +97,24 @@ App.prototype.handleError = function(err) { /** - * Updates the UI to show if baking is in process or not. - * - * @param {bakingStatus} - */ -App.prototype.setBakingStatus = function(bakingStatus) { - this.baking = bakingStatus; - - let inputLoadingIcon = document.querySelector("#input .title .loading-icon"), - outputLoadingIcon = document.querySelector("#output .title .loading-icon"), - outputElement = document.querySelector("#output-text"); - - if (bakingStatus) { - inputLoadingIcon.style.display = "inline-block"; - outputLoadingIcon.style.display = "inline-block"; - outputElement.classList.add("disabled"); - outputElement.disabled = true; - } else { - inputLoadingIcon.style.display = "none"; - outputLoadingIcon.style.display = "none"; - outputElement.classList.remove("disabled"); - outputElement.disabled = false; - } -}; - - -/** - * Calls the Chef to bake the current input using the current recipe. + * Asks the ChefWorker to bake the current input using the current recipe. * * @param {boolean} [step] - Set to true if we should only execute one operation instead of the * whole recipe. */ -App.prototype.bake = async function(step) { - let response; - +App.prototype.bake = function(step) { if (this.baking) return; - this.setBakingStatus(true); + // Reset attemptHighlight flag + this.options.attemptHighlight = true; - try { - response = await this.chef.bake( - this.getInput(), // The user's input - this.getRecipeConfig(), // The configuration of the recipe - this.options, // Options set by the user - this.progress, // The current position in the recipe - step // Whether or not to take one step or execute the whole recipe - ); - } catch (err) { - this.handleError(err); - } - - this.setBakingStatus(false); - - if (!response) return; - - if (response.error) { - this.handleError(response.error); - } - - this.options = response.options; - this.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result; - this.progress = response.progress; - this.manager.recipe.updateBreakpointIndicator(response.progress); - this.manager.output.set(response.result, response.type, response.duration); - - // If baking took too long, disable auto-bake - if (response.duration > this.options.autoBakeThreshold && this.autoBake_) { - this.manager.controls.setAutoBake(false); - this.alert("Baking took longer than " + this.options.autoBakeThreshold + - "ms, Auto Bake has been disabled.", "warning", 5000); - } + this.manager.worker.bake( + this.getInput(), // The user's input + this.getRecipeConfig(), // The configuration of the recipe + this.options, // Options set by the user + this.progress, // The current position in the recipe + step // Whether or not to take one step or execute the whole recipe + ); }; @@ -171,30 +122,31 @@ App.prototype.bake = async function(step) { * Runs Auto Bake if it is set. */ App.prototype.autoBake = function() { - if (this.autoBake_ && !this.autoBakePause) { + if (this.autoBake_ && !this.autoBakePause && !this.baking) { this.bake(); + } else { + this.manager.controls.showStaleIndicator(); } }; /** - * Runs a silent bake forcing the browser to load and cache all the relevant JavaScript code needed + * Runs a silent bake, forcing the browser to load and cache all the relevant JavaScript code needed * to do a real bake. * - * The output will not be modified (hence "silent" bake). This will only actually execute the - * recipe if auto-bake is enabled, otherwise it will just load the recipe, ingredients and dish. - * - * @returns {number} - The number of miliseconds it took to run the silent bake. + * The output will not be modified (hence "silent" bake). This will only actually execute the recipe + * if auto-bake is enabled, otherwise it will just wake up the ChefWorker with an empty recipe. */ App.prototype.silentBake = function() { - let startTime = new Date().getTime(), - recipeConfig = this.getRecipeConfig(); + let recipeConfig = []; if (this.autoBake_) { - this.chef.silentBake(recipeConfig); + // If auto-bake is not enabled we don't want to actually run the recipe as it may be disabled + // for a good reason. + recipeConfig = this.getRecipeConfig(); } - return new Date().getTime() - startTime; + this.manager.worker.silentBake(recipeConfig); }; @@ -264,7 +216,7 @@ App.prototype.populateOperationsList = function() { App.prototype.initialiseSplitter = function() { this.columnSplitter = Split(["#operations", "#recipe", "#IO"], { sizes: [20, 30, 50], - minSize: [240, 325, 440], + minSize: [240, 325, 450], gutterSize: 4, onDrag: function() { this.manager.controls.adjustWidth(); diff --git a/src/web/ControlsWaiter.js b/src/web/ControlsWaiter.js index 696c4217..d7241e12 100755 --- a/src/web/ControlsWaiter.js +++ b/src/web/ControlsWaiter.js @@ -78,10 +78,11 @@ ControlsWaiter.prototype.setAutoBake = function(value) { * Handler to trigger baking. */ ControlsWaiter.prototype.bakeClick = function() { - this.app.bake(); - const outputText = document.getElementById("output-text"); - outputText.focus(); - outputText.setSelectionRange(0, 0); + if (document.getElementById("bake").textContent.indexOf("Bake") > 0) { + this.app.bake(); + } else { + this.manager.worker.cancelBake(); + } }; @@ -90,9 +91,6 @@ ControlsWaiter.prototype.bakeClick = function() { */ ControlsWaiter.prototype.stepClick = function() { this.app.bake(true); - const outputText = document.getElementById("output-text"); - outputText.focus(); - outputText.setSelectionRange(0, 0); }; @@ -375,4 +373,49 @@ ControlsWaiter.prototype.supportButtonClick = function(e) { } }; + +/** + * Shows the stale indicator to show that the input or recipe has changed + * since the last bake. + */ +ControlsWaiter.prototype.showStaleIndicator = function() { + const staleIndicator = document.getElementById("stale-indicator"); + + staleIndicator.style.visibility = "visible"; + staleIndicator.style.opacity = 1; +}; + + +/** + * Hides the stale indicator to show that the input or recipe has not changed + * since the last bake. + */ +ControlsWaiter.prototype.hideStaleIndicator = function() { + const staleIndicator = document.getElementById("stale-indicator"); + + staleIndicator.style.opacity = 0; + staleIndicator.style.visibility = "hidden"; +}; + + +/** + * Switches the Bake button between 'Bake' and 'Cancel' functions. + * + * @param {boolean} cancel - Whether to change to cancel or not + */ +ControlsWaiter.prototype.toggleBakeButtonFunction = function(cancel) { + const bakeButton = document.getElementById("bake"), + btnText = bakeButton.querySelector("span"); + + if (cancel) { + btnText.innerText = "Cancel"; + bakeButton.classList.remove("btn-success"); + bakeButton.classList.add("btn-danger"); + } else { + btnText.innerText = "Bake!"; + bakeButton.classList.remove("btn-danger"); + bakeButton.classList.add("btn-success"); + } +}; + export default ControlsWaiter; diff --git a/src/web/HighlighterWaiter.js b/src/web/HighlighterWaiter.js index cafedc22..c650e6ba 100755 --- a/src/web/HighlighterWaiter.js +++ b/src/web/HighlighterWaiter.js @@ -10,9 +10,11 @@ import Utils from "../core/Utils.js"; * * @constructor * @param {App} app - The main view object for CyberChef. + * @param {Manager} manager - The CyberChef event manager. */ -const HighlighterWaiter = function(app) { +const HighlighterWaiter = function(app, manager) { this.app = app; + this.manager = manager; this.mouseButtonDown = false; this.mouseTarget = null; @@ -329,41 +331,6 @@ HighlighterWaiter.prototype.removeHighlights = function() { }; -/** - * Generates a list of all the highlight functions assigned to operations in the recipe, if the - * entire recipe supports highlighting. - * - * @returns {Object[]} highlights - * @returns {function} highlights[].f - * @returns {function} highlights[].b - * @returns {Object[]} highlights[].args - */ -HighlighterWaiter.prototype.generateHighlightList = function() { - const recipeConfig = this.app.getRecipeConfig(); - const highlights = []; - - for (let i = 0; i < recipeConfig.length; i++) { - if (recipeConfig[i].disabled) continue; - - // If any breakpoints are set, do not attempt to highlight - if (recipeConfig[i].breakpoint) return false; - - const op = this.app.operations[recipeConfig[i].op]; - - // If any of the operations do not support highlighting, fail immediately. - if (op.highlight === false || op.highlight === undefined) return false; - - highlights.push({ - f: op.highlight, - b: op.highlightReverse, - args: recipeConfig[i].args - }); - } - - return highlights; -}; - - /** * Highlights the given offsets in the output. * We will only highlight if: @@ -376,26 +343,8 @@ HighlighterWaiter.prototype.generateHighlightList = function() { * @param {number} pos.end - The end offset. */ HighlighterWaiter.prototype.highlightOutput = function(pos) { - const highlights = this.generateHighlightList(); - - if (!highlights || !this.app.autoBake_) { - return false; - } - - for (let i = 0; i < highlights.length; i++) { - // Remove multiple highlights before processing again - pos = [pos[0]]; - - if (typeof highlights[i].f == "function") { - pos = highlights[i].f(pos, highlights[i].args); - } - } - - document.getElementById("output-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end); - this.highlight( - document.getElementById("output-text"), - document.getElementById("output-highlighter"), - pos); + if (!this.app.autoBake_ || this.app.baking) return false; + this.manager.worker.highlight(this.app.getRecipeConfig(), "forward", pos); }; @@ -411,25 +360,28 @@ HighlighterWaiter.prototype.highlightOutput = function(pos) { * @param {number} pos.end - The end offset. */ HighlighterWaiter.prototype.highlightInput = function(pos) { - const highlights = this.generateHighlightList(); + if (!this.app.autoBake_ || this.app.baking) return false; + this.manager.worker.highlight(this.app.getRecipeConfig(), "reverse", pos); +}; - if (!highlights || !this.app.autoBake_) { - return false; - } - for (let i = 0; i < highlights.length; i++) { - // Remove multiple highlights before processing again - pos = [pos[0]]; +/** + * Displays highlight offsets sent back from the Chef. + * + * @param {Object} pos - The position object for the highlight. + * @param {number} pos.start - The start offset. + * @param {number} pos.end - The end offset. + * @param {string} direction + */ +HighlighterWaiter.prototype.displayHighlights = function(pos, direction) { + if (!pos) return; - if (typeof highlights[i].b == "function") { - pos = highlights[i].b(pos, highlights[i].args); - } - } + const io = direction === "forward" ? "output" : "input"; - document.getElementById("input-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end); + document.getElementById(io + "-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end); this.highlight( - document.getElementById("input-text"), - document.getElementById("input-highlighter"), + document.getElementById(io + "-text"), + document.getElementById(io + "-highlighter"), pos); }; diff --git a/src/web/InputWaiter.js b/src/web/InputWaiter.js index eda090b0..b771be2a 100755 --- a/src/web/InputWaiter.js +++ b/src/web/InputWaiter.js @@ -158,17 +158,15 @@ InputWaiter.prototype.inputDrop = function(e) { const CHUNK_SIZE = 20480; // 20KB const setInput = function() { - if (inputCharcode.length > 100000 && this.app.autoBake_) { - this.manager.controls.setAutoBake(false); - this.app.alert("Turned off Auto Bake as the input is large", "warning", 5000); - } - - this.set(inputCharcode); + this.app.autoBakePause = true; const recipeConfig = this.app.getRecipeConfig(); if (!recipeConfig[0] || recipeConfig[0].op !== "From Hex") { recipeConfig.unshift({op: "From Hex", args: ["Space"]}); this.app.setRecipeConfig(recipeConfig); } + this.app.autoBakePause = false; + + this.set(inputCharcode); el.classList.remove("loadingFile"); }.bind(this); diff --git a/src/web/Manager.js b/src/web/Manager.js index 1942bc5a..39efc458 100755 --- a/src/web/Manager.js +++ b/src/web/Manager.js @@ -1,3 +1,4 @@ +import WorkerWaiter from "./WorkerWaiter.js"; import WindowWaiter from "./WindowWaiter.js"; import ControlsWaiter from "./ControlsWaiter.js"; import RecipeWaiter from "./RecipeWaiter.js"; @@ -49,6 +50,7 @@ const Manager = function(app) { this.statechange = new CustomEvent("statechange", {bubbles: true}); // Define Waiter objects to handle various areas + this.worker = new WorkerWaiter(this.app, this); this.window = new WindowWaiter(this.app); this.controls = new ControlsWaiter(this.app, this); this.recipe = new RecipeWaiter(this.app, this); @@ -56,7 +58,7 @@ const Manager = function(app) { this.input = new InputWaiter(this.app, this); this.output = new OutputWaiter(this.app, this); this.options = new OptionsWaiter(this.app); - this.highlighter = new HighlighterWaiter(this.app); + this.highlighter = new HighlighterWaiter(this.app, this); this.seasonal = new SeasonalWaiter(this.app, this); // Object to store dynamic handlers to fire on elements that may not exist yet @@ -70,6 +72,7 @@ const Manager = function(app) { * Sets up the various components and listeners. */ Manager.prototype.setup = function() { + this.worker.registerChefWorker(); this.recipe.initialiseOperationDragNDrop(); this.controls.autoBakeChange(); this.seasonal.load(); diff --git a/src/web/OutputWaiter.js b/src/web/OutputWaiter.js index ee5d57ca..0b16c0f2 100755 --- a/src/web/OutputWaiter.js +++ b/src/web/OutputWaiter.js @@ -201,4 +201,44 @@ OutputWaiter.prototype.maximiseOutputClick = function(e) { } }; + +/** + * Shows or hides the loading icon. + * + * @param {boolean} value + */ +OutputWaiter.prototype.toggleLoader = function(value) { + const outputLoader = document.getElementById("output-loader"), + outputElement = document.getElementById("output-text"); + + if (value) { + this.manager.controls.hideStaleIndicator(); + this.bakingStatusTimeout = setTimeout(function() { + outputElement.disabled = true; + outputLoader.style.visibility = "visible"; + outputLoader.style.opacity = 1; + this.manager.controls.toggleBakeButtonFunction(true); + }.bind(this), 200); + } else { + clearTimeout(this.bakingStatusTimeout); + outputElement.disabled = false; + outputLoader.style.opacity = 0; + outputLoader.style.visibility = "hidden"; + this.manager.controls.toggleBakeButtonFunction(false); + this.setStatusMsg(""); + } +}; + + +/** + * Sets the baking status message value. + * + * @param {string} msg + */ +OutputWaiter.prototype.setStatusMsg = function(msg) { + const el = document.querySelector("#output-loader .loading-msg"); + + el.textContent = msg; +}; + export default OutputWaiter; diff --git a/src/web/WorkerWaiter.js b/src/web/WorkerWaiter.js new file mode 100644 index 00000000..362ab128 --- /dev/null +++ b/src/web/WorkerWaiter.js @@ -0,0 +1,180 @@ +import Utils from "../core/Utils.js"; +import ChefWorker from "worker-loader?inline&fallback=false!../core/ChefWorker.js"; + +/** + * Waiter to handle conversations with the ChefWorker. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * @constructor + * @param {App} app - The main view object for CyberChef. + * @param {Manager} manager - The CyberChef event manager. + */ +const WorkerWaiter = function(app, manager) { + this.app = app; + this.manager = manager; +}; + + +/** + * Sets up the ChefWorker and associated listeners. + */ +WorkerWaiter.prototype.registerChefWorker = function() { + this.chefWorker = new ChefWorker(); + this.chefWorker.addEventListener("message", this.handleChefMessage.bind(this)); + + let docURL = document.location.href.split(/[#?]/)[0]; + const index = docURL.lastIndexOf("/"); + if (index > 0) { + docURL = docURL.substring(0, index); + } + this.chefWorker.postMessage({"action": "docURL", "data": docURL}); +}; + + +/** + * Handler for messages sent back by the ChefWorker. + * + * @param {MessageEvent} e + */ +WorkerWaiter.prototype.handleChefMessage = function(e) { + const r = e.data; + switch (r.action) { + case "bakeSuccess": + this.bakingComplete(r.data); + break; + case "bakeError": + this.app.handleError(r.data); + this.setBakingStatus(false); + break; + case "silentBakeComplete": + break; + case "workerLoaded": + this.app.workerLoaded = true; + this.app.loaded(); + break; + case "statusMessage": + this.manager.output.setStatusMsg(r.data); + break; + case "optionUpdate": + this.app.options[r.data.option] = r.data.value; + break; + case "highlightsCalculated": + this.manager.highlighter.displayHighlights(r.data.pos, r.data.direction); + break; + default: + console.error("Unrecognised message from ChefWorker", e); + break; + } +}; + + +/** + * Updates the UI to show if baking is in process or not. + * + * @param {bakingStatus} + */ +WorkerWaiter.prototype.setBakingStatus = function(bakingStatus) { + this.app.baking = bakingStatus; + + this.manager.output.toggleLoader(bakingStatus); +}; + + +/** + * Cancels the current bake by terminating the ChefWorker and creating a new one. + */ +WorkerWaiter.prototype.cancelBake = function() { + this.chefWorker.terminate(); + this.registerChefWorker(); + this.setBakingStatus(false); + this.manager.controls.showStaleIndicator(); +}; + + +/** + * Handler for completed bakes. + * + * @param {Object} response + */ +WorkerWaiter.prototype.bakingComplete = function(response) { + this.setBakingStatus(false); + + if (!response) return; + + if (response.error) { + this.app.handleError(response.error); + } + + this.app.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result; + this.app.progress = response.progress; + this.manager.recipe.updateBreakpointIndicator(response.progress); + this.manager.output.set(response.result, response.type, response.duration); +}; + + +/** + * Asks the ChefWorker to bake the current input using the current recipe. + * + * @param {string} input + * @param {Object[]} recipeConfig + * @param {Object} options + * @param {number} progress + * @param {boolean} step + */ +WorkerWaiter.prototype.bake = function(input, recipeConfig, options, progress, step) { + this.setBakingStatus(true); + + this.chefWorker.postMessage({ + action: "bake", + data: { + input: input, + recipeConfig: recipeConfig, + options: options, + progress: progress, + step: step + } + }); +}; + + +/** + * Asks the ChefWorker to run a silent bake, forcing the browser to load and cache all the relevant + * JavaScript code needed to do a real bake. + * + * @param {Objectp[]} [recipeConfig] + */ +WorkerWaiter.prototype.silentBake = function(recipeConfig) { + this.chefWorker.postMessage({ + action: "silentBake", + data: { + recipeConfig: recipeConfig + } + }); +}; + + +/** + * Asks the ChefWorker to calculate highlight offsets if possible. + * + * @param {Object[]} recipeConfig + * @param {string} direction + * @param {Object} pos - The position object for the highlight. + * @param {number} pos.start - The start offset. + * @param {number} pos.end - The end offset. + */ +WorkerWaiter.prototype.highlight = function(recipeConfig, direction, pos) { + this.chefWorker.postMessage({ + action: "highlight", + data: { + recipeConfig: recipeConfig, + direction: direction, + pos: pos + } + }); +}; + + +export default WorkerWaiter; diff --git a/src/web/html/index.html b/src/web/html/index.html index 52eed427..02b8e2d1 100755 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -35,9 +35,7 @@ "use strict"; // Load theme before the preloader is shown - try { - document.querySelector(":root").className = JSON.parse(localStorage.getItem("options")).theme; - } catch (e) {} + document.querySelector(":root").className = (JSON.parse(localStorage.getItem("options")) || {}).theme; // Define loading messages const loadingMsgs = [ @@ -73,7 +71,8 @@ loadingMsgs.push(msg); try { const el = document.getElementById("preloader-msg"); - el.className = "loading"; // Causes CSS transition on first message + if (!el.classList.contains("loading")) + el.classList.add("loading"); // Causes CSS transition on first message el.innerHTML = msg; } catch (err) {} // Ignore errors if DOM not yet ready } @@ -90,8 +89,8 @@
    -
    -
    +
    +
    Edit @@ -142,7 +141,7 @@