mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-22 07:46:16 -04:00
Added populateMultiOption ingredient type
This commit is contained in:
parent
87e956fe7d
commit
53226c1050
5 changed files with 92 additions and 76 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,6 +7,7 @@ docs/*
|
||||||
!docs/*.ico
|
!docs/*.ico
|
||||||
.vscode
|
.vscode
|
||||||
.*.swp
|
.*.swp
|
||||||
|
.DS_Store
|
||||||
src/core/config/modules/*
|
src/core/config/modules/*
|
||||||
src/core/config/OperationConfig.json
|
src/core/config/OperationConfig.json
|
||||||
src/core/operations/index.mjs
|
src/core/operations/index.mjs
|
||||||
|
|
|
@ -60,95 +60,57 @@ class MultipleBombe extends Operation {
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
"name": "Standard Enigmas",
|
"name": "Standard Enigmas",
|
||||||
"type": "populateOption",
|
"type": "populateMultiOption",
|
||||||
"value": [
|
"value": [
|
||||||
{
|
{
|
||||||
name: "German Service Enigma (First - 3 rotor)",
|
name: "German Service Enigma (First - 3 rotor)",
|
||||||
value: rotorsFormat(ROTORS, 0, 5)
|
value: [
|
||||||
|
rotorsFormat(ROTORS, 0, 5),
|
||||||
|
"",
|
||||||
|
rotorsFormat(REFLECTORS, 0, 1)
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "German Service Enigma (Second - 3 rotor)",
|
name: "German Service Enigma (Second - 3 rotor)",
|
||||||
value: rotorsFormat(ROTORS, 0, 8)
|
value: [
|
||||||
|
rotorsFormat(ROTORS, 0, 8),
|
||||||
|
"",
|
||||||
|
rotorsFormat(REFLECTORS, 0, 2)
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "German Service Enigma (Third - 4 rotor)",
|
name: "German Service Enigma (Third - 4 rotor)",
|
||||||
value: rotorsFormat(ROTORS, 0, 8)
|
value: [
|
||||||
|
rotorsFormat(ROTORS, 0, 8),
|
||||||
|
rotorsFormat(ROTORS_FOURTH, 1, 2),
|
||||||
|
rotorsFormat(REFLECTORS, 2, 3)
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "German Service Enigma (Fourth - 4 rotor)",
|
name: "German Service Enigma (Fourth - 4 rotor)",
|
||||||
value: rotorsFormat(ROTORS, 0, 8)
|
value: [
|
||||||
|
rotorsFormat(ROTORS, 0, 8),
|
||||||
|
rotorsFormat(ROTORS_FOURTH, 1, 3),
|
||||||
|
rotorsFormat(REFLECTORS, 2, 4)
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "User defined",
|
name: "User defined",
|
||||||
value: ""
|
value: ["", "", ""]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"target": 1
|
"target": [1, 2, 3]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Main rotors",
|
name: "Main rotors",
|
||||||
type: "text",
|
type: "text",
|
||||||
value: ""
|
value: ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Standard Enigmas",
|
|
||||||
"type": "populateOption",
|
|
||||||
"value": [
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (First - 3 rotor)",
|
|
||||||
value: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (Second - 3 rotor)",
|
|
||||||
value: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (Third - 4 rotor)",
|
|
||||||
value: rotorsFormat(ROTORS_FOURTH, 1, 2)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (Fourth - 4 rotor)",
|
|
||||||
value: rotorsFormat(ROTORS_FOURTH, 1, 3)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "User defined",
|
|
||||||
value: ""
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"target": 3
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "4th rotor",
|
name: "4th rotor",
|
||||||
type: "text",
|
type: "text",
|
||||||
value: ""
|
value: ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Standard Enigmas",
|
|
||||||
"type": "populateOption",
|
|
||||||
"value": [
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (First - 3 rotor)",
|
|
||||||
value: rotorsFormat(REFLECTORS, 0, 1)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (Second - 3 rotor)",
|
|
||||||
value: rotorsFormat(REFLECTORS, 0, 2)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (Third - 4 rotor)",
|
|
||||||
value: rotorsFormat(REFLECTORS, 2, 3)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "German Service Enigma (Fourth - 4 rotor)",
|
|
||||||
value: rotorsFormat(REFLECTORS, 2, 4)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "User defined",
|
|
||||||
value: ""
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"target": 5
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "Reflectors",
|
name: "Reflectors",
|
||||||
type: "text",
|
type: "text",
|
||||||
|
@ -217,11 +179,11 @@ class MultipleBombe extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const mainRotorsStr = args[1];
|
const mainRotorsStr = args[1];
|
||||||
const fourthRotorsStr = args[3];
|
const fourthRotorsStr = args[2];
|
||||||
const reflectorsStr = args[5];
|
const reflectorsStr = args[3];
|
||||||
let crib = args[6];
|
let crib = args[4];
|
||||||
const offset = args[7];
|
const offset = args[5];
|
||||||
const check = args[8];
|
const check = args[6];
|
||||||
const rotors = [];
|
const rotors = [];
|
||||||
const fourthRotors = [];
|
const fourthRotors = [];
|
||||||
const reflectors = [];
|
const reflectors = [];
|
||||||
|
|
|
@ -39,7 +39,7 @@ class HTMLIngredient {
|
||||||
*/
|
*/
|
||||||
toHtml() {
|
toHtml() {
|
||||||
let html = "",
|
let html = "",
|
||||||
i, m;
|
i, m, eventFn;
|
||||||
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case "string":
|
case "string":
|
||||||
|
@ -142,10 +142,11 @@ class HTMLIngredient {
|
||||||
</div>`;
|
</div>`;
|
||||||
break;
|
break;
|
||||||
case "populateOption":
|
case "populateOption":
|
||||||
|
case "populateMultiOption":
|
||||||
html += `<div class="form-group">
|
html += `<div class="form-group">
|
||||||
<label for="${this.id}" class="bmd-label-floating">${this.name}</label>
|
<label for="${this.id}" class="bmd-label-floating">${this.name}</label>
|
||||||
<select
|
<select
|
||||||
class="form-control arg"
|
class="form-control arg no-state-change populate-option"
|
||||||
id="${this.id}"
|
id="${this.id}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
${this.disabled ? "disabled" : ""}>`;
|
${this.disabled ? "disabled" : ""}>`;
|
||||||
|
@ -155,14 +156,20 @@ class HTMLIngredient {
|
||||||
} else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
} else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
||||||
html += "</optgroup>";
|
html += "</optgroup>";
|
||||||
} else {
|
} else {
|
||||||
html += `<option populate-value="${this.value[i].value}">${this.value[i].name}</option>`;
|
const val = this.type === "populateMultiOption" ?
|
||||||
|
JSON.stringify(this.value[i].value) :
|
||||||
|
this.value[i].value;
|
||||||
|
html += `<option populate-value='${val}'>${this.value[i].name}</option>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html += `</select>
|
html += `</select>
|
||||||
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
|
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
this.manager.addDynamicListener("#" + this.id, "change", this.populateOptionChange, this);
|
eventFn = this.type === "populateMultiOption" ?
|
||||||
|
this.populateMultiOptionChange :
|
||||||
|
this.populateOptionChange;
|
||||||
|
this.manager.addDynamicListener("#" + this.id, "change", eventFn, this);
|
||||||
break;
|
break;
|
||||||
case "editableOption":
|
case "editableOption":
|
||||||
html += `<div class="form-group input-group">
|
html += `<div class="form-group input-group">
|
||||||
|
@ -248,6 +255,9 @@ class HTMLIngredient {
|
||||||
* @param {event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
populateOptionChange(e) {
|
populateOptionChange(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
const el = e.target;
|
const el = e.target;
|
||||||
const op = el.parentNode.parentNode;
|
const op = el.parentNode.parentNode;
|
||||||
const target = op.querySelectorAll(".arg")[this.target];
|
const target = op.querySelectorAll(".arg")[this.target];
|
||||||
|
@ -260,6 +270,37 @@ class HTMLIngredient {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for populate multi option changes.
|
||||||
|
* Populates the relevant arguments with the specified values.
|
||||||
|
*
|
||||||
|
* @param {event} e
|
||||||
|
*/
|
||||||
|
populateMultiOptionChange(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const el = e.target;
|
||||||
|
const op = el.parentNode.parentNode;
|
||||||
|
const args = op.querySelectorAll(".arg");
|
||||||
|
const targets = this.target.map(i => args[i]);
|
||||||
|
const vals = JSON.parse(el.childNodes[el.selectedIndex].getAttribute("populate-value"));
|
||||||
|
const evt = new Event("change");
|
||||||
|
|
||||||
|
for (let i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].value = vals[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire change event after all targets have been assigned
|
||||||
|
this.manager.recipe.ingChange();
|
||||||
|
|
||||||
|
// Send change event for each target once all have been assigned, to update the label placement.
|
||||||
|
for (const target of targets) {
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for editable option clicks.
|
* Handler for editable option clicks.
|
||||||
* Populates the input box with the selected value.
|
* Populates the input box with the selected value.
|
||||||
|
|
|
@ -205,6 +205,7 @@ class RecipeWaiter {
|
||||||
* @fires Manager#statechange
|
* @fires Manager#statechange
|
||||||
*/
|
*/
|
||||||
ingChange(e) {
|
ingChange(e) {
|
||||||
|
if (e && e.target && e.target.classList.contains("no-state-change")) return;
|
||||||
window.dispatchEvent(this.manager.statechange);
|
window.dispatchEvent(this.manager.statechange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,6 +393,15 @@ class RecipeWaiter {
|
||||||
this.buildRecipeOperation(item);
|
this.buildRecipeOperation(item);
|
||||||
document.getElementById("rec-list").appendChild(item);
|
document.getElementById("rec-list").appendChild(item);
|
||||||
|
|
||||||
|
// Trigger populateOption events
|
||||||
|
const populateOptions = item.querySelectorAll(".populate-option");
|
||||||
|
const evt = new Event("change", {bubbles: true});
|
||||||
|
if (populateOptions.length) {
|
||||||
|
for (const el of populateOptions) {
|
||||||
|
el.dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item.dispatchEvent(this.manager.operationadd);
|
item.dispatchEvent(this.manager.operationadd);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@ TestRegister.addTests([
|
||||||
"op": "Multiple Bombe",
|
"op": "Multiple Bombe",
|
||||||
"args": [
|
"args": [
|
||||||
// I, II and III
|
// I, II and III
|
||||||
"User defined", "EKMFLGDQVZNTOWYHXUSPAIBRCJ<R\nAJDKSIRUXBLHWTMCQGZNPYFVOE<F\nBDFHJLCPRTXVZNYEIWGAKMUSQO<W",
|
"User defined",
|
||||||
"User defined", "",
|
"EKMFLGDQVZNTOWYHXUSPAIBRCJ<R\nAJDKSIRUXBLHWTMCQGZNPYFVOE<F\nBDFHJLCPRTXVZNYEIWGAKMUSQO<W",
|
||||||
"User defined", "AY BR CU DH EQ FS GL IP JX KN MO TZ VW", // B
|
"",
|
||||||
|
"AY BR CU DH EQ FS GL IP JX KN MO TZ VW", // B
|
||||||
"THISISATESTMESSAGE", 0, false
|
"THISISATESTMESSAGE", 0, false
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -35,9 +36,10 @@ TestRegister.addTests([
|
||||||
"op": "Multiple Bombe",
|
"op": "Multiple Bombe",
|
||||||
"args": [
|
"args": [
|
||||||
// I, II and III
|
// I, II and III
|
||||||
"User defined", "EKMFLGDQVZNTOWYHXUSPAIBRCJ<R\nAJDKSIRUXBLHWTMCQGZNPYFVOE<F\nBDFHJLCPRTXVZNYEIWGAKMUSQO<W",
|
"User defined",
|
||||||
"User defined", "LEYJVCNIXWPBQMDRTAKZGFUHOS", // Beta
|
"EKMFLGDQVZNTOWYHXUSPAIBRCJ<R\nAJDKSIRUXBLHWTMCQGZNPYFVOE<F\nBDFHJLCPRTXVZNYEIWGAKMUSQO<W",
|
||||||
"User defined", "AE BN CK DQ FU GY HW IJ LO MP RX SZ TV", // B thin
|
"LEYJVCNIXWPBQMDRTAKZGFUHOS", // Beta
|
||||||
|
"AE BN CK DQ FU GY HW IJ LO MP RX SZ TV", // B thin
|
||||||
"THISISATESTMESSAGE", 0, false
|
"THISISATESTMESSAGE", 0, false
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue