mirror of
https://github.com/gchq/CyberChef.git
synced 2024-11-02 06:01:02 +01:00
Highlighting now works with the web worker
This commit is contained in:
parent
8c960f0661
commit
13f07abb8a
@ -123,4 +123,38 @@ Chef.prototype.silentBake = function(recipeConfig) {
|
||||
return new Date().getTime() - startTime;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates highlight offsets if possible.
|
||||
*
|
||||
* @param {Object[]} recipeConfig
|
||||
* @param {string} direction
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
* @returns {Object}
|
||||
*/
|
||||
Chef.prototype.calculateHighlights = function(recipeConfig, direction, pos) {
|
||||
const recipe = new Recipe(recipeConfig);
|
||||
const highlights = recipe.generateHighlightList();
|
||||
|
||||
if (!highlights) return false;
|
||||
|
||||
for (let i = 0; i < highlights.length; i++) {
|
||||
// Remove multiple highlights before processing again
|
||||
pos = [pos[0]];
|
||||
|
||||
const func = direction === "forward" ? highlights[i].f : highlights[i].b;
|
||||
|
||||
if (typeof func == "function") {
|
||||
pos = func(pos, highlights[i].args);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pos: pos,
|
||||
direction: direction
|
||||
};
|
||||
};
|
||||
|
||||
export default Chef;
|
||||
|
@ -53,6 +53,13 @@ self.addEventListener("message", function(e) {
|
||||
// imported into an inline worker.
|
||||
self.docURL = e.data.data;
|
||||
break;
|
||||
case "highlight":
|
||||
calculateHighlights(
|
||||
e.data.data.recipeConfig,
|
||||
e.data.data.direction,
|
||||
e.data.data.pos
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -121,6 +128,25 @@ function loadRequiredModules(recipeConfig) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates highlight offsets if possible.
|
||||
*
|
||||
* @param {Object[]} recipeConfig
|
||||
* @param {string} direction
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
function calculateHighlights(recipeConfig, direction, pos) {
|
||||
pos = self.chef.calculateHighlights(recipeConfig, direction, pos);
|
||||
|
||||
self.postMessage({
|
||||
action: "highlightsCalculated",
|
||||
data: pos
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send status update to the app.
|
||||
*
|
||||
|
@ -54,6 +54,14 @@ Operation.prototype._parseConfig = function(operationConfig) {
|
||||
const ingredient = new Ingredient(ingredientConfig);
|
||||
this.addIngredient(ingredient);
|
||||
}
|
||||
|
||||
if (this.highlight === "func") {
|
||||
this.highlight = OpModules[this.module][`${this.name}-highlight`];
|
||||
}
|
||||
|
||||
if (this.highlightReverse === "func") {
|
||||
this.highlightReverse = OpModules[this.module][`${this.name}-highlightReverse`];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -215,4 +215,37 @@ Recipe.prototype.fromString = function(recipeStr) {
|
||||
this._parseConfig(recipeConfig);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
|
||||
* entire recipe supports highlighting.
|
||||
*
|
||||
* @returns {Object[]} highlights
|
||||
* @returns {function} highlights[].f
|
||||
* @returns {function} highlights[].b
|
||||
* @returns {Object[]} highlights[].args
|
||||
*/
|
||||
Recipe.prototype.generateHighlightList = function() {
|
||||
const highlights = [];
|
||||
|
||||
for (let i = 0; i < this.opList.length; i++) {
|
||||
let op = this.opList[i];
|
||||
if (op.isDisabled()) continue;
|
||||
|
||||
// If any breakpoints are set, do not attempt to highlight
|
||||
if (op.isBreakpoint()) return false;
|
||||
|
||||
// If any of the operations do not support highlighting, fail immediately.
|
||||
if (op.highlight === false || op.highlight === undefined) return false;
|
||||
|
||||
highlights.push({
|
||||
f: op.highlight,
|
||||
b: op.highlightReverse,
|
||||
args: op.getIngValues()
|
||||
});
|
||||
}
|
||||
|
||||
return highlights;
|
||||
};
|
||||
|
||||
export default Recipe;
|
||||
|
@ -184,8 +184,8 @@ const OperationConfig = {
|
||||
"From Base64": {
|
||||
module: "Default",
|
||||
description: "Base64 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers.<br><br>This operation decodes data from an ASCII Base64 string back into its raw format.<br><br>e.g. <code>aGVsbG8=</code> becomes <code>hello</code>",
|
||||
highlight: Base64.highlightFrom,
|
||||
highlightReverse: Base64.highlightTo,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "string",
|
||||
outputType: "byteArray",
|
||||
args: [
|
||||
@ -195,7 +195,7 @@ const OperationConfig = {
|
||||
value: Base64.ALPHABET_OPTIONS
|
||||
},
|
||||
{
|
||||
name: "Remove non‑alphabet chars",
|
||||
name: "Remove non-alphabet chars",
|
||||
type: "boolean",
|
||||
value: Base64.REMOVE_NON_ALPH_CHARS
|
||||
}
|
||||
@ -204,8 +204,8 @@ const OperationConfig = {
|
||||
"To Base64": {
|
||||
module: "Default",
|
||||
description: "Base64 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers.<br><br>This operation encodes data in an ASCII Base64 string.<br><br>e.g. <code>hello</code> becomes <code>aGVsbG8=</code>",
|
||||
highlight: Base64.highlightTo,
|
||||
highlightReverse: Base64.highlightFrom,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "byteArray",
|
||||
outputType: "string",
|
||||
args: [
|
||||
@ -228,7 +228,7 @@ const OperationConfig = {
|
||||
value: Base58.ALPHABET_OPTIONS
|
||||
},
|
||||
{
|
||||
name: "Remove non‑alphabet chars",
|
||||
name: "Remove non-alphabet chars",
|
||||
type: "boolean",
|
||||
value: Base58.REMOVE_NON_ALPH_CHARS
|
||||
}
|
||||
@ -259,7 +259,7 @@ const OperationConfig = {
|
||||
value: Base64.BASE32_ALPHABET
|
||||
},
|
||||
{
|
||||
name: "Remove non‑alphabet chars",
|
||||
name: "Remove non-alphabet chars",
|
||||
type: "boolean",
|
||||
value: Base64.REMOVE_NON_ALPH_CHARS
|
||||
}
|
||||
@ -446,8 +446,8 @@ const OperationConfig = {
|
||||
"From Hex": {
|
||||
module: "Default",
|
||||
description: "Converts a hexadecimal byte string back into its raw value.<br><br>e.g. <code>ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a</code> becomes the UTF-8 encoded string <code>Γειά σου</code>",
|
||||
highlight: ByteRepr.highlightFrom,
|
||||
highlightReverse: ByteRepr.highlightTo,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "string",
|
||||
outputType: "byteArray",
|
||||
args: [
|
||||
@ -461,8 +461,8 @@ const OperationConfig = {
|
||||
"To Hex": {
|
||||
module: "Default",
|
||||
description: "Converts the input string to hexadecimal bytes separated by the specified delimiter.<br><br>e.g. The UTF-8 encoded string <code>Γειά σου</code> becomes <code>ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a</code>",
|
||||
highlight: ByteRepr.highlightTo,
|
||||
highlightReverse: ByteRepr.highlightFrom,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "byteArray",
|
||||
outputType: "string",
|
||||
args: [
|
||||
@ -506,8 +506,8 @@ const OperationConfig = {
|
||||
"From Charcode": {
|
||||
module: "Default",
|
||||
description: "Converts unicode character codes back into text.<br><br>e.g. <code>0393 03b5 03b9 03ac 20 03c3 03bf 03c5</code> becomes <code>Γειά σου</code>",
|
||||
highlight: ByteRepr.highlightFrom,
|
||||
highlightReverse: ByteRepr.highlightTo,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "string",
|
||||
outputType: "byteArray",
|
||||
args: [
|
||||
@ -527,8 +527,8 @@ const OperationConfig = {
|
||||
"To Charcode": {
|
||||
module: "Default",
|
||||
description: "Converts text to its unicode character code equivalent.<br><br>e.g. <code>Γειά σου</code> becomes <code>0393 03b5 03b9 03ac 20 03c3 03bf 03c5</code>",
|
||||
highlight: ByteRepr.highlightTo,
|
||||
highlightReverse: ByteRepr.highlightFrom,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
@ -547,8 +547,8 @@ const OperationConfig = {
|
||||
"From Binary": {
|
||||
module: "Default",
|
||||
description: "Converts a binary string back into its raw form.<br><br>e.g. <code>01001000 01101001</code> becomes <code>Hi</code>",
|
||||
highlight: ByteRepr.highlightFromBinary,
|
||||
highlightReverse: ByteRepr.highlightToBinary,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "string",
|
||||
outputType: "byteArray",
|
||||
args: [
|
||||
@ -562,8 +562,8 @@ const OperationConfig = {
|
||||
"To Binary": {
|
||||
module: "Default",
|
||||
description: "Displays the input data as a binary string.<br><br>e.g. <code>Hi</code> becomes <code>01001000 01101001</code>",
|
||||
highlight: ByteRepr.highlightToBinary,
|
||||
highlightReverse: ByteRepr.highlightFromBinary,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "byteArray",
|
||||
outputType: "string",
|
||||
args: [
|
||||
@ -603,8 +603,8 @@ const OperationConfig = {
|
||||
"From Hexdump": {
|
||||
module: "Default",
|
||||
description: "Attempts to convert a hexdump back into raw data. This operation supports many different hexdump variations, but probably not all. Make sure you verify that the data it gives you is correct before continuing analysis.",
|
||||
highlight: Hexdump.highlightFrom,
|
||||
highlightReverse: Hexdump.highlightTo,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "string",
|
||||
outputType: "byteArray",
|
||||
args: []
|
||||
@ -612,8 +612,8 @@ const OperationConfig = {
|
||||
"To Hexdump": {
|
||||
module: "Default",
|
||||
description: "Creates a hexdump of the input data, displaying both the hexadecimal values of each byte and an ASCII representation alongside.",
|
||||
highlight: Hexdump.highlightTo,
|
||||
highlightReverse: Hexdump.highlightFrom,
|
||||
highlight: "func",
|
||||
highlightReverse: "func",
|
||||
inputType: "byteArray",
|
||||
outputType: "string",
|
||||
args: [
|
||||
|
@ -158,6 +158,34 @@ OpModules.Default = {
|
||||
"Conditional Jump": FlowControl.runCondJump,
|
||||
"Return": FlowControl.runReturn,
|
||||
"Comment": FlowControl.runComment,
|
||||
|
||||
|
||||
/*
|
||||
Highlighting functions.
|
||||
|
||||
This is a temporary solution as highlighting should be entirely
|
||||
overhauled at some point.
|
||||
*/
|
||||
"From Base64-highlight": Base64.highlightFrom,
|
||||
"From Base64-highlightReverse": Base64.highlightTo,
|
||||
"To Base64-highlight": Base64.highlightTo,
|
||||
"To Base64-highlightReverse": Base64.highlightFrom,
|
||||
"From Hex-highlight": ByteRepr.highlightFrom,
|
||||
"From Hex-highlightReverse": ByteRepr.highlightTo,
|
||||
"To Hex-highlight": ByteRepr.highlightTo,
|
||||
"To Hex-highlightReverse": ByteRepr.highlightFrom,
|
||||
"From Charcode-highlight": ByteRepr.highlightFrom,
|
||||
"From Charcode-highlightReverse": ByteRepr.highlightTo,
|
||||
"To Charcode-highlight": ByteRepr.highlightTo,
|
||||
"To Charcode-highlightReverse": ByteRepr.highlightFrom,
|
||||
"From Binary-highlight": ByteRepr.highlightFromBinary,
|
||||
"From Binary-highlightReverse": ByteRepr.highlightToBinary,
|
||||
"To Binary-highlight": ByteRepr.highlightToBinary,
|
||||
"To Binary-highlightReverse": ByteRepr.highlightFromBinary,
|
||||
"From Hexdump-highlight": Hexdump.highlightFrom,
|
||||
"From Hexdump-highlightReverse": Hexdump.highlightTo,
|
||||
"To Hexdump-highlight": Hexdump.highlightTo,
|
||||
"To Hexdump-highlightReverse": Hexdump.highlightFrom,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
|
@ -92,7 +92,7 @@ const Hexdump = {
|
||||
const w = (width - 13) / 4;
|
||||
// w should be the specified width of the hexdump and therefore a round number
|
||||
if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) {
|
||||
if (self) self.setOption("attemptHighlight", false);
|
||||
//TODO if (self) self.setOption("attemptHighlight", false);
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
@ -10,9 +10,11 @@ import Utils from "../core/Utils.js";
|
||||
*
|
||||
* @constructor
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
const HighlighterWaiter = function(app) {
|
||||
const HighlighterWaiter = function(app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
|
||||
this.mouseButtonDown = false;
|
||||
this.mouseTarget = null;
|
||||
@ -329,41 +331,6 @@ HighlighterWaiter.prototype.removeHighlights = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
|
||||
* entire recipe supports highlighting.
|
||||
*
|
||||
* @returns {Object[]} highlights
|
||||
* @returns {function} highlights[].f
|
||||
* @returns {function} highlights[].b
|
||||
* @returns {Object[]} highlights[].args
|
||||
*/
|
||||
HighlighterWaiter.prototype.generateHighlightList = function() {
|
||||
const recipeConfig = this.app.getRecipeConfig();
|
||||
const highlights = [];
|
||||
|
||||
for (let i = 0; i < recipeConfig.length; i++) {
|
||||
if (recipeConfig[i].disabled) continue;
|
||||
|
||||
// If any breakpoints are set, do not attempt to highlight
|
||||
if (recipeConfig[i].breakpoint) return false;
|
||||
|
||||
const op = this.app.operations[recipeConfig[i].op];
|
||||
|
||||
// If any of the operations do not support highlighting, fail immediately.
|
||||
if (op.highlight === false || op.highlight === undefined) return false;
|
||||
|
||||
highlights.push({
|
||||
f: op.highlight,
|
||||
b: op.highlightReverse,
|
||||
args: recipeConfig[i].args
|
||||
});
|
||||
}
|
||||
|
||||
return highlights;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Highlights the given offsets in the output.
|
||||
* We will only highlight if:
|
||||
@ -376,26 +343,8 @@ HighlighterWaiter.prototype.generateHighlightList = function() {
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
HighlighterWaiter.prototype.highlightOutput = function(pos) {
|
||||
const highlights = this.generateHighlightList();
|
||||
|
||||
if (!highlights || !this.app.autoBake_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < highlights.length; i++) {
|
||||
// Remove multiple highlights before processing again
|
||||
pos = [pos[0]];
|
||||
|
||||
if (typeof highlights[i].f == "function") {
|
||||
pos = highlights[i].f(pos, highlights[i].args);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
|
||||
this.highlight(
|
||||
document.getElementById("output-text"),
|
||||
document.getElementById("output-highlighter"),
|
||||
pos);
|
||||
if (!this.app.autoBake_ || this.app.baking) return false;
|
||||
this.manager.worker.highlight(this.app.getRecipeConfig(), "forward", pos);
|
||||
};
|
||||
|
||||
|
||||
@ -411,25 +360,28 @@ HighlighterWaiter.prototype.highlightOutput = function(pos) {
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
HighlighterWaiter.prototype.highlightInput = function(pos) {
|
||||
const highlights = this.generateHighlightList();
|
||||
if (!this.app.autoBake_ || this.app.baking) return false;
|
||||
this.manager.worker.highlight(this.app.getRecipeConfig(), "reverse", pos);
|
||||
};
|
||||
|
||||
if (!highlights || !this.app.autoBake_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < highlights.length; i++) {
|
||||
// Remove multiple highlights before processing again
|
||||
pos = [pos[0]];
|
||||
/**
|
||||
* Displays highlight offsets sent back from the Chef.
|
||||
*
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
* @param {string} direction
|
||||
*/
|
||||
HighlighterWaiter.prototype.displayHighlights = function(pos, direction) {
|
||||
if (!pos) return;
|
||||
|
||||
if (typeof highlights[i].b == "function") {
|
||||
pos = highlights[i].b(pos, highlights[i].args);
|
||||
}
|
||||
}
|
||||
const io = direction === "forward" ? "output" : "input";
|
||||
|
||||
document.getElementById("input-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
|
||||
document.getElementById(io + "-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
|
||||
this.highlight(
|
||||
document.getElementById("input-text"),
|
||||
document.getElementById("input-highlighter"),
|
||||
document.getElementById(io + "-text"),
|
||||
document.getElementById(io + "-highlighter"),
|
||||
pos);
|
||||
};
|
||||
|
||||
|
@ -58,7 +58,7 @@ const Manager = function(app) {
|
||||
this.input = new InputWaiter(this.app, this);
|
||||
this.output = new OutputWaiter(this.app, this);
|
||||
this.options = new OptionsWaiter(this.app);
|
||||
this.highlighter = new HighlighterWaiter(this.app);
|
||||
this.highlighter = new HighlighterWaiter(this.app, this);
|
||||
this.seasonal = new SeasonalWaiter(this.app, this);
|
||||
|
||||
// Object to store dynamic handlers to fire on elements that may not exist yet
|
||||
|
@ -57,6 +57,9 @@ WorkerWaiter.prototype.handleChefMessage = function(e) {
|
||||
case "statusMessage":
|
||||
this.manager.output.setStatusMsg(e.data.data);
|
||||
break;
|
||||
case "highlightsCalculated":
|
||||
this.manager.highlighter.displayHighlights(e.data.data.pos, e.data.data.direction);
|
||||
break;
|
||||
default:
|
||||
console.error("Unrecognised message from ChefWorker", e);
|
||||
break;
|
||||
@ -150,4 +153,25 @@ WorkerWaiter.prototype.silentBake = function(recipeConfig) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Asks the ChefWorker to calculate highlight offsets if possible.
|
||||
*
|
||||
* @param {Object[]} recipeConfig
|
||||
* @param {string} direction
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
WorkerWaiter.prototype.highlight = function(recipeConfig, direction, pos) {
|
||||
this.chefWorker.postMessage({
|
||||
action: "highlight",
|
||||
data: {
|
||||
recipeConfig: recipeConfig,
|
||||
direction: direction,
|
||||
pos: pos
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export default WorkerWaiter;
|
||||
|
Loading…
Reference in New Issue
Block a user