2
0
mirror of https://github.com/gchq/CyberChef synced 2025-12-15 15:53:30 +00:00

Compare commits

..

24 Commits

Author SHA1 Message Date
n1474335
2a91af152d Fixed sitemap generation 2019-09-04 11:14:45 +01:00
n1474335
0ac211ce77 9.4.1 2019-08-30 18:49:11 +01:00
n1474335
32c0d6f253 Updated dependencies 2019-08-30 18:49:05 +01:00
n1474335
de762847e9 9.4.0 2019-08-30 15:48:47 +01:00
n1474335
6248e32148 Updated CHANGELOG 2019-08-30 15:47:50 +01:00
n1474335
52f88ee32d Merge branch 'j433866-render-markdown' 2019-08-30 15:46:37 +01:00
n1474335
f8d1cf2f60 Tidied up 'Render Markdown' operation 2019-08-30 15:46:24 +01:00
n1474335
e129425d8d Merge branch 'render-markdown' of https://github.com/j433866/CyberChef into j433866-render-markdown 2019-08-30 15:33:47 +01:00
n1474335
ae20d82e1d Fix Nightwatch test 2019-08-30 15:30:30 +01:00
n1474335
463b2ce040 9.3.0 2019-08-30 11:58:37 +01:00
n1474335
412b47abba Updated CHANGELOG 2019-08-30 11:58:32 +01:00
n1474335
ed216eee73 Merge branch 'j433866-show-on-map' 2019-08-30 11:57:00 +01:00
n1474335
9dd5234962 Tidied up 'Show on map' operation 2019-08-30 11:56:48 +01:00
n1474335
018532016b Merge branch 'show-on-map' of https://github.com/j433866/CyberChef into j433866-show-on-map 2019-08-30 11:44:12 +01:00
n1474335
7dfecc38f6 Added more UI tests to ensure all modules load, categories can be viewed, and operations can be dragged 2019-08-30 11:43:30 +01:00
n1474335
572f035877 Background magic is now debounced to prevent it firing too often. 2019-08-29 14:08:56 +01:00
j433866
b94eb6adb0 Add syntax highlighting
Explicitly disable HTML rendering.
Updated description.
2019-08-29 14:08:07 +01:00
j433866
45fccb94e1 Merge remote-tracking branch 'upstream/master' into render-markdown 2019-08-29 13:23:37 +01:00
j433866
2628f17fae Change maps source to use Wikimedia maps.
Add link to Wikimedia maps ToS.
If there's no data, show the map anyway.
2019-08-29 11:43:45 +01:00
j433866
69fb6e77fc Merge remote-tracking branch 'upstream/master' into show-on-map 2019-08-29 10:42:40 +01:00
j433866
82b5e97a2b Merge branch 'master' into render-markdown 2019-08-22 12:31:52 +01:00
j433866
7f168d49a6 Add render markdown operation 2019-07-12 09:33:13 +01:00
j433866
b491b9d77d Move conversion of co-ordinates to run() instead of present() 2019-01-18 11:31:53 +00:00
j433866
237f792fb4 Add new Show on map operation 2019-01-18 11:19:06 +00:00
18 changed files with 1271 additions and 1538 deletions

View File

@@ -2,6 +2,12 @@
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
### [9.4.0] - 2019-08-30
- 'Render Markdown' operation added [@j433866] | [#627]
### [9.3.0] - 2019-08-30
- 'Show on map' operation added [@j433866] | [#477]
### [9.2.0] - 2019-08-23
- 'Parse UDP' operation added [@h345983745] | [#614]
@@ -170,6 +176,8 @@ All major and minor version changes will be documented in this file. Details of
[9.4.0]: https://github.com/gchq/CyberChef/releases/tag/v9.4.0
[9.3.0]: https://github.com/gchq/CyberChef/releases/tag/v9.3.0
[9.2.0]: https://github.com/gchq/CyberChef/releases/tag/v9.2.0
[9.1.0]: https://github.com/gchq/CyberChef/releases/tag/v9.1.0
[9.0.0]: https://github.com/gchq/CyberChef/releases/tag/v9.0.0
@@ -279,6 +287,7 @@ All major and minor version changes will be documented in this file. Details of
[#467]: https://github.com/gchq/CyberChef/pull/467
[#468]: https://github.com/gchq/CyberChef/pull/468
[#476]: https://github.com/gchq/CyberChef/pull/476
[#477]: https://github.com/gchq/CyberChef/pull/477
[#489]: https://github.com/gchq/CyberChef/pull/489
[#496]: https://github.com/gchq/CyberChef/pull/496
[#506]: https://github.com/gchq/CyberChef/pull/506
@@ -296,3 +305,4 @@ All major and minor version changes will be documented in this file. Details of
[#591]: https://github.com/gchq/CyberChef/pull/591
[#595]: https://github.com/gchq/CyberChef/pull/595
[#614]: https://github.com/gchq/CyberChef/pull/614
[#627]: https://github.com/gchq/CyberChef/pull/627

View File

@@ -140,8 +140,7 @@ module.exports = function (grunt) {
mode: "production",
target: "web",
entry: Object.assign({
main: "./src/web/index.js",
sitemap: "./src/web/static/sitemap.js"
main: "./src/web/index.js"
}, moduleEntryPoints),
output: {
path: __dirname + "/build/prod",
@@ -232,7 +231,6 @@ module.exports = function (grunt) {
"build/prod/**/*",
"!build/prod/index.html",
"!build/prod/BundleAnalyzerReport.html",
"!build/prod/sitemap.js"
],
dest: `build/prod/CyberChef_v${pkg.version}.zip`
}
@@ -328,7 +326,7 @@ module.exports = function (grunt) {
command: "git gc --prune=now --aggressive"
},
sitemap: {
command: "node build/prod/sitemap.js > build/prod/sitemap.xml"
command: "node --experimental-modules --no-warnings --no-deprecation src/web/static/sitemap.mjs > build/prod/sitemap.xml"
},
generateConfig: {
command: [

2354
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "9.2.3",
"version": "9.4.1",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -36,19 +36,19 @@
"node >= 10"
],
"devDependencies": {
"@babel/core": "^7.5.0",
"@babel/plugin-transform-runtime": "^7.5.0",
"@babel/preset-env": "^7.5.0",
"autoprefixer": "^9.6.0",
"babel-eslint": "^10.0.2",
"@babel/core": "^7.5.5",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"autoprefixer": "^9.6.1",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-dynamic-import-node": "^2.2.0",
"chromedriver": "^75.0.1",
"babel-plugin-dynamic-import-node": "^2.3.0",
"chromedriver": "^76.0.1",
"colors": "^1.3.3",
"css-loader": "^3.0.0",
"eslint": "^6.0.1",
"css-loader": "^3.2.0",
"eslint": "^6.2.2",
"exports-loader": "^0.7.0",
"file-loader": "^4.0.0",
"file-loader": "^4.2.0",
"grunt": "^1.0.4",
"grunt-accessibility": "~6.0.0",
"grunt-chmod": "~1.1.1",
@@ -63,27 +63,27 @@
"grunt-zip": "^0.18.2",
"html-webpack-plugin": "^3.2.0",
"imports-loader": "^0.8.0",
"mini-css-extract-plugin": "^0.7.0",
"nightwatch": "^1.1.13",
"mini-css-extract-plugin": "^0.8.0",
"nightwatch": "^1.2.1",
"node-sass": "^4.12.0",
"postcss-css-variables": "^0.13.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"prompt": "^1.0.0",
"sass-loader": "^7.1.0",
"sitemap": "^3.2.0",
"style-loader": "^0.23.1",
"svg-url-loader": "^3.0.0",
"url-loader": "^2.0.1",
"webpack": "^4.35.2",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-server": "^3.7.2",
"sass-loader": "^8.0.0",
"sitemap": "^4.1.1",
"style-loader": "^1.0.0",
"svg-url-loader": "^3.0.1",
"url-loader": "^2.1.0",
"webpack": "^4.39.3",
"webpack-bundle-analyzer": "^3.4.1",
"webpack-dev-server": "^3.8.0",
"webpack-node-externals": "^1.7.2",
"worker-loader": "^2.0.0"
},
"dependencies": {
"@babel/polyfill": "^7.4.4",
"@babel/runtime": "^7.5.0",
"@babel/runtime": "^7.5.5",
"arrive": "^2.4.1",
"babel-plugin-transform-builtin-extend": "1.1.2",
"bcryptjs": "^2.4.3",
@@ -95,22 +95,22 @@
"bson": "^4.0.2",
"chi-squared": "^1.1.0",
"clippyjs": "0.0.3",
"core-js": "^3.1.4",
"crypto-api": "^0.8.3",
"core-js": "^3.2.1",
"crypto-api": "^0.8.5",
"crypto-js": "^3.1.9-1",
"ctph.js": "0.0.5",
"d3": "^5.9.7",
"d3": "^5.11.0",
"d3-hexbin": "^0.2.2",
"diff": "^4.0.1",
"es6-promisify": "^6.0.1",
"escodegen": "^1.11.1",
"es6-promisify": "^6.0.2",
"escodegen": "^1.12.0",
"esm": "^3.2.25",
"esmangle": "^1.0.1",
"esprima": "^4.0.1",
"exif-parser": "^0.1.12",
"file-saver": "^2.0.2",
"geodesy": "^1.1.3",
"highlight.js": "^9.15.8",
"highlight.js": "^9.15.10",
"jimp": "^0.6.4",
"jquery": "3.4.1",
"js-crc": "^0.2.0",
@@ -120,14 +120,15 @@
"jsonwebtoken": "^8.5.1",
"jsqr": "^1.2.0",
"jsrsasign": "8.0.12",
"kbpgp": "2.1.2",
"kbpgp": "2.1.3",
"libbzip2-wasm": "0.0.4",
"libyara-wasm": "0.0.12",
"lodash": "^4.17.15",
"loglevel": "^1.6.3",
"loglevel-message-prefix": "^3.0.0",
"markdown-it": "^9.1.0",
"moment": "^2.24.0",
"moment-timezone": "^0.5.25",
"moment-timezone": "^0.5.26",
"ngeohash": "^0.6.3",
"node-forge": "^0.8.5",
"node-md6": "^0.1.0",
@@ -157,6 +158,7 @@
"test": "grunt test",
"test-node-consumer": "grunt testnodeconsumer",
"testui": "grunt testui",
"testuidev": "npx nightwatch --env=dev",
"lint": "grunt lint",
"newop": "node --experimental-modules src/core/config/scripts/newOperation.mjs"
}

View File

@@ -1303,6 +1303,30 @@ export function sendStatusMessage(msg) {
console.debug(msg);
}
const debounceTimeouts = {};
/**
* Debouncer to stop functions from being executed multiple times in a
* short space of time
* https://davidwalsh.name/javascript-debounce-function
*
* @param {function} func - The function to be executed after the debounce time
* @param {number} wait - The time (ms) to wait before executing the function
* @param {string} id - Unique ID to reference the timeout for the function
* @param {object} scope - The object to bind to the debounced function
* @param {array} args - Array of arguments to be passed to func
* @returns {function}
*/
export function debounce(func, wait, id, scope, args) {
return function() {
const later = function() {
func.apply(scope, args);
};
clearTimeout(debounceTimeouts[id]);
debounceTimeouts[id] = setTimeout(later, wait);
};
}
/*
* Polyfills

View File

@@ -228,6 +228,7 @@
"Convert speed",
"Convert data units",
"Convert co-ordinate format",
"Show on map",
"Parse UNIX file permissions",
"Swap endianness",
"Parse colour code",
@@ -357,7 +358,8 @@
"BSON serialise",
"BSON deserialise",
"To MessagePack",
"From MessagePack"
"From MessagePack",
"Render Markdown"
]
},
{

View File

@@ -6,9 +6,22 @@
* @license Apache-2.0
*/
import geohash from "ngeohash";
import geodesy from "geodesy";
import OperationError from "../errors/OperationError.mjs";
import geohash from "ngeohash";
/*
Currently unable to update to geodesy v2 as we cannot load .js modules into a .mjs file.
When we do update, imports will look like this:
import LatLonEllipsoidal from "geodesy/latlon-ellipsoidal.js";
import Mgrs from "geodesy/mgrs.js";
import OsGridRef from "geodesy/osgridref.js";
import Utm from "geodesy/utm.js";
*/
import geodesy from "geodesy";
const LatLonEllipsoidal = geodesy.LatLonEllipsoidal,
Mgrs = geodesy.Mgrs,
OsGridRef = geodesy.OsGridRef,
Utm = geodesy.Utm;
/**
* Co-ordinate formats
@@ -116,22 +129,22 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
switch (inFormat) {
case "Geohash":
hash = geohash.decode(input.replace(/[^A-Za-z0-9]/g, ""));
latlon = new geodesy.LatLonEllipsoidal(hash.latitude, hash.longitude);
latlon = new LatLonEllipsoidal(hash.latitude, hash.longitude);
break;
case "Military Grid Reference System":
utm = geodesy.Mgrs.parse(input.replace(/[^A-Za-z0-9]/g, "")).toUtm();
utm = Mgrs.parse(input.replace(/[^A-Za-z0-9]/g, "")).toUtm();
latlon = utm.toLatLonE();
break;
case "Ordnance Survey National Grid":
osng = geodesy.OsGridRef.parse(input.replace(/[^A-Za-z0-9]/g, ""));
latlon = geodesy.OsGridRef.osGridToLatLon(osng);
osng = OsGridRef.parse(input.replace(/[^A-Za-z0-9]/g, ""));
latlon = OsGridRef.osGridToLatLon(osng);
break;
case "Universal Transverse Mercator":
// Geodesy needs a space between the first 2 digits and the next letter
if (/^[\d]{2}[A-Za-z]/.test(input)) {
input = input.slice(0, 2) + " " + input.slice(2);
}
utm = geodesy.Utm.parse(input);
utm = Utm.parse(input);
latlon = utm.toLatLonE();
break;
case "Degrees Minutes Seconds":
@@ -143,7 +156,7 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
if (splitLat.length >= 3 && splitLong.length >= 3) {
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2], 10);
lon = convDMSToDD(splitLong[0], splitLong[1], splitLong[2], 10);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lon.degrees);
latlon = new LatLonEllipsoidal(lat.degrees, lon.degrees);
} else {
throw new OperationError("Invalid co-ordinate format for Degrees Minutes Seconds");
}
@@ -152,7 +165,7 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
splitLat = splitInput(split[0]);
if (splitLat.length >= 3) {
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2]);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lat.degrees);
latlon = new LatLonEllipsoidal(lat.degrees, lat.degrees);
} else {
throw new OperationError("Invalid co-ordinate format for Degrees Minutes Seconds");
}
@@ -168,7 +181,7 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
// Convert to decimal degrees, and then convert to a geodesy object
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
lon = convDDMToDD(splitLong[0], splitLong[1], 10);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lon.degrees);
latlon = new LatLonEllipsoidal(lat.degrees, lon.degrees);
} else {
// Not a pair, so only try to convert one set of co-ordinates
splitLat = splitInput(input);
@@ -176,7 +189,7 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
throw new OperationError("Invalid co-ordinate format for Degrees Decimal Minutes.");
}
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lat.degrees);
latlon = new LatLonEllipsoidal(lat.degrees, lat.degrees);
}
break;
case "Decimal Degrees":
@@ -186,14 +199,14 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
if (splitLat.length !== 1 || splitLong.length !== 1) {
throw new OperationError("Invalid co-ordinate format for Decimal Degrees.");
}
latlon = new geodesy.LatLonEllipsoidal(splitLat[0], splitLong[0]);
latlon = new LatLonEllipsoidal(splitLat[0], splitLong[0]);
} else {
// Not a pair, so only try to convert one set of co-ordinates
splitLat = splitInput(split[0]);
if (splitLat.length !== 1) {
throw new OperationError("Invalid co-ordinate format for Decimal Degrees.");
}
latlon = new geodesy.LatLonEllipsoidal(splitLat[0], splitLat[0]);
latlon = new LatLonEllipsoidal(splitLat[0], splitLat[0]);
}
break;
default:
@@ -260,7 +273,7 @@ export function convertCoordinates (input, inFormat, inDelim, outFormat, outDeli
convLat = mgrs.toString(precision);
break;
case "Ordnance Survey National Grid":
osng = geodesy.OsGridRef.latLonToOsGrid(latlon);
osng = OsGridRef.latLonToOsGrid(latlon);
if (osng.toString() === "") {
throw new OperationError("Could not convert co-ordinates to OS National Grid. Are the co-ordinates in range?");
}

View File

@@ -0,0 +1,69 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import MarkdownIt from "markdown-it";
import hljs from "highlight.js";
/**
* Render Markdown operation
*/
class RenderMarkdown extends Operation {
/**
* RenderMarkdown constructor
*/
constructor() {
super();
this.name = "Render Markdown";
this.module = "Code";
this.description = "Renders input Markdown as HTML. HTML rendering is disabled to avoid XSS.";
this.infoURL = "https://wikipedia.org/wiki/Markdown";
this.inputType = "string";
this.outputType = "html";
this.args = [
{
name: "Autoconvert URLs to links",
type: "boolean",
value: false
},
{
name: "Enable syntax highlighting",
type: "boolean",
value: true
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
run(input, args) {
const [convertLinks, enableHighlighting] = args,
md = new MarkdownIt({
linkify: convertLinks,
html: false, // Explicitly disable HTML rendering
highlight: function(str, lang) {
if (lang && hljs.getLanguage(lang) && enableHighlighting) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}
return "";
}
}),
rendered = md.render(input);
return `<div style="font-family: var(--primary-font-family)">${rendered}</div>`;
}
}
export default RenderMarkdown;

View File

@@ -0,0 +1,113 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import {FORMATS, convertCoordinates} from "../lib/ConvertCoordinates.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Show on map operation
*/
class ShowOnMap extends Operation {
/**
* ShowOnMap constructor
*/
constructor() {
super();
this.name = "Show on map";
this.module = "Hashing";
this.description = "Displays co-ordinates on a slippy map.<br><br>Co-ordinates will be converted to decimal degrees before being shown on the map.<br><br>Supported formats:<ul><li>Degrees Minutes Seconds (DMS)</li><li>Degrees Decimal Minutes (DDM)</li><li>Decimal Degrees (DD)</li><li>Geohash</li><li>Military Grid Reference System (MGRS)</li><li>Ordnance Survey National Grid (OSNG)</li><li>Universal Transverse Mercator (UTM)</li></ul><br>This operation will not work offline.";
this.infoURL = "https://foundation.wikimedia.org/wiki/Maps_Terms_of_Use";
this.inputType = "string";
this.outputType = "string";
this.presentType = "html";
this.args = [
{
name: "Zoom Level",
type: "number",
value: 13
},
{
name: "Input Format",
type: "option",
value: ["Auto"].concat(FORMATS)
},
{
name: "Input Delimiter",
type: "option",
value: [
"Auto",
"Direction Preceding",
"Direction Following",
"\\n",
"Comma",
"Semi-colon",
"Colon"
]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
if (input.replace(/\s+/g, "") !== "") {
const inFormat = args[1],
inDelim = args[2];
let latLong;
try {
latLong = convertCoordinates(input, inFormat, inDelim, "Decimal Degrees", "Comma", "None", 5);
} catch (error) {
throw new OperationError(error);
}
latLong = latLong.replace(/[,]$/, "");
latLong = latLong.replace(/°/g, "");
return latLong;
}
return input;
}
/**
* @param {string} data
* @param {Object[]} args
* @returns {string}
*/
async present(data, args) {
if (data.replace(/\s+/g, "") === "") {
data = "0, 0";
}
const zoomLevel = args[0];
const tileUrl = "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",
tileAttribution = "<a href=\"https://wikimediafoundation.org/wiki/Maps_Terms_of_Use\">Wikimedia maps</a> | &copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
leafletUrl = "https://unpkg.com/leaflet@1.5.0/dist/leaflet.js",
leafletCssUrl = "https://unpkg.com/leaflet@1.5.0/dist/leaflet.css";
return `<link rel="stylesheet" href="${leafletCssUrl}" crossorigin=""/>
<style>#output-html { white-space: normal; padding: 0; }</style>
<div id="presentedMap" style="width: 100%; height: 100%;"></div>
<script type="text/javascript">
var mapscript = document.createElement('script');
document.body.appendChild(mapscript);
mapscript.onload = function() {
var presentMap = L.map('presentedMap').setView([${data}], ${zoomLevel});
L.tileLayer('${tileUrl}', {
attribution: '${tileAttribution}'
}).addTo(presentMap);
L.marker([${data}]).addTo(presentMap)
.bindPopup('${data}')
.openPopup();
};
mapscript.src = "${leafletUrl}";
</script>`;
}
}
export default ShowOnMap;

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Utils from "../core/Utils";
import Utils, { debounce } from "../core/Utils";
import {fromBase64} from "../core/lib/Base64";
import Manager from "./Manager";
import HTMLCategory from "./HTMLCategory";
@@ -41,7 +41,6 @@ class App {
this.autoBakePause = false;
this.progress = 0;
this.ingId = 0;
this.timeouts = {};
}
@@ -295,7 +294,7 @@ class App {
minSize: minimise ? [0, 0, 0] : [240, 310, 450],
gutterSize: 4,
expandToMin: true,
onDrag: this.debounce(function() {
onDrag: debounce(function() {
this.manager.recipe.adjustWidth();
this.manager.input.calcMaxTabs();
this.manager.output.calcMaxTabs();
@@ -723,6 +722,7 @@ class App {
this.updateTitle(false, null, true);
}
/**
* Update the page title to contain the new recipe
*
@@ -766,29 +766,6 @@ class App {
this.loadURIParams();
}
/**
* Debouncer to stop functions from being executed multiple times in a
* short space of time
* https://davidwalsh.name/javascript-debounce-function
*
* @param {function} func - The function to be executed after the debounce time
* @param {number} wait - The time (ms) to wait before executing the function
* @param {string} id - Unique ID to reference the timeout for the function
* @param {object} scope - The object to bind to the debounced function
* @param {array} args - Array of arguments to be passed to func
* @returns {function}
*/
debounce(func, wait, id, scope, args) {
return function() {
const later = function() {
func.apply(scope, args);
};
clearTimeout(this.timeouts[id]);
this.timeouts[id] = setTimeout(later, wait);
}.bind(this);
}
}
export default App;

View File

@@ -1,4 +1,4 @@
import sm from "sitemap";
import Sitemap from "sitemap";
import OperationConfig from "../../core/config/OperationConfig.json";
@@ -10,7 +10,7 @@ import OperationConfig from "../../core/config/OperationConfig.json";
* @license Apache-2.0
*/
const sitemap = sm.createSitemap({
const sitemap = Sitemap.createSitemap({
hostname: "https://gchq.github.io/CyberChef",
});

View File

@@ -45,7 +45,7 @@ div#output {
position: relative;
}
#operations {
#operations.split {
overflow: auto;
}

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import ChefWorker from "worker-loader?inline&fallback=false!../../core/ChefWorker";
import ChefWorker from "worker-loader?inline&fallback=false!../../core/ChefWorker.js";
/**
* Waiter to handle conversations with a ChefWorker in the background.

View File

@@ -5,9 +5,9 @@
* @license Apache-2.0
*/
import LoaderWorker from "worker-loader?inline&fallback=false!../workers/LoaderWorker";
import InputWorker from "worker-loader?inline&fallback=false!../workers/InputWorker";
import Utils from "../../core/Utils.mjs";
import LoaderWorker from "worker-loader?inline&fallback=false!../workers/LoaderWorker.js";
import InputWorker from "worker-loader?inline&fallback=false!../workers/InputWorker.mjs";
import Utils, { debounce } from "../../core/Utils.mjs";
import { toBase64 } from "../../core/lib/Base64.mjs";
import { isImage } from "../../core/lib/FileType.mjs";
@@ -270,7 +270,7 @@ class InputWaiter {
this.showLoadingInfo(r.data, true);
break;
case "setInput":
this.app.debounce(this.set, 50, "setInput", this, [r.data.inputObj, r.data.silent])();
debounce(this.set, 50, "setInput", this, [r.data.inputObj, r.data.silent])();
break;
case "inputAdded":
this.inputAdded(r.data.changeTab, r.data.inputNum);
@@ -316,7 +316,7 @@ class InputWaiter {
*/
bakeAll() {
this.app.progress = 0;
this.app.debounce(this.manager.controls.toggleBakeButtonFunction, 20, "toggleBakeButton", this, ["loading"]);
debounce(this.manager.controls.toggleBakeButtonFunction, 20, "toggleBakeButton", this, ["loading"]);
this.inputWorker.postMessage({
action: "bakeAll"
});
@@ -681,7 +681,7 @@ class InputWaiter {
* @param {event} e
*/
debounceInputChange(e) {
this.app.debounce(this.inputChange, 50, "inputChange", this, [e])();
debounce(this.inputChange, 50, "inputChange", this, [e])();
}
/**

View File

@@ -5,10 +5,10 @@
* @license Apache-2.0
*/
import Utils from "../../core/Utils.mjs";
import Utils, { debounce } from "../../core/Utils.mjs";
import Dish from "../../core/Dish.mjs";
import FileSaver from "file-saver";
import ZipWorker from "worker-loader?inline&fallback=false!../workers/ZipWorker";
import ZipWorker from "worker-loader?inline&fallback=false!../workers/ZipWorker.mjs";
/**
* Waiter to handle events related to the output
@@ -369,7 +369,7 @@ class OutputWaiter {
}
this.setOutputInfo(length, lines, output.data.duration);
this.backgroundMagic();
debounce(this.backgroundMagic, 50, "backgroundMagic", this, [])();
}
}.bind(this));
}
@@ -717,7 +717,7 @@ class OutputWaiter {
}
}
this.app.debounce(this.set, 50, "setOutput", this, [inputNum])();
debounce(this.set, 50, "setOutput", this, [inputNum])();
document.getElementById("output-html").scroll(0, 0);
document.getElementById("output-text").scroll(0, 0);

View File

@@ -4,6 +4,8 @@
* @license Apache-2.0
*/
import { debounce } from "../../core/Utils.mjs";
/**
* Waiter to handle events related to the window object.
*/
@@ -25,7 +27,7 @@ class WindowWaiter {
* continuous resetting).
*/
windowResize() {
this.app.debounce(this.app.resetLayout, 200, "windowResize", this.app, [])();
debounce(this.app.resetLayout, 200, "windowResize", this.app, [])();
}

View File

@@ -5,8 +5,9 @@
* @license Apache-2.0
*/
import ChefWorker from "worker-loader?inline&fallback=false!../../core/ChefWorker";
import DishWorker from "worker-loader?inline&fallback=false!../workers/DishWorker";
import ChefWorker from "worker-loader?inline&fallback=false!../../core/ChefWorker.js";
import DishWorker from "worker-loader?inline&fallback=false!../workers/DishWorker.mjs";
import { debounce } from "../../core/Utils.mjs";
/**
* Waiter to handle conversations with the ChefWorker
@@ -281,7 +282,7 @@ class WorkerWaiter {
*/
setBakingStatus(bakingStatus) {
this.app.baking = bakingStatus;
this.app.debounce(this.manager.controls.toggleBakeButtonFunction, 20, "toggleBakeButton", this, [bakingStatus ? "cancel" : "bake"])();
debounce(this.manager.controls.toggleBakeButtonFunction, 20, "toggleBakeButton", this, [bakingStatus ? "cancel" : "bake"])();
if (bakingStatus) this.manager.output.hideMagicButton();
}

View File

@@ -75,7 +75,7 @@ module.exports = {
// Confirm that it has been added to the recipe
browser
.useCss()
.waitForElementVisible(op)
.waitForElementVisible(op, 100)
.expect.element(op).text.to.contain("To Hex");
// Enter input
@@ -107,6 +107,10 @@ module.exports = {
loadOp("BSON deserialise", browser)
.waitForElementNotVisible("#output-loader", 5000);
// Charts
loadOp("Entropy", browser)
.waitForElementNotVisible("#output-loader", 5000);
// Ciphers
loadOp("AES Encrypt", browser)
.waitForElementNotVisible("#output-loader", 5000);
@@ -135,6 +139,10 @@ module.exports = {
loadOp("Encode text", browser)
.waitForElementNotVisible("#output-loader", 5000);
// Hashing
loadOp("Streebog", browser)
.waitForElementNotVisible("#output-loader", 5000);
// Image
loadOp("Extract EXIF", browser)
.waitForElementNotVisible("#output-loader", 5000);
@@ -162,6 +170,54 @@ module.exports = {
// UserAgent
loadOp("Parse User Agent", browser)
.waitForElementNotVisible("#output-loader", 5000);
// YARA
loadOp("YARA Rules", browser)
.waitForElementNotVisible("#output-loader", 5000);
browser.click("#clr-recipe");
},
"Move around the UI": browser => {
const otherCat = "//a[contains(@class, 'category-title') and contains(@data-target, '#catOther')]",
genUUID = "//li[contains(@class, 'operation') and text()='Generate UUID']";
browser.useXpath();
// Scroll to a lower category
browser
.getLocationInView(otherCat)
.expect.element(otherCat).to.be.visible;
// Open category
browser
.click(otherCat)
.expect.element(genUUID).to.be.visible;
// Add op to recipe
/* mouseButtonUp drops wherever the actual cursor is, not necessarily in the right place,
so we can't test Sortable.js properly using Nightwatch. html-dnd doesn't work either.
Instead of relying on drag and drop, we double click on the op to load it. */
browser
.getLocationInView(genUUID)
.moveToElement(genUUID, 10, 10)
.doubleClick()
.useCss()
.waitForElementVisible(".operation .op-title", 1000)
.waitForElementNotVisible("#stale-indicator", 1000)
.expect.element("#output-text").to.have.value.which.matches(/[\da-f-]{36}/);
browser.click("#clr-recipe");
},
"Search": browser => {
// Search for an op
browser
.useCss()
.clearValue("#search")
.setValue("#search", "md5")
.useXpath()
.waitForElementVisible("//ul[@id='search-results']//u[text()='MD5']", 1000);
},
after: browser => {