mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-20 06:55:08 -04:00
Added a CodeQL workflow to check for bugs through code analysis. Fixed numerous bugs and implemented safeguards as already reported.
This commit is contained in:
parent
892a3716ed
commit
1abc46058c
32 changed files with 87 additions and 61 deletions
32
.github/workflows/codeql.yml
vendored
Normal file
32
.github/workflows/codeql.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ master ]
|
||||||
|
schedule:
|
||||||
|
- cron: '22 17 * * 5'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'javascript' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
|
@ -174,7 +174,7 @@ module.exports = function (grunt) {
|
||||||
// previous one fails. & would coninue on a fail
|
// previous one fails. & would coninue on a fail
|
||||||
.join("&&")
|
.join("&&")
|
||||||
// Windows does not support \n properly
|
// Windows does not support \n properly
|
||||||
.replace("\n", "\\n");
|
.replace(/\n/g, "\\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
|
|
|
@ -212,7 +212,7 @@ self.loadRequiredModules = function(recipeConfig) {
|
||||||
if (!(module in OpModules)) {
|
if (!(module in OpModules)) {
|
||||||
log.info(`Loading ${module} module`);
|
log.info(`Loading ${module} module`);
|
||||||
self.sendStatusMessage(`Loading ${module} module`);
|
self.sendStatusMessage(`Loading ${module} module`);
|
||||||
self.importScripts(`${self.docURL}/modules/${module}.js`);
|
self.importScripts(`${self.docURL}/modules/${module}.js`); // lgtm [js/client-side-unvalidated-url-redirection]
|
||||||
self.sendStatusMessage("");
|
self.sendStatusMessage("");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -207,7 +207,7 @@ class Dish {
|
||||||
const data = new Uint8Array(this.value.slice(0, 2048)),
|
const data = new Uint8Array(this.value.slice(0, 2048)),
|
||||||
types = detectFileType(data);
|
types = detectFileType(data);
|
||||||
|
|
||||||
if (!types.length || !types[0].mime || !types[0].mime === "text/plain") {
|
if (!types.length || !types[0].mime || !(types[0].mime === "text/plain")) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return types[0].mime;
|
return types[0].mime;
|
||||||
|
|
|
@ -705,7 +705,7 @@ class Utils {
|
||||||
*/
|
*/
|
||||||
static stripHtmlTags(htmlStr, removeScriptAndStyle=false) {
|
static stripHtmlTags(htmlStr, removeScriptAndStyle=false) {
|
||||||
if (removeScriptAndStyle) {
|
if (removeScriptAndStyle) {
|
||||||
htmlStr = htmlStr.replace(/<(script|style)[^>]*>.*<\/(script|style)>/gmi, "");
|
htmlStr = htmlStr.replace(/<(script|style)[^>]*>.*?<\/(script|style)>/gi, "");
|
||||||
}
|
}
|
||||||
return htmlStr.replace(/<[^>]+>/g, "");
|
return htmlStr.replace(/<[^>]+>/g, "");
|
||||||
}
|
}
|
||||||
|
@ -729,11 +729,10 @@ class Utils {
|
||||||
">": ">",
|
">": ">",
|
||||||
'"': """,
|
'"': """,
|
||||||
"'": "'", // ' not recommended because it's not in the HTML spec
|
"'": "'", // ' not recommended because it's not in the HTML spec
|
||||||
"/": "/", // forward slash is included as it helps end an HTML entity
|
|
||||||
"`": "`"
|
"`": "`"
|
||||||
};
|
};
|
||||||
|
|
||||||
return str.replace(/[&<>"'/`]/g, function (match) {
|
return str.replace(/[&<>"'`]/g, function (match) {
|
||||||
return HTML_CHARS[match];
|
return HTML_CHARS[match];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -879,7 +878,7 @@ class Utils {
|
||||||
while ((m = recipeRegex.exec(recipe))) {
|
while ((m = recipeRegex.exec(recipe))) {
|
||||||
// Translate strings in args back to double-quotes
|
// Translate strings in args back to double-quotes
|
||||||
args = m[2]
|
args = m[2]
|
||||||
.replace(/"/g, '\\"') // Escape double quotes
|
.replace(/"/g, '\\"') // Escape double quotes lgtm [js/incomplete-sanitization]
|
||||||
.replace(/(^|,|{|:)'/g, '$1"') // Replace opening ' with "
|
.replace(/(^|,|{|:)'/g, '$1"') // Replace opening ' with "
|
||||||
.replace(/([^\\]|(?:\\\\)+)'(,|:|}|$)/g, '$1"$2') // Replace closing ' with "
|
.replace(/([^\\]|(?:\\\\)+)'(,|:|}|$)/g, '$1"$2') // Replace closing ' with "
|
||||||
.replace(/\\'/g, "'"); // Unescape single quotes
|
.replace(/\\'/g, "'"); // Unescape single quotes
|
||||||
|
|
|
@ -121,7 +121,7 @@ prompt.get(schema, (err, result) => {
|
||||||
|
|
||||||
const moduleName = result.opName.replace(/\w\S*/g, txt => {
|
const moduleName = result.opName.replace(/\w\S*/g, txt => {
|
||||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||||
}).replace(/[\s-()/./]/g, "");
|
}).replace(/[\s-()./]/g, "");
|
||||||
|
|
||||||
|
|
||||||
const template = `/**
|
const template = `/**
|
||||||
|
|
|
@ -32,9 +32,9 @@ export const ALPHABET_OPTIONS = [
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function alphabetName(alphabet) {
|
export function alphabetName(alphabet) {
|
||||||
alphabet = alphabet.replace("'", "'");
|
alphabet = alphabet.replace(/'/g, "'");
|
||||||
alphabet = alphabet.replace("\"", """);
|
alphabet = alphabet.replace(/"/g, """);
|
||||||
alphabet = alphabet.replace("\\", "\");
|
alphabet = alphabet.replace(/\\/g, "\");
|
||||||
let name;
|
let name;
|
||||||
|
|
||||||
ALPHABET_OPTIONS.forEach(function(a) {
|
ALPHABET_OPTIONS.forEach(function(a) {
|
||||||
|
|
|
@ -86,8 +86,8 @@ export function getScatterValues(input, recordDelimiter, fieldDelimiter, columnH
|
||||||
}
|
}
|
||||||
|
|
||||||
values = values.map(row => {
|
values = values.map(row => {
|
||||||
const x = parseFloat(row[0], 10),
|
const x = parseFloat(row[0]),
|
||||||
y = parseFloat(row[1], 10);
|
y = parseFloat(row[1]);
|
||||||
|
|
||||||
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
|
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
|
@ -121,8 +121,8 @@ export function getScatterValuesWithColour(input, recordDelimiter, fieldDelimite
|
||||||
}
|
}
|
||||||
|
|
||||||
values = values.map(row => {
|
values = values.map(row => {
|
||||||
const x = parseFloat(row[0], 10),
|
const x = parseFloat(row[0]),
|
||||||
y = parseFloat(row[1], 10),
|
y = parseFloat(row[1]),
|
||||||
colour = row[2];
|
colour = row[2];
|
||||||
|
|
||||||
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
|
@ -157,7 +157,7 @@ export function getSeriesValues(input, recordDelimiter, fieldDelimiter, columnHe
|
||||||
values.forEach(row => {
|
values.forEach(row => {
|
||||||
const serie = row[0],
|
const serie = row[0],
|
||||||
xVal = row[1],
|
xVal = row[1],
|
||||||
val = parseFloat(row[2], 10);
|
val = parseFloat(row[2]);
|
||||||
|
|
||||||
if (Number.isNaN(val)) throw new OperationError("Values must be numbers in base 10.");
|
if (Number.isNaN(val)) throw new OperationError("Values must be numbers in base 10.");
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ function locatePotentialSig(buf, sig, offset) {
|
||||||
export function isType(type, buf) {
|
export function isType(type, buf) {
|
||||||
const types = detectFileType(buf);
|
const types = detectFileType(buf);
|
||||||
|
|
||||||
if (!(types && types.length)) return false;
|
if (!types.length) return false;
|
||||||
|
|
||||||
if (typeof type === "string") {
|
if (typeof type === "string") {
|
||||||
return types.reduce((acc, t) => {
|
return types.reduce((acc, t) => {
|
||||||
|
|
|
@ -177,7 +177,7 @@ export default class Stream {
|
||||||
|
|
||||||
// Get the skip table.
|
// Get the skip table.
|
||||||
const skiptable = preprocess(val, length);
|
const skiptable = preprocess(val, length);
|
||||||
let found = true;
|
let found;
|
||||||
|
|
||||||
while (this.position < this.length) {
|
while (this.position < this.length) {
|
||||||
// Until we hit the final element of val in the stream.
|
// Until we hit the final element of val in the stream.
|
||||||
|
|
|
@ -39,8 +39,8 @@ class ExtractEmailAddresses extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const displayTotal = args[0],
|
const displayTotal = args[0],
|
||||||
// email regex from: https://www.regextester.com/98066
|
// email regex from: https://www.regextester.com/98066
|
||||||
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/ig;
|
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}\])/ig;
|
||||||
return search(input, regex, null, displayTotal);
|
return search(input, regex, null, displayTotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ class FromBCD extends Operation {
|
||||||
if (!packed) {
|
if (!packed) {
|
||||||
// Discard each high nibble
|
// Discard each high nibble
|
||||||
for (let i = 0; i < nibbles.length; i++) {
|
for (let i = 0; i < nibbles.length; i++) {
|
||||||
nibbles.splice(i, 1);
|
nibbles.splice(i, 1); // lgtm [js/loop-iteration-skipped-due-to-shifting]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ class FromBase extends Operation {
|
||||||
}
|
}
|
||||||
|
|
||||||
const number = input.replace(/\s/g, "").split(".");
|
const number = input.replace(/\s/g, "").split(".");
|
||||||
let result = new BigNumber(number[0], radix) || 0;
|
let result = new BigNumber(number[0], radix);
|
||||||
|
|
||||||
if (number.length === 1) return result;
|
if (number.length === 1) return result;
|
||||||
|
|
||||||
|
|
|
@ -84,10 +84,10 @@ class FromBase32 extends Operation {
|
||||||
chr5 = ((enc7 & 7) << 5) | enc8;
|
chr5 = ((enc7 & 7) << 5) | enc8;
|
||||||
|
|
||||||
output.push(chr1);
|
output.push(chr1);
|
||||||
if (enc2 & 3 !== 0 || enc3 !== 32) output.push(chr2);
|
if ((enc2 & 3) !== 0 || enc3 !== 32) output.push(chr2);
|
||||||
if (enc4 & 15 !== 0 || enc5 !== 32) output.push(chr3);
|
if ((enc4 & 15) !== 0 || enc5 !== 32) output.push(chr3);
|
||||||
if (enc5 & 1 !== 0 || enc6 !== 32) output.push(chr4);
|
if ((enc5 & 1) !== 0 || enc6 !== 32) output.push(chr4);
|
||||||
if (enc7 & 7 !== 0 || enc8 !== 32) output.push(chr5);
|
if ((enc7 & 7) !== 0 || enc8 !== 32) output.push(chr5);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -376,7 +376,7 @@ class Lorenz extends Operation {
|
||||||
// Psi wheels only move sometimes, dependent on M37 current setting and limitations
|
// Psi wheels only move sometimes, dependent on M37 current setting and limitations
|
||||||
|
|
||||||
const basicmotor = m37lug;
|
const basicmotor = m37lug;
|
||||||
let totalmotor = basicmotor;
|
let totalmotor;
|
||||||
let lim = 0;
|
let lim = 0;
|
||||||
|
|
||||||
p5[2] = p5[1];
|
p5[2] = p5[1];
|
||||||
|
|
|
@ -51,7 +51,7 @@ class OpticalCharacterRecognition extends Operation {
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
const [showConfidence] = args;
|
const [showConfidence] = args;
|
||||||
|
|
||||||
if (!isWorkerEnvironment()) throw OperationError("This operation only works in a browser");
|
if (!isWorkerEnvironment()) throw new OperationError("This operation only works in a browser");
|
||||||
|
|
||||||
const type = isImage(input);
|
const type = isImage(input);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
|
|
|
@ -111,7 +111,7 @@ class PHPDeserialize extends Operation {
|
||||||
} else {
|
} else {
|
||||||
const numberCheck = lastItem.match(/[0-9]+/);
|
const numberCheck = lastItem.match(/[0-9]+/);
|
||||||
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
|
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
|
||||||
result.push("\"" + lastItem + "\": " + item);
|
result.push('"' + lastItem + '": ' + item);
|
||||||
} else {
|
} else {
|
||||||
result.push(lastItem + ": " + item);
|
result.push(lastItem + ": " + item);
|
||||||
}
|
}
|
||||||
|
@ -149,11 +149,11 @@ class PHPDeserialize extends Operation {
|
||||||
const length = readUntil(":");
|
const length = readUntil(":");
|
||||||
expect("\"");
|
expect("\"");
|
||||||
const value = read(length);
|
const value = read(length);
|
||||||
expect("\";");
|
expect('";');
|
||||||
if (args[0]) {
|
if (args[0]) {
|
||||||
return "\"" + value.replace(/"/g, "\\\"") + "\"";
|
return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]
|
||||||
} else {
|
} else {
|
||||||
return "\"" + value + "\"";
|
return '"' + value + '"';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ class ParseIPv6Address extends Operation {
|
||||||
|
|
||||||
|
|
||||||
// Detect possible EUI-64 addresses
|
// Detect possible EUI-64 addresses
|
||||||
if ((ipv6[5] & 0xff === 0xff) && (ipv6[6] >>> 8 === 0xfe)) {
|
if (((ipv6[5] & 0xff) === 0xff) && (ipv6[6] >>> 8 === 0xfe)) {
|
||||||
output += "\n\nThis IPv6 address contains a modified EUI-64 address, identified by the presence of FF:FE in the 12th and 13th octets.";
|
output += "\n\nThis IPv6 address contains a modified EUI-64 address, identified by the presence of FF:FE in the 12th and 13th octets.";
|
||||||
|
|
||||||
const intIdent = Utils.hex(ipv6[4] >>> 8) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" +
|
const intIdent = Utils.hex(ipv6[4] >>> 8) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" +
|
||||||
|
|
|
@ -87,7 +87,7 @@ class ParseSSHHostKey extends Operation {
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
convertKeyToBinary(inputKey, inputFormat) {
|
convertKeyToBinary(inputKey, inputFormat) {
|
||||||
const keyPattern = new RegExp(/^(?:[ssh]|[ecdsa-sha2])\S+\s+(\S*)/),
|
const keyPattern = new RegExp(/^(?:ssh|ecdsa-sha2)\S+\s+(\S*)/),
|
||||||
keyMatch = inputKey.match(keyPattern);
|
keyMatch = inputKey.match(keyPattern);
|
||||||
|
|
||||||
if (keyMatch) {
|
if (keyMatch) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class RegularExpression extends Operation {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Email address",
|
name: "Email address",
|
||||||
value: "(?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9])?\\.)+[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\\])"
|
value: "(?:[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9](?:[\\u00A0-\\uD7FF\\uE000-\\uFFFF-a-z0-9-]*[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9])?\\.)+[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9](?:[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9-]*[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}\\])"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "URL",
|
name: "URL",
|
||||||
|
|
|
@ -81,7 +81,7 @@ class SharpenImage extends Operation {
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Sharpening image... (Blurring cloned image)");
|
self.sendStatusMessage("Sharpening image... (Blurring cloned image)");
|
||||||
const blurImage = gaussianBlur(image.clone(), radius, 3);
|
const blurImage = gaussianBlur(image.clone(), radius);
|
||||||
|
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
|
|
|
@ -125,7 +125,7 @@ class Sort extends Operation {
|
||||||
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
||||||
if (ret !== 0) return ret;
|
if (ret !== 0) return ret;
|
||||||
}
|
}
|
||||||
if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
|
if (!isNaN(a_[i]) && !isNaN(b_[i])) { // Compare numbers
|
||||||
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ class Sort extends Operation {
|
||||||
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
||||||
if (ret !== 0) return ret;
|
if (ret !== 0) return ret;
|
||||||
}
|
}
|
||||||
if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
|
if (!isNaN(a_[i]) && !isNaN(b_[i])) { // Compare numbers
|
||||||
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ToCharcode extends Operation {
|
||||||
const delim = Utils.charRep(args[0] || "Space"),
|
const delim = Utils.charRep(args[0] || "Space"),
|
||||||
base = args[1];
|
base = args[1];
|
||||||
let output = "",
|
let output = "",
|
||||||
padding = 2,
|
padding,
|
||||||
ordinal;
|
ordinal;
|
||||||
|
|
||||||
if (base < 2 || base > 36) {
|
if (base < 2 || base > 36) {
|
||||||
|
|
|
@ -47,7 +47,6 @@ class UnescapeUnicodeCharacters extends Operation {
|
||||||
while ((m = regex.exec(input))) {
|
while ((m = regex.exec(input))) {
|
||||||
// Add up to match
|
// Add up to match
|
||||||
output += input.slice(i, m.index);
|
output += input.slice(i, m.index);
|
||||||
i = m.index;
|
|
||||||
|
|
||||||
// Add match
|
// Add match
|
||||||
output += Utils.chr(parseInt(m[1], 16));
|
output += Utils.chr(parseInt(m[1], 16));
|
||||||
|
|
|
@ -153,7 +153,7 @@ class HTMLIngredient {
|
||||||
for (i = 0; i < this.value.length; i++) {
|
for (i = 0; i < this.value.length; i++) {
|
||||||
if ((m = this.value[i].match(/\[([a-z0-9 -()^]+)\]/i))) {
|
if ((m = this.value[i].match(/\[([a-z0-9 -()^]+)\]/i))) {
|
||||||
html += `<optgroup label="${m[1]}">`;
|
html += `<optgroup label="${m[1]}">`;
|
||||||
} else if ((m = this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
} else if (this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i)) {
|
||||||
html += "</optgroup>";
|
html += "</optgroup>";
|
||||||
} else {
|
} else {
|
||||||
html += `<option ${this.defaultIndex === i ? "selected" : ""}>${this.value[i]}</option>`;
|
html += `<option ${this.defaultIndex === i ? "selected" : ""}>${this.value[i]}</option>`;
|
||||||
|
@ -177,7 +177,7 @@ class HTMLIngredient {
|
||||||
for (i = 0; i < this.value.length; i++) {
|
for (i = 0; i < this.value.length; i++) {
|
||||||
if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
|
if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
|
||||||
html += `<optgroup label="${m[1]}">`;
|
html += `<optgroup label="${m[1]}">`;
|
||||||
} else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
} else if (this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i)) {
|
||||||
html += "</optgroup>";
|
html += "</optgroup>";
|
||||||
} else {
|
} else {
|
||||||
const val = this.type === "populateMultiOption" ?
|
const val = this.type === "populateMultiOption" ?
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import HTMLIngredient from "./HTMLIngredient.mjs";
|
import HTMLIngredient from "./HTMLIngredient.mjs";
|
||||||
|
import Utils from "../core/Utils.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,7 +73,7 @@ class HTMLOperation {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
toFullHtml() {
|
toFullHtml() {
|
||||||
let html = `<div class="op-title">${this.name}</div>
|
let html = `<div class="op-title">${Utils.escapeHtml(this.name)}</div>
|
||||||
<div class="ingredients">`;
|
<div class="ingredients">`;
|
||||||
|
|
||||||
for (let i = 0; i < this.ingList.length; i++) {
|
for (let i = 0; i < this.ingList.length; i++) {
|
||||||
|
@ -151,15 +152,16 @@ class HTMLOperation {
|
||||||
*/
|
*/
|
||||||
function titleFromWikiLink(url) {
|
function titleFromWikiLink(url) {
|
||||||
const splitURL = url.split("/");
|
const splitURL = url.split("/");
|
||||||
if (splitURL.indexOf("wikipedia.org") < 0 && splitURL.indexOf("forensicswiki.org") < 0) {
|
if (!splitURL.includes("wikipedia.org") && !splitURL.includes("forensicswiki.xyz")) {
|
||||||
// Not a wiki link, return full URL
|
// Not a wiki link, return full URL
|
||||||
return `<a href='${url}' target='_blank'>More Information<i class='material-icons inline-icon'>open_in_new</i></a>`;
|
return `<a href='${url}' target='_blank'>More Information<i class='material-icons inline-icon'>open_in_new</i></a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wikiName = splitURL.indexOf("forensicswiki.org") < 0 ? "Wikipedia" : "Forensics Wiki";
|
const wikiName = splitURL.includes("forensicswiki.xyz") ? "Forensics Wiki" : "Wikipedia";
|
||||||
|
|
||||||
const pageTitle = decodeURIComponent(splitURL[splitURL.length - 1])
|
const pageTitle = decodeURIComponent(splitURL[splitURL.length - 1])
|
||||||
.replace(/_/g, " ");
|
.replace(/_/g, " ")
|
||||||
|
.replace(/index\.php\?title=/g, "");
|
||||||
return `<a href='${url}' target='_blank'>${pageTitle}<i class='material-icons inline-icon'>open_in_new</i></a> on ${wikiName}`;
|
return `<a href='${url}' target='_blank'>${pageTitle}<i class='material-icons inline-icon'>open_in_new</i></a> on ${wikiName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Must be text/javascript rather than application/javascript otherwise IE won't recognise it...
|
// Must be text/javascript rather than application/javascript otherwise IE won't recognise it...
|
||||||
if (navigator.userAgent && navigator.userAgent.match(/Trident/)) {
|
if (navigator.userAgent && navigator.userAgent.match(/Trident/)) {
|
||||||
document.write("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
document.getElementById("notice").innerHTML += "Internet Explorer is not supported, please use Firefox or Chrome instead";
|
||||||
alert("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
alert("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -102,7 +102,7 @@ class ControlsWaiter {
|
||||||
const saveLinkEl = document.getElementById("save-link");
|
const saveLinkEl = document.getElementById("save-link");
|
||||||
const saveLink = this.generateStateUrl(includeRecipe, includeInput, recipeConfig);
|
const saveLink = this.generateStateUrl(includeRecipe, includeInput, recipeConfig);
|
||||||
|
|
||||||
saveLinkEl.innerHTML = Utils.truncate(saveLink, 120);
|
saveLinkEl.innerHTML = Utils.escapeHtml(Utils.truncate(saveLink, 120));
|
||||||
saveLinkEl.setAttribute("href", saveLink);
|
saveLinkEl.setAttribute("href", saveLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ class ControlsWaiter {
|
||||||
|
|
||||||
const params = [
|
const params = [
|
||||||
includeRecipe ? ["recipe", recipeStr] : undefined,
|
includeRecipe ? ["recipe", recipeStr] : undefined,
|
||||||
includeInput ? ["input", input] : undefined,
|
includeInput ? ["input", Utils.escapeHtml(input)] : undefined,
|
||||||
];
|
];
|
||||||
|
|
||||||
const hash = params
|
const hash = params
|
||||||
|
|
|
@ -510,10 +510,6 @@ class InputWaiter {
|
||||||
if (inputNum !== activeTab) return;
|
if (inputNum !== activeTab) return;
|
||||||
|
|
||||||
const fileLoaded = document.getElementById("input-file-loaded");
|
const fileLoaded = document.getElementById("input-file-loaded");
|
||||||
let oldProgress = fileLoaded.textContent;
|
|
||||||
if (oldProgress !== "Error") {
|
|
||||||
oldProgress = parseInt(oldProgress.replace("%", ""), 10);
|
|
||||||
}
|
|
||||||
if (progress === "error") {
|
if (progress === "error") {
|
||||||
fileLoaded.textContent = "Error";
|
fileLoaded.textContent = "Error";
|
||||||
fileLoaded.style.color = "#FF0000";
|
fileLoaded.style.color = "#FF0000";
|
||||||
|
@ -1276,7 +1272,7 @@ class InputWaiter {
|
||||||
const func = function(time) {
|
const func = function(time) {
|
||||||
if (this.mousedown) {
|
if (this.mousedown) {
|
||||||
this.changeTabRight();
|
this.changeTabRight();
|
||||||
const newTime = (time > 50) ? time = time - 10 : 50;
|
const newTime = (time > 50) ? time - 10 : 50;
|
||||||
setTimeout(func.bind(this, [newTime]), newTime);
|
setTimeout(func.bind(this, [newTime]), newTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1293,7 +1289,7 @@ class InputWaiter {
|
||||||
const func = function(time) {
|
const func = function(time) {
|
||||||
if (this.mousedown) {
|
if (this.mousedown) {
|
||||||
this.changeTabLeft();
|
this.changeTabLeft();
|
||||||
const newTime = (time > 50) ? time = time - 10 : 50;
|
const newTime = (time > 50) ? time - 10 : 50;
|
||||||
setTimeout(func.bind(this, [newTime]), newTime);
|
setTimeout(func.bind(this, [newTime]), newTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,7 +121,7 @@ class OperationsWaiter {
|
||||||
if (nameMatch || descPos >= 0) {
|
if (nameMatch || descPos >= 0) {
|
||||||
const operation = new HTMLOperation(opName, this.app.operations[opName], this.app, this.manager);
|
const operation = new HTMLOperation(opName, this.app.operations[opName], this.app, this.manager);
|
||||||
if (highlight) {
|
if (highlight) {
|
||||||
operation.highlightSearchStrings(calcMatchRanges(idxs) || [], [[descPos, inStr.length]]);
|
operation.highlightSearchStrings(calcMatchRanges(idxs), [[descPos, inStr.length]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nameMatch) {
|
if (nameMatch) {
|
||||||
|
|
|
@ -306,8 +306,6 @@ class OutputWaiter {
|
||||||
outputText.value = "";
|
outputText.value = "";
|
||||||
outputHtml.innerHTML = "";
|
outputHtml.innerHTML = "";
|
||||||
|
|
||||||
lines = 0;
|
|
||||||
length = 0;
|
|
||||||
this.toggleLoader(false);
|
this.toggleLoader(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +763,7 @@ class OutputWaiter {
|
||||||
const func = function(time) {
|
const func = function(time) {
|
||||||
if (this.mousedown) {
|
if (this.mousedown) {
|
||||||
this.changeTabRight();
|
this.changeTabRight();
|
||||||
const newTime = (time > 50) ? time = time - 10 : 50;
|
const newTime = (time > 50) ? time - 10 : 50;
|
||||||
setTimeout(func.bind(this, [newTime]), newTime);
|
setTimeout(func.bind(this, [newTime]), newTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -782,7 +780,7 @@ class OutputWaiter {
|
||||||
const func = function(time) {
|
const func = function(time) {
|
||||||
if (this.mousedown) {
|
if (this.mousedown) {
|
||||||
this.changeTabLeft();
|
this.changeTabLeft();
|
||||||
const newTime = (time > 50) ? time = time - 10 : 50;
|
const newTime = (time > 50) ? time - 10 : 50;
|
||||||
setTimeout(func.bind(this, [newTime]), newTime);
|
setTimeout(func.bind(this, [newTime]), newTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -316,7 +316,7 @@ class RecipeWaiter {
|
||||||
};
|
};
|
||||||
} else if (ingList[j].getAttribute("type") === "number") {
|
} else if (ingList[j].getAttribute("type") === "number") {
|
||||||
// number
|
// number
|
||||||
ingredients[j] = parseFloat(ingList[j].value, 10);
|
ingredients[j] = parseFloat(ingList[j].value);
|
||||||
} else {
|
} else {
|
||||||
// all others
|
// all others
|
||||||
ingredients[j] = ingList[j].value;
|
ingredients[j] = ingList[j].value;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue