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