From c39622ed1e3136d0e60108905d88a7cd2da190b1 Mon Sep 17 00:00:00 2001 From: toby Date: Fri, 21 Apr 2017 17:48:42 -0400 Subject: [PATCH 01/27] Add support for async ops using async/await --- src/core/Chef.js | 4 ++-- src/core/FlowControl.js | 4 ++-- src/core/Recipe.js | 6 +++--- src/web/App.js | 4 ++-- test/TestRegister.js | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/Chef.js b/src/core/Chef.js index 8192640f..81eb0595 100755 --- a/src/core/Chef.js +++ b/src/core/Chef.js @@ -34,7 +34,7 @@ var Chef = function() { * @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) */ -Chef.prototype.bake = function(inputText, recipeConfig, options, progress, step) { +Chef.prototype.bake = async function(inputText, recipeConfig, options, progress, step) { var startTime = new Date().getTime(), recipe = new Recipe(recipeConfig), containsFc = recipe.containsFlowControl(), @@ -72,7 +72,7 @@ Chef.prototype.bake = function(inputText, recipeConfig, options, progress, step) } try { - progress = recipe.execute(this.dish, progress); + progress = await recipe.execute(this.dish, progress); } catch (err) { // Return the error in the result so that everything else gets correctly updated // rather than throwing it here and losing state info. diff --git a/src/core/FlowControl.js b/src/core/FlowControl.js index 54541f74..015e5904 100755 --- a/src/core/FlowControl.js +++ b/src/core/FlowControl.js @@ -38,7 +38,7 @@ const FlowControl = { * @param {Operation[]} state.opList - The list of operations in the recipe. * @returns {Object} The updated state of the recipe. */ - runFork: function(state) { + runFork: async function(state) { var opList = state.opList, inputType = opList[state.progress].inputType, outputType = opList[state.progress].outputType, @@ -73,7 +73,7 @@ const FlowControl = { for (i = 0; i < inputs.length; i++) { var dish = new Dish(inputs[i], inputType); try { - progress = recipe.execute(dish, 0); + progress = await recipe.execute(dish, 0); } catch (err) { if (!ignoreErrors) { throw err; diff --git a/src/core/Recipe.js b/src/core/Recipe.js index b0a39673..ed8c19b0 100755 --- a/src/core/Recipe.js +++ b/src/core/Recipe.js @@ -145,7 +145,7 @@ Recipe.prototype.lastOpIndex = function(startIndex) { * @param {number} [startFrom=0] - The index of the Operation to start executing from * @returns {number} - The final progress through the recipe */ -Recipe.prototype.execute = function(dish, startFrom) { +Recipe.prototype.execute = async function(dish, startFrom) { startFrom = startFrom || 0; var op, input, output, numJumps = 0; @@ -170,11 +170,11 @@ Recipe.prototype.execute = function(dish, startFrom) { "numJumps" : numJumps }; - state = op.run(state); + state = await op.run(state); i = state.progress; numJumps = state.numJumps; } else { - output = op.run(input, op.getIngValues()); + output = await op.run(input, op.getIngValues()); dish.set(output, op.outputType); } } catch (err) { diff --git a/src/web/App.js b/src/web/App.js index 59121bd9..945b28e0 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -73,11 +73,11 @@ App.prototype.handleError = function(err) { * @param {boolean} [step] - Set to true if we should only execute one operation instead of the * whole recipe. */ -App.prototype.bake = function(step) { +App.prototype.bake = async function(step) { var response; try { - response = this.chef.bake( + 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 diff --git a/test/TestRegister.js b/test/TestRegister.js index fdd3431b..bfdb6974 100644 --- a/test/TestRegister.js +++ b/test/TestRegister.js @@ -40,13 +40,13 @@ import Chef from "../src/core/Chef.js"; this.tests.map(function(test, i) { var chef = new Chef(); - return Promise.resolve(chef.bake( + return chef.bake( test.input, test.recipeConfig, {}, 0, false - )) + ) .then(function(result) { var ret = { test: test, From 02f855ff096a8d0210c97fbe1113267c261c5f93 Mon Sep 17 00:00:00 2001 From: toby Date: Fri, 21 Apr 2017 17:49:10 -0400 Subject: [PATCH 02/27] Add more tests for flow control ops --- test/tests/operations/FlowControl.js | 133 +++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/test/tests/operations/FlowControl.js b/test/tests/operations/FlowControl.js index 96ae2e80..985481cd 100644 --- a/test/tests/operations/FlowControl.js +++ b/test/tests/operations/FlowControl.js @@ -66,6 +66,62 @@ TestRegister.addTests([ {"op":"To Base64", "args":["A-Za-z0-9+/="]} ] }, + { + name: "Jump: skips 0", + input: [ + "should be changed", + ].join("\n"), + expectedOutput: [ + "should be changed was changed", + ].join("\n"), + recipeConfig: [ + { + op: "Jump", + args: [0, 10], + }, + { + op: "Find / Replace", + args: [ + { + "option": "Regex", + "string": "should be changed" + }, + "should be changed was changed", + true, + true, + true, + ], + }, + ], + }, + { + name: "Jump: skips 1", + input: [ + "shouldnt be changed", + ].join("\n"), + expectedOutput: [ + "shouldnt be changed", + ].join("\n"), + recipeConfig: [ + { + op: "Jump", + args: [1, 10], + }, + { + op: "Find / Replace", + args: [ + { + "option": "Regex", + "string": "shouldnt be changed" + }, + "shouldnt be changed was changed", + true, + true, + true, + ], + }, + ], + }, { name: "Conditional Jump: Skips 0", input: [ @@ -111,4 +167,81 @@ TestRegister.addTests([ }, ], }, + { + name: "Conditional Jump: Skips 1", + input: [ + "match", + "should not be changed", + "should be changed", + ].join("\n"), + expectedOutput: [ + "match", + "should not be changed", + "should be changed was changed" + ].join("\n"), + recipeConfig: [ + { + op: "Conditional Jump", + args: ["match", 1, 10], + }, + { + op: "Find / Replace", + args: [ + { + "option": "Regex", + "string": "should not be changed" + }, + "should not be changed was changed", + true, + true, + true, + ], + }, + { + op: "Find / Replace", + args: [ + { + "option": "Regex", + "string": "should be changed" + }, + "should be changed was changed", + true, + true, + true, + ], + }, + ], + }, + { + name: "Conditional Jump: Skips negatively", + input: [ + "match", + ].join("\n"), + expectedOutput: [ + "replaced", + ].join("\n"), + recipeConfig: [ + { + op: "Jump", + args: [1], + }, + { + op: "Find / Replace", + args: [ + { + "option": "Regex", + "string": "match" + }, + "replaced", + true, + true, + true, + ], + }, + { + op: "Conditional Jump", + args: ["match", -2, 10], + }, + ], + }, ]); From 9f60dc3dd6ec364ca0d422b2d674c67ec7cb20d0 Mon Sep 17 00:00:00 2001 From: toby Date: Fri, 21 Apr 2017 17:56:16 -0400 Subject: [PATCH 03/27] Change ecmaVersion to 8 to make eslint happy --- src/.eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/.eslintrc.json b/src/.eslintrc.json index 677146b5..2f48f1d4 100755 --- a/src/.eslintrc.json +++ b/src/.eslintrc.json @@ -1,6 +1,6 @@ { "parserOptions": { - "ecmaVersion": 6, + "ecmaVersion": 8, "ecmaFeatures": { "impliedStrict": true }, From 3fb660d8164b4b21969e6ab616bdb4255e841aad Mon Sep 17 00:00:00 2001 From: toby Date: Fri, 21 Apr 2017 18:05:30 -0400 Subject: [PATCH 04/27] Add jsdoc-babel plugin This is to stop jsdoc parsing errors. More information in this thread: https://github.com/jsdoc3/jsdoc/issues/555 --- docs/jsdoc.conf.json | 5 ++++- package.json | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/jsdoc.conf.json b/docs/jsdoc.conf.json index 00a85cc3..3c247edc 100755 --- a/docs/jsdoc.conf.json +++ b/docs/jsdoc.conf.json @@ -2,7 +2,10 @@ "tags": { "allowUnknownTags": true }, - "plugins": ["plugins/markdown"], + "plugins": [ + "plugins/markdown", + "node_modules/jsdoc-babel" + ], "templates": { "systemName": "CyberChef", "footer": "", diff --git a/package.json b/package.json index 9381cf03..8f41b1e3 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "html-webpack-plugin": "^2.28.0", "imports-loader": "^0.7.1", "ink-docstrap": "^1.1.4", + "jsdoc-babel": "^0.3.0", "less": "^2.7.2", "less-loader": "^4.0.2", "style-loader": "^0.15.0", From a13e2468db234acbb67b0587b46dd5df29c92957 Mon Sep 17 00:00:00 2001 From: toby Date: Fri, 21 Apr 2017 20:04:12 -0400 Subject: [PATCH 05/27] Added UI loading indications to the HTML app --- src/web/App.js | 38 ++++++++++++++++++++++++++++++++ src/web/css/structure/layout.css | 33 +++++++++++++++++++++++++++ src/web/html/index.html | 2 ++ 3 files changed, 73 insertions(+) diff --git a/src/web/App.js b/src/web/App.js index 945b28e0..9c45765d 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -30,6 +30,7 @@ var App = function(categories, operations, defaultFavourites, defaultOptions) { this.chef = new Chef(); this.manager = new Manager(this); + this.baking = false; this.autoBake_ = false; this.progress = 0; this.ingId = 0; @@ -67,6 +68,37 @@ 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; + + var inputLoadingIcon = document.querySelector("#input .title .loading-icon"), + outputLoadingIcon = document.querySelector("#output .title .loading-icon"), + inputElement = document.querySelector("#input-text"), + outputElement = document.querySelector("#output-text"); + + if (bakingStatus) { + inputLoadingIcon.style.display = "inline-block"; + outputLoadingIcon.style.display = "inline-block"; + inputElement.classList.add("disabled"); + outputElement.classList.add("disabled"); + inputElement.disabled = true; + outputElement.disabled = true; + } else { + inputLoadingIcon.style.display = "none"; + outputLoadingIcon.style.display = "none"; + inputElement.classList.remove("disabled"); + outputElement.classList.remove("disabled"); + inputElement.disabled = false; + outputElement.disabled = false; + } +}; + + /** * Calls the Chef to bake the current input using the current recipe. * @@ -76,6 +108,10 @@ App.prototype.handleError = function(err) { App.prototype.bake = async function(step) { var response; + if (this.baking) return; + + this.setBakingStatus(true); + try { response = await this.chef.bake( this.getInput(), // The user's input @@ -94,6 +130,8 @@ App.prototype.bake = async function(step) { this.handleError(response.error); } + this.setBakingStatus(false); + this.options = response.options; this.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result; this.progress = response.progress; diff --git a/src/web/css/structure/layout.css b/src/web/css/structure/layout.css index 8286eb82..3cd5abe7 100755 --- a/src/web/css/structure/layout.css +++ b/src/web/css/structure/layout.css @@ -430,3 +430,36 @@ span.btn img { border-top: none; margin-top: 0; } + + +@-moz-keyframes spinner { + from { -moz-transform: rotate(0deg); } + to { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spinner { + from { -webkit-transform: rotate(0deg); } + to { -webkit-transform: rotate(359deg); } +} +@keyframes spinner { + from {transform:rotate(0deg);} + to {transform:rotate(359deg);} +} + +.loading-icon::before { + content: "\21bb"; +} + +.loading-icon { + -webkit-animation-name: spinner; + -webkit-animation-duration: 1000ms; + -webkit-animation-iteration-count: infinite; + -webkit-animation-timing-function: linear; + -moz-animation-name: spinner; + -moz-animation-duration: 1000ms; + -moz-animation-iteration-count: infinite; + -moz-animation-timing-function: linear; + -ms-animation-name: spinner; + -ms-animation-duration: 1000ms; + -ms-animation-iteration-count: infinite; + -ms-animation-timing-function: linear; +} diff --git a/src/web/html/index.html b/src/web/html/index.html index 35877e45..afe56fae 100755 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -100,6 +100,7 @@
+
@@ -116,6 +117,7 @@
+
From 21c0fed8339eb2921e456f2dc298920eff3d28c5 Mon Sep 17 00:00:00 2001 From: toby Date: Sun, 23 Apr 2017 13:14:59 -0400 Subject: [PATCH 06/27] Fix bug: baking error did not reset baking status --- src/web/App.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/App.js b/src/web/App.js index 9c45765d..b4fb3a75 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -124,14 +124,14 @@ App.prototype.bake = async function(step) { this.handleError(err); } + this.setBakingStatus(false); + if (!response) return; if (response.error) { this.handleError(response.error); } - this.setBakingStatus(false); - this.options = response.options; this.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result; this.progress = response.progress; From 50784f260082677d31a4a7f48ee47a1bfddc5a4e Mon Sep 17 00:00:00 2001 From: toby Date: Sun, 23 Apr 2017 13:41:28 -0400 Subject: [PATCH 07/27] Debounce autobake in the web app. Added debounce with guidance from the underscore.js implementation: https://github.com/jashkenas/underscore/blob/e944e0275abb3e1f366417ba8facb5754a7ad273/underscore.js#L880 --- src/core/Utils.js | 27 +++++++++++++++++++++++++++ src/web/App.js | 2 ++ 2 files changed, 29 insertions(+) diff --git a/src/core/Utils.js b/src/core/Utils.js index 2e4b354b..a49565e5 100755 --- a/src/core/Utils.js +++ b/src/core/Utils.js @@ -1185,6 +1185,33 @@ const Utils = { "Latin1": CryptoJS.enc.Latin1, }, + + /** + * A utility for "debouncing" functions. + * Debouncing is when you want to ensure events triggered by an event are rate-limited. + * @constant + */ + debounce(fn, delay) { + let timeout; + + return function() { + /** + * later calls the debounced function with arguments. + * If the debounced function is called again, then the timeout + * which calls later is cancelled. + */ + let later = () => { + fn.apply(this, arguments); + }; + + if (timeout) { + clearTimeout(timeout); + } + + timeout = setTimeout(later, delay); + }; + }, + }; export default Utils; diff --git a/src/web/App.js b/src/web/App.js index b4fb3a75..de8af4a7 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -36,6 +36,8 @@ var App = function(categories, operations, defaultFavourites, defaultOptions) { this.ingId = 0; window.chef = this.chef; + + this.autoBake = Utils.debounce(this.autoBake, 300); }; From 5b03a84be83317583b2cabe0ae1926aa48156578 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 13 Apr 2017 18:43:38 +0100 Subject: [PATCH 08/27] use .fill to initialise Arrays --- src/core/operations/Entropy.js | 7 +------ src/core/operations/IP.js | 6 +----- src/core/operations/StrUtils.js | 4 +--- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/core/operations/Entropy.js b/src/core/operations/Entropy.js index e7ad3028..3451914d 100755 --- a/src/core/operations/Entropy.js +++ b/src/core/operations/Entropy.js @@ -88,17 +88,12 @@ const Entropy = { runFreqDistrib: function (input, args) { if (!input.length) return "No data"; - let distrib = new Array(256), + let distrib = new Array(256).fill(0), percentages = new Array(256), len = input.length, showZeroes = args[0], i; - // Initialise distrib to 0 - for (i = 0; i < 256; i++) { - distrib[i] = 0; - } - // Count bytes for (i = 0; i < len; i++) { distrib[input[i]]++; diff --git a/src/core/operations/IP.js b/src/core/operations/IP.js index 603a495c..8a852789 100755 --- a/src/core/operations/IP.js +++ b/src/core/operations/IP.js @@ -713,13 +713,9 @@ const IP = { ip2 = IP._strToIpv6(range[14]); let t = "", - total = new Array(128), + total = new Array(128).fill(), i; - // Initialise total array to "0" - for (i = 0; i < 128; i++) - total[i] = "0"; - for (i = 0; i < 8; i++) { t = (ip2[i] - ip1[i]).toString(2); if (t !== "0") { diff --git a/src/core/operations/StrUtils.js b/src/core/operations/StrUtils.js index 6d9a5114..4203efa6 100755 --- a/src/core/operations/StrUtils.js +++ b/src/core/operations/StrUtils.js @@ -397,9 +397,7 @@ const StrUtils = { } // Initialise output strings - for (s = 0; s < samples.length; s++) { - outputs[s] = ""; - } + outputs.fill("", 0, samples.length); // Loop through each character in the first sample for (i = 0; i < samples[0].length; i++) { From 15aea9e9ea962dbb74af51ecb3aa906a9db7331e Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Tue, 2 May 2017 23:06:28 +0100 Subject: [PATCH 09/27] auto-fix prefer-const --- src/core/operations/Code.js | 8 ++++---- src/core/operations/StrUtils.js | 4 ++-- src/web/ControlsWaiter.js | 4 ++-- test/TestRegister.js | 4 ++-- test/index.js | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/core/operations/Code.js b/src/core/operations/Code.js index f7b72f5e..c1df6714 100755 --- a/src/core/operations/Code.js +++ b/src/core/operations/Code.js @@ -426,7 +426,7 @@ const Code = { * @returns {string} */ _replaceVariableNames(input, replacer) { - let tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig; + const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig; return input.replace(tokenRegex, (...args) => { let match = args[0], @@ -450,7 +450,7 @@ const Code = { * */ runToSnakeCase(input, args) { - let smart = args[0]; + const smart = args[0]; if (smart) { return Code._replaceVariableNames(input, snakeCase); @@ -469,7 +469,7 @@ const Code = { * */ runToCamelCase(input, args) { - let smart = args[0]; + const smart = args[0]; if (smart) { return Code._replaceVariableNames(input, camelCase); @@ -488,7 +488,7 @@ const Code = { * */ runToKebabCase(input, args) { - let smart = args[0]; + const smart = args[0]; if (smart) { return Code._replaceVariableNames(input, kebabCase); diff --git a/src/core/operations/StrUtils.js b/src/core/operations/StrUtils.js index 4203efa6..1eed465a 100755 --- a/src/core/operations/StrUtils.js +++ b/src/core/operations/StrUtils.js @@ -471,7 +471,7 @@ const StrUtils = { number = args[1]; delimiter = Utils.charRep[delimiter]; - let splitInput = input.split(delimiter); + const splitInput = input.split(delimiter); return splitInput .filter((line, lineIndex) => { @@ -499,7 +499,7 @@ const StrUtils = { number = args[1]; delimiter = Utils.charRep[delimiter]; - let splitInput = input.split(delimiter); + const splitInput = input.split(delimiter); return splitInput .filter((line, lineIndex) => { diff --git a/src/web/ControlsWaiter.js b/src/web/ControlsWaiter.js index 3f22b742..1af61e74 100755 --- a/src/web/ControlsWaiter.js +++ b/src/web/ControlsWaiter.js @@ -244,8 +244,8 @@ ControlsWaiter.prototype.loadClick = function() { * Saves the recipe specified in the save textarea to local storage. */ ControlsWaiter.prototype.saveButtonClick = function() { - let recipeName = Utils.escapeHtml(document.getElementById("save-name").value); - let recipeStr = document.getElementById("save-text").value; + const recipeName = Utils.escapeHtml(document.getElementById("save-name").value); + const recipeStr = document.getElementById("save-text").value; if (!recipeName) { this.app.alert("Please enter a recipe name", "danger", 2000); diff --git a/test/TestRegister.js b/test/TestRegister.js index 3088c8fe..a66d65f2 100644 --- a/test/TestRegister.js +++ b/test/TestRegister.js @@ -38,7 +38,7 @@ import Chef from "../src/core/Chef.js"; TestRegister.prototype.runTests = function() { return Promise.all( this.tests.map(function(test, i) { - let chef = new Chef(); + const chef = new Chef(); return Promise.resolve(chef.bake( test.input, @@ -48,7 +48,7 @@ import Chef from "../src/core/Chef.js"; false )) .then(function(result) { - let ret = { + const ret = { test: test, status: null, output: null, diff --git a/test/index.js b/test/index.js index 2543a33d..d5037a78 100644 --- a/test/index.js +++ b/test/index.js @@ -32,7 +32,7 @@ let allTestsPassing = true, * @returns {string} */ function statusToIcon(status) { - let icons = { + const icons = { erroring: "🔥", failing: "❌", passing: "✔️️", @@ -48,7 +48,7 @@ function statusToIcon(status) { */ function handleTestResult(testResult) { allTestsPassing = allTestsPassing && testResult.status === "passing"; - let newCount = (testStatusCounts[testResult.status] || 0) + 1; + const newCount = (testStatusCounts[testResult.status] || 0) + 1; testStatusCounts[testResult.status] = newCount; testStatusCounts.total += 1; @@ -83,8 +83,8 @@ TestRegister.runTests() console.log("\n"); - for (let testStatus in testStatusCounts) { - let count = testStatusCounts[testStatus]; + for (const testStatus in testStatusCounts) { + const count = testStatusCounts[testStatus]; if (count > 0) { console.log(testStatus.toUpperCase(), count); } From 0a3233d289a6a8ff35ec7d303ef3049aec74b04e Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Tue, 2 May 2017 23:13:50 +0100 Subject: [PATCH 10/27] move spider images to .json file --- src/web/SeasonalWaiter.js | 8 +++++--- src/web/spiderImages.json | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 src/web/spiderImages.json diff --git a/src/web/SeasonalWaiter.js b/src/web/SeasonalWaiter.js index b2fae5c8..69ea2c06 100755 --- a/src/web/SeasonalWaiter.js +++ b/src/web/SeasonalWaiter.js @@ -1,3 +1,8 @@ +import spiderImages from "./spiderImages.json"; + + +const { spider16, spider32, spider64 } = spiderImages; + /** * Waiter to handle seasonal events and easter eggs. * @@ -38,9 +43,6 @@ SeasonalWaiter.prototype.load = function() { * #spiderchef */ SeasonalWaiter.prototype.insertSpiderIcons = function() { - let spider16 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3UlEQVQ4y2NgGJaAmYGBgVnf0oKJgYGBobWtXamqqoYTn2I4CI+LTzM2NTulpKbu+vPHz2dV5RWlluZmi3j5+KqFJSSEzpw8uQPdAEYYIzo5Kfjrl28rWFlZzjAzMYuEBQao3Lh+g+HGvbsMzExMDN++fWf4/PXLBzY2tqYNK1f2+4eHM2xcuRLigsT09Igf3384MTExbf767etBI319jU8fPsi+//jx/72HDxh5uLkZ7ty7y/Dz1687Avz8n2UUFR3Z2NjOySoqfmdhYGBg+PbtuwI7O8e5H79+8X379t357PnzYo+ePP7y6cuXc9++f69nYGRsvf/w4XdtLS2R799/bBUWFHr57sP7Jbs3b/ZkzswvUP3165fZ7z9//r988WIVAyPDr8tXr576+u3bpb9//7YwMjKeV1dV41NWVGoVEhDgPH761DJREeHaz1+/lqlpafUx6+jrRfz4+fPy+w8fTu/fsf3uw7t3L39+//4cv7DwGQYGhpdPbt9m4BcRFlNWVJC4fuvWASszs4C379792Ldt2xZBUdEdDP5hYSqQGIjDGa965uYKCalpZQwMDAxhMTG9DAwMDLaurhIkJY7A8IgGBgYGBgd3Dz2yUpeFo6O4rasrA9T24ZRxAAMTwMpgEJwLAAAAAElFTkSuQmCC", - spider32 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACYVBMVEUAAAAcJSU2Pz85QkM9RUWEhIWMjI2MkJEcJSU2Pz85QkM9RUWWlpc9RUVXXl4cJSU2Pz85QkM8REU9RUVRWFh6ens9RUVCSkpNVFRdY2McJSU5QkM7REQ9RUVGTk5KUlJQVldcY2Rla2uTk5WampscJSVUWltZX2BrcHF1e3scJSUjLCw9RUVASEhFTU1HTk9bYWJeZGRma2xudHV1eHiZmZocJSUyOjpJUFFQVldSWlpTWVpXXl5YXl5rb3B9fX6RkZIcJSUmLy8tNTU9RUVFTU1IT1BOVldRV1hTWlp0enocJSUfKChJUFBWXV1hZ2hnbGwcJSVETExLUlJLU1NNVVVPVlZYXl9cY2RiaGlobW5rcXFyd3h0eHgcJSUpMTFDS0tQV1dRV1hSWFlWXF1bYWJma2tobW5uc3SsrK0cJSVJUFBMVFROVlZVW1xZX2BdYmNhZ2hjaGhla2tqcHBscHE4Pz9KUlJRWVlSWVlXXF1aYGFbYWFfZWZlampqbW4cJSUgKSkiKysuNjY0PD01PT07QkNES0tHTk5JUFBMUlNMU1NOU1ROVVVPVVZRVlZRV1dSWVlWXFxXXV5aX2BbYWFbYWJcYmJcYmNcY2RdYmNgZmZhZmdkaWpkampkamtlamtla2tma2tma2xnbG1obW5pbG1pb3Bqb3Brb3BtcXJudHVvcHFvcXJvc3NwcXNwdXVxc3RzeXl1eXp2eXl3ent6e3x+gYKAhISBg4SKi4yLi4yWlpeampudnZ6fn6CkpaanqKiur6+vr7C4uLm6urq6u7u8vLy9vb3Av8DR0dL2b74UAAAAgHRSTlMAEBAQEBAQECAgICAgMDBAQEBAQEBAUFBQUGBgYGBgYGBgYGBgcHBwcHCAgICAgICAgICAgICPj4+Pj4+Pj4+Pj5+fn5+fn5+fn5+vr6+vr6+/v7+/v7+/v7+/v7+/z8/Pz8/Pz8/Pz8/P39/f39/f39/f39/f7+/v7+/v7+/v78x6RlYAAAGBSURBVDjLY2AYWUCSgUGAk4GBTdlUhQebvP7yjIgCPQbWzBMnjx5wwJSX37Rwfm1isqj9/iPHTuxYlyeMJi+yunfptBkZOw/uWj9h3vatcycu8eRGlldb3Vsts3ph/cFTh7fN3bCoe2Vf8+TZoQhTvBa6REozVC7cuPvQnmULJm1e2z+308eyJieEBSLPXbKQIUqQIczk+N6eNaumtnZMaWhaHM89m8XVCqJA02Y5w0xmga6yfVsamtrN4xoXNzS0JTHkK3CXy4EVFMumcxUy2LbENTVkZfEzMDAudtJyTmNwS2XQreAFyvOlK9louDNVaXurmjkGgnTMkWDgXswtNouFISEX6Awv+RihQi5OcYY4DtVARpCCFCMGhiJ1hjwFBpagEAaWEpFoC0WQOCOjFMRRwXYMDB4BDLJ+QLYsg7GBGjtasLnEMjCIrWBgyAZ7058FI9x1SoFEnTCDsCyIhynPILYYSFgbYpUDA5bpQBluXzxpI1yYAbd2sCMYRhwAAHB9ZPztbuMUAAAAAElFTkSuQmCC", - spider64 = "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"; // Favicon document.querySelector("link[rel=icon]").setAttribute("href", "data:image/png;base64," + spider16); diff --git a/src/web/spiderImages.json b/src/web/spiderImages.json new file mode 100644 index 00000000..119a7412 --- /dev/null +++ b/src/web/spiderImages.json @@ -0,0 +1,5 @@ +{ + "spider16": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3UlEQVQ4y2NgGJaAmYGBgVnf0oKJgYGBobWtXamqqoYTn2I4CI+LTzM2NTulpKbu+vPHz2dV5RWlluZmi3j5+KqFJSSEzpw8uQPdAEYYIzo5Kfjrl28rWFlZzjAzMYuEBQao3Lh+g+HGvbsMzExMDN++fWf4/PXLBzY2tqYNK1f2+4eHM2xcuRLigsT09Igf3384MTExbf767etBI319jU8fPsi+//jx/72HDxh5uLkZ7ty7y/Dz1687Avz8n2UUFR3Z2NjOySoqfmdhYGBg+PbtuwI7O8e5H79+8X379t357PnzYo+ePP7y6cuXc9++f69nYGRsvf/w4XdtLS2R799/bBUWFHr57sP7Jbs3b/ZkzswvUP3165fZ7z9//r988WIVAyPDr8tXr576+u3bpb9//7YwMjKeV1dV41NWVGoVEhDgPH761DJREeHaz1+/lqlpafUx6+jrRfz4+fPy+w8fTu/fsf3uw7t3L39+//4cv7DwGQYGhpdPbt9m4BcRFlNWVJC4fuvWASszs4C379792Ldt2xZBUdEdDP5hYSqQGIjDGa965uYKCalpZQwMDAxhMTG9DAwMDLaurhIkJY7A8IgGBgYGBgd3Dz2yUpeFo6O4rasrA9T24ZRxAAMTwMpgEJwLAAAAAElFTkSuQmCC", + "spider32": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACYVBMVEUAAAAcJSU2Pz85QkM9RUWEhIWMjI2MkJEcJSU2Pz85QkM9RUWWlpc9RUVXXl4cJSU2Pz85QkM8REU9RUVRWFh6ens9RUVCSkpNVFRdY2McJSU5QkM7REQ9RUVGTk5KUlJQVldcY2Rla2uTk5WampscJSVUWltZX2BrcHF1e3scJSUjLCw9RUVASEhFTU1HTk9bYWJeZGRma2xudHV1eHiZmZocJSUyOjpJUFFQVldSWlpTWVpXXl5YXl5rb3B9fX6RkZIcJSUmLy8tNTU9RUVFTU1IT1BOVldRV1hTWlp0enocJSUfKChJUFBWXV1hZ2hnbGwcJSVETExLUlJLU1NNVVVPVlZYXl9cY2RiaGlobW5rcXFyd3h0eHgcJSUpMTFDS0tQV1dRV1hSWFlWXF1bYWJma2tobW5uc3SsrK0cJSVJUFBMVFROVlZVW1xZX2BdYmNhZ2hjaGhla2tqcHBscHE4Pz9KUlJRWVlSWVlXXF1aYGFbYWFfZWZlampqbW4cJSUgKSkiKysuNjY0PD01PT07QkNES0tHTk5JUFBMUlNMU1NOU1ROVVVPVVZRVlZRV1dSWVlWXFxXXV5aX2BbYWFbYWJcYmJcYmNcY2RdYmNgZmZhZmdkaWpkampkamtlamtla2tma2tma2xnbG1obW5pbG1pb3Bqb3Brb3BtcXJudHVvcHFvcXJvc3NwcXNwdXVxc3RzeXl1eXp2eXl3ent6e3x+gYKAhISBg4SKi4yLi4yWlpeampudnZ6fn6CkpaanqKiur6+vr7C4uLm6urq6u7u8vLy9vb3Av8DR0dL2b74UAAAAgHRSTlMAEBAQEBAQECAgICAgMDBAQEBAQEBAUFBQUGBgYGBgYGBgYGBgcHBwcHCAgICAgICAgICAgICPj4+Pj4+Pj4+Pj5+fn5+fn5+fn5+vr6+vr6+/v7+/v7+/v7+/v7+/z8/Pz8/Pz8/Pz8/P39/f39/f39/f39/f7+/v7+/v7+/v78x6RlYAAAGBSURBVDjLY2AYWUCSgUGAk4GBTdlUhQebvP7yjIgCPQbWzBMnjx5wwJSX37Rwfm1isqj9/iPHTuxYlyeMJi+yunfptBkZOw/uWj9h3vatcycu8eRGlldb3Vsts3ph/cFTh7fN3bCoe2Vf8+TZoQhTvBa6REozVC7cuPvQnmULJm1e2z+308eyJieEBSLPXbKQIUqQIczk+N6eNaumtnZMaWhaHM89m8XVCqJA02Y5w0xmga6yfVsamtrN4xoXNzS0JTHkK3CXy4EVFMumcxUy2LbENTVkZfEzMDAudtJyTmNwS2XQreAFyvOlK9louDNVaXurmjkGgnTMkWDgXswtNouFISEX6Awv+RihQi5OcYY4DtVARpCCFCMGhiJ1hjwFBpagEAaWEpFoC0WQOCOjFMRRwXYMDB4BDLJ+QLYsg7GBGjtasLnEMjCIrWBgyAZ7058FI9x1SoFEnTCDsCyIhynPILYYSFgbYpUDA5bpQBluXzxpI1yYAbd2sCMYRhwAAHB9ZPztbuMUAAAAAElFTkSuQmCC", + "spider64": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJZUlEQVR42u1ZaXMU1xXlJ+gHpFITOy5sAcnIYCi2aIL2bTSSZrSP1NpHK41kISQBHgFaQIJBCMwi4TFUGYcPzggwEMcxHVGxQaag5QR/np/QP+Hmnsdr0hpmtEACwulb9aq7p7d3zz333Pt61q2zzTbbbLPNNttss80222yzzTbbVmu7MzKcJRWVkXjntqam6jyURPeGQqeTpqbOqp+evxC5dGlam5m5rE3PzGi8Hzx/4aLzbXDe09HdYxwZHaPc4mLFXVoW9pRXGNv3pDngeHlNLfE2Ljjj4xPOUGjSYKfpq6/+TLdv36bbX39Nt27epGvXvqSLl6bp3LlPtdOnz7jWrPNZ7kLCKCovp5bOTmP/4EHq6vmYMtzuSKbbbQCAHE8Rxd47MjrmuHjxkjF3/z4tLCzQkyc6PX78mB49ekQPHjygub/P0d27f6FrX/6JpqbO0YkT48E1R/sCr9cYHZ+gqrp64mPq+riXcoqKKC0vP9q6VyV/fQOiH+LrsPVY7z82PBKZnb1Bd+7cpfn5eQbgCT1hAADC/MN5uj83R99881eanZ2lL5gN/nrxjihAXwvOJ7l9vuiBQ4dF9LEtLC0V+2rv/ijTX6luaCS3rxT57wADAMTBQ4c9PIIDg4PBwYOHaHhklM5MnSWkwLff/o0+v3qVHv34Iz344QEDc4d8VVXUEAhQXXMzVdQqzKweKq6oABARzOGNOZ+Wl6fD6T25ubQrPT0E5xF93o82tbdjkkZ+iZfAAgbD6fZ6o339A8S0p7HjJ2h4eIQOHf6EujlV9nX3UOj0JDXzfXje+KlTdOPGDeF0T1+fGHg+2JSen08tHZ0CiPySEoPn8vq1IaOgIAzneQK0UzjcQd6qaqrlCVfV1+tpubnRnv5+2p2ZqYMF/oZGPTh0xLhy5Sr9wLn9j++/p5nLn9FxBoLZQJ1dKrkys6iYNeTExEnx3PqWFuF4W9deKq2upkEGCyzyMBC709MFC7r391Fjayv9MSdHZyCU1xJ5FjrNdN6VnU1KS4CjU4Yoh/m8CsezCguFJgAMV05ueP+BfhF5OL+gL9A/f/qJ7t3TaPLMFB09eoy6mTkMGg2PjTELOsS20OcTACgMKqJugqA0NtE7ycn0202b6A+ZmYIVAAKApGZlgRHB/0lqQPAqFEVE9hntM0R0ZblTzeswWdCeU8HAtYW+Uu0AUx+0f/jwoXD+56c/073v7tHU2XMiFbrUfVTNAtfL10FIAQL2QftsBrOEnavld5kg7E7PoF+99x79ev162rJrV9RMi6a2dvKUlQsR5uAgII7/ivMsbEE4g2hggjzC7LQL1OftovoO0WJKUn0gYEAn2hmMXo4QHIXQIfLfsfOXPwuLvB86cpQqamooyEzg1BLMwv04RkoE+B3B4BBBMHEcCwIP0N+ByJdUVhpgBJ7j4WvdANDjeTUglOaWEChfJF7uJzPX2HEPaj1vg7EAbHO5QnAeIPgqKvUB7gtAdbBgcvKMqOnc/NAIVwCcq21qElFnCgvaI9cBBFKhlSPbPzBIbbzduGULpWzfLkDAdZs++sgEwSlZqoIJMg2CzFSNGzODwdBfOi26+w4YTCm9LhDQwQDzdzguFf4FALjciTws8/u1yyx2N2/dovPnL9DRY8PkZ204xtuhoSM0wI7V8DEiirQCCHD+99u2CUdx3Lmvmz7kfemoGDgPEDr4HNKAf1MlAC4wgMGLWFJXQUrklZSEX6rLE2rOyDIQGlhgBUAyYFEZkm2vAGVi4qQ+x83M0389pevXr6OToy07d4qcR+krr/KzqpeJ/IfjGO+npDx3FCKHVPjd1q2LAMBI3ryZ9vL7U56BEzLfD80ACFba876OlGCQV9dAcT0Pyw7PgWij6zPP5Xt9EYgg+n3LosdVzdfz5CI8KY1LH31+5Yro9KanZwjHmPzmHTsoOeVDemfDBuE8dGVnWpqx3unUrE4CDLCAG64XAHB88IFgQV5xMY7DFmc16A6CZvnNBYYVcW+yKj0A/VHTsQ8dwMPNc6X+Gg0VIGbVpzYGWundjRujmGQWi9Eol7+TJ0/R2Nhx2sNlM9YJRPDdDRsM5DGPJB4KHOIhngHhAwixAGAAuDZ2lsuiYnFWBQOYrdEYNochilyiV6YHoH+rRNJkAG+fUw31PzU7Z1EFKPD69CIuQ1Bm6URoh8tFmVym3nc6rZOPyi0cD8HxeHPg3x2InNrbS79JTsYzNXmPuBclsO3ZvKwAOJEGsmI5rT0M+gSf3y9K5LIA1LUEIlL1k0AhCYBH5r9TCqBqib4D+c/1PyInGOThkvuaHCYALhlpbQWBMGR/4IpzTqlpbKQyf0045vdoe0zATHagSYMeWFMkbscnHRYPZjoFJaIiUkz9EJy15j/X3qCsAIqMcFjSWrNE1Iygg0fEmrtLzEUTdT/OhBFht9fHDVCbEUt3LJxi08B8Xj6vTDESriq9lVWqBECgHujqiqAUmufb1X3cfRXoluhjZWiwkOnSUcUS6ZD8LUmmhks6b5j1ezkAkAKZBe5QvPPcNBnoCawMwT66Qxk0R2xwwRAui2iSDGuaPDcubzo3EJq8wcx/9Vmk3QryH42QBQCFF0UagIiJtjX6DskIXTLEucJSHIIIMuO0BOcjn3A3ybU/lu5RCUBc5qA0Ih0Q2EWiCPRk7VfMNhjLW1zETic1tLYZDMKyuSsdfh5l6bwho5+0il4kyA0VohlNcF5FP8DlWo/VB16HYB2hJ0pzgIe2mcXxP2IOumPRY17U0tll8KIkZNb+sppafOxYkQPSaYfchyYoL9GMqWYpTLRIq1QUcT4O3aPQgqVqPwIOIMwDhzX6mQUFIQAgo+9MzcrWrML3mj6+YIKiFCZyhL87RqVQKrEskF+P1BUvfLCAkfRwoPUtq6l5o5+lZb5SolJo6oT8avTCl+c9OTmat6pKW8mLkvBpGzlvsiGuQr4ZEEwA1EQgoR/gNtxIxKBluz+OtMJiF31jHxqXBiAqAUj4WRxpADFM0DCFlv1khvX7Wol4vF4AIldVVxdZqlrIfiCYQPHDy6bAGv7nKYRVY6JewExZVAP+ey5Rv+Ba97aaUHMW5NauLmMZFkegBb/EP14d6NoS9QLWFSzWBmuZza8CQmSpXsAqmGtVy14VALWuuYWWy+W3OteXa4jwceQX6+BKG6J1/8+2VCNkm2222WabbbbZZpttttlmm22rt38DCdA0vq3bcAkAAAAASUVORK5CYII=" +} From b365ce319569196aff0de36a24963f6eef664ea1 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 3 May 2017 00:40:39 +0100 Subject: [PATCH 11/27] fix the first 100 prefer-const errors --- src/web/ControlsWaiter.js | 86 ++++++++++++++++++------------------ src/web/HTMLIngredient.js | 15 +++---- src/web/HighlighterWaiter.js | 56 +++++++++++------------ src/web/InputWaiter.js | 18 ++++---- src/web/Manager.js | 15 ++++--- src/web/OperationsWaiter.js | 42 ++++++++---------- src/web/OptionsWaiter.js | 12 ++--- src/web/OutputWaiter.js | 22 ++++----- src/web/RecipeWaiter.js | 13 +++--- test/index.js | 8 ++-- 10 files changed, 141 insertions(+), 146 deletions(-) diff --git a/src/web/ControlsWaiter.js b/src/web/ControlsWaiter.js index 1af61e74..26038364 100755 --- a/src/web/ControlsWaiter.js +++ b/src/web/ControlsWaiter.js @@ -23,14 +23,14 @@ const ControlsWaiter = function(app, manager) { * without wrapping or overflowing. */ ControlsWaiter.prototype.adjustWidth = function() { - let controls = document.getElementById("controls"), - step = document.getElementById("step"), - clrBreaks = document.getElementById("clr-breaks"), - saveImg = document.querySelector("#save img"), - loadImg = document.querySelector("#load img"), - stepImg = document.querySelector("#step img"), - clrRecipImg = document.querySelector("#clr-recipe img"), - clrBreaksImg = document.querySelector("#clr-breaks img"); + const controls = document.getElementById("controls"); + const step = document.getElementById("step"); + const clrBreaks = document.getElementById("clr-breaks"); + const saveImg = document.querySelector("#save img"); + const loadImg = document.querySelector("#load img"); + const stepImg = document.querySelector("#step img"); + const clrRecipImg = document.querySelector("#clr-recipe img"); + const clrBreaksImg = document.querySelector("#clr-breaks img"); if (controls.clientWidth < 470) { step.childNodes[1].nodeValue = " Step"; @@ -100,8 +100,8 @@ ControlsWaiter.prototype.stepClick = function() { * Handler for changes made to the Auto Bake checkbox. */ ControlsWaiter.prototype.autoBakeChange = function() { - let autoBakeLabel = document.getElementById("auto-bake-label"), - autoBakeCheckbox = document.getElementById("auto-bake"); + const autoBakeLabel = document.getElementById("auto-bake-label"); + const autoBakeCheckbox = document.getElementById("auto-bake"); this.app.autoBake_ = autoBakeCheckbox.checked; @@ -145,10 +145,10 @@ ControlsWaiter.prototype.clearBreaksClick = function() { ControlsWaiter.prototype.initialiseSaveLink = function(recipeConfig) { recipeConfig = recipeConfig || this.app.getRecipeConfig(); - let includeRecipe = document.getElementById("save-link-recipe-checkbox").checked, - includeInput = document.getElementById("save-link-input-checkbox").checked, - saveLinkEl = document.getElementById("save-link"), - saveLink = this.generateStateUrl(includeRecipe, includeInput, recipeConfig); + const includeRecipe = document.getElementById("save-link-recipe-checkbox").checked; + const includeInput = document.getElementById("save-link-input-checkbox").checked; + const saveLinkEl = document.getElementById("save-link"); + const saveLink = this.generateStateUrl(includeRecipe, includeInput, recipeConfig); saveLinkEl.innerHTML = Utils.truncate(saveLink, 120); saveLinkEl.setAttribute("href", saveLink); @@ -167,23 +167,27 @@ ControlsWaiter.prototype.initialiseSaveLink = function(recipeConfig) { ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput, recipeConfig, baseURL) { recipeConfig = recipeConfig || this.app.getRecipeConfig(); - let link = baseURL || window.location.protocol + "//" + + const link = baseURL || window.location.protocol + "//" + window.location.host + - window.location.pathname, - recipeStr = JSON.stringify(recipeConfig), - inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding + window.location.pathname; + const recipeStr = JSON.stringify(recipeConfig); + const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding - includeRecipe = includeRecipe && (recipeConfig.length > 0); - includeInput = includeInput && (inputStr.length > 0) && (inputStr.length < 8000); + const myIncludeRecipe = includeRecipe && (recipeConfig.length > 0); + const myIncludeInput = includeInput && (inputStr.length > 0) && (inputStr.length < 8000); - if (includeRecipe) { - link += "?recipe=" + encodeURIComponent(recipeStr); - } + const params = [ + myIncludeRecipe ? ["recipe", recipeStr] : undefined, + myIncludeInput ? ["input", inputStr] : undefined, + ]; - if (includeRecipe && includeInput) { - link += "&input=" + encodeURIComponent(inputStr); - } else if (includeInput) { - link += "?input=" + encodeURIComponent(inputStr); + const query = params + .filter(v => v) + .map(([key, value]) => `${key}=${encodeURIComponent(value)}`) + .join("&"); + + if (query) { + return `${link}?${query}`; } return link; @@ -205,8 +209,8 @@ ControlsWaiter.prototype.saveTextChange = function() { * Handler for the 'Save' command. Pops up the save dialog box. */ ControlsWaiter.prototype.saveClick = function() { - let recipeConfig = this.app.getRecipeConfig(), - recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{"); + const recipeConfig = this.app.getRecipeConfig(); + const recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{"); document.getElementById("save-text").value = recipeStr; @@ -303,13 +307,11 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() { * Removes the currently selected recipe from local storage. */ ControlsWaiter.prototype.loadDeleteClick = function() { - let id = parseInt(document.getElementById("load-name").value, 10), - savedRecipes = localStorage.savedRecipes ? + const id = parseInt(document.getElementById("load-name").value, 10); + const rawSavedRecipes = localStorage.savedRecipes ? JSON.parse(localStorage.savedRecipes) : []; - savedRecipes = savedRecipes.filter(function(r) { - return r.id !== id; - }); + const savedRecipes = rawSavedRecipes.filter(r => r.id !== id); localStorage.savedRecipes = JSON.stringify(savedRecipes); this.populateLoadRecipesList(); @@ -320,14 +322,12 @@ ControlsWaiter.prototype.loadDeleteClick = function() { * Displays the selected recipe in the load text box. */ ControlsWaiter.prototype.loadNameChange = function(e) { - let el = e.target, - savedRecipes = localStorage.savedRecipes ? - JSON.parse(localStorage.savedRecipes) : [], - id = parseInt(el.value, 10); + const el = e.target; + const savedRecipes = localStorage.savedRecipes ? + JSON.parse(localStorage.savedRecipes) : []; + const id = parseInt(el.value, 10); - const recipe = savedRecipes.filter(function(r) { - return r.id === id; - })[0]; + const recipe = savedRecipes.find(r => r.id === id); document.getElementById("load-text").value = recipe.recipe; }; @@ -352,8 +352,8 @@ ControlsWaiter.prototype.loadButtonClick = function() { * Populates the bug report information box with useful technical info. */ ControlsWaiter.prototype.supportButtonClick = function() { - let reportBugInfo = document.getElementById("report-bug-info"), - saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/"); + const reportBugInfo = document.getElementById("report-bug-info"); + const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/"); reportBugInfo.innerHTML = "* CyberChef compile time: " + COMPILE_TIME + "\n" + "* User-Agent: \n" + navigator.userAgent + "\n" + diff --git a/src/web/HTMLIngredient.js b/src/web/HTMLIngredient.js index 34bf547b..3f360f04 100755 --- a/src/web/HTMLIngredient.js +++ b/src/web/HTMLIngredient.js @@ -158,13 +158,12 @@ HTMLIngredient.prototype.toHtml = function() { * @param {event} e */ HTMLIngredient.prototype.toggleDisableArgs = function(e) { - let el = e.target, - op = el.parentNode.parentNode, - args = op.querySelectorAll(".arg-group"), - els; + const el = e.target; + const op = el.parentNode.parentNode; + const args = op.querySelectorAll(".arg-group"); for (let i = 0; i < this.disableArgs.length; i++) { - els = args[this.disableArgs[i]].querySelectorAll("input, select, button"); + const els = args[this.disableArgs[i]].querySelectorAll("input, select, button"); for (let j = 0; j < els.length; j++) { if (els[j].getAttribute("disabled")) { @@ -186,9 +185,9 @@ HTMLIngredient.prototype.toggleDisableArgs = function(e) { * @param {event} e */ HTMLIngredient.prototype.populateOptionChange = function(e) { - let el = e.target, - op = el.parentNode.parentNode, - target = op.querySelectorAll(".arg-group")[this.target].querySelector("input, select, textarea"); + const el = e.target; + const op = el.parentNode.parentNode; + const target = op.querySelectorAll(".arg-group")[this.target].querySelector("input, select, textarea"); target.value = el.childNodes[el.selectedIndex].getAttribute("populate-value"); diff --git a/src/web/HighlighterWaiter.js b/src/web/HighlighterWaiter.js index 94d388c5..7c9b7e42 100755 --- a/src/web/HighlighterWaiter.js +++ b/src/web/HighlighterWaiter.js @@ -64,8 +64,8 @@ HighlighterWaiter.prototype._isSelectionBackwards = function() { * @returns {number} */ HighlighterWaiter.prototype._getOutputHtmlOffset = function(node, offset) { - let sel = window.getSelection(), - range = document.createRange(); + const sel = window.getSelection(); + const range = document.createRange(); range.selectNodeContents(document.getElementById("output-html")); range.setEnd(node, offset); @@ -85,8 +85,8 @@ HighlighterWaiter.prototype._getOutputHtmlOffset = function(node, offset) { * @returns {number} pos.end */ HighlighterWaiter.prototype._getOutputHtmlSelectionOffsets = function() { - let sel = window.getSelection(), - range, + const sel = window.getSelection(); + let range, start = 0, end = 0, backwards = false; @@ -151,9 +151,9 @@ HighlighterWaiter.prototype.inputMousedown = function(e) { this.mouseTarget = HighlighterWaiter.INPUT; this.removeHighlights(); - let el = e.target, - start = el.selectionStart, - end = el.selectionEnd; + const el = e.target; + const start = el.selectionStart; + const end = el.selectionEnd; if (start !== 0 || end !== 0) { document.getElementById("input-selection-info").innerHTML = this.selectionInfo(start, end); @@ -173,9 +173,9 @@ HighlighterWaiter.prototype.outputMousedown = function(e) { this.mouseTarget = HighlighterWaiter.OUTPUT; this.removeHighlights(); - let el = e.target, - start = el.selectionStart, - end = el.selectionEnd; + const el = e.target; + const start = el.selectionStart; + const end = el.selectionEnd; if (start !== 0 || end !== 0) { document.getElementById("output-selection-info").innerHTML = this.selectionInfo(start, end); @@ -244,9 +244,9 @@ HighlighterWaiter.prototype.inputMousemove = function(e) { this.mouseTarget !== HighlighterWaiter.INPUT) return; - let el = e.target, - start = el.selectionStart, - end = el.selectionEnd; + const el = e.target; + const start = el.selectionStart; + const end = el.selectionEnd; if (start !== 0 || end !== 0) { document.getElementById("input-selection-info").innerHTML = this.selectionInfo(start, end); @@ -268,9 +268,9 @@ HighlighterWaiter.prototype.outputMousemove = function(e) { this.mouseTarget !== HighlighterWaiter.OUTPUT) return; - let el = e.target, - start = el.selectionStart, - end = el.selectionEnd; + const el = e.target; + const start = el.selectionStart; + const end = el.selectionEnd; if (start !== 0 || end !== 0) { document.getElementById("output-selection-info").innerHTML = this.selectionInfo(start, end); @@ -308,11 +308,11 @@ HighlighterWaiter.prototype.outputHtmlMousemove = function(e) { * @returns {string} */ HighlighterWaiter.prototype.selectionInfo = function(start, end) { - let width = end.toString().length; - width = width < 2 ? 2 : width; - let startStr = Utils.pad(start.toString(), width, " ").replace(/ /g, " "), - endStr = Utils.pad(end.toString(), width, " ").replace(/ /g, " "), - lenStr = Utils.pad((end-start).toString(), width, " ").replace(/ /g, " "); + const len = end.toString().length; + const width = len < 2 ? 2 : len; + const startStr = Utils.pad(start.toString(), width, " ").replace(/ /g, " "); + const endStr = Utils.pad(end.toString(), width, " ").replace(/ /g, " "); + const lenStr = Utils.pad((end-start).toString(), width, " ").replace(/ /g, " "); return "start: " + startStr + "
end: " + endStr + "
length: " + lenStr; }; @@ -339,8 +339,8 @@ HighlighterWaiter.prototype.removeHighlights = function() { * @returns {Object[]} highlights[].args */ HighlighterWaiter.prototype.generateHighlightList = function() { - let recipeConfig = this.app.getRecipeConfig(), - highlights = []; + const recipeConfig = this.app.getRecipeConfig(); + const highlights = []; for (let i = 0; i < recipeConfig.length; i++) { if (recipeConfig[i].disabled) continue; @@ -452,11 +452,11 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) { // be displayed by the HTML textarea and will mess up highlighting offsets. if (!this.app.dishStr || this.app.dishStr.indexOf("\r") >= 0) return false; - let startPlaceholder = "[startHighlight]", - startPlaceholderRegex = /\[startHighlight\]/g, - endPlaceholder = "[endHighlight]", - endPlaceholderRegex = /\[endHighlight\]/g, - text = textarea.value; + const startPlaceholder = "[startHighlight]"; + const startPlaceholderRegex = /\[startHighlight\]/g; + const endPlaceholder = "[endHighlight]"; + const endPlaceholderRegex = /\[endHighlight\]/g; + let text = textarea.value; // Put placeholders in position // If there's only one value, select that diff --git a/src/web/InputWaiter.js b/src/web/InputWaiter.js index f2e8a836..040716bb 100755 --- a/src/web/InputWaiter.js +++ b/src/web/InputWaiter.js @@ -92,8 +92,8 @@ InputWaiter.prototype.inputChange = function(e) { this.app.progress = 0; // Update the input metadata info - let inputText = this.get(), - lines = inputText.count("\n") + 1; + const inputText = this.get(); + const lines = inputText.count("\n") + 1; this.setInputInfo(inputText.length, lines); @@ -149,13 +149,13 @@ InputWaiter.prototype.inputDrop = function(e) { e.stopPropagation(); e.preventDefault(); - let el = e.target, - file = e.dataTransfer.files[0], - text = e.dataTransfer.getData("Text"), - reader = new FileReader(), - inputCharcode = "", - offset = 0, - CHUNK_SIZE = 20480; // 20KB + const el = e.target; + const file = e.dataTransfer.files[0]; + const text = e.dataTransfer.getData("Text"); + const reader = new FileReader(); + let inputCharcode = ""; + let offset = 0; + const CHUNK_SIZE = 20480; // 20KB const setInput = function() { if (inputCharcode.length > 100000 && this.app.autoBake_) { diff --git a/src/web/Manager.js b/src/web/Manager.js index efefc44d..ca334dcc 100755 --- a/src/web/Manager.js +++ b/src/web/Manager.js @@ -261,15 +261,16 @@ Manager.prototype.addDynamicListener = function(selector, eventType, callback, s * @param {Event} e - The event to be handled */ Manager.prototype.dynamicListenerHandler = function(e) { - let handlers = this.dynamicHandlers[e.type], - matches = e.target.matches || - e.target.webkitMatchesSelector || - e.target.mozMatchesSelector || - e.target.msMatchesSelector || - e.target.oMatchesSelector; + const { type, target } = e; + const handlers = this.dynamicHandlers[type]; + const matches = target.matches || + target.webkitMatchesSelector || + target.mozMatchesSelector || + target.msMatchesSelector || + target.oMatchesSelector; for (let i = 0; i < handlers.length; i++) { - if (matches && e.target[matches.name](handlers[i].selector)) { + if (matches && matches.call(target, handlers[i].selector)) { handlers[i].callback(e); } } diff --git a/src/web/OperationsWaiter.js b/src/web/OperationsWaiter.js index 7103ac38..992b737e 100755 --- a/src/web/OperationsWaiter.js +++ b/src/web/OperationsWaiter.js @@ -68,9 +68,9 @@ OperationsWaiter.prototype.searchOperations = function(e) { ops[selected-1].classList.add("selected-op"); } } else { - let searchResultsEl = document.getElementById("search-results"), - el = e.target, - str = el.value; + const searchResultsEl = document.getElementById("search-results"); + const el = e.target; + const str = el.value; while (searchResultsEl.firstChild) { try { @@ -81,12 +81,10 @@ OperationsWaiter.prototype.searchOperations = function(e) { $("#categories .in").collapse("hide"); if (str) { - let matchedOps = this.filterOperations(str, true), - matchedOpsHtml = ""; - - for (let i = 0; i < matchedOps.length; i++) { - matchedOpsHtml += matchedOps[i].toStubHtml(); - } + const matchedOps = this.filterOperations(str, true); + const matchedOpsHtml = matchedOps + .map(v => v.toStubHtml()) + .join(""); searchResultsEl.innerHTML = matchedOpsHtml; searchResultsEl.dispatchEvent(this.manager.oplistcreate); @@ -103,16 +101,16 @@ OperationsWaiter.prototype.searchOperations = function(e) { * name and description * @returns {string[]} */ -OperationsWaiter.prototype.filterOperations = function(searchStr, highlight) { - let matchedOps = [], - matchedDescs = []; +OperationsWaiter.prototype.filterOperations = function(inStr, highlight) { + const matchedOps = []; + const matchedDescs = []; - searchStr = searchStr.toLowerCase(); + const searchStr = inStr.toLowerCase(); for (const opName in this.app.operations) { - let op = this.app.operations[opName], - namePos = opName.toLowerCase().indexOf(searchStr), - descPos = op.description.toLowerCase().indexOf(searchStr); + const op = this.app.operations[opName]; + const namePos = opName.toLowerCase().indexOf(searchStr); + const descPos = op.description.toLowerCase().indexOf(searchStr); if (namePos >= 0 || descPos >= 0) { const operation = new HTMLOperation(opName, this.app.operations[opName], this.app, this.manager); @@ -236,12 +234,8 @@ OperationsWaiter.prototype.editFavouritesClick = function(e) { * Saves the selected favourites and reloads them. */ OperationsWaiter.prototype.saveFavouritesClick = function() { - let favouritesList = [], - favs = document.querySelectorAll("#edit-favourites-list li"); - - for (let i = 0; i < favs.length; i++) { - favouritesList.push(favs[i].textContent); - } + const favs = document.querySelectorAll("#edit-favourites-list li"); + const favouritesList = Array.from(favs, e => e.textContent); this.app.saveFavourites(favouritesList); this.app.loadFavourites(); @@ -281,8 +275,8 @@ OperationsWaiter.prototype.opIconMouseover = function(e) { * @param {event} e */ OperationsWaiter.prototype.opIconMouseleave = function(e) { - let opEl = e.target.parentNode, - toEl = e.toElement || e.relatedElement; + const opEl = e.target.parentNode; + const toEl = e.toElement || e.relatedElement; if (e.target.getAttribute("data-toggle") === "popover" && toEl === opEl) { $(opEl).popover("show"); diff --git a/src/web/OptionsWaiter.js b/src/web/OptionsWaiter.js index 6e92f4a0..ee3db0af 100755 --- a/src/web/OptionsWaiter.js +++ b/src/web/OptionsWaiter.js @@ -75,8 +75,8 @@ OptionsWaiter.prototype.resetOptionsClick = function() { * @param {boolean} state */ OptionsWaiter.prototype.switchChange = function(e, state) { - let el = e.target, - option = el.getAttribute("option"); + const el = e.target; + const option = el.getAttribute("option"); this.app.options[option] = state; localStorage.setItem("options", JSON.stringify(this.app.options)); @@ -90,8 +90,8 @@ OptionsWaiter.prototype.switchChange = function(e, state) { * @param {event} e */ OptionsWaiter.prototype.numberChange = function(e) { - let el = e.target, - option = el.getAttribute("option"); + const el = e.target; + const option = el.getAttribute("option"); this.app.options[option] = parseInt(el.value, 10); localStorage.setItem("options", JSON.stringify(this.app.options)); @@ -105,8 +105,8 @@ OptionsWaiter.prototype.numberChange = function(e) { * @param {event} e */ OptionsWaiter.prototype.selectChange = function(e) { - let el = e.target, - option = el.getAttribute("option"); + const el = e.target; + const option = el.getAttribute("option"); this.app.options[option] = el.value; localStorage.setItem("options", JSON.stringify(this.app.options)); diff --git a/src/web/OutputWaiter.js b/src/web/OutputWaiter.js index 7ff2cf0b..98292784 100755 --- a/src/web/OutputWaiter.js +++ b/src/web/OutputWaiter.js @@ -36,10 +36,10 @@ OutputWaiter.prototype.get = function() { * @param {number} duration - The length of time (ms) it took to generate the output */ OutputWaiter.prototype.set = function(dataStr, type, duration) { - let outputText = document.getElementById("output-text"), - outputHtml = document.getElementById("output-html"), - outputHighlighter = document.getElementById("output-highlighter"), - inputHighlighter = document.getElementById("input-highlighter"); + const outputText = document.getElementById("output-text"); + const outputHtml = document.getElementById("output-html"); + const outputHighlighter = document.getElementById("output-highlighter"); + const inputHighlighter = document.getElementById("input-highlighter"); if (type === "html") { outputText.style.display = "none"; @@ -103,11 +103,11 @@ OutputWaiter.prototype.setOutputInfo = function(length, lines, duration) { * without wrapping or overflowing. */ OutputWaiter.prototype.adjustWidth = function() { - let output = document.getElementById("output"), - saveToFile = document.getElementById("save-to-file"), - switchIO = document.getElementById("switch"), - undoSwitch = document.getElementById("undo-switch"), - maximiseOutput = document.getElementById("maximise-output"); + const output = document.getElementById("output"); + const saveToFile = document.getElementById("save-to-file"); + const switchIO = document.getElementById("switch"); + const undoSwitch = document.getElementById("undo-switch"); + const maximiseOutput = document.getElementById("maximise-output"); if (output.clientWidth < 680) { saveToFile.childNodes[1].nodeValue = ""; @@ -129,8 +129,8 @@ OutputWaiter.prototype.adjustWidth = function() { * Saves the current output to a file, downloaded as a URL octet stream. */ OutputWaiter.prototype.saveClick = function() { - let data = Utils.toBase64(this.app.dishStr), - filename = window.prompt("Please enter a filename:", "download.dat"); + const data = Utils.toBase64(this.app.dishStr); + const filename = window.prompt("Please enter a filename:", "download.dat"); if (filename) { const el = document.createElement("a"); diff --git a/src/web/RecipeWaiter.js b/src/web/RecipeWaiter.js index 57d7b272..b9cf23c5 100755 --- a/src/web/RecipeWaiter.js +++ b/src/web/RecipeWaiter.js @@ -60,8 +60,8 @@ RecipeWaiter.prototype.initialiseOperationDragNDrop = function() { }.bind(this)); Sortable.utils.on(recList, "touchend", function(e) { - let loc = e.changedTouches[0], - target = document.elementFromPoint(loc.clientX, loc.clientY); + const loc = e.changedTouches[0]; + const target = document.elementFromPoint(loc.clientX, loc.clientY); this.removeIntent = !recList.contains(target); }.bind(this)); @@ -276,8 +276,9 @@ RecipeWaiter.prototype.operationChildDblclick = function(e) { * @returns {recipeConfig} */ RecipeWaiter.prototype.getConfig = function() { - let config = [], ingredients, ingList, disabled, bp, item, - operations = document.querySelectorAll("#rec-list li.operation"); + const config = []; + let ingredients, ingList, disabled, bp, item; + const operations = document.querySelectorAll("#rec-list li.operation"); for (let i = 0; i < operations.length; i++) { ingredients = []; @@ -402,8 +403,8 @@ RecipeWaiter.prototype.clearRecipe = function() { * @param {event} e */ RecipeWaiter.prototype.dropdownToggleClick = function(e) { - let el = e.target, - button = el.parentNode.parentNode.previousSibling; + const el = e.target; + const button = el.parentNode.parentNode.previousSibling; button.innerHTML = el.textContent + " "; this.ingChange(); diff --git a/test/index.js b/test/index.js index d5037a78..c3bd49e6 100644 --- a/test/index.js +++ b/test/index.js @@ -19,10 +19,10 @@ import "./tests/operations/FlowControl.js"; import "./tests/operations/MorseCode.js"; import "./tests/operations/StrUtils.js"; -let allTestsPassing = true, - testStatusCounts = { - total: 0, - }; +let allTestsPassing = true; +const testStatusCounts = { + total: 0, +}; /** From 6122e33f4faf58c8c0ecf24267a60978079ac598 Mon Sep 17 00:00:00 2001 From: toby Date: Wed, 3 May 2017 10:27:13 -0400 Subject: [PATCH 12/27] Removed debounced autobake & stop disabling input --- src/web/App.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/web/App.js b/src/web/App.js index de8af4a7..4ab96b05 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -36,8 +36,6 @@ var App = function(categories, operations, defaultFavourites, defaultOptions) { this.ingId = 0; window.chef = this.chef; - - this.autoBake = Utils.debounce(this.autoBake, 300); }; @@ -80,22 +78,17 @@ App.prototype.setBakingStatus = function(bakingStatus) { var inputLoadingIcon = document.querySelector("#input .title .loading-icon"), outputLoadingIcon = document.querySelector("#output .title .loading-icon"), - inputElement = document.querySelector("#input-text"), outputElement = document.querySelector("#output-text"); if (bakingStatus) { inputLoadingIcon.style.display = "inline-block"; outputLoadingIcon.style.display = "inline-block"; - inputElement.classList.add("disabled"); outputElement.classList.add("disabled"); - inputElement.disabled = true; outputElement.disabled = true; } else { inputLoadingIcon.style.display = "none"; outputLoadingIcon.style.display = "none"; - inputElement.classList.remove("disabled"); outputElement.classList.remove("disabled"); - inputElement.disabled = false; outputElement.disabled = false; } }; From 274e1139fab94940464a1e1d9c776a9fb2335e62 Mon Sep 17 00:00:00 2001 From: toby Date: Wed, 3 May 2017 10:43:30 -0400 Subject: [PATCH 13/27] Remove debounce from Utils --- src/core/Utils.js | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/core/Utils.js b/src/core/Utils.js index a49565e5..2e4b354b 100755 --- a/src/core/Utils.js +++ b/src/core/Utils.js @@ -1185,33 +1185,6 @@ const Utils = { "Latin1": CryptoJS.enc.Latin1, }, - - /** - * A utility for "debouncing" functions. - * Debouncing is when you want to ensure events triggered by an event are rate-limited. - * @constant - */ - debounce(fn, delay) { - let timeout; - - return function() { - /** - * later calls the debounced function with arguments. - * If the debounced function is called again, then the timeout - * which calls later is cancelled. - */ - let later = () => { - fn.apply(this, arguments); - }; - - if (timeout) { - clearTimeout(timeout); - } - - timeout = setTimeout(later, delay); - }; - }, - }; export default Utils; From 66a93b81c609668c487a22b3c076cc5d4ebf3587 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 15:38:38 +0000 Subject: [PATCH 14/27] Added hasher argument to PBKDF2 and EVPKDF operations. --- src/core/config/OperationConfig.js | 10 ++++++++++ src/core/operations/Cipher.js | 31 ++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 3c07dcb8..708980df 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -1401,6 +1401,11 @@ const OperationConfig = { type: "number", value: Cipher.KDF_ITERATIONS }, + { + name: "Hashing function", + type: "option", + value: Cipher.HASHERS + }, { name: "Salt (hex)", type: "string", @@ -1434,6 +1439,11 @@ const OperationConfig = { type: "number", value: Cipher.KDF_ITERATIONS }, + { + name: "Hashing function", + type: "option", + value: Cipher.HASHERS + }, { name: "Salt (hex)", type: "string", diff --git a/src/core/operations/Cipher.js b/src/core/operations/Cipher.js index 42332530..8db28d0b 100755 --- a/src/core/operations/Cipher.js +++ b/src/core/operations/Cipher.js @@ -309,6 +309,11 @@ const Cipher = { * @default */ KDF_ITERATIONS: 1, + /** + * @constant + * @default + */ + HASHERS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD160"], /** * Derive PBKDF2 key operation. @@ -320,11 +325,16 @@ const Cipher = { runPbkdf2: function (input, args) { let keySize = args[0] / 32, iterations = args[1], - salt = CryptoJS.enc.Hex.parse(args[2] || ""), - inputFormat = args[3], - outputFormat = args[4], + hasher = args[2], + salt = CryptoJS.enc.Hex.parse(args[3] || ""), + inputFormat = args[4], + outputFormat = args[5], passphrase = Utils.format[inputFormat].parse(input), - key = CryptoJS.PBKDF2(passphrase, salt, { keySize: keySize, iterations: iterations }); + key = CryptoJS.PBKDF2(passphrase, salt, { + keySize: keySize, + hasher: CryptoJS.algo[hasher], + iterations: iterations, + }); return key.toString(Utils.format[outputFormat]); }, @@ -340,11 +350,16 @@ const Cipher = { runEvpkdf: function (input, args) { let keySize = args[0] / 32, iterations = args[1], - salt = CryptoJS.enc.Hex.parse(args[2] || ""), - inputFormat = args[3], - outputFormat = args[4], + hasher = args[2], + salt = CryptoJS.enc.Hex.parse(args[3] || ""), + inputFormat = args[4], + outputFormat = args[5], passphrase = Utils.format[inputFormat].parse(input), - key = CryptoJS.EvpKDF(passphrase, salt, { keySize: keySize, iterations: iterations }); + key = CryptoJS.EvpKDF(passphrase, salt, { + keySize: keySize, + hasher: CryptoJS.algo[hasher], + iterations: iterations, + }); return key.toString(Utils.format[outputFormat]); }, From b010fd88e848a641c0346dc46561a60d876a99d6 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 15:42:24 +0000 Subject: [PATCH 15/27] Fix X.509 signature breakout bug --- src/core/operations/PublicKey.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/operations/PublicKey.js b/src/core/operations/PublicKey.js index b3e5357d..918535e9 100755 --- a/src/core/operations/PublicKey.js +++ b/src/core/operations/PublicKey.js @@ -124,10 +124,17 @@ const PublicKey = { } // Signature fields - if (r.ASN1HEX.dump(certSig).indexOf("SEQUENCE") === 0) { // DSA or ECDSA + var breakoutSig = false; + try { + breakoutSig = r.ASN1HEX.dump(certSig).indexOf("SEQUENCE") === 0; + } catch(err) { + // Error processing signature, output without further breakout + } + + if (breakoutSig) { // DSA or ECDSA sigStr = " r: " + PublicKey._formatByteStr(r.ASN1HEX.getDecendantHexVByNthList(certSig, 0, [0]), 16, 18) + "\n" + " s: " + PublicKey._formatByteStr(r.ASN1HEX.getDecendantHexVByNthList(certSig, 0, [1]), 16, 18) + "\n"; - } else { // RSA + } else { // RSA or unknown sigStr = " Signature: " + PublicKey._formatByteStr(certSig, 16, 18) + "\n"; } From 508a3711757699a1d83ba60cb510aa2aece37437 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 15:54:59 +0000 Subject: [PATCH 16/27] Fixed offset checker array initialisation --- src/core/operations/StrUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/StrUtils.js b/src/core/operations/StrUtils.js index 4203efa6..28c5c263 100755 --- a/src/core/operations/StrUtils.js +++ b/src/core/operations/StrUtils.js @@ -385,7 +385,7 @@ const StrUtils = { runOffsetChecker: function(input, args) { let sampleDelim = args[0], samples = input.split(sampleDelim), - outputs = [], + outputs = new Array(samples.length), i = 0, s = 0, match = false, From 59a36e77bd51884b12201c92e298ef524ef7ff7c Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 15:55:58 +0000 Subject: [PATCH 17/27] 5.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1911dffe..59622794 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "5.3.0", + "version": "5.3.1", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From 951b168f3a010e237a2bb1fc3edcc76e75b68a87 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 16:00:40 +0000 Subject: [PATCH 18/27] 5.3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59622794..0f5399c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "5.3.1", + "version": "5.3.2", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From 76204f5f4746cedfe182273a4789330ab1283893 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 16:03:25 +0000 Subject: [PATCH 19/27] Fixed lint errors --- src/core/operations/PublicKey.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/operations/PublicKey.js b/src/core/operations/PublicKey.js index 918535e9..237c968a 100755 --- a/src/core/operations/PublicKey.js +++ b/src/core/operations/PublicKey.js @@ -124,10 +124,10 @@ const PublicKey = { } // Signature fields - var breakoutSig = false; + let breakoutSig = false; try { breakoutSig = r.ASN1HEX.dump(certSig).indexOf("SEQUENCE") === 0; - } catch(err) { + } catch (err) { // Error processing signature, output without further breakout } From 5d52c49c31d77523cae459ce2b4a24c161979e8b Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 5 May 2017 16:04:22 +0000 Subject: [PATCH 20/27] 5.3.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f5399c0..efe7851c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "5.3.2", + "version": "5.3.3", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From e9c3bebfff8a50a519017d312d272379c72a68ec Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 13:59:33 +0100 Subject: [PATCH 21/27] Fixed lint error --- src/web/App.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/web/App.js b/src/web/App.js index 76615acd..0cd0ebde 100755 --- a/src/web/App.js +++ b/src/web/App.js @@ -76,7 +76,7 @@ App.prototype.handleError = function(err) { App.prototype.setBakingStatus = function(bakingStatus) { this.baking = bakingStatus; - var inputLoadingIcon = document.querySelector("#input .title .loading-icon"), + let inputLoadingIcon = document.querySelector("#input .title .loading-icon"), outputLoadingIcon = document.querySelector("#output .title .loading-icon"), outputElement = document.querySelector("#output-text"); @@ -109,8 +109,8 @@ App.prototype.bake = async function(step) { try { response = await this.chef.bake( - this.getInput(), // The user's input - this.getRecipeConfig(), // The configuration of the recipe + 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 From dc7a7267c99a0adb60e1bb062f16c14ff096c879 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 14:00:41 +0100 Subject: [PATCH 22/27] 5.3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc5df19a..84478fec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "5.3.3", + "version": "5.3.4", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From f67157f0ad224e1b7cfd895c33fe38a12583ce07 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 14:59:41 +0100 Subject: [PATCH 23/27] Fixed erroring dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc5df19a..69bc64e0 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "google-code-prettify": "^1.0.5", "jquery": "^3.1.1", "jsbn": "^1.1.0", - "jsrsasign": "^7.1.0", + "jsrsasign": "7.1.3", "lodash": "^4.17.4", "moment": "^2.17.1", "moment-timezone": "^0.5.11", From a85096ea118d16c0c326de81f8d865190518f131 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 15:00:46 +0100 Subject: [PATCH 24/27] 5.3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 69bc64e0..ae663ad4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "5.3.3", + "version": "5.3.4", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From 6abd10f9e2dfbed354b10c4fbc665ce87003630f Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 16:12:09 +0100 Subject: [PATCH 25/27] Tidying codebase --- Gruntfile.js | 5 +- src/web/ControlsWaiter.js | 12 ++--- src/web/SeasonalWaiter.js | 108 -------------------------------------- src/web/spiderImages.json | 5 -- 4 files changed, 10 insertions(+), 120 deletions(-) delete mode 100644 src/web/spiderImages.json diff --git a/Gruntfile.js b/Gruntfile.js index 18dc35eb..dd8f0a17 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -237,7 +237,10 @@ module.exports = function (grunt) { compileTime: compileTime }) ], - watch: true + watch: true, + stats: { + warningsFilter: /source-map/ + } }, webProd: { target: "web", diff --git a/src/web/ControlsWaiter.js b/src/web/ControlsWaiter.js index 26038364..86a5fe40 100755 --- a/src/web/ControlsWaiter.js +++ b/src/web/ControlsWaiter.js @@ -168,17 +168,17 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput recipeConfig = recipeConfig || this.app.getRecipeConfig(); const link = baseURL || window.location.protocol + "//" + - window.location.host + - window.location.pathname; + window.location.host + + window.location.pathname; const recipeStr = JSON.stringify(recipeConfig); const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding - const myIncludeRecipe = includeRecipe && (recipeConfig.length > 0); - const myIncludeInput = includeInput && (inputStr.length > 0) && (inputStr.length < 8000); + includeRecipe = includeRecipe && (recipeConfig.length > 0); + includeInput = includeInput && (inputStr.length > 0) && (inputStr.length < 8000); const params = [ - myIncludeRecipe ? ["recipe", recipeStr] : undefined, - myIncludeInput ? ["input", inputStr] : undefined, + includeRecipe ? ["recipe", recipeStr] : undefined, + includeInput ? ["input", inputStr] : undefined, ]; const query = params diff --git a/src/web/SeasonalWaiter.js b/src/web/SeasonalWaiter.js index 69ea2c06..fb671024 100755 --- a/src/web/SeasonalWaiter.js +++ b/src/web/SeasonalWaiter.js @@ -1,8 +1,3 @@ -import spiderImages from "./spiderImages.json"; - - -const { spider16, spider32, spider64 } = spiderImages; - /** * Waiter to handle seasonal events and easter eggs. * @@ -24,66 +19,12 @@ const SeasonalWaiter = function(app, manager) { * Loads all relevant items depending on the current date. */ SeasonalWaiter.prototype.load = function() { - //var now = new Date(); - - // SpiderChef - // if (now.getMonth() === 3 && now.getDate() === 1) { // Apr 1 - // this.insertSpiderIcons(); - // this.insertSpiderText(); - // } - // Konami code this.kkeys = []; window.addEventListener("keydown", this.konamiCodeListener.bind(this)); }; -/** - * Replaces chef icons with spider icons. - * #spiderchef - */ -SeasonalWaiter.prototype.insertSpiderIcons = function() { - - // Favicon - document.querySelector("link[rel=icon]").setAttribute("href", "data:image/png;base64," + spider16); - - // Bake button - document.querySelector("#bake img").setAttribute("src", "data:image/png;base64," + spider32); - - // About box - document.querySelector(".about-img-left").setAttribute("src", "data:image/png;base64," + spider64); -}; - - -/** - * Replaces all instances of the word "cyber" with "spider". - * #spiderchef - */ -SeasonalWaiter.prototype.insertSpiderText = function() { - // Title - document.title = document.title.replace(/Cyber/g, "Spider"); - - // Body - SeasonalWaiter.treeWalk(document.body, function(node) { - // process only text nodes - if (node.nodeType === 3) { - node.nodeValue = node.nodeValue.replace(/Cyber/g, "Spider"); - } - }, true); - - // Bake button - SeasonalWaiter.treeWalk(document.getElementById("bake-group"), function(node) { - // process only text nodes - if (node.nodeType === 3) { - node.nodeValue = node.nodeValue.replace(/Bake/g, "Spin"); - } - }, true); - - // Recipe title - document.querySelector("#recipe .title").innerHTML = "Web"; -}; - - /** * Listen for the Konami code sequence of keys. Turn the page upside down if they are all heard in * sequence. @@ -104,53 +45,4 @@ SeasonalWaiter.prototype.konamiCodeListener = function(e) { } }; - -/** - * Walks through the entire DOM starting at the specified element and operates on each node. - * - * @static - * @param {element} parent - The DOM node to start from - * @param {Function} fn - The callback function to operate on each node - * @param {booleam} allNodes - Whether to operate on every node or not - */ -SeasonalWaiter.treeWalk = (function() { - // Create closure for constants - const skipTags = { - "SCRIPT": true, "IFRAME": true, "OBJECT": true, - "EMBED": true, "STYLE": true, "LINK": true, "META": true - }; - - return function(parent, fn, allNodes) { - let node = parent.firstChild; - - while (node && node !== parent) { - if (allNodes || node.nodeType === 1) { - if (fn(node) === false) { - return false; - } - } - // If it's an element && - // has children && - // has a tagname && is not in the skipTags list - // then, we can enumerate children - if (node.nodeType === 1 && - node.firstChild && - !(node.tagName && skipTags[node.tagName])) { - node = node.firstChild; - } else if (node.nextSibling) { - node = node.nextSibling; - } else { - // No child and no nextsibling - // Find parent that has a nextSibling - while ((node = node.parentNode) !== parent) { - if (node.nextSibling) { - node = node.nextSibling; - break; - } - } - } - } - }; -})(); - export default SeasonalWaiter; diff --git a/src/web/spiderImages.json b/src/web/spiderImages.json deleted file mode 100644 index 119a7412..00000000 --- a/src/web/spiderImages.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "spider16": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3UlEQVQ4y2NgGJaAmYGBgVnf0oKJgYGBobWtXamqqoYTn2I4CI+LTzM2NTulpKbu+vPHz2dV5RWlluZmi3j5+KqFJSSEzpw8uQPdAEYYIzo5Kfjrl28rWFlZzjAzMYuEBQao3Lh+g+HGvbsMzExMDN++fWf4/PXLBzY2tqYNK1f2+4eHM2xcuRLigsT09Igf3384MTExbf767etBI319jU8fPsi+//jx/72HDxh5uLkZ7ty7y/Dz1687Avz8n2UUFR3Z2NjOySoqfmdhYGBg+PbtuwI7O8e5H79+8X379t357PnzYo+ePP7y6cuXc9++f69nYGRsvf/w4XdtLS2R799/bBUWFHr57sP7Jbs3b/ZkzswvUP3165fZ7z9//r988WIVAyPDr8tXr576+u3bpb9//7YwMjKeV1dV41NWVGoVEhDgPH761DJREeHaz1+/lqlpafUx6+jrRfz4+fPy+w8fTu/fsf3uw7t3L39+//4cv7DwGQYGhpdPbt9m4BcRFlNWVJC4fuvWASszs4C379792Ldt2xZBUdEdDP5hYSqQGIjDGa965uYKCalpZQwMDAxhMTG9DAwMDLaurhIkJY7A8IgGBgYGBgd3Dz2yUpeFo6O4rasrA9T24ZRxAAMTwMpgEJwLAAAAAElFTkSuQmCC", - "spider32": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACYVBMVEUAAAAcJSU2Pz85QkM9RUWEhIWMjI2MkJEcJSU2Pz85QkM9RUWWlpc9RUVXXl4cJSU2Pz85QkM8REU9RUVRWFh6ens9RUVCSkpNVFRdY2McJSU5QkM7REQ9RUVGTk5KUlJQVldcY2Rla2uTk5WampscJSVUWltZX2BrcHF1e3scJSUjLCw9RUVASEhFTU1HTk9bYWJeZGRma2xudHV1eHiZmZocJSUyOjpJUFFQVldSWlpTWVpXXl5YXl5rb3B9fX6RkZIcJSUmLy8tNTU9RUVFTU1IT1BOVldRV1hTWlp0enocJSUfKChJUFBWXV1hZ2hnbGwcJSVETExLUlJLU1NNVVVPVlZYXl9cY2RiaGlobW5rcXFyd3h0eHgcJSUpMTFDS0tQV1dRV1hSWFlWXF1bYWJma2tobW5uc3SsrK0cJSVJUFBMVFROVlZVW1xZX2BdYmNhZ2hjaGhla2tqcHBscHE4Pz9KUlJRWVlSWVlXXF1aYGFbYWFfZWZlampqbW4cJSUgKSkiKysuNjY0PD01PT07QkNES0tHTk5JUFBMUlNMU1NOU1ROVVVPVVZRVlZRV1dSWVlWXFxXXV5aX2BbYWFbYWJcYmJcYmNcY2RdYmNgZmZhZmdkaWpkampkamtlamtla2tma2tma2xnbG1obW5pbG1pb3Bqb3Brb3BtcXJudHVvcHFvcXJvc3NwcXNwdXVxc3RzeXl1eXp2eXl3ent6e3x+gYKAhISBg4SKi4yLi4yWlpeampudnZ6fn6CkpaanqKiur6+vr7C4uLm6urq6u7u8vLy9vb3Av8DR0dL2b74UAAAAgHRSTlMAEBAQEBAQECAgICAgMDBAQEBAQEBAUFBQUGBgYGBgYGBgYGBgcHBwcHCAgICAgICAgICAgICPj4+Pj4+Pj4+Pj5+fn5+fn5+fn5+vr6+vr6+/v7+/v7+/v7+/v7+/z8/Pz8/Pz8/Pz8/P39/f39/f39/f39/f7+/v7+/v7+/v78x6RlYAAAGBSURBVDjLY2AYWUCSgUGAk4GBTdlUhQebvP7yjIgCPQbWzBMnjx5wwJSX37Rwfm1isqj9/iPHTuxYlyeMJi+yunfptBkZOw/uWj9h3vatcycu8eRGlldb3Vsts3ph/cFTh7fN3bCoe2Vf8+TZoQhTvBa6REozVC7cuPvQnmULJm1e2z+308eyJieEBSLPXbKQIUqQIczk+N6eNaumtnZMaWhaHM89m8XVCqJA02Y5w0xmga6yfVsamtrN4xoXNzS0JTHkK3CXy4EVFMumcxUy2LbENTVkZfEzMDAudtJyTmNwS2XQreAFyvOlK9louDNVaXurmjkGgnTMkWDgXswtNouFISEX6Awv+RihQi5OcYY4DtVARpCCFCMGhiJ1hjwFBpagEAaWEpFoC0WQOCOjFMRRwXYMDB4BDLJ+QLYsg7GBGjtasLnEMjCIrWBgyAZ7058FI9x1SoFEnTCDsCyIhynPILYYSFgbYpUDA5bpQBluXzxpI1yYAbd2sCMYRhwAAHB9ZPztbuMUAAAAAElFTkSuQmCC", - "spider64": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJZUlEQVR42u1ZaXMU1xXlJ+gHpFITOy5sAcnIYCi2aIL2bTSSZrSP1NpHK41kISQBHgFaQIJBCMwi4TFUGYcPzggwEMcxHVGxQaag5QR/np/QP+Hmnsdr0hpmtEACwulb9aq7p7d3zz333Pt61q2zzTbbbLPNNttss80222yzzTbbVmu7MzKcJRWVkXjntqam6jyURPeGQqeTpqbOqp+evxC5dGlam5m5rE3PzGi8Hzx/4aLzbXDe09HdYxwZHaPc4mLFXVoW9pRXGNv3pDngeHlNLfE2Ljjj4xPOUGjSYKfpq6/+TLdv36bbX39Nt27epGvXvqSLl6bp3LlPtdOnz7jWrPNZ7kLCKCovp5bOTmP/4EHq6vmYMtzuSKbbbQCAHE8Rxd47MjrmuHjxkjF3/z4tLCzQkyc6PX78mB49ekQPHjygub/P0d27f6FrX/6JpqbO0YkT48E1R/sCr9cYHZ+gqrp64mPq+riXcoqKKC0vP9q6VyV/fQOiH+LrsPVY7z82PBKZnb1Bd+7cpfn5eQbgCT1hAADC/MN5uj83R99881eanZ2lL5gN/nrxjihAXwvOJ7l9vuiBQ4dF9LEtLC0V+2rv/ijTX6luaCS3rxT57wADAMTBQ4c9PIIDg4PBwYOHaHhklM5MnSWkwLff/o0+v3qVHv34Iz344QEDc4d8VVXUEAhQXXMzVdQqzKweKq6oABARzOGNOZ+Wl6fD6T25ubQrPT0E5xF93o82tbdjkkZ+iZfAAgbD6fZ6o339A8S0p7HjJ2h4eIQOHf6EujlV9nX3UOj0JDXzfXje+KlTdOPGDeF0T1+fGHg+2JSen08tHZ0CiPySEoPn8vq1IaOgIAzneQK0UzjcQd6qaqrlCVfV1+tpubnRnv5+2p2ZqYMF/oZGPTh0xLhy5Sr9wLn9j++/p5nLn9FxBoLZQJ1dKrkys6iYNeTExEnx3PqWFuF4W9deKq2upkEGCyzyMBC709MFC7r391Fjayv9MSdHZyCU1xJ5FjrNdN6VnU1KS4CjU4Yoh/m8CsezCguFJgAMV05ueP+BfhF5OL+gL9A/f/qJ7t3TaPLMFB09eoy6mTkMGg2PjTELOsS20OcTACgMKqJugqA0NtE7ycn0202b6A+ZmYIVAAKApGZlgRHB/0lqQPAqFEVE9hntM0R0ZblTzeswWdCeU8HAtYW+Uu0AUx+0f/jwoXD+56c/073v7tHU2XMiFbrUfVTNAtfL10FIAQL2QftsBrOEnavld5kg7E7PoF+99x79ev162rJrV9RMi6a2dvKUlQsR5uAgII7/ivMsbEE4g2hggjzC7LQL1OftovoO0WJKUn0gYEAn2hmMXo4QHIXQIfLfsfOXPwuLvB86cpQqamooyEzg1BLMwv04RkoE+B3B4BBBMHEcCwIP0N+ByJdUVhpgBJ7j4WvdANDjeTUglOaWEChfJF7uJzPX2HEPaj1vg7EAbHO5QnAeIPgqKvUB7gtAdbBgcvKMqOnc/NAIVwCcq21qElFnCgvaI9cBBFKhlSPbPzBIbbzduGULpWzfLkDAdZs++sgEwSlZqoIJMg2CzFSNGzODwdBfOi26+w4YTCm9LhDQwQDzdzguFf4FALjciTws8/u1yyx2N2/dovPnL9DRY8PkZ204xtuhoSM0wI7V8DEiirQCCHD+99u2CUdx3Lmvmz7kfemoGDgPEDr4HNKAf1MlAC4wgMGLWFJXQUrklZSEX6rLE2rOyDIQGlhgBUAyYFEZkm2vAGVi4qQ+x83M0389pevXr6OToy07d4qcR+krr/KzqpeJ/IfjGO+npDx3FCKHVPjd1q2LAMBI3ryZ9vL7U56BEzLfD80ACFba876OlGCQV9dAcT0Pyw7PgWij6zPP5Xt9EYgg+n3LosdVzdfz5CI8KY1LH31+5Yro9KanZwjHmPzmHTsoOeVDemfDBuE8dGVnWpqx3unUrE4CDLCAG64XAHB88IFgQV5xMY7DFmc16A6CZvnNBYYVcW+yKj0A/VHTsQ8dwMPNc6X+Gg0VIGbVpzYGWundjRujmGQWi9Eol7+TJ0/R2Nhx2sNlM9YJRPDdDRsM5DGPJB4KHOIhngHhAwixAGAAuDZ2lsuiYnFWBQOYrdEYNochilyiV6YHoH+rRNJkAG+fUw31PzU7Z1EFKPD69CIuQ1Bm6URoh8tFmVym3nc6rZOPyi0cD8HxeHPg3x2InNrbS79JTsYzNXmPuBclsO3ZvKwAOJEGsmI5rT0M+gSf3y9K5LIA1LUEIlL1k0AhCYBH5r9TCqBqib4D+c/1PyInGOThkvuaHCYALhlpbQWBMGR/4IpzTqlpbKQyf0045vdoe0zATHagSYMeWFMkbscnHRYPZjoFJaIiUkz9EJy15j/X3qCsAIqMcFjSWrNE1Iygg0fEmrtLzEUTdT/OhBFht9fHDVCbEUt3LJxi08B8Xj6vTDESriq9lVWqBECgHujqiqAUmufb1X3cfRXoluhjZWiwkOnSUcUS6ZD8LUmmhks6b5j1ezkAkAKZBe5QvPPcNBnoCawMwT66Qxk0R2xwwRAui2iSDGuaPDcubzo3EJq8wcx/9Vmk3QryH42QBQCFF0UagIiJtjX6DskIXTLEucJSHIIIMuO0BOcjn3A3ybU/lu5RCUBc5qA0Ih0Q2EWiCPRk7VfMNhjLW1zETic1tLYZDMKyuSsdfh5l6bwho5+0il4kyA0VohlNcF5FP8DlWo/VB16HYB2hJ0pzgIe2mcXxP2IOumPRY17U0tll8KIkZNb+sppafOxYkQPSaYfchyYoL9GMqWYpTLRIq1QUcT4O3aPQgqVqPwIOIMwDhzX6mQUFIQAgo+9MzcrWrML3mj6+YIKiFCZyhL87RqVQKrEskF+P1BUvfLCAkfRwoPUtq6l5o5+lZb5SolJo6oT8avTCl+c9OTmat6pKW8mLkvBpGzlvsiGuQr4ZEEwA1EQgoR/gNtxIxKBluz+OtMJiF31jHxqXBiAqAUj4WRxpADFM0DCFlv1khvX7Wol4vF4AIldVVxdZqlrIfiCYQPHDy6bAGv7nKYRVY6JewExZVAP+ey5Rv+Ba97aaUHMW5NauLmMZFkegBb/EP14d6NoS9QLWFSzWBmuZza8CQmSpXsAqmGtVy14VALWuuYWWy+W3OteXa4jwceQX6+BKG6J1/8+2VCNkm2222WabbbbZZpttttlmm22rt38DCdA0vq3bcAkAAAAASUVORK5CYII=" -} From 1adedff61ac573bc7e3e7f4e1818b67951101813 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 16:14:30 +0100 Subject: [PATCH 26/27] Filter out source-map warnings in webpack output --- Gruntfile.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index dd8f0a17..b57f7f6d 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -220,7 +220,8 @@ module.exports = function (grunt) { ] }, stats: { - children: false + children: false, + warningsFilter: /source-map/ } }, webDev: { @@ -237,10 +238,7 @@ module.exports = function (grunt) { compileTime: compileTime }) ], - watch: true, - stats: { - warningsFilter: /source-map/ - } + watch: true }, webProd: { target: "web", From c43b67ea902b14aa3dccd9366919aa3a345ed2bb Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sat, 6 May 2017 16:15:29 +0100 Subject: [PATCH 27/27] 5.3.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae663ad4..38e06792 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "5.3.4", + "version": "5.3.5", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef",