ソースを参照

Merge conflicts

n1474335 8 年 前
コミット
03fc22d3da

+ 1 - 1
.eslintrc.json

@@ -1,6 +1,6 @@
 {
     "parserOptions": {
-        "ecmaVersion": 6,
+        "ecmaVersion": 8,
         "ecmaFeatures": {
             "impliedStrict": true
         },

+ 4 - 1
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": "",

+ 1 - 0
package.json

@@ -51,6 +51,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",

+ 2 - 2
src/core/Chef.js

@@ -34,7 +34,7 @@ const 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) {
     let 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.

+ 2 - 2
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) {
         let opList       = state.opList,
             inputType    = opList[state.progress].inputType,
             outputType   = opList[state.progress].outputType,
@@ -74,7 +74,7 @@ const FlowControl = {
         for (i = 0; i < inputs.length; i++) {
             const dish = new Dish(inputs[i], inputType);
             try {
-                progress = recipe.execute(dish, 0);
+                progress = await recipe.execute(dish, 0);
             } catch (err) {
                 if (!ignoreErrors) {
                     throw err;

+ 3 - 3
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;
     let 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) {

+ 35 - 2
src/web/App.js

@@ -30,6 +30,7 @@ const 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,17 +68,47 @@ 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"),
+        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.
  *
  * @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) {
     let response;
 
+    if (this.baking) return;
+
+    this.setBakingStatus(true);
+
     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
@@ -88,6 +119,8 @@ App.prototype.bake = function(step) {
         this.handleError(err);
     }
 
+    this.setBakingStatus(false);
+
     if (!response) return;
 
     if (response.error) {

+ 33 - 0
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;
+}

+ 2 - 0
src/web/html/index.html

@@ -100,6 +100,7 @@
                     <div id="input" class="split no-select">
                         <div class="title no-select">
                             <label for="input-text">Input</label>
+                            <div class="loading-icon" style="display: none"></div>
                             <div class="btn-group io-btn-group">
                                 <button type="button" class="btn btn-default btn-sm" id="clr-io"><img aria-hidden="true" src="<%- require('../static/images/recycle-16x16.png') %>" alt="Recycle Icon"/> Clear I/O</button>
                                 <button type="button" class="btn btn-default btn-sm" id="reset-layout"><img aria-hidden="true" src="<%- require('../static/images/layout-16x16.png') %>" alt="Grid Icon"/> Reset layout</button>
@@ -116,6 +117,7 @@
                     <div id="output" class="split">
                         <div class="title no-select">
                             <label for="output-text">Output</label>
+                            <div class="loading-icon" style="display: none"></div>
                             <div class="btn-group io-btn-group">
                                 <button type="button" class="btn btn-default btn-sm" id="save-to-file" title="Save to file"><img aria-hidden="true" src="<%- require('../static/images/save_as-16x16.png') %>" alt="Save Icon"/> Save to file</button>
                                 <button type="button" class="btn btn-default btn-sm" id="switch" title="Move output to input"><img aria-hidden="true" src="<%- require('../static/images/switch-16x16.png') %>" alt="Switch Icon"/> Move output to input</button>

+ 2 - 2
test/TestRegister.js

@@ -40,13 +40,13 @@ import Chef from "../src/core/Chef.js";
             this.tests.map(function(test, i) {
                 let chef = new Chef();
 
-                return Promise.resolve(chef.bake(
+                return chef.bake(
                     test.input,
                     test.recipeConfig,
                     {},
                     0,
                     false
-                ))
+                )
                 .then(function(result) {
                     let ret = {
                         test: test,

+ 133 - 0
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: [
@@ -141,4 +197,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],
+            },
+        ],
+    },
 ]);