mirror of
https://github.com/gchq/CyberChef.git
synced 2024-11-16 17:08:31 +01:00
Improve handling of displaying large outputs.
Bring getDishStr and getDishBuffer back.
This commit is contained in:
parent
e95f92cdeb
commit
4dcd60adc0
4 changed files with 192 additions and 103 deletions
|
@ -155,6 +155,15 @@ function silentBake(data) {
|
||||||
async function getDishAs(data) {
|
async function getDishAs(data) {
|
||||||
const value = await self.chef.getDishAs(data.dish, data.type);
|
const value = await self.chef.getDishAs(data.dish, data.type);
|
||||||
|
|
||||||
|
if (data.type === "ArrayBuffer") {
|
||||||
|
self.postMessage({
|
||||||
|
action: "dishReturned",
|
||||||
|
data: {
|
||||||
|
value: value,
|
||||||
|
id: data.id
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
} else {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "dishReturned",
|
action: "dishReturned",
|
||||||
data: {
|
data: {
|
||||||
|
@ -163,6 +172,7 @@ async function getDishAs(data) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -573,7 +573,7 @@ class InputWaiter {
|
||||||
* @param {event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
debounceInputChange(e) {
|
debounceInputChange(e) {
|
||||||
this.debounce(this.inputChange.bind(this), 100, [e])();
|
this.debounce(this.inputChange.bind(this), 50, [e])();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1076,6 +1076,7 @@ class InputWaiter {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setupInputWorker();
|
this.setupInputWorker();
|
||||||
|
this.manager.worker.setupChefWorker();
|
||||||
this.addInput(true);
|
this.addInput(true);
|
||||||
this.bakeAll();
|
this.bakeAll();
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,13 +241,15 @@ class OutputWaiter {
|
||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
async set(inputNum) {
|
async set(inputNum) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(async function(resolve, reject) {
|
||||||
const output = this.outputs[inputNum];
|
const output = this.outputs[inputNum];
|
||||||
if (output === undefined || output === null) return;
|
if (output === undefined || output === null) return;
|
||||||
if (typeof inputNum !== "number") inputNum = parseInt(inputNum, 10);
|
if (typeof inputNum !== "number") inputNum = parseInt(inputNum, 10);
|
||||||
|
|
||||||
if (inputNum !== this.getActiveTab()) return;
|
if (inputNum !== this.getActiveTab()) return;
|
||||||
|
|
||||||
|
this.toggleLoader(true);
|
||||||
|
|
||||||
const outputText = document.getElementById("output-text");
|
const outputText = document.getElementById("output-text");
|
||||||
const outputHtml = document.getElementById("output-html");
|
const outputHtml = document.getElementById("output-html");
|
||||||
const outputFile = document.getElementById("output-file");
|
const outputFile = document.getElementById("output-file");
|
||||||
|
@ -276,9 +278,7 @@ class OutputWaiter {
|
||||||
if (output.status === "pending" || output.status === "baking") {
|
if (output.status === "pending" || output.status === "baking") {
|
||||||
// show the loader and the status message if it's being shown
|
// show the loader and the status message if it's being shown
|
||||||
// otherwise don't do anything
|
// otherwise don't do anything
|
||||||
this.toggleLoader(true);
|
|
||||||
document.querySelector("#output-loader .loading-msg").textContent = output.statusMessage;
|
document.querySelector("#output-loader .loading-msg").textContent = output.statusMessage;
|
||||||
|
|
||||||
} else if (output.status === "error") {
|
} else if (output.status === "error") {
|
||||||
// style the tab if it's being shown
|
// style the tab if it's being shown
|
||||||
this.toggleLoader(false);
|
this.toggleLoader(false);
|
||||||
|
@ -292,8 +292,8 @@ class OutputWaiter {
|
||||||
outputText.value = output.error;
|
outputText.value = output.error;
|
||||||
outputHtml.innerHTML = "";
|
outputHtml.innerHTML = "";
|
||||||
} else if (output.status === "baked" || output.status === "inactive") {
|
} else if (output.status === "baked" || output.status === "inactive") {
|
||||||
|
document.querySelector("#output-loader .loading-msg").textContent = `Loading output ${inputNum}`;
|
||||||
this.displayTabInfo(inputNum);
|
this.displayTabInfo(inputNum);
|
||||||
this.toggleLoader(false);
|
|
||||||
this.closeFile();
|
this.closeFile();
|
||||||
let scriptElements, lines, length;
|
let scriptElements, lines, length;
|
||||||
|
|
||||||
|
@ -309,6 +309,7 @@ class OutputWaiter {
|
||||||
|
|
||||||
lines = 0;
|
lines = 0;
|
||||||
length = 0;
|
length = 0;
|
||||||
|
this.toggleLoader(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,8 +333,6 @@ class OutputWaiter {
|
||||||
log.error(err);
|
log.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
length = output.data.dish.value.length;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "ArrayBuffer":
|
case "ArrayBuffer":
|
||||||
outputText.style.display = "block";
|
outputText.style.display = "block";
|
||||||
|
@ -344,8 +343,8 @@ class OutputWaiter {
|
||||||
outputText.value = "";
|
outputText.value = "";
|
||||||
outputHtml.innerHTML = "";
|
outputHtml.innerHTML = "";
|
||||||
|
|
||||||
length = output.data.result.length;
|
length = output.data.result.byteLength;
|
||||||
this.setFile(output.data.result);
|
this.setFile(await this.getDishBuffer(output.data.dish));
|
||||||
break;
|
break;
|
||||||
case "string":
|
case "string":
|
||||||
default:
|
default:
|
||||||
|
@ -362,6 +361,14 @@ class OutputWaiter {
|
||||||
length = output.data.result.length;
|
length = output.data.result.length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
this.toggleLoader(false);
|
||||||
|
|
||||||
|
if (output.data.type === "html") {
|
||||||
|
const dishStr = await this.getDishStr(output.data.dish);
|
||||||
|
length = dishStr.length;
|
||||||
|
lines = dishStr.count("\n") + 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.setOutputInfo(length, lines, output.data.duration);
|
this.setOutputInfo(length, lines, output.data.duration);
|
||||||
this.backgroundMagic();
|
this.backgroundMagic();
|
||||||
}
|
}
|
||||||
|
@ -395,6 +402,35 @@ class OutputWaiter {
|
||||||
document.getElementById("output-text").classList.remove("blur");
|
document.getElementById("output-text").classList.remove("blur");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the dish as a string, returning the cached version if possible.
|
||||||
|
*
|
||||||
|
* @param {Dish} dish
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
async getDishStr(dish) {
|
||||||
|
return await new Promise(resolve => {
|
||||||
|
this.manager.worker.getDishAs(dish, "string", r => {
|
||||||
|
resolve(r.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the dish as an ArrayBuffer, returning the cached version if possible.
|
||||||
|
*
|
||||||
|
* @param {Dish} dish
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
async getDishBuffer(dish) {
|
||||||
|
return await new Promise(resolve => {
|
||||||
|
this.manager.worker.getDishAs(dish, "ArrayBuffer", r => {
|
||||||
|
resolve(r.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save bombe object then remove it from the DOM so that it does not cause performance issues.
|
* Save bombe object then remove it from the DOM so that it does not cause performance issues.
|
||||||
*/
|
*/
|
||||||
|
@ -410,7 +446,7 @@ class OutputWaiter {
|
||||||
* recipe is taking longer than 200ms. We add it to the DOM just before that so that
|
* recipe is taking longer than 200ms. We add it to the DOM just before that so that
|
||||||
* it is ready to fade in without stuttering.
|
* it is ready to fade in without stuttering.
|
||||||
*
|
*
|
||||||
* @param {boolean} value - true == show loader
|
* @param {boolean} value - If true, show the loader
|
||||||
*/
|
*/
|
||||||
toggleLoader(value) {
|
toggleLoader(value) {
|
||||||
clearTimeout(this.appendBombeTimeout);
|
clearTimeout(this.appendBombeTimeout);
|
||||||
|
@ -489,7 +525,8 @@ class OutputWaiter {
|
||||||
* Spawns a new ZipWorker and sends it the outputs so that they can
|
* Spawns a new ZipWorker and sends it the outputs so that they can
|
||||||
* be zipped for download
|
* be zipped for download
|
||||||
*/
|
*/
|
||||||
downloadAllFiles() {
|
async downloadAllFiles() {
|
||||||
|
return new Promise(resolve => {
|
||||||
const inputNums = Object.keys(this.outputs);
|
const inputNums = Object.keys(this.outputs);
|
||||||
for (let i = 0; i < inputNums.length; i++) {
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
const iNum = inputNums[i];
|
const iNum = inputNums[i];
|
||||||
|
@ -539,7 +576,7 @@ class OutputWaiter {
|
||||||
fileExtension: fileExt
|
fileExtension: fileExt
|
||||||
});
|
});
|
||||||
this.zipWorker.addEventListener("message", this.handleZipWorkerMessage.bind(this));
|
this.zipWorker.addEventListener("message", this.handleZipWorkerMessage.bind(this));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -993,10 +1030,12 @@ class OutputWaiter {
|
||||||
/**
|
/**
|
||||||
* Triggers the BackgroundWorker to attempt Magic on the current output.
|
* Triggers the BackgroundWorker to attempt Magic on the current output.
|
||||||
*/
|
*/
|
||||||
backgroundMagic() {
|
async backgroundMagic() {
|
||||||
this.hideMagicButton();
|
this.hideMagicButton();
|
||||||
if (!this.app.options.autoMagic || !this.getActive(true)) return;
|
if (!this.app.options.autoMagic || !this.getActive(true)) return;
|
||||||
const sample = this.getActive(true).slice(0, 1000) || "";
|
const dish = this.outputs[this.getActiveTab()].data.dish;
|
||||||
|
const buffer = await this.getDishBuffer(dish);
|
||||||
|
const sample = buffer.slice(0, 1000) || "";
|
||||||
|
|
||||||
if (sample.length || sample.byteLength) {
|
if (sample.length || sample.byteLength) {
|
||||||
this.manager.background.magic(sample);
|
this.manager.background.magic(sample);
|
||||||
|
@ -1063,7 +1102,9 @@ class OutputWaiter {
|
||||||
/**
|
/**
|
||||||
* Handler for file slice display events.
|
* Handler for file slice display events.
|
||||||
*/
|
*/
|
||||||
displayFileSlice() {
|
async displayFileSlice() {
|
||||||
|
document.querySelector("#output-loader .loading-msg").textContent = "Loading file slice...";
|
||||||
|
this.toggleLoader(true);
|
||||||
const outputText = document.getElementById("output-text"),
|
const outputText = document.getElementById("output-text"),
|
||||||
outputHtml = document.getElementById("output-html"),
|
outputHtml = document.getElementById("output-html"),
|
||||||
outputFile = document.getElementById("output-file"),
|
outputFile = document.getElementById("output-file"),
|
||||||
|
@ -1074,11 +1115,13 @@ class OutputWaiter {
|
||||||
sliceToEl = document.getElementById("output-file-slice-to"),
|
sliceToEl = document.getElementById("output-file-slice-to"),
|
||||||
sliceFrom = parseInt(sliceFromEl.value, 10),
|
sliceFrom = parseInt(sliceFromEl.value, 10),
|
||||||
sliceTo = parseInt(sliceToEl.value, 10),
|
sliceTo = parseInt(sliceToEl.value, 10),
|
||||||
str = Utils.arrayBufferToStr(this.getActive(false).slice(sliceFrom, sliceTo));
|
dish = this.outputs[this.getActiveTab()].data.dish,
|
||||||
|
dishBuffer = await this.getDishBuffer(dish),
|
||||||
|
str = Utils.arrayBufferToStr(dishBuffer.slice(sliceFrom, sliceTo));
|
||||||
|
|
||||||
outputText.classList.remove("blur");
|
outputText.classList.remove("blur");
|
||||||
showFileOverlay.style.display = "block";
|
showFileOverlay.style.display = "block";
|
||||||
outputText.value = Utils.printable(str);
|
outputText.value = str;
|
||||||
|
|
||||||
|
|
||||||
outputText.style.display = "block";
|
outputText.style.display = "block";
|
||||||
|
@ -1087,6 +1130,7 @@ class OutputWaiter {
|
||||||
outputHighlighter.display = "block";
|
outputHighlighter.display = "block";
|
||||||
inputHighlighter.display = "block";
|
inputHighlighter.display = "block";
|
||||||
|
|
||||||
|
this.toggleLoader(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,24 +24,54 @@ class WorkerWaiter {
|
||||||
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.chefWorkers = [];
|
this.chefWorkers = [];
|
||||||
|
this.dishWorker = null;
|
||||||
this.maxWorkers = navigator.hardwareConcurrency || 4;
|
this.maxWorkers = navigator.hardwareConcurrency || 4;
|
||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
this.inputNums = [];
|
this.inputNums = [];
|
||||||
this.totalOutputs = 0;
|
this.totalOutputs = 0;
|
||||||
this.loadingOutputs = 0;
|
this.loadingOutputs = 0;
|
||||||
this.bakeId = 0;
|
this.bakeId = 0;
|
||||||
|
this.callbacks = {};
|
||||||
|
this.callbackID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminates any existing ChefWorkers and sets up a new worker
|
* Terminates any existing ChefWorkers and sets up a new worker
|
||||||
*/
|
*/
|
||||||
setupChefWorker() {
|
setupChefWorker() {
|
||||||
for (let i = 0; i < this.chefWorkers.length; i++) {
|
for (let i = this.chefWorkers.length - 1; i >= 0; i--) {
|
||||||
const worker = this.chefWorkers.pop();
|
this.removeChefWorker(this.chefWorkers[i]);
|
||||||
worker.terminate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addChefWorker();
|
this.addChefWorker();
|
||||||
|
this.setupDishWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a separate ChefWorker for performing dish operations.
|
||||||
|
* Using a separate worker so that we can run dish operations without
|
||||||
|
* affecting a bake which may be in progress.
|
||||||
|
*/
|
||||||
|
setupDishWorker() {
|
||||||
|
if (this.dishWorker !== null) {
|
||||||
|
this.dishWorker.terminate();
|
||||||
|
}
|
||||||
|
log.debug("Adding new ChefWorker (DishWorker)");
|
||||||
|
|
||||||
|
this.dishWorker = new ChefWorker();
|
||||||
|
this.dishWorker.addEventListener("message", this.handleChefMessage.bind(this));
|
||||||
|
|
||||||
|
let docURL = document.location.href.split(/[#?]/)[0];
|
||||||
|
const index = docURL.lastIndexOf("/");
|
||||||
|
if (index > 0) {
|
||||||
|
docURL = docURL.substring(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dishWorker.postMessage({"action": "docURL", "data": docURL});
|
||||||
|
this.dishWorker.postMessage({
|
||||||
|
action: "setLogLevel",
|
||||||
|
data: log.getLevel()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,10 +203,11 @@ class WorkerWaiter {
|
||||||
this.manager.output.updateOutputError(r.data.error, inputNum, r.data.progress);
|
this.manager.output.updateOutputError(r.data.error, inputNum, r.data.progress);
|
||||||
this.app.progress = r.data.progress;
|
this.app.progress = r.data.progress;
|
||||||
this.workerFinished(currentWorker);
|
this.workerFinished(currentWorker);
|
||||||
// do more here
|
|
||||||
break;
|
break;
|
||||||
case "dishReturned":
|
case "dishReturned":
|
||||||
this.callbacks[r.data.id](r.data);
|
this.callbacks[r.data.id](r.data);
|
||||||
|
this.dishWorker.terminate();
|
||||||
|
this.dishWorker = null;
|
||||||
break;
|
break;
|
||||||
case "silentBakeComplete":
|
case "silentBakeComplete":
|
||||||
break;
|
break;
|
||||||
|
@ -447,6 +478,7 @@ class WorkerWaiter {
|
||||||
* @param {boolean} inputData.step
|
* @param {boolean} inputData.step
|
||||||
*/
|
*/
|
||||||
bakeAllInputs(inputData) {
|
bakeAllInputs(inputData) {
|
||||||
|
return new Promise(resolve => {
|
||||||
if (this.app.baking) return;
|
if (this.app.baking) return;
|
||||||
const inputNums = inputData.nums;
|
const inputNums = inputData.nums;
|
||||||
const step = inputData.step;
|
const step = inputData.step;
|
||||||
|
@ -488,6 +520,7 @@ class WorkerWaiter {
|
||||||
this.manager.output.updateOutputMessage(`Input ${inputNums[i]} has not been baked yet.`, inputNums[i], false);
|
this.manager.output.updateOutputMessage(`Input ${inputNums[i]} has not been baked yet.`, inputNums[i], false);
|
||||||
this.manager.output.updateOutputStatus("pending", inputNums[i]);
|
this.manager.output.updateOutputStatus("pending", inputNums[i]);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -520,11 +553,12 @@ class WorkerWaiter {
|
||||||
*/
|
*/
|
||||||
getDishAs(dish, type, callback) {
|
getDishAs(dish, type, callback) {
|
||||||
const id = this.callbackID++;
|
const id = this.callbackID++;
|
||||||
const workerId = this.addChefWorker();
|
|
||||||
if (workerId === -1) return;
|
|
||||||
|
|
||||||
this.callbacks[id] = callback;
|
this.callbacks[id] = callback;
|
||||||
this.chefWorkers[workerId].worker.postMessage({
|
|
||||||
|
if (this.dishWorker === null) this.setupDishWorker();
|
||||||
|
|
||||||
|
this.dishWorker.postMessage({
|
||||||
action: "getDishAs",
|
action: "getDishAs",
|
||||||
data: {
|
data: {
|
||||||
dish: dish,
|
dish: dish,
|
||||||
|
|
Loading…
Reference in a new issue