mirror of
https://github.com/gchq/CyberChef
synced 2025-01-09 02:58:46 +00:00
Output over 1MiB is passed back as an ArrayBuffer and an output file card is displayed.
This commit is contained in:
parent
0e7989111f
commit
af71ca6a25
7 changed files with 130 additions and 35 deletions
|
@ -76,10 +76,15 @@ Chef.prototype.bake = async function(input, recipeConfig, options, progress, ste
|
||||||
progress = err.progress;
|
progress = err.progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Depending on the size of the output, we may send it back as a string or an ArrayBuffer.
|
||||||
|
// This can prevent unnecessary casting as an ArrayBuffer can be easily downloaded as a file.
|
||||||
|
// 1048576 bytes = 1 MiB
|
||||||
|
const returnType = this.dish.size() > 1048576 ? Dish.ARRAY_BUFFER : Dish.STRING;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: this.dish.type === Dish.HTML ?
|
result: this.dish.type === Dish.HTML ?
|
||||||
this.dish.get(Dish.HTML) :
|
this.dish.get(Dish.HTML) :
|
||||||
this.dish.get(Dish.STRING),
|
this.dish.get(returnType),
|
||||||
type: Dish.enumLookup(this.dish.type),
|
type: Dish.enumLookup(this.dish.type),
|
||||||
progress: progress,
|
progress: progress,
|
||||||
duration: new Date().getTime() - startTime,
|
duration: new Date().getTime() - startTime,
|
||||||
|
|
|
@ -349,7 +349,14 @@ const Utils = {
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // returns []
|
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
|
||||||
|
* Utils.convertToByteArray("Привет", "utf8");
|
||||||
|
*
|
||||||
|
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
|
||||||
|
* Utils.convertToByteArray("d097d0b4d180d0b0d0b2d181d182d0b2d183d0b9d182d0b5", "hex");
|
||||||
|
*
|
||||||
|
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
|
||||||
|
* Utils.convertToByteArray("0JfQtNGA0LDQstGB0YLQstGD0LnRgtC1", "base64");
|
||||||
*/
|
*/
|
||||||
convertToByteArray: function(str, type) {
|
convertToByteArray: function(str, type) {
|
||||||
switch (type.toLowerCase()) {
|
switch (type.toLowerCase()) {
|
||||||
|
@ -511,6 +518,22 @@ const Utils = {
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an ArrayBuffer to a string.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer} arrayBuffer
|
||||||
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns "hello"
|
||||||
|
* Utils.arrayBufferToStr(Uint8Array.from([104,101,108,108,111]).buffer);
|
||||||
|
*/
|
||||||
|
arrayBufferToStr: function(arrayBuffer) {
|
||||||
|
const byteArray = Array.prototype.slice.call(new Uint8Array(arrayBuffer));
|
||||||
|
return Utils.byteArrayToUtf8(byteArray);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64's the input byte array using the given alphabet, returning a string.
|
* Base64's the input byte array using the given alphabet, returning a string.
|
||||||
*
|
*
|
||||||
|
|
|
@ -79,13 +79,13 @@ InputWaiter.prototype.setFile = function(file) {
|
||||||
fileName = document.getElementById("input-file-name"),
|
fileName = document.getElementById("input-file-name"),
|
||||||
fileSize = document.getElementById("input-file-size"),
|
fileSize = document.getElementById("input-file-size"),
|
||||||
fileType = document.getElementById("input-file-type"),
|
fileType = document.getElementById("input-file-type"),
|
||||||
fileUploaded = document.getElementById("input-file-uploaded");
|
fileLoaded = document.getElementById("input-file-loaded");
|
||||||
|
|
||||||
fileOverlay.style.display = "block";
|
fileOverlay.style.display = "block";
|
||||||
fileName.textContent = file.name;
|
fileName.textContent = file.name;
|
||||||
fileSize.textContent = file.size.toLocaleString() + " bytes";
|
fileSize.textContent = file.size.toLocaleString() + " bytes";
|
||||||
fileType.textContent = file.type;
|
fileType.textContent = file.type;
|
||||||
fileUploaded.textContent = "0%";
|
fileLoaded.textContent = "0%";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,8 +210,8 @@ InputWaiter.prototype.inputDrop = function(e) {
|
||||||
InputWaiter.prototype.handleLoaderMessage = function(e) {
|
InputWaiter.prototype.handleLoaderMessage = function(e) {
|
||||||
const r = e.data;
|
const r = e.data;
|
||||||
if (r.hasOwnProperty("progress")) {
|
if (r.hasOwnProperty("progress")) {
|
||||||
const fileUploaded = document.getElementById("input-file-uploaded");
|
const fileLoaded = document.getElementById("input-file-loaded");
|
||||||
fileUploaded.textContent = r.progress + "%";
|
fileLoaded.textContent = r.progress + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r.hasOwnProperty("fileBuffer")) {
|
if (r.hasOwnProperty("fileBuffer")) {
|
||||||
|
@ -246,6 +246,7 @@ InputWaiter.prototype.clearIoClick = function() {
|
||||||
document.getElementById("output-info").innerHTML = "";
|
document.getElementById("output-info").innerHTML = "";
|
||||||
document.getElementById("input-selection-info").innerHTML = "";
|
document.getElementById("input-selection-info").innerHTML = "";
|
||||||
document.getElementById("output-selection-info").innerHTML = "";
|
document.getElementById("output-selection-info").innerHTML = "";
|
||||||
|
document.getElementById("output-file").style.display = "none";
|
||||||
window.dispatchEvent(this.manager.statechange);
|
window.dispatchEvent(this.manager.statechange);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,47 +31,85 @@ OutputWaiter.prototype.get = function() {
|
||||||
/**
|
/**
|
||||||
* Sets the output in the output textarea.
|
* Sets the output in the output textarea.
|
||||||
*
|
*
|
||||||
* @param {string} dataStr - The output string/HTML
|
* @param {string|ArrayBuffer} data - The output string/HTML/ArrayBuffer
|
||||||
* @param {string} type - The data type of the output
|
* @param {string} type - The data type of the output
|
||||||
* @param {number} duration - The length of time (ms) it took to generate the output
|
* @param {number} duration - The length of time (ms) it took to generate the output
|
||||||
*/
|
*/
|
||||||
OutputWaiter.prototype.set = function(dataStr, type, duration) {
|
OutputWaiter.prototype.set = function(data, type, duration) {
|
||||||
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 outputHighlighter = document.getElementById("output-highlighter");
|
const outputHighlighter = document.getElementById("output-highlighter");
|
||||||
const inputHighlighter = document.getElementById("input-highlighter");
|
const inputHighlighter = document.getElementById("input-highlighter");
|
||||||
|
let scriptElements, lines, length;
|
||||||
|
|
||||||
if (type === "html") {
|
switch (type) {
|
||||||
outputText.style.display = "none";
|
case "html":
|
||||||
outputHtml.style.display = "block";
|
outputText.style.display = "none";
|
||||||
outputHighlighter.display = "none";
|
outputHtml.style.display = "block";
|
||||||
inputHighlighter.display = "none";
|
outputFile.style.display = "none";
|
||||||
|
outputHighlighter.display = "none";
|
||||||
|
inputHighlighter.display = "none";
|
||||||
|
|
||||||
outputText.value = "";
|
outputText.value = "";
|
||||||
outputHtml.innerHTML = dataStr;
|
outputHtml.innerHTML = data;
|
||||||
|
length = data.length;
|
||||||
|
|
||||||
// Execute script sections
|
// Execute script sections
|
||||||
const scriptElements = outputHtml.querySelectorAll("script");
|
scriptElements = outputHtml.querySelectorAll("script");
|
||||||
for (let i = 0; i < scriptElements.length; i++) {
|
for (let i = 0; i < scriptElements.length; i++) {
|
||||||
try {
|
try {
|
||||||
eval(scriptElements[i].innerHTML); // eslint-disable-line no-eval
|
eval(scriptElements[i].innerHTML); // eslint-disable-line no-eval
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
} else {
|
case "ArrayBuffer":
|
||||||
outputText.style.display = "block";
|
outputText.style.display = "block";
|
||||||
outputHtml.style.display = "none";
|
outputHtml.style.display = "none";
|
||||||
outputHighlighter.display = "block";
|
outputHighlighter.display = "none";
|
||||||
inputHighlighter.display = "block";
|
inputHighlighter.display = "none";
|
||||||
|
|
||||||
outputText.value = Utils.printable(dataStr, true);
|
outputText.value = "";
|
||||||
outputHtml.innerHTML = "";
|
outputHtml.innerHTML = "";
|
||||||
|
length = data.byteLength;
|
||||||
|
|
||||||
|
this.setFile(new File([data], "output.dat"));
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
default:
|
||||||
|
outputText.style.display = "block";
|
||||||
|
outputHtml.style.display = "none";
|
||||||
|
outputFile.style.display = "none";
|
||||||
|
outputHighlighter.display = "block";
|
||||||
|
inputHighlighter.display = "block";
|
||||||
|
|
||||||
|
outputText.value = Utils.printable(data, true);
|
||||||
|
outputHtml.innerHTML = "";
|
||||||
|
|
||||||
|
lines = data.count("\n") + 1;
|
||||||
|
length = data.length;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.manager.highlighter.removeHighlights();
|
this.manager.highlighter.removeHighlights();
|
||||||
const lines = dataStr.count("\n") + 1;
|
this.setOutputInfo(length, lines, duration);
|
||||||
this.setOutputInfo(dataStr.length, lines, duration);
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows file details.
|
||||||
|
*
|
||||||
|
* @param {File} file
|
||||||
|
*/
|
||||||
|
OutputWaiter.prototype.setFile = function(file) {
|
||||||
|
// Display file overlay in output area with details
|
||||||
|
const fileOverlay = document.getElementById("output-file"),
|
||||||
|
fileSize = document.getElementById("output-file-size");
|
||||||
|
|
||||||
|
fileOverlay.style.display = "block";
|
||||||
|
fileSize.textContent = file.size.toLocaleString() + " bytes";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +124,8 @@ OutputWaiter.prototype.setOutputInfo = function(length, lines, duration) {
|
||||||
let width = length.toString().length;
|
let width = length.toString().length;
|
||||||
width = width < 4 ? 4 : width;
|
width = width < 4 ? 4 : width;
|
||||||
|
|
||||||
|
lines = typeof lines === "number" ? lines : "";
|
||||||
|
|
||||||
const lengthStr = Utils.pad(length.toString(), width, " ").replace(/ /g, " ");
|
const lengthStr = Utils.pad(length.toString(), width, " ").replace(/ /g, " ");
|
||||||
const linesStr = Utils.pad(lines.toString(), width, " ").replace(/ /g, " ");
|
const linesStr = Utils.pad(lines.toString(), width, " ").replace(/ /g, " ");
|
||||||
const timeStr = Utils.pad(duration.toString() + "ms", width, " ").replace(/ /g, " ");
|
const timeStr = Utils.pad(duration.toString() + "ms", width, " ").replace(/ /g, " ");
|
||||||
|
|
|
@ -111,7 +111,19 @@ WorkerWaiter.prototype.bakingComplete = function(response) {
|
||||||
this.app.handleError(response.error);
|
this.app.handleError(response.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.app.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result;
|
switch (response.type) {
|
||||||
|
case "html":
|
||||||
|
this.app.dishStr = Utils.stripHtmlTags(response.result, true);
|
||||||
|
break;
|
||||||
|
case "ArrayBuffer":
|
||||||
|
this.app.dishStr = "";
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
default:
|
||||||
|
this.app.dishStr = response.result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
this.app.progress = response.progress;
|
this.app.progress = response.progress;
|
||||||
this.manager.recipe.updateBreakpointIndicator(response.progress);
|
this.manager.recipe.updateBreakpointIndicator(response.progress);
|
||||||
this.manager.output.set(response.result, response.type, response.duration);
|
this.manager.output.set(response.result, response.type, response.duration);
|
||||||
|
|
|
@ -190,7 +190,7 @@
|
||||||
Name: <span id="input-file-name"></span><br>
|
Name: <span id="input-file-name"></span><br>
|
||||||
Size: <span id="input-file-size"></span><br>
|
Size: <span id="input-file-size"></span><br>
|
||||||
Type: <span id="input-file-type"></span><br>
|
Type: <span id="input-file-type"></span><br>
|
||||||
Uploaded: <span id="input-file-uploaded"></span>
|
Loaded: <span id="input-file-loaded"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -216,6 +216,19 @@
|
||||||
<div id="output-highlighter" class="no-select"></div>
|
<div id="output-highlighter" class="no-select"></div>
|
||||||
<div id="output-html"></div>
|
<div id="output-html"></div>
|
||||||
<textarea id="output-text" readonly="readonly"></textarea>
|
<textarea id="output-text" readonly="readonly"></textarea>
|
||||||
|
<div id="output-file">
|
||||||
|
<div style="position: relative; height: 100%;">
|
||||||
|
<div class="card">
|
||||||
|
<img aria-hidden="true" src="<%- require('../static/images/cyberchef-256x256.png') %>" alt="File icon"/>
|
||||||
|
<div class="card-body">
|
||||||
|
Size: <span id="output-file-size"></span><br>
|
||||||
|
Download<br>
|
||||||
|
Display in output<br>
|
||||||
|
Options for how much to display
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="output-loader">
|
<div id="output-loader">
|
||||||
<div class="loader"></div>
|
<div class="loader"></div>
|
||||||
<div class="loading-msg"></div>
|
<div class="loading-msg"></div>
|
||||||
|
|
|
@ -77,7 +77,8 @@
|
||||||
transition: all 0.5s ease;
|
transition: all 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#input-file {
|
#input-file,
|
||||||
|
#output-file {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
Loading…
Reference in a new issue