Input and Output character encodings are now stored in the URL, allowing for accuate deeplinking

This commit is contained in:
n1474335 2022-09-16 19:24:57 +01:00
parent a141873db8
commit a07b8f693b
5 changed files with 51 additions and 30 deletions

View File

@ -451,6 +451,7 @@ class App {
* Searches the URI parameters for recipe and input parameters. * Searches the URI parameters for recipe and input parameters.
* If recipe is present, replaces the current recipe with the recipe provided in the URI. * If recipe is present, replaces the current recipe with the recipe provided in the URI.
* If input is present, decodes and sets the input to the one provided in the URI. * If input is present, decodes and sets the input to the one provided in the URI.
* If character encodings are present, sets them appropriately.
* If theme is present, uses the theme. * If theme is present, uses the theme.
* *
* @fires Manager#statechange * @fires Manager#statechange
@ -490,6 +491,16 @@ class App {
} catch (err) {} } catch (err) {}
} }
// Input Character Encoding
if (this.uriParams.ienc) {
this.manager.input.chrEncChange(parseInt(this.uriParams.ienc, 10));
}
// Output Character Encoding
if (this.uriParams.oenc) {
this.manager.output.chrEncChange(parseInt(this.uriParams.oenc, 10));
}
// 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));
@ -731,19 +742,19 @@ class App {
debounce(function() { debounce(function() {
this.progress = 0; this.progress = 0;
this.autoBake(); this.autoBake();
this.updateTitle(true, null, true); this.updateURL(true, null, true);
}, 20, "stateChange", this, [])(); }, 20, "stateChange", this, [])();
} }
/** /**
* Update the page title to contain the new recipe * Update the page title and URL to contain the new recipe
* *
* @param {boolean} includeInput * @param {boolean} includeInput
* @param {string} input * @param {string} [input=null]
* @param {boolean} [changeUrl=true] * @param {boolean} [changeUrl=true]
*/ */
updateTitle(includeInput, input, changeUrl=true) { updateURL(includeInput, input=null, changeUrl=true) {
// Set title // Set title
const recipeConfig = this.getRecipeConfig(); const recipeConfig = this.getRecipeConfig();
let title = "CyberChef"; let title = "CyberChef";

View File

@ -21,6 +21,7 @@ class StatusBarPanel {
this.bakeStats = opts.bakeStats ? opts.bakeStats : null; this.bakeStats = opts.bakeStats ? opts.bakeStats : null;
this.eolHandler = opts.eolHandler; this.eolHandler = opts.eolHandler;
this.chrEncHandler = opts.chrEncHandler; this.chrEncHandler = opts.chrEncHandler;
this.chrEncGetter = opts.chrEncGetter;
this.eolVal = null; this.eolVal = null;
this.chrEncVal = null; this.chrEncVal = null;
@ -222,9 +223,9 @@ class StatusBarPanel {
/** /**
* Gets the current character encoding of the document * Gets the current character encoding of the document
* @param {number} chrEncVal
*/ */
updateCharEnc(chrEncVal) { updateCharEnc() {
const chrEncVal = this.chrEncGetter();
if (chrEncVal === this.chrEncVal) return; if (chrEncVal === this.chrEncVal) return;
const name = CHR_ENC_SIMPLE_REVERSE_LOOKUP[chrEncVal] ? CHR_ENC_SIMPLE_REVERSE_LOOKUP[chrEncVal] : "Raw Bytes"; const name = CHR_ENC_SIMPLE_REVERSE_LOOKUP[chrEncVal] ? CHR_ENC_SIMPLE_REVERSE_LOOKUP[chrEncVal] : "Raw Bytes";
@ -399,7 +400,7 @@ function makePanel(opts) {
return (view) => { return (view) => {
sbPanel.updateEOL(view.state); sbPanel.updateEOL(view.state);
sbPanel.updateCharEnc(opts.initialChrEncVal); sbPanel.updateCharEnc();
sbPanel.updateBakeStats(); sbPanel.updateBakeStats();
sbPanel.updateStats(view.state.doc); sbPanel.updateStats(view.state.doc);
sbPanel.updateSelection(view.state, false); sbPanel.updateSelection(view.state, false);
@ -408,6 +409,7 @@ function makePanel(opts) {
"dom": sbPanel.dom, "dom": sbPanel.dom,
update(update) { update(update) {
sbPanel.updateEOL(update.state); sbPanel.updateEOL(update.state);
sbPanel.updateCharEnc();
sbPanel.updateSelection(update.state, update.selectionSet); sbPanel.updateSelection(update.state, update.selectionSet);
sbPanel.updateBakeStats(); sbPanel.updateBakeStats();
if (update.geometryChanged) { if (update.geometryChanged) {

View File

@ -138,9 +138,14 @@ class ControlsWaiter {
} }
} }
const inputChrEnc = this.manager.input.inputChrEnc;
const outputChrEnc = this.manager.output.outputChrEnc;
const params = [ const params = [
includeRecipe ? ["recipe", recipeStr] : undefined, includeRecipe ? ["recipe", recipeStr] : undefined,
includeInput && input.length ? ["input", Utils.escapeHtml(input)] : undefined, includeInput && input.length ? ["input", Utils.escapeHtml(input)] : undefined,
inputChrEnc !== 0 ? ["ienc", inputChrEnc] : undefined,
outputChrEnc !== 0 ? ["oenc", outputChrEnc] : undefined
]; ];
const hash = params const hash = params

View File

@ -89,7 +89,7 @@ class InputWaiter {
label: "Input", label: "Input",
eolHandler: this.eolChange.bind(this), eolHandler: this.eolChange.bind(this),
chrEncHandler: this.chrEncChange.bind(this), chrEncHandler: this.chrEncChange.bind(this),
initialChrEncVal: this.inputChrEnc chrEncGetter: this.getChrEnc.bind(this)
}), }),
// Mutable state // Mutable state
@ -148,10 +148,19 @@ class InputWaiter {
* @param {number} chrEncVal * @param {number} chrEncVal
*/ */
chrEncChange(chrEncVal) { chrEncChange(chrEncVal) {
if (typeof chrEncVal !== "number") return;
this.inputChrEnc = chrEncVal; this.inputChrEnc = chrEncVal;
this.inputChange(); this.inputChange();
} }
/**
* Getter for the input character encoding
* @returns {number}
*/
getChrEnc() {
return this.inputChrEnc;
}
/** /**
* Sets word wrap on the input editor * Sets word wrap on the input editor
* @param {boolean} wrap * @param {boolean} wrap
@ -418,7 +427,7 @@ class InputWaiter {
this.app.handleError(r.data); this.app.handleError(r.data);
break; break;
case "setUrl": case "setUrl":
this.setUrl(r.data); this.app.updateURL(r.data.includeInput, r.data.input);
break; break;
case "getInput": case "getInput":
case "getInputNums": case "getInputNums":
@ -486,10 +495,7 @@ class InputWaiter {
// Set URL to current input // Set URL to current input
if (inputVal.length >= 0 && inputVal.length <= 51200) { if (inputVal.length >= 0 && inputVal.length <= 51200) {
const inputStr = toBase64(inputVal, "A-Za-z0-9+/"); const inputStr = toBase64(inputVal, "A-Za-z0-9+/");
this.setUrl({ this.app.updateURL(true, inputStr);
includeInput: true,
input: inputStr
});
} }
if (!silent) window.dispatchEvent(this.manager.statechange); if (!silent) window.dispatchEvent(this.manager.statechange);
@ -616,10 +622,8 @@ class InputWaiter {
const recipeStr = buffer.byteLength < 51200 ? toBase64(buffer, "A-Za-z0-9+/") : ""; // B64 alphabet with no padding const recipeStr = buffer.byteLength < 51200 ? toBase64(buffer, "A-Za-z0-9+/") : ""; // B64 alphabet with no padding
this.setUrl({ const includeInput = recipeStr.length > 0 && buffer.byteLength < 51200;
includeInput: recipeStr.length > 0 && buffer.byteLength < 51200, this.app.updateURL(includeInput, recipeStr);
input: recipeStr
});
const transferable = [buffer]; const transferable = [buffer];
this.inputWorker.postMessage({ this.inputWorker.postMessage({
@ -1326,18 +1330,6 @@ class InputWaiter {
this.changeTab(inputNum, this.app.options.syncTabs); this.changeTab(inputNum, this.app.options.syncTabs);
} }
/**
* Update the input URL to the new value
*
* @param {object} urlData - Object containing the URL data
* @param {boolean} urlData.includeInput - If true, the input is included in the title
* @param {string} urlData.input - The input data to be included
*/
setUrl(urlData) {
this.app.updateTitle(urlData.includeInput, urlData.input, true);
}
} }
export default InputWaiter; export default InputWaiter;

View File

@ -92,7 +92,7 @@ class OutputWaiter {
bakeStats: this.bakeStats, bakeStats: this.bakeStats,
eolHandler: this.eolChange.bind(this), eolHandler: this.eolChange.bind(this),
chrEncHandler: this.chrEncChange.bind(this), chrEncHandler: this.chrEncChange.bind(this),
initialChrEncVal: this.outputChrEnc chrEncGetter: this.getChrEnc.bind(this)
}), }),
htmlPlugin(this.htmlOutput), htmlPlugin(this.htmlOutput),
copyOverride(), copyOverride(),
@ -145,9 +145,20 @@ class OutputWaiter {
* @param {number} chrEncVal * @param {number} chrEncVal
*/ */
chrEncChange(chrEncVal) { chrEncChange(chrEncVal) {
if (typeof chrEncVal !== "number") return;
this.outputChrEnc = chrEncVal; this.outputChrEnc = 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
this.app.updateURL(true);
}
/**
* Getter for the input character encoding
* @returns {number}
*/
getChrEnc() {
return this.outputChrEnc;
} }
/** /**