mirror of
https://github.com/gchq/CyberChef
synced 2025-01-04 00:38:41 +00:00
Input and Output encodings are now saved per tab
This commit is contained in:
parent
5efd125d9b
commit
bdb8c02d5a
9 changed files with 87 additions and 33 deletions
|
@ -11,6 +11,7 @@ import HTMLCategory from "./HTMLCategory.mjs";
|
|||
import HTMLOperation from "./HTMLOperation.mjs";
|
||||
import Split from "split.js";
|
||||
import moment from "moment-timezone";
|
||||
import cptable from "codepage";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -41,6 +42,10 @@ class App {
|
|||
this.autoBakePause = false;
|
||||
this.progress = 0;
|
||||
this.ingId = 0;
|
||||
|
||||
this.appLoaded = false;
|
||||
this.workerLoaded = false;
|
||||
this.waitersLoaded = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,11 +64,10 @@ class App {
|
|||
this.manager.output.saveBombe();
|
||||
this.adjustComponentSizes();
|
||||
this.setCompileMessage();
|
||||
this.uriParams = this.getURIParams();
|
||||
|
||||
log.debug("App loaded");
|
||||
this.appLoaded = true;
|
||||
|
||||
this.loadURIParams();
|
||||
this.loaded();
|
||||
}
|
||||
|
||||
|
@ -76,9 +80,12 @@ class App {
|
|||
loaded() {
|
||||
// Check that both the app and the worker have loaded successfully, and that
|
||||
// we haven't already loaded before attempting to remove the loading screen.
|
||||
if (!this.workerLoaded || !this.appLoaded ||
|
||||
if (!this.workerLoaded || !this.appLoaded || !this.waitersLoaded ||
|
||||
!document.getElementById("loader-wrapper")) return;
|
||||
|
||||
// Load state from URI
|
||||
this.loadURIParams(this.uriParams);
|
||||
|
||||
// Trigger CSS animations to remove preloader
|
||||
document.body.classList.add("loaded");
|
||||
|
||||
|
@ -454,11 +461,12 @@ class App {
|
|||
* If character encodings are present, sets them appropriately.
|
||||
* If theme is present, uses the theme.
|
||||
*
|
||||
* @param {Object} params
|
||||
* @fires Manager#statechange
|
||||
*/
|
||||
loadURIParams() {
|
||||
loadURIParams(params=this.getURIParams()) {
|
||||
this.autoBakePause = true;
|
||||
this.uriParams = this.getURIParams();
|
||||
this.uriParams = params;
|
||||
|
||||
// Read in recipe from URI params
|
||||
if (this.uriParams.recipe) {
|
||||
|
@ -483,15 +491,8 @@ class App {
|
|||
search.dispatchEvent(new Event("search"));
|
||||
}
|
||||
|
||||
// Read in input data from URI params
|
||||
if (this.uriParams.input) {
|
||||
try {
|
||||
const inputData = fromBase64(this.uriParams.input);
|
||||
this.setInput(inputData);
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
// Input Character Encoding
|
||||
// Must be set before the input is loaded
|
||||
if (this.uriParams.ienc) {
|
||||
this.manager.input.chrEncChange(parseInt(this.uriParams.ienc, 10));
|
||||
}
|
||||
|
@ -501,6 +502,21 @@ class App {
|
|||
this.manager.output.chrEncChange(parseInt(this.uriParams.oenc, 10));
|
||||
}
|
||||
|
||||
// Read in input data from URI params
|
||||
if (this.uriParams.input) {
|
||||
try {
|
||||
let inputVal;
|
||||
const inputChrEnc = this.manager.input.getChrEnc();
|
||||
const inputData = fromBase64(this.uriParams.input);
|
||||
if (inputChrEnc > 0) {
|
||||
inputVal= cptable.utils.decode(inputChrEnc, inputData);
|
||||
} else {
|
||||
inputVal = Utils.arrayBufferToStr(inputData);
|
||||
}
|
||||
this.setInput(inputVal);
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
// Read in theme from URI params
|
||||
if (this.uriParams.theme) {
|
||||
this.manager.options.changeTheme(Utils.escapeHtml(this.uriParams.theme));
|
||||
|
|
|
@ -93,6 +93,23 @@ class Manager {
|
|||
this.bindings.updateKeybList();
|
||||
this.background.registerChefWorker();
|
||||
this.seasonal.load();
|
||||
|
||||
this.confirmWaitersLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that all Waiters have loaded correctly.
|
||||
*/
|
||||
confirmWaitersLoaded() {
|
||||
if (this.tabs.getActiveTab("input") >= 0 &&
|
||||
this.tabs.getActiveTab("output") >= 0) {
|
||||
log.debug("Waiters loaded");
|
||||
this.app.waitersLoaded = true;
|
||||
this.app.loaded();
|
||||
} else {
|
||||
// Not loaded yet, try again soon
|
||||
setTimeout(this.confirmWaitersLoaded.bind(this), 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ class StatusBarPanel {
|
|||
|
||||
|
||||
/**
|
||||
* Gets the current character encoding of the document
|
||||
* Sets the current character encoding of the document
|
||||
*/
|
||||
updateCharEnc() {
|
||||
const chrEncVal = this.chrEncGetter();
|
||||
|
|
|
@ -138,8 +138,8 @@ class ControlsWaiter {
|
|||
}
|
||||
}
|
||||
|
||||
const inputChrEnc = this.manager.input.inputChrEnc;
|
||||
const outputChrEnc = this.manager.output.outputChrEnc;
|
||||
const inputChrEnc = this.manager.input.getChrEnc();
|
||||
const outputChrEnc = this.manager.output.getChrEnc();
|
||||
|
||||
const params = [
|
||||
includeRecipe ? ["recipe", recipeStr] : undefined,
|
||||
|
|
|
@ -51,8 +51,8 @@ class HighlighterWaiter {
|
|||
const selectionRanges = e.state.selection.ranges;
|
||||
|
||||
// Adjust offsets based on the width of the character set
|
||||
const inputCharacterWidth = chrEncWidth(this.manager.input.inputChrEnc);
|
||||
const outputCharacterWidth = chrEncWidth(this.manager.output.outputChrEnc);
|
||||
const inputCharacterWidth = chrEncWidth(this.manager.input.getChrEnc());
|
||||
const outputCharacterWidth = chrEncWidth(this.manager.output.getChrEnc());
|
||||
let ratio = 1;
|
||||
if (inputCharacterWidth !== outputCharacterWidth &&
|
||||
inputCharacterWidth !== 0 && outputCharacterWidth !== 0) {
|
||||
|
|
|
@ -469,6 +469,7 @@ class InputWaiter {
|
|||
* @param {string} file.type
|
||||
* @param {string} status
|
||||
* @param {number} progress
|
||||
* @param {number} encoding
|
||||
* @param {boolean} [silent=false] - If false, fires the manager statechange event
|
||||
*/
|
||||
async set(inputNum, inputData, silent=false) {
|
||||
|
@ -476,13 +477,14 @@ class InputWaiter {
|
|||
const activeTab = this.manager.tabs.getActiveTab("input");
|
||||
if (inputNum !== activeTab) return;
|
||||
|
||||
this.inputChrEnc = inputData.encoding;
|
||||
|
||||
if (inputData.file) {
|
||||
this.setFile(inputNum, inputData);
|
||||
} else {
|
||||
this.clearFile(inputNum);
|
||||
}
|
||||
|
||||
// TODO Per-tab encodings?
|
||||
let inputVal;
|
||||
if (this.inputChrEnc > 0) {
|
||||
inputVal = cptable.utils.decode(this.inputChrEnc, new Uint8Array(inputData.buffer));
|
||||
|
@ -609,8 +611,8 @@ class InputWaiter {
|
|||
// If value is a string, interpret it using the specified character encoding
|
||||
if (typeof value === "string") {
|
||||
stringSample = value.slice(0, 4096);
|
||||
if (this.inputChrEnc > 0) {
|
||||
buffer = cptable.utils.encode(this.inputChrEnc, value);
|
||||
if (this.getChrEnc() > 0) {
|
||||
buffer = cptable.utils.encode(this.getChrEnc(), value);
|
||||
buffer = new Uint8Array(buffer).buffer;
|
||||
} else {
|
||||
buffer = Utils.strToArrayBuffer(value);
|
||||
|
@ -631,7 +633,8 @@ class InputWaiter {
|
|||
data: {
|
||||
inputNum: inputNum,
|
||||
buffer: buffer,
|
||||
stringSample: stringSample
|
||||
stringSample: stringSample,
|
||||
encoding: this.getChrEnc()
|
||||
}
|
||||
}, transferable);
|
||||
}
|
||||
|
@ -924,7 +927,7 @@ class InputWaiter {
|
|||
* @param {number} inputNum - The inputNum of the tab to change to
|
||||
* @param {boolean} [changeOutput=false] - If true, also changes the output
|
||||
*/
|
||||
changeTab(inputNum, changeOutput) {
|
||||
changeTab(inputNum, changeOutput=false) {
|
||||
if (this.manager.tabs.getTabItem(inputNum, "input") !== null) {
|
||||
this.manager.tabs.changeTab(inputNum, "input");
|
||||
this.inputWorker.postMessage({
|
||||
|
|
|
@ -51,7 +51,6 @@ class OutputWaiter {
|
|||
};
|
||||
// Hold a copy of the currently displayed output so that we don't have to update it unnecessarily
|
||||
this.currentOutputCache = null;
|
||||
this.outputChrEnc = 0;
|
||||
this.initEditor();
|
||||
|
||||
this.outputs = {};
|
||||
|
@ -146,7 +145,14 @@ class OutputWaiter {
|
|||
*/
|
||||
chrEncChange(chrEncVal) {
|
||||
if (typeof chrEncVal !== "number") return;
|
||||
this.outputChrEnc = chrEncVal;
|
||||
|
||||
const currentTabNum = this.manager.tabs.getActiveTab("output");
|
||||
if (currentTabNum >= 0) {
|
||||
this.outputs[currentTabNum].encoding = chrEncVal;
|
||||
} else {
|
||||
throw new Error("Cannot change output chrEnc to " + chrEncVal);
|
||||
}
|
||||
|
||||
// Reset the output, forcing it to re-decode the data with the new character encoding
|
||||
this.setOutput(this.currentOutputCache, true);
|
||||
// Update the URL manually since we aren't firing a statechange event
|
||||
|
@ -154,11 +160,15 @@ class OutputWaiter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Getter for the input character encoding
|
||||
* Getter for the output character encoding
|
||||
* @returns {number}
|
||||
*/
|
||||
getChrEnc() {
|
||||
return this.outputChrEnc;
|
||||
const currentTabNum = this.manager.tabs.getActiveTab("output");
|
||||
if (currentTabNum < 0) {
|
||||
return 0;
|
||||
}
|
||||
return this.outputs[currentTabNum].encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,11 +205,12 @@ class OutputWaiter {
|
|||
|
||||
// If data is an ArrayBuffer, convert to a string in the correct character encoding
|
||||
if (data instanceof ArrayBuffer) {
|
||||
if (this.outputChrEnc === 0) {
|
||||
const encoding = this.getChrEnc();
|
||||
if (encoding === 0) {
|
||||
data = Utils.arrayBufferToStr(data);
|
||||
} else {
|
||||
try {
|
||||
data = cptable.utils.decode(this.outputChrEnc, new Uint8Array(data));
|
||||
data = cptable.utils.decode(encoding, new Uint8Array(data));
|
||||
} catch (err) {
|
||||
data = err;
|
||||
}
|
||||
|
@ -324,7 +335,8 @@ class OutputWaiter {
|
|||
error: null,
|
||||
status: "inactive",
|
||||
bakeId: -1,
|
||||
progress: false
|
||||
progress: false,
|
||||
encoding: 0
|
||||
};
|
||||
|
||||
this.outputs[inputNum] = newOutput;
|
||||
|
@ -851,7 +863,7 @@ class OutputWaiter {
|
|||
|
||||
if (!this.manager.tabs.getTabItem(inputNum, "output") && numTabs < this.maxTabs) {
|
||||
// Create a new tab element
|
||||
const newTab = this.manager.tabs.reateTabElement(inputNum, changeTab, "output");
|
||||
const newTab = this.manager.tabs.createTabElement(inputNum, changeTab, "output");
|
||||
tabsWrapper.appendChild(newTab);
|
||||
} else if (numTabs === this.maxTabs) {
|
||||
// Can't create a new tab
|
||||
|
|
|
@ -217,7 +217,7 @@ class WorkerWaiter {
|
|||
break;
|
||||
case "workerLoaded":
|
||||
this.app.workerLoaded = true;
|
||||
log.debug("ChefWorker loaded.");
|
||||
log.debug("ChefWorker loaded");
|
||||
if (!this.loaded) {
|
||||
this.app.loaded();
|
||||
this.loaded = true;
|
||||
|
|
|
@ -30,6 +30,7 @@ self.pendingFiles = [];
|
|||
* @property {string} file.type
|
||||
* @property {string} status
|
||||
* @property {number} progress
|
||||
* @property {number} encoding
|
||||
*/
|
||||
self.inputs = {};
|
||||
self.loaderWorkers = [];
|
||||
|
@ -512,6 +513,7 @@ self.updateInputProgress = function(inputData) {
|
|||
* @param {object} inputData
|
||||
* @param {number} inputData.inputNum - The input that's having its value updated
|
||||
* @param {ArrayBuffer} inputData.buffer - The new value of the input as a buffer
|
||||
* @param {number} [inputData.encoding] - The character encoding of the input data
|
||||
* @param {string} [inputData.stringSample] - A sample of the value as a string (truncated to 4096 chars)
|
||||
*/
|
||||
self.updateInputValue = function(inputData) {
|
||||
|
@ -522,6 +524,9 @@ self.updateInputValue = function(inputData) {
|
|||
throw new Error(`No input with ID ${inputNum} exists`);
|
||||
|
||||
self.inputs[inputNum].buffer = inputData.buffer;
|
||||
if ("encoding" in inputData) {
|
||||
self.inputs[inputNum].encoding = inputData.encoding;
|
||||
}
|
||||
if (!("stringSample" in inputData)) {
|
||||
inputData.stringSample = Utils.arrayBufferToStr(inputData.buffer.slice(0, 4096));
|
||||
}
|
||||
|
@ -756,7 +761,8 @@ self.addInput = function(
|
|||
stringSample: "",
|
||||
file: null,
|
||||
status: "pending",
|
||||
progress: 0
|
||||
progress: 0,
|
||||
encoding: 0
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
|
|
Loading…
Reference in a new issue