cyberchef 10.23.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/devcontainer.json +1 -1
- package/.nvmrc +1 -1
- package/CHANGELOG.md +79 -0
- package/CONTRIBUTING.md +4 -1
- package/Dockerfile +2 -2
- package/Gruntfile.js +3 -17
- package/README.md +3 -3
- package/babel.config.js +4 -1
- package/package.json +31 -27
- package/src/core/ChefWorker.js +1 -1
- package/src/core/Recipe.mjs +1 -1
- package/src/core/config/Categories.json +2 -1
- package/src/core/config/OperationConfig.json +54 -3
- package/src/core/config/modules/Default.mjs +2 -0
- package/src/core/config/scripts/fixCryptoApiImports.mjs +54 -0
- package/src/core/config/scripts/fixSnackBarMarkup.mjs +28 -0
- package/src/core/lib/Extract.mjs +5 -0
- package/src/core/lib/Magic.mjs +1 -1
- package/src/core/lib/ParityBit.mjs +50 -0
- package/src/core/operations/AnalyseUUID.mjs +109 -6
- package/src/core/operations/ExtractEmailAddresses.mjs +2 -3
- package/src/core/operations/FromPunycode.mjs +1 -1
- package/src/core/operations/ParityBit.mjs +128 -0
- package/src/core/operations/RegularExpression.mjs +2 -1
- package/src/core/operations/RenderMarkdown.mjs +35 -4
- package/src/core/operations/ShowBase64Offsets.mjs +28 -28
- package/src/core/operations/ToPunycode.mjs +1 -1
- package/src/core/operations/index.mjs +2 -0
- package/src/node/NodeRecipe.mjs +8 -7
- package/src/node/api.mjs +4 -4
- package/src/node/index.mjs +5 -0
- package/src/web/HTMLOperation.mjs +8 -2
- package/src/web/html/index.html +1 -1
- package/src/web/index.js +2 -2
- package/src/web/static/sitemap.mjs +1 -1
- package/src/web/waiters/OperationsWaiter.mjs +30 -13
- package/tests/lib/wasmFetchPolyfill.mjs +31 -0
- package/tests/node/consumers/cjs-consumer.js +2 -2
- package/tests/node/consumers/esm-consumer.mjs +2 -2
- package/tests/node/tests/Categories.mjs +2 -2
- package/tests/node/tests/nodeApi.mjs +55 -58
- package/tests/node/tests/operations.mjs +2 -3
- package/tests/operations/index.mjs +6 -0
- package/tests/operations/tests/AnalyseUUID.mjs +66 -0
- package/tests/operations/tests/Base64.mjs +11 -0
- package/tests/operations/tests/ExtractEmailAddresses.mjs +38 -12
- package/tests/operations/tests/Fernet.mjs +18 -3
- package/tests/operations/tests/ParityBit.mjs +147 -0
- package/tests/operations/tests/RegularExpression.mjs +75 -0
- package/tests/operations/tests/RenderMarkdown.mjs +110 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parity Bit functions.
|
|
3
|
+
*
|
|
4
|
+
* @author j83305 [awz22@protonmail.com]
|
|
5
|
+
* @copyright Crown Copyright 2020
|
|
6
|
+
* @license Apache-2.0
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Function to take the user input and encode using the given arguments
|
|
14
|
+
* @param input string of binary
|
|
15
|
+
* @param args array
|
|
16
|
+
*/
|
|
17
|
+
export function calculateParityBit(input, args) {
|
|
18
|
+
let count1s = 0;
|
|
19
|
+
for (let i = 0; i < input.length; i++) {
|
|
20
|
+
const character = input.charAt(i);
|
|
21
|
+
if (character === "1") {
|
|
22
|
+
count1s++;
|
|
23
|
+
} else if (character !== args[3] && character !== "0" && character !== " ") {
|
|
24
|
+
throw new OperationError("unexpected character encountered: \"" + character + "\"");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let parityBit = "1";
|
|
28
|
+
const flipflop = args[0] === "Even Parity" ? 0 : 1;
|
|
29
|
+
if (count1s % 2 === flipflop) {
|
|
30
|
+
parityBit = "0";
|
|
31
|
+
}
|
|
32
|
+
if (args[1] === "End") {
|
|
33
|
+
return input + parityBit;
|
|
34
|
+
} else {
|
|
35
|
+
return parityBit + input;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* just removes the parity bit to return the original data
|
|
41
|
+
* @param input string of binary, encoded
|
|
42
|
+
* @param args array
|
|
43
|
+
*/
|
|
44
|
+
export function decodeParityBit(input, args) {
|
|
45
|
+
if (args[1] === "End") {
|
|
46
|
+
return input.slice(0, -1);
|
|
47
|
+
} else {
|
|
48
|
+
return input.slice(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @author n1474335 [n1474335@gmail.com]
|
|
3
|
+
* @author ko80240 [csk.dev@proton.me]
|
|
3
4
|
* @copyright Crown Copyright 2023
|
|
4
5
|
* @license Apache-2.0
|
|
5
6
|
*/
|
|
@@ -8,6 +9,7 @@ import * as uuid from "uuid";
|
|
|
8
9
|
|
|
9
10
|
import Operation from "../Operation.mjs";
|
|
10
11
|
import OperationError from "../errors/OperationError.mjs";
|
|
12
|
+
import { toHex } from "../lib/Hex.mjs";
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Analyse UUID operation
|
|
@@ -22,27 +24,128 @@ class AnalyseUUID extends Operation {
|
|
|
22
24
|
|
|
23
25
|
this.name = "Analyse UUID";
|
|
24
26
|
this.module = "Crypto";
|
|
25
|
-
this.description = "
|
|
27
|
+
this.description = "Operation for extracting metadata and detecting the version of a given UUID.";
|
|
26
28
|
this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier";
|
|
27
29
|
this.inputType = "string";
|
|
28
30
|
this.outputType = "string";
|
|
29
|
-
this.args = [
|
|
31
|
+
this.args = [
|
|
32
|
+
{
|
|
33
|
+
name: "Include Metadata",
|
|
34
|
+
type: "boolean",
|
|
35
|
+
value: true
|
|
36
|
+
}
|
|
37
|
+
];
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
/**
|
|
33
|
-
* @param {string} input
|
|
41
|
+
* @param {string} input - Expects a valid UUID string
|
|
34
42
|
* @param {Object[]} args
|
|
35
43
|
* @returns {string}
|
|
36
44
|
*/
|
|
37
45
|
run(input, args) {
|
|
46
|
+
input = input.trim();
|
|
47
|
+
|
|
48
|
+
let uuidVersion, uuidBytes;
|
|
38
49
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
uuidVersion = uuid.version(input); // Re-using the uuid library to extract version
|
|
51
|
+
uuidBytes = uuid.parse(input); // Re-using the uuid library to parse bytes
|
|
41
52
|
} catch (error) {
|
|
42
53
|
throw new OperationError("Invalid UUID");
|
|
43
54
|
}
|
|
44
|
-
}
|
|
45
55
|
|
|
56
|
+
const [includeMetadata] = args;
|
|
57
|
+
const dv = new DataView(uuidBytes.buffer, uuidBytes.byteOffset, uuidBytes.byteLength); // Dataview helps handle the multi-byte ints
|
|
58
|
+
const uuidInteger = (dv.getBigUint64(0) << 64n) | dv.getBigUint64(8);
|
|
59
|
+
|
|
60
|
+
const sections = [`Version:\n${uuidVersion}`];
|
|
61
|
+
|
|
62
|
+
if (includeMetadata) {
|
|
63
|
+
const parser = UUID_PARSERS[uuidVersion];
|
|
64
|
+
const decoded = parser?.(uuidBytes, dv);
|
|
65
|
+
sections.push(formatDecoded(decoded));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
sections.push(`UUID Integer:\n${uuidInteger}`);
|
|
69
|
+
|
|
70
|
+
return sections.filter(Boolean).join("\n\n");
|
|
71
|
+
}
|
|
46
72
|
}
|
|
47
73
|
|
|
48
74
|
export default AnalyseUUID;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Metadata can be extracted for versions 1, 6, and 7.
|
|
78
|
+
* Enum-like frozen mapping of UUID version to parser function.
|
|
79
|
+
*/
|
|
80
|
+
const UUID_PARSERS = Object.freeze({
|
|
81
|
+
1: parsev1v6,
|
|
82
|
+
6: parsev1v6,
|
|
83
|
+
7: parsev7,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Versions 1 and 6. Note 6 is a re-order of 1.
|
|
88
|
+
* Version 1 == layout: timeLow(32) | timeMid(16) | timeHi(12)
|
|
89
|
+
* Version 6 == layout: timeHi(32) | timeMid(16) | timeLow(12)
|
|
90
|
+
*/
|
|
91
|
+
function parsev1v6(uuidBytes, dv) {
|
|
92
|
+
const isV1 = (uuidBytes[6] >> 4) === 1;
|
|
93
|
+
|
|
94
|
+
const timeStamp =
|
|
95
|
+
isV1 ? (
|
|
96
|
+
(BigInt(dv.getUint16(6) & 0x0fff) << 48n) | // mask off version bits
|
|
97
|
+
(BigInt(dv.getUint16(4)) << 32n) |
|
|
98
|
+
BigInt(dv.getUint32(0))
|
|
99
|
+
) : (
|
|
100
|
+
(BigInt(dv.getUint32(0)) << 28n) |
|
|
101
|
+
(BigInt(dv.getUint16(4)) << 12n) |
|
|
102
|
+
(BigInt(dv.getUint16(6) & 0x0fff))
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Convert to Unix time
|
|
106
|
+
const milliseconds =
|
|
107
|
+
Number(
|
|
108
|
+
(timeStamp - 122192928000000000n) / 10000n
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
timestamp: milliseconds,
|
|
113
|
+
isoTimestamp: new Date(milliseconds).toISOString(),
|
|
114
|
+
clock: ((uuidBytes[8] & 0x3f) << 8) | uuidBytes[9],
|
|
115
|
+
node: toHex(uuidBytes.slice(10), ":").toUpperCase()
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Version 7 */
|
|
120
|
+
function parsev7(uuidBytes, dv) {
|
|
121
|
+
const milliseconds = Number((BigInt(dv.getUint32(0)) << 16n) | BigInt(dv.getUint16(4)));
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
timestamp: milliseconds,
|
|
125
|
+
isoTimestamp: new Date(milliseconds).toISOString(),
|
|
126
|
+
randA: ((uuidBytes[6] & 0x0f) << 8) | uuidBytes[7],
|
|
127
|
+
randB: toHex(uuidBytes.slice(8), "").toUpperCase()
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Formats metadata
|
|
133
|
+
*
|
|
134
|
+
* @param {Object|undefined} decoded
|
|
135
|
+
* @returns {string}
|
|
136
|
+
*/
|
|
137
|
+
function formatDecoded(decoded) {
|
|
138
|
+
if (!decoded) return "No metadata available. Only versions 1, 6, 7 are supported.";
|
|
139
|
+
|
|
140
|
+
return Object.entries({
|
|
141
|
+
"Timestamp": decoded.timestamp,
|
|
142
|
+
"Timestamp (ISO)": decoded.isoTimestamp,
|
|
143
|
+
"Node": decoded.node,
|
|
144
|
+
"Clock": decoded.clock,
|
|
145
|
+
"Rand A": decoded.randA,
|
|
146
|
+
"Rand B": decoded.randB
|
|
147
|
+
})
|
|
148
|
+
.filter(([, value]) => value !== undefined)
|
|
149
|
+
.map(([label, value]) => `${label}:\n${value}`)
|
|
150
|
+
.join("\n\n");
|
|
151
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
|
-
import { search } from "../lib/Extract.mjs";
|
|
8
|
+
import { EMAIL_REGEX, search } from "../lib/Extract.mjs";
|
|
9
9
|
import { caseInsensitiveSort } from "../lib/Sort.mjs";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -50,8 +50,7 @@ class ExtractEmailAddresses extends Operation {
|
|
|
50
50
|
*/
|
|
51
51
|
run(input, args) {
|
|
52
52
|
const [displayTotal, sort, unique] = args,
|
|
53
|
-
|
|
54
|
-
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}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\])/ig;
|
|
53
|
+
regex = EMAIL_REGEX;
|
|
55
54
|
|
|
56
55
|
const results = search(
|
|
57
56
|
input,
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author j83305 [awz22@protonmail.com]
|
|
3
|
+
* @copyright Crown Copyright 2020
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import { calculateParityBit, decodeParityBit } from "../lib/ParityBit.mjs";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parity Bit operation
|
|
12
|
+
*/
|
|
13
|
+
class ParityBit extends Operation {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ParityBit constructor
|
|
17
|
+
*/
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
|
|
21
|
+
this.name = "Parity Bit";
|
|
22
|
+
this.module = "Default";
|
|
23
|
+
this.description = "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurence of the delimiter character";
|
|
24
|
+
this.infoURL = "https://wikipedia.org/wiki/Parity_bit";
|
|
25
|
+
this.inputType = "string";
|
|
26
|
+
this.outputType = "string";
|
|
27
|
+
this.args = [
|
|
28
|
+
{
|
|
29
|
+
name: "Mode",
|
|
30
|
+
type: "option",
|
|
31
|
+
value: [
|
|
32
|
+
"Even Parity",
|
|
33
|
+
"Odd Parity"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "Postion",
|
|
38
|
+
type: "option",
|
|
39
|
+
value: [
|
|
40
|
+
"Start",
|
|
41
|
+
"End"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "Encode or Decode",
|
|
46
|
+
type: "option",
|
|
47
|
+
value: [
|
|
48
|
+
"Encode",
|
|
49
|
+
"Decode"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "Delimiter",
|
|
54
|
+
type: "shortString",
|
|
55
|
+
value: ""
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} input
|
|
62
|
+
* @param {Object[]} args
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
65
|
+
run(input, args) {
|
|
66
|
+
if (input.length === 0) {
|
|
67
|
+
return input;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* determines weather to use the encode or decode method based off args[2]
|
|
71
|
+
* @param input input to be encoded or decoded
|
|
72
|
+
* @param args array
|
|
73
|
+
*/
|
|
74
|
+
const method = (input, args) => args[2] === "Encode" ? calculateParityBit(input, args) : decodeParityBit(input, args);
|
|
75
|
+
if (args[3].length > 0) {
|
|
76
|
+
const byteStrings = input.split(args[3]);
|
|
77
|
+
for (let byteStringsArrayIndex = 0; byteStringsArrayIndex < byteStrings.length; byteStringsArrayIndex++) {
|
|
78
|
+
byteStrings[byteStringsArrayIndex] = method(byteStrings[byteStringsArrayIndex], args);
|
|
79
|
+
}
|
|
80
|
+
return byteStrings.join(args[3]);
|
|
81
|
+
}
|
|
82
|
+
return method(input, args);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Highlight Parity Bit
|
|
87
|
+
*
|
|
88
|
+
* @param {Object[]} pos
|
|
89
|
+
* @param {number} pos[].start
|
|
90
|
+
* @param {number} pos[].end
|
|
91
|
+
* @param {Object[]} args
|
|
92
|
+
* @returns {Object[]} pos
|
|
93
|
+
*/
|
|
94
|
+
highlight(pos, args) {
|
|
95
|
+
if (args[3].length === 0) {
|
|
96
|
+
if (args[1] === "Prepend") {
|
|
97
|
+
pos[0].start += 1;
|
|
98
|
+
pos[0].end += 1;
|
|
99
|
+
}
|
|
100
|
+
return pos;
|
|
101
|
+
}
|
|
102
|
+
// need to be able to read input to do the highlighting when there is a delimiter
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Highlight Parity Bit in reverse
|
|
107
|
+
*
|
|
108
|
+
* @param {Object[]} pos
|
|
109
|
+
* @param {number} pos[].start
|
|
110
|
+
* @param {number} pos[].end
|
|
111
|
+
* @param {Object[]} args
|
|
112
|
+
* @returns {Object[]} pos
|
|
113
|
+
*/
|
|
114
|
+
highlightReverse(pos, args) {
|
|
115
|
+
if (args[3].length === 0) {
|
|
116
|
+
if (args[1] === "Prepend") {
|
|
117
|
+
if (pos[0].start > 0) {
|
|
118
|
+
pos[0].start -= 1;
|
|
119
|
+
}
|
|
120
|
+
pos[0].end -= 1;
|
|
121
|
+
}
|
|
122
|
+
return pos;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default ParityBit;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import XRegExp from "xregexp";
|
|
8
8
|
import Operation from "../Operation.mjs";
|
|
9
9
|
import Utils from "../Utils.mjs";
|
|
10
|
+
import { EMAIL_REGEX } from "../lib/Extract.mjs";
|
|
10
11
|
import OperationError from "../errors/OperationError.mjs";
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -45,7 +46,7 @@ class RegularExpression extends Operation {
|
|
|
45
46
|
},
|
|
46
47
|
{
|
|
47
48
|
name: "Email address",
|
|
48
|
-
value:
|
|
49
|
+
value: EMAIL_REGEX.source // We use a different regex library, so just take the source regex string here
|
|
49
50
|
},
|
|
50
51
|
{
|
|
51
52
|
name: "URL",
|
|
@@ -35,6 +35,11 @@ class RenderMarkdown extends Operation {
|
|
|
35
35
|
name: "Enable syntax highlighting",
|
|
36
36
|
type: "boolean",
|
|
37
37
|
value: true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "Open links in new tab.",
|
|
41
|
+
type: "boolean",
|
|
42
|
+
value: false
|
|
38
43
|
}
|
|
39
44
|
];
|
|
40
45
|
}
|
|
@@ -45,7 +50,7 @@ class RenderMarkdown extends Operation {
|
|
|
45
50
|
* @returns {html}
|
|
46
51
|
*/
|
|
47
52
|
run(input, args) {
|
|
48
|
-
const [convertLinks, enableHighlighting] = args,
|
|
53
|
+
const [convertLinks, enableHighlighting, openLinksBlank] = args,
|
|
49
54
|
md = new MarkdownIt({
|
|
50
55
|
linkify: convertLinks,
|
|
51
56
|
html: false, // Explicitly disable HTML rendering
|
|
@@ -58,12 +63,38 @@ class RenderMarkdown extends Operation {
|
|
|
58
63
|
|
|
59
64
|
return "";
|
|
60
65
|
}
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
});
|
|
67
|
+
if (openLinksBlank) {
|
|
68
|
+
this.makeLinksOpenInNewTab(md);
|
|
69
|
+
}
|
|
70
|
+
const rendered = md.render(input);
|
|
64
71
|
return `<div style="font-family: var(--primary-font-family)">${rendered}</div>`;
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Adds target="_blank" to links.
|
|
76
|
+
* @param {MarkdownIt} md
|
|
77
|
+
*/
|
|
78
|
+
makeLinksOpenInNewTab(md) {
|
|
79
|
+
// Adapted from: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
|
|
80
|
+
// Remember old renderer, if overridden, or proxy to default renderer
|
|
81
|
+
const defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
|
|
82
|
+
return self.renderToken(tokens, idx, options);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// eslint-disable-next-line camelcase
|
|
86
|
+
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
|
|
87
|
+
const token = tokens[idx];
|
|
88
|
+
if (token.attrIndex("target") >= 0) {
|
|
89
|
+
// Target attribute already set, do not replace.
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
token.attrPush(["target", "_blank"]); // add new attribute
|
|
93
|
+
|
|
94
|
+
// pass token to default renderer.
|
|
95
|
+
return defaultRender(tokens, idx, options, env, self);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
67
98
|
}
|
|
68
99
|
|
|
69
100
|
export default RenderMarkdown;
|
|
@@ -77,84 +77,84 @@ class ShowBase64Offsets extends Operation {
|
|
|
77
77
|
staticSection = offset0.slice(0, -3);
|
|
78
78
|
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
79
79
|
Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
|
|
80
|
-
staticSection + "</span>" +
|
|
81
|
-
"<span class='hl5'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
|
82
|
-
"<span class='hl3'>" + offset0.substr(offset0.length - 2) + "</span>";
|
|
80
|
+
Utils.escapeHtml(staticSection) + "</span>" +
|
|
81
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset0.substr(offset0.length - 3, 1)) + "</span>" +
|
|
82
|
+
"<span class='hl3'>" + Utils.escapeHtml(offset0.substr(offset0.length - 2)) + "</span>";
|
|
83
83
|
} else if (len0 % 4 === 3) {
|
|
84
84
|
staticSection = offset0.slice(0, -2);
|
|
85
85
|
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
86
86
|
Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
|
|
87
|
-
staticSection + "</span>" +
|
|
88
|
-
"<span class='hl5'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
|
89
|
-
"<span class='hl3'>" + offset0.substr(offset0.length - 1) + "</span>";
|
|
87
|
+
Utils.escapeHtml(staticSection) + "</span>" +
|
|
88
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset0.substr(offset0.length - 2, 1)) + "</span>" +
|
|
89
|
+
"<span class='hl3'>" + Utils.escapeHtml(offset0.substr(offset0.length - 1)) + "</span>";
|
|
90
90
|
} else {
|
|
91
91
|
staticSection = offset0;
|
|
92
92
|
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
93
93
|
Utils.escapeHtml(fromBase64(staticSection, alphabet)) + "'>" +
|
|
94
|
-
staticSection + "</span>";
|
|
94
|
+
Utils.escapeHtml(staticSection) + "</span>";
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
if (!showVariable) {
|
|
98
|
-
offset0 = staticSection;
|
|
98
|
+
offset0 = Utils.escapeHtml(staticSection);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
// Highlight offset 1
|
|
103
|
-
padding = "<span class='hl3'>" + offset1.substr(0, 1) + "</span>" +
|
|
104
|
-
"<span class='hl5'>" + offset1.substr(1, 1) + "</span>";
|
|
103
|
+
padding = "<span class='hl3'>" + Utils.escapeHtml(offset1.substr(0, 1)) + "</span>" +
|
|
104
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset1.substr(1, 1)) + "</span>";
|
|
105
105
|
offset1 = offset1.substr(2);
|
|
106
106
|
if (len1 % 4 === 2) {
|
|
107
107
|
staticSection = offset1.slice(0, -3);
|
|
108
108
|
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
109
109
|
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
|
|
110
|
-
staticSection + "</span>" +
|
|
111
|
-
"<span class='hl5'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
|
112
|
-
"<span class='hl3'>" + offset1.substr(offset1.length - 2) + "</span>";
|
|
110
|
+
Utils.escapeHtml(staticSection) + "</span>" +
|
|
111
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset1.substr(offset1.length - 3, 1)) + "</span>" +
|
|
112
|
+
"<span class='hl3'>" + Utils.escapeHtml(offset1.substr(offset1.length - 2)) + "</span>";
|
|
113
113
|
} else if (len1 % 4 === 3) {
|
|
114
114
|
staticSection = offset1.slice(0, -2);
|
|
115
115
|
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
116
116
|
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
|
|
117
|
-
staticSection + "</span>" +
|
|
118
|
-
"<span class='hl5'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
|
119
|
-
"<span class='hl3'>" + offset1.substr(offset1.length - 1) + "</span>";
|
|
117
|
+
Utils.escapeHtml(staticSection) + "</span>" +
|
|
118
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset1.substr(offset1.length - 2, 1)) + "</span>" +
|
|
119
|
+
"<span class='hl3'>" + Utils.escapeHtml(offset1.substr(offset1.length - 1)) + "</span>";
|
|
120
120
|
} else {
|
|
121
121
|
staticSection = offset1;
|
|
122
122
|
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
123
123
|
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1)) + "'>" +
|
|
124
|
-
staticSection + "</span>";
|
|
124
|
+
Utils.escapeHtml(staticSection) + "</span>";
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
if (!showVariable) {
|
|
128
|
-
offset1 = staticSection;
|
|
128
|
+
offset1 = Utils.escapeHtml(staticSection);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// Highlight offset 2
|
|
132
|
-
padding = "<span class='hl3'>" + offset2.substr(0, 2) + "</span>" +
|
|
133
|
-
"<span class='hl5'>" + offset2.substr(2, 1) + "</span>";
|
|
132
|
+
padding = "<span class='hl3'>" + Utils.escapeHtml(offset2.substr(0, 2)) + "</span>" +
|
|
133
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset2.substr(2, 1)) + "</span>";
|
|
134
134
|
offset2 = offset2.substr(3);
|
|
135
135
|
if (len2 % 4 === 2) {
|
|
136
136
|
staticSection = offset2.slice(0, -3);
|
|
137
137
|
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
138
138
|
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
|
139
|
-
staticSection + "</span>" +
|
|
140
|
-
"<span class='hl5'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
|
141
|
-
"<span class='hl3'>" + offset2.substr(offset2.length - 2) + "</span>";
|
|
139
|
+
Utils.escapeHtml(staticSection) + "</span>" +
|
|
140
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset2.substr(offset2.length - 3, 1)) + "</span>" +
|
|
141
|
+
"<span class='hl3'>" + Utils.escapeHtml(offset2.substr(offset2.length - 2)) + "</span>";
|
|
142
142
|
} else if (len2 % 4 === 3) {
|
|
143
143
|
staticSection = offset2.slice(0, -2);
|
|
144
144
|
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
145
145
|
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
|
146
|
-
staticSection + "</span>" +
|
|
147
|
-
"<span class='hl5'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
|
148
|
-
"<span class='hl3'>" + offset2.substr(offset2.length - 1) + "</span>";
|
|
146
|
+
Utils.escapeHtml(staticSection) + "</span>" +
|
|
147
|
+
"<span class='hl5'>" + Utils.escapeHtml(offset2.substr(offset2.length - 2, 1)) + "</span>" +
|
|
148
|
+
"<span class='hl3'>" + Utils.escapeHtml(offset2.substr(offset2.length - 1)) + "</span>";
|
|
149
149
|
} else {
|
|
150
150
|
staticSection = offset2;
|
|
151
151
|
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
|
152
152
|
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2)) + "'>" +
|
|
153
|
-
staticSection + "</span>";
|
|
153
|
+
Utils.escapeHtml(staticSection) + "</span>";
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
if (!showVariable) {
|
|
157
|
-
offset2 = staticSection;
|
|
157
|
+
offset2 = Utils.escapeHtml(staticSection);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
return (showVariable ? "Characters highlighted in <span class='hl5'>green</span> could change if the input is surrounded by more data." +
|
|
@@ -288,6 +288,7 @@ import PHPDeserialize from "./PHPDeserialize.mjs";
|
|
|
288
288
|
import PHPSerialize from "./PHPSerialize.mjs";
|
|
289
289
|
import PLISTViewer from "./PLISTViewer.mjs";
|
|
290
290
|
import PadLines from "./PadLines.mjs";
|
|
291
|
+
import ParityBit from "./ParityBit.mjs";
|
|
291
292
|
import ParseASN1HexString from "./ParseASN1HexString.mjs";
|
|
292
293
|
import ParseCSR from "./ParseCSR.mjs";
|
|
293
294
|
import ParseColourCode from "./ParseColourCode.mjs";
|
|
@@ -765,6 +766,7 @@ export {
|
|
|
765
766
|
PHPSerialize,
|
|
766
767
|
PLISTViewer,
|
|
767
768
|
PadLines,
|
|
769
|
+
ParityBit,
|
|
768
770
|
ParseASN1HexString,
|
|
769
771
|
ParseCSR,
|
|
770
772
|
ParseColourCode,
|
package/src/node/NodeRecipe.mjs
CHANGED
|
@@ -88,16 +88,17 @@ class NodeRecipe {
|
|
|
88
88
|
* @param {NodeDish} dish
|
|
89
89
|
* @returns {NodeDish}
|
|
90
90
|
*/
|
|
91
|
-
execute(dish) {
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
async execute(dish) {
|
|
92
|
+
let prev = dish;
|
|
93
|
+
for (const curr of this.opList) {
|
|
94
94
|
if (Object.prototype.hasOwnProperty.call(curr, "op") &&
|
|
95
95
|
Object.prototype.hasOwnProperty.call(curr, "args")) {
|
|
96
|
-
|
|
96
|
+
prev = await curr.op(prev, curr.args);
|
|
97
|
+
} else {
|
|
98
|
+
prev = await curr(prev);
|
|
97
99
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}, dish);
|
|
100
|
+
}
|
|
101
|
+
return prev;
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
package/src/node/api.mjs
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import NodeDish from "./NodeDish.mjs";
|
|
12
12
|
import NodeRecipe from "./NodeRecipe.mjs";
|
|
13
|
-
import OperationConfig from "../core/config/OperationConfig.json"
|
|
13
|
+
import OperationConfig from "../core/config/OperationConfig.json" with { type: "json" };
|
|
14
14
|
import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs";
|
|
15
15
|
import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs";
|
|
16
16
|
|
|
@@ -324,10 +324,10 @@ export function help(input) {
|
|
|
324
324
|
* @returns {NodeDish} of the result
|
|
325
325
|
* @throws {TypeError} if invalid recipe given.
|
|
326
326
|
*/
|
|
327
|
-
export function bake(input, recipeConfig) {
|
|
328
|
-
const recipe =
|
|
327
|
+
export async function bake(input, recipeConfig) {
|
|
328
|
+
const recipe = new NodeRecipe(recipeConfig);
|
|
329
329
|
const dish = ensureIsDish(input);
|
|
330
|
-
return recipe.execute(dish);
|
|
330
|
+
return await recipe.execute(dish);
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
|
package/src/node/index.mjs
CHANGED
|
@@ -289,6 +289,7 @@ import {
|
|
|
289
289
|
PHPSerialize as core_PHPSerialize,
|
|
290
290
|
PLISTViewer as core_PLISTViewer,
|
|
291
291
|
PadLines as core_PadLines,
|
|
292
|
+
ParityBit as core_ParityBit,
|
|
292
293
|
ParseASN1HexString as core_ParseASN1HexString,
|
|
293
294
|
ParseCSR as core_ParseCSR,
|
|
294
295
|
ParseColourCode as core_ParseColourCode,
|
|
@@ -766,6 +767,7 @@ function generateChef() {
|
|
|
766
767
|
"PHPSerialize": _wrap(core_PHPSerialize),
|
|
767
768
|
"PLISTViewer": _wrap(core_PLISTViewer),
|
|
768
769
|
"padLines": _wrap(core_PadLines),
|
|
770
|
+
"parityBit": _wrap(core_ParityBit),
|
|
769
771
|
"parseASN1HexString": _wrap(core_ParseASN1HexString),
|
|
770
772
|
"parseCSR": _wrap(core_ParseCSR),
|
|
771
773
|
"parseColourCode": _wrap(core_ParseColourCode),
|
|
@@ -1260,6 +1262,7 @@ const PHPDeserialize = chef.PHPDeserialize;
|
|
|
1260
1262
|
const PHPSerialize = chef.PHPSerialize;
|
|
1261
1263
|
const PLISTViewer = chef.PLISTViewer;
|
|
1262
1264
|
const padLines = chef.padLines;
|
|
1265
|
+
const parityBit = chef.parityBit;
|
|
1263
1266
|
const parseASN1HexString = chef.parseASN1HexString;
|
|
1264
1267
|
const parseCSR = chef.parseCSR;
|
|
1265
1268
|
const parseColourCode = chef.parseColourCode;
|
|
@@ -1739,6 +1742,7 @@ const operations = [
|
|
|
1739
1742
|
PHPSerialize,
|
|
1740
1743
|
PLISTViewer,
|
|
1741
1744
|
padLines,
|
|
1745
|
+
parityBit,
|
|
1742
1746
|
parseASN1HexString,
|
|
1743
1747
|
parseCSR,
|
|
1744
1748
|
parseColourCode,
|
|
@@ -2222,6 +2226,7 @@ export {
|
|
|
2222
2226
|
PHPSerialize,
|
|
2223
2227
|
PLISTViewer,
|
|
2224
2228
|
padLines,
|
|
2229
|
+
parityBit,
|
|
2225
2230
|
parseASN1HexString,
|
|
2226
2231
|
parseCSR,
|
|
2227
2232
|
parseColourCode,
|