mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-21 23:36:16 -04:00
initial functionality commit
This commit is contained in:
parent
567474ce00
commit
7d15bfe58a
4 changed files with 208 additions and 0 deletions
|
@ -331,6 +331,7 @@ const Categories = [
|
||||||
"Extract EXIF",
|
"Extract EXIF",
|
||||||
"Numberwang",
|
"Numberwang",
|
||||||
"XKCD Random Number",
|
"XKCD Random Number",
|
||||||
|
"Set Operations"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,7 @@ import StrUtils from "../operations/StrUtils.js";
|
||||||
import Tidy from "../operations/Tidy.js";
|
import Tidy from "../operations/Tidy.js";
|
||||||
import Unicode from "../operations/Unicode.js";
|
import Unicode from "../operations/Unicode.js";
|
||||||
import URL_ from "../operations/URL.js";
|
import URL_ from "../operations/URL.js";
|
||||||
|
import SetOps from "../operations/SetOperations.js";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4018,6 +4019,29 @@ const OperationConfig = {
|
||||||
inputType: "string",
|
inputType: "string",
|
||||||
outputType: "number",
|
outputType: "number",
|
||||||
args: []
|
args: []
|
||||||
|
},
|
||||||
|
"Set Operations": {
|
||||||
|
module: "Default",
|
||||||
|
description: "Performs set operations",
|
||||||
|
inputType: "string",
|
||||||
|
outputType: "html",
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "Sample delimiter",
|
||||||
|
type: "binaryString",
|
||||||
|
value: SetOps.SAMPLE_DELIMITER
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Item delimiter",
|
||||||
|
type: "binaryString",
|
||||||
|
value: SetOps.ITEM_DELIMITER
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Operation",
|
||||||
|
type: "option",
|
||||||
|
value: SetOps.OPERATION
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import Tidy from "../../operations/Tidy.js";
|
||||||
import Unicode from "../../operations/Unicode.js";
|
import Unicode from "../../operations/Unicode.js";
|
||||||
import UUID from "../../operations/UUID.js";
|
import UUID from "../../operations/UUID.js";
|
||||||
import XKCD from "../../operations/XKCD.js";
|
import XKCD from "../../operations/XKCD.js";
|
||||||
|
import SetOps from "../../operations/SetOperations.js";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,6 +165,7 @@ OpModules.Default = {
|
||||||
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
|
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
|
||||||
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
|
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
|
||||||
"XKCD Random Number": XKCD.runRandomNumber,
|
"XKCD Random Number": XKCD.runRandomNumber,
|
||||||
|
"Set Operations": SetOps.runSetOperation.bind(SetOps),
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
181
src/core/operations/SetOperations.js
Normal file
181
src/core/operations/SetOperations.js
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
import Utils from "../Utils.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SetOps {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this._sampleDelimiter = "\\n\\n";
|
||||||
|
this._operation = ["Union", "Intersection", "Set Difference", "Symmetric Difference", "Cartesian Product", "Power Set"];
|
||||||
|
this._itemDelimiter = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
get OPERATION() {
|
||||||
|
return this._operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
get SAMPLE_DELIMITER() {
|
||||||
|
return this._sampleDelimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
get ITEM_DELIMITER() {
|
||||||
|
return this._itemDelimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} input
|
||||||
|
* @param {*} args
|
||||||
|
*/
|
||||||
|
runSetOperation(input, args) {
|
||||||
|
const [sampleDelim, itemDelimiter, operation] = args;
|
||||||
|
const sets = input.split(sampleDelim);
|
||||||
|
|
||||||
|
if (!sets || (sets.length !== 2 && operation !== "Power Set") || (sets.length !== 1 && operation === "Power Set")) {
|
||||||
|
return "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._operation.indexOf(operation) === -1) {
|
||||||
|
return "Invalid 'Operation' option.";
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
Union: this.runUnion,
|
||||||
|
Intersection: this.runIntersect,
|
||||||
|
"Set Difference": this.runSetDifference,
|
||||||
|
"Symmetric Difference": this.runSymmetricDifference,
|
||||||
|
"Cartesian Product": this.runCartesianProduct,
|
||||||
|
"Power Set": this.runPowerSet(itemDelimiter),
|
||||||
|
}[operation]
|
||||||
|
.apply(null, sets.map(s => s.split(itemDelimiter)));
|
||||||
|
|
||||||
|
// Formatting issues due to the nested characteristics of power set.
|
||||||
|
if (operation === "Power Set") {
|
||||||
|
result = result.map(i => `${i}\n`).join("");
|
||||||
|
} else {
|
||||||
|
result = result.join(itemDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils.escapeHtml(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} a
|
||||||
|
* @param {*} a
|
||||||
|
*/
|
||||||
|
runUnion(a, b) {
|
||||||
|
|
||||||
|
const result = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} r
|
||||||
|
*/
|
||||||
|
const addUnique = (hash) => (item) => {
|
||||||
|
if (!hash[item]) {
|
||||||
|
hash[item] = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
a.map(addUnique(result));
|
||||||
|
b.map(addUnique(result));
|
||||||
|
|
||||||
|
return Object.keys(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} a
|
||||||
|
* @param {*} b
|
||||||
|
*/
|
||||||
|
runIntersect(a, b) {
|
||||||
|
return a.filter((item) => {
|
||||||
|
return b.indexOf(item) > -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} a
|
||||||
|
* @param {*} b
|
||||||
|
*/
|
||||||
|
runSetDifference(a, b) {
|
||||||
|
return a.filter((item) => {
|
||||||
|
return b.indexOf(item) === -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} a
|
||||||
|
* @param {*} b
|
||||||
|
*/
|
||||||
|
runSymmetricDifference(a, b) {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} refArray
|
||||||
|
*/
|
||||||
|
const getDifference = (refArray) => (item) => {
|
||||||
|
return refArray.indexOf(item) === -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
return a
|
||||||
|
.filter(getDifference(b))
|
||||||
|
.concat(b.filter(getDifference(a)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} a
|
||||||
|
* @param {*} b
|
||||||
|
*/
|
||||||
|
runCartesianProduct(a, b) {
|
||||||
|
return Array(Math.max(a.length, b.length))
|
||||||
|
.fill(null)
|
||||||
|
.map((item, index) => `(${a[index] || undefined},${b[index] || undefined})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} a
|
||||||
|
*/
|
||||||
|
runPowerSet(delimiter) {
|
||||||
|
return function(a) {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} dec
|
||||||
|
*/
|
||||||
|
const toBinary = (dec) => (dec >>> 0).toString(2);
|
||||||
|
|
||||||
|
const result = new Set();
|
||||||
|
const maxBinaryValue = parseInt(Number(a.map(i => "1").reduce((p, c) => p + c)), 2);
|
||||||
|
const binaries = [...Array(maxBinaryValue + 1).keys()]
|
||||||
|
.map(toBinary)
|
||||||
|
.map(i => i.padStart(toBinary(maxBinaryValue).length, "0"));
|
||||||
|
|
||||||
|
binaries.forEach((binary) => {
|
||||||
|
const split = binary.split("");
|
||||||
|
result.add(a.filter((item, index) => split[index] === "1"));
|
||||||
|
});
|
||||||
|
|
||||||
|
// map for formatting & put in length order.
|
||||||
|
return [...result].map(r => r.join(delimiter)).sort((a, b) => a.length - b.length);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new SetOps();
|
Loading…
Add table
Add a link
Reference in a new issue