cyberchef 9.39.4 → 9.40.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/package.json +1 -1
- package/src/core/config/Categories.json +1 -0
- package/src/core/config/OperationConfig.json +41 -1
- package/src/core/config/modules/Default.mjs +2 -0
- package/src/core/lib/Base85.mjs +5 -4
- package/src/core/operations/FromBase45.mjs +14 -2
- package/src/core/operations/FromBase85.mjs +46 -4
- package/src/core/operations/PLISTViewer.mjs +133 -0
- package/src/core/operations/Subsection.mjs +1 -1
- package/src/core/operations/index.mjs +2 -0
- package/src/node/index.mjs +5 -0
- package/tests/lib/TestRegister.mjs +18 -1
- package/tests/operations/index.mjs +1 -0
- package/tests/operations/tests/Base85.mjs +48 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyberchef",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.40.0",
|
|
4
4
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
|
5
5
|
"author": "n1474335 <n1474335@gmail.com>",
|
|
6
6
|
"homepage": "https://gchq.github.io/CyberChef",
|
|
@@ -5652,6 +5652,11 @@
|
|
|
5652
5652
|
"name": "Alphabet",
|
|
5653
5653
|
"type": "string",
|
|
5654
5654
|
"value": "0-9A-Z $%*+\\-./:"
|
|
5655
|
+
},
|
|
5656
|
+
{
|
|
5657
|
+
"name": "Remove non-alphabet chars",
|
|
5658
|
+
"type": "boolean",
|
|
5659
|
+
"value": true
|
|
5655
5660
|
}
|
|
5656
5661
|
]
|
|
5657
5662
|
},
|
|
@@ -5995,6 +6000,31 @@
|
|
|
5995
6000
|
"value": "0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~"
|
|
5996
6001
|
}
|
|
5997
6002
|
]
|
|
6003
|
+
},
|
|
6004
|
+
{
|
|
6005
|
+
"name": "Remove non-alphabet chars",
|
|
6006
|
+
"type": "boolean",
|
|
6007
|
+
"value": true
|
|
6008
|
+
}
|
|
6009
|
+
],
|
|
6010
|
+
"checks": [
|
|
6011
|
+
{
|
|
6012
|
+
"pattern": "^\\s*(?:<~)?[\\s!-uz]*[!-uz]{15}[\\s!-uz]*(?:~>)?\\s*$",
|
|
6013
|
+
"args": [
|
|
6014
|
+
"!-u"
|
|
6015
|
+
]
|
|
6016
|
+
},
|
|
6017
|
+
{
|
|
6018
|
+
"pattern": "^[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*[0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]{15}[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*$",
|
|
6019
|
+
"args": [
|
|
6020
|
+
"0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#"
|
|
6021
|
+
]
|
|
6022
|
+
},
|
|
6023
|
+
{
|
|
6024
|
+
"pattern": "^[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*[0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]{15}[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*$",
|
|
6025
|
+
"args": [
|
|
6026
|
+
"0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~"
|
|
6027
|
+
]
|
|
5998
6028
|
}
|
|
5999
6029
|
]
|
|
6000
6030
|
},
|
|
@@ -8740,6 +8770,16 @@
|
|
|
8740
8770
|
}
|
|
8741
8771
|
]
|
|
8742
8772
|
},
|
|
8773
|
+
"P-list Viewer": {
|
|
8774
|
+
"module": "Default",
|
|
8775
|
+
"description": "In the macOS, iOS, NeXTSTEP, and GNUstep programming frameworks, property list files are files that store serialized objects. Property list files use the filename extension .plist, and thus are often referred to as p-list files.<br><br>This operation displays plist files in a human readable format.",
|
|
8776
|
+
"infoURL": "https://wikipedia.org/wiki/Property_list",
|
|
8777
|
+
"inputType": "string",
|
|
8778
|
+
"outputType": "string",
|
|
8779
|
+
"flowControl": false,
|
|
8780
|
+
"manualBake": false,
|
|
8781
|
+
"args": []
|
|
8782
|
+
},
|
|
8743
8783
|
"Pad lines": {
|
|
8744
8784
|
"module": "Default",
|
|
8745
8785
|
"description": "Add the specified number of the specified character to the beginning or end of each line",
|
|
@@ -12917,7 +12957,7 @@
|
|
|
12917
12957
|
},
|
|
12918
12958
|
"Subsection": {
|
|
12919
12959
|
"module": "Default",
|
|
12920
|
-
"description": "Select a part of the input data using a regular expression (regex), and run all subsequent operations on each match separately.<br><br>You can use up to one capture group, where the recipe will only be run on the data in the capture group. If there's more than one capture group, only the first one will be operated on.",
|
|
12960
|
+
"description": "Select a part of the input data using a regular expression (regex), and run all subsequent operations on each match separately.<br><br>You can use up to one capture group, where the recipe will only be run on the data in the capture group. If there's more than one capture group, only the first one will be operated on.<br><br>Use the Merge operation to reset the effects of subsection.",
|
|
12921
12961
|
"infoURL": "",
|
|
12922
12962
|
"inputType": "string",
|
|
12923
12963
|
"outputType": "string",
|
|
@@ -92,6 +92,7 @@ import OR from "../../operations/OR.mjs";
|
|
|
92
92
|
import OffsetChecker from "../../operations/OffsetChecker.mjs";
|
|
93
93
|
import PEMToHex from "../../operations/PEMToHex.mjs";
|
|
94
94
|
import PHPDeserialize from "../../operations/PHPDeserialize.mjs";
|
|
95
|
+
import PLISTViewer from "../../operations/PLISTViewer.mjs";
|
|
95
96
|
import PadLines from "../../operations/PadLines.mjs";
|
|
96
97
|
import ParseColourCode from "../../operations/ParseColourCode.mjs";
|
|
97
98
|
import ParseDateTime from "../../operations/ParseDateTime.mjs";
|
|
@@ -261,6 +262,7 @@ OpModules.Default = {
|
|
|
261
262
|
"Offset checker": OffsetChecker,
|
|
262
263
|
"PEM to Hex": PEMToHex,
|
|
263
264
|
"PHP Deserialize": PHPDeserialize,
|
|
265
|
+
"P-list Viewer": PLISTViewer,
|
|
264
266
|
"Pad lines": PadLines,
|
|
265
267
|
"Parse colour code": ParseColourCode,
|
|
266
268
|
"Parse DateTime": ParseDateTime,
|
package/src/core/lib/Base85.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import Utils from "../Utils.mjs";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Base85 resources.
|
|
3
5
|
*
|
|
@@ -32,13 +34,12 @@ export const ALPHABET_OPTIONS = [
|
|
|
32
34
|
* @returns {string}
|
|
33
35
|
*/
|
|
34
36
|
export function alphabetName(alphabet) {
|
|
35
|
-
alphabet = alphabet
|
|
36
|
-
alphabet = alphabet.replace(/"/g, """);
|
|
37
|
-
alphabet = alphabet.replace(/\\/g, "\");
|
|
37
|
+
alphabet = escape(alphabet);
|
|
38
38
|
let name;
|
|
39
39
|
|
|
40
40
|
ALPHABET_OPTIONS.forEach(function(a) {
|
|
41
|
-
|
|
41
|
+
const expanded = Utils.expandAlphRange(a.value).join("");
|
|
42
|
+
if (alphabet === escape(expanded)) name = a.name;
|
|
42
43
|
});
|
|
43
44
|
|
|
44
45
|
return name;
|
|
@@ -32,7 +32,12 @@ class FromBase45 extends Operation {
|
|
|
32
32
|
name: "Alphabet",
|
|
33
33
|
type: "string",
|
|
34
34
|
value: ALPHABET
|
|
35
|
-
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "Remove non-alphabet chars",
|
|
38
|
+
type: "boolean",
|
|
39
|
+
value: true
|
|
40
|
+
},
|
|
36
41
|
];
|
|
37
42
|
|
|
38
43
|
this.highlight = highlightFromBase45;
|
|
@@ -46,10 +51,17 @@ class FromBase45 extends Operation {
|
|
|
46
51
|
*/
|
|
47
52
|
run(input, args) {
|
|
48
53
|
if (!input) return [];
|
|
49
|
-
const alphabet = Utils.expandAlphRange(args[0]);
|
|
54
|
+
const alphabet = Utils.expandAlphRange(args[0]).join("");
|
|
55
|
+
const removeNonAlphChars = args[1];
|
|
50
56
|
|
|
51
57
|
const res = [];
|
|
52
58
|
|
|
59
|
+
// Remove non-alphabet characters
|
|
60
|
+
if (removeNonAlphChars) {
|
|
61
|
+
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
|
62
|
+
input = input.replace(re, "");
|
|
63
|
+
}
|
|
64
|
+
|
|
53
65
|
for (const triple of Utils.chunked(input, 3)) {
|
|
54
66
|
triple.reverse();
|
|
55
67
|
let b = 0;
|
|
@@ -32,6 +32,40 @@ class FromBase85 extends Operation {
|
|
|
32
32
|
type: "editableOption",
|
|
33
33
|
value: ALPHABET_OPTIONS
|
|
34
34
|
},
|
|
35
|
+
{
|
|
36
|
+
name: "Remove non-alphabet chars",
|
|
37
|
+
type: "boolean",
|
|
38
|
+
value: true
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
this.checks = [
|
|
42
|
+
{
|
|
43
|
+
pattern:
|
|
44
|
+
"^\\s*(?:<~)?" + // Optional whitespace and starting marker
|
|
45
|
+
"[\\s!-uz]*" + // Any amount of base85 characters and whitespace
|
|
46
|
+
"[!-uz]{15}" + // At least 15 continoues base85 characters without whitespace
|
|
47
|
+
"[\\s!-uz]*" + // Any amount of base85 characters and whitespace
|
|
48
|
+
"(?:~>)?\\s*$", // Optional ending marker and whitespace
|
|
49
|
+
args: ["!-u"],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
pattern:
|
|
53
|
+
"^" +
|
|
54
|
+
"[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*" +
|
|
55
|
+
"[0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]{15}" + // At least 15 continoues base85 characters without whitespace
|
|
56
|
+
"[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*" +
|
|
57
|
+
"$",
|
|
58
|
+
args: ["0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#"],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern:
|
|
62
|
+
"^" +
|
|
63
|
+
"[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*" +
|
|
64
|
+
"[0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]{15}" + // At least 15 continoues base85 characters without whitespace
|
|
65
|
+
"[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*" +
|
|
66
|
+
"$",
|
|
67
|
+
args: ["0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~"],
|
|
68
|
+
},
|
|
35
69
|
];
|
|
36
70
|
}
|
|
37
71
|
|
|
@@ -43,6 +77,7 @@ class FromBase85 extends Operation {
|
|
|
43
77
|
run(input, args) {
|
|
44
78
|
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
|
45
79
|
encoding = alphabetName(alphabet),
|
|
80
|
+
removeNonAlphChars = args[1],
|
|
46
81
|
result = [];
|
|
47
82
|
|
|
48
83
|
if (alphabet.length !== 85 ||
|
|
@@ -50,11 +85,18 @@ class FromBase85 extends Operation {
|
|
|
50
85
|
throw new OperationError("Alphabet must be of length 85");
|
|
51
86
|
}
|
|
52
87
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const matches = input.match(/<~(.+?)~>/);
|
|
88
|
+
// Remove delimiters if present
|
|
89
|
+
const matches = input.match(/^<~(.+?)~>$/);
|
|
56
90
|
if (matches !== null) input = matches[1];
|
|
57
91
|
|
|
92
|
+
// Remove non-alphabet characters
|
|
93
|
+
if (removeNonAlphChars) {
|
|
94
|
+
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
|
95
|
+
input = input.replace(re, "");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (input.length === 0) return [];
|
|
99
|
+
|
|
58
100
|
let i = 0;
|
|
59
101
|
let block, blockBytes;
|
|
60
102
|
while (i < input.length) {
|
|
@@ -69,7 +111,7 @@ class FromBase85 extends Operation {
|
|
|
69
111
|
.map((chr, idx) => {
|
|
70
112
|
const digit = alphabet.indexOf(chr);
|
|
71
113
|
if (digit < 0 || digit > 84) {
|
|
72
|
-
throw `Invalid character '${chr}' at index ${idx}`;
|
|
114
|
+
throw `Invalid character '${chr}' at index ${i + idx}`;
|
|
73
115
|
}
|
|
74
116
|
return digit;
|
|
75
117
|
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author n1073645 [n1073645@gmail.com]
|
|
3
|
+
* @copyright Crown Copyright 2019
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* P-list Viewer operation
|
|
11
|
+
*/
|
|
12
|
+
class PlistViewer extends Operation {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* PlistViewer constructor
|
|
16
|
+
*/
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
|
|
20
|
+
this.name = "P-list Viewer";
|
|
21
|
+
this.module = "Default";
|
|
22
|
+
this.description = "In the macOS, iOS, NeXTSTEP, and GNUstep programming frameworks, property list files are files that store serialized objects. Property list files use the filename extension .plist, and thus are often referred to as p-list files.<br><br>This operation displays plist files in a human readable format.";
|
|
23
|
+
this.infoURL = "https://wikipedia.org/wiki/Property_list";
|
|
24
|
+
this.inputType = "string";
|
|
25
|
+
this.outputType = "string";
|
|
26
|
+
this.args = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} input
|
|
31
|
+
* @param {Object[]} args
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
run(input, args) {
|
|
35
|
+
|
|
36
|
+
// Regexes are designed to transform the xml format into a more readable string format.
|
|
37
|
+
input = input.slice(input.indexOf("<plist"))
|
|
38
|
+
.replace(/<plist.+>/g, "plist => ")
|
|
39
|
+
.replace(/<dict>/g, "{")
|
|
40
|
+
.replace(/<\/dict>/g, "}")
|
|
41
|
+
.replace(/<array>/g, "[")
|
|
42
|
+
.replace(/<\/array>/g, "]")
|
|
43
|
+
.replace(/<key>.+<\/key>/g, m => `${m.slice(5, m.indexOf(/<\/key>/g)-5)}\t=> `)
|
|
44
|
+
.replace(/<real>.+<\/real>/g, m => `${m.slice(6, m.indexOf(/<\/real>/g)-6)}\n`)
|
|
45
|
+
.replace(/<string>.+<\/string>/g, m => `"${m.slice(8, m.indexOf(/<\/string>/g)-8)}"\n`)
|
|
46
|
+
.replace(/<integer>.+<\/integer>/g, m => `${m.slice(9, m.indexOf(/<\/integer>/g)-9)}\n`)
|
|
47
|
+
.replace(/<false\/>/g, m => "false")
|
|
48
|
+
.replace(/<true\/>/g, m => "true")
|
|
49
|
+
.replace(/<\/plist>/g, "/plist")
|
|
50
|
+
.replace(/<date>.+<\/date>/g, m => `${m.slice(6, m.indexOf(/<\/integer>/g)-6)}`)
|
|
51
|
+
.replace(/<data>(\s|.)+?<\/data>/g, m => `${m.slice(6, m.indexOf(/<\/data>/g)-6)}`)
|
|
52
|
+
.replace(/[ \t\r\f\v]/g, "");
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Depending on the type of brace, it will increment the depth and amount of arrays accordingly.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} elem
|
|
58
|
+
* @param {array} vals
|
|
59
|
+
* @param {number} offset
|
|
60
|
+
*/
|
|
61
|
+
function braces(elem, vals, offset) {
|
|
62
|
+
const temp = vals.indexOf(elem);
|
|
63
|
+
if (temp !== -1) {
|
|
64
|
+
depthCount += offset;
|
|
65
|
+
if (temp === 1)
|
|
66
|
+
arrCount += offset;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let result = "";
|
|
71
|
+
let arrCount = 0;
|
|
72
|
+
let depthCount = 0;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Formats the input after the regex has replaced all of the relevant parts.
|
|
76
|
+
*
|
|
77
|
+
* @param {array} input
|
|
78
|
+
* @param {number} index
|
|
79
|
+
*/
|
|
80
|
+
function printIt(input, index) {
|
|
81
|
+
if (!(input.length))
|
|
82
|
+
return;
|
|
83
|
+
|
|
84
|
+
let temp = "";
|
|
85
|
+
const origArr = arrCount;
|
|
86
|
+
let currElem = input[0];
|
|
87
|
+
|
|
88
|
+
// If the current position points at a larger dynamic structure.
|
|
89
|
+
if (currElem.indexOf("=>") !== -1) {
|
|
90
|
+
|
|
91
|
+
// If the LHS also points at a larger structure (nested plists in a dictionary).
|
|
92
|
+
if (input[1].indexOf("=>") !== -1)
|
|
93
|
+
temp = currElem.slice(0, -2) + " => " + input[1].slice(0, -2) + " =>\n";
|
|
94
|
+
else
|
|
95
|
+
temp = currElem.slice(0, -2) + " => " + input[1] + "\n";
|
|
96
|
+
|
|
97
|
+
input = input.slice(1);
|
|
98
|
+
} else {
|
|
99
|
+
// Controls the tab depth for how many closing braces there have been.
|
|
100
|
+
|
|
101
|
+
braces(currElem, ["}", "]"], -1);
|
|
102
|
+
|
|
103
|
+
// Has to be here since the formatting breaks otherwise.
|
|
104
|
+
temp = currElem + "\n";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
currElem = input[0];
|
|
108
|
+
|
|
109
|
+
// Tab out to the correct distance.
|
|
110
|
+
result += ("\t".repeat(depthCount));
|
|
111
|
+
|
|
112
|
+
// If it is enclosed in an array show index.
|
|
113
|
+
if (arrCount > 0 && currElem !== "]")
|
|
114
|
+
result += index.toString() + " => ";
|
|
115
|
+
|
|
116
|
+
result += temp;
|
|
117
|
+
|
|
118
|
+
// Controls the tab depth for how many opening braces there have been.
|
|
119
|
+
braces(currElem, ["{", "["], 1);
|
|
120
|
+
|
|
121
|
+
// If there has been a new array then reset index.
|
|
122
|
+
if (arrCount > origArr)
|
|
123
|
+
return printIt(input.slice(1), 0);
|
|
124
|
+
return printIt(input.slice(1), ++index);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
input = input.split("\n").filter(e => e !== "");
|
|
128
|
+
printIt(input, 0);
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default PlistViewer;
|
|
@@ -22,7 +22,7 @@ class Subsection extends Operation {
|
|
|
22
22
|
this.name = "Subsection";
|
|
23
23
|
this.flowControl = true;
|
|
24
24
|
this.module = "Default";
|
|
25
|
-
this.description = "Select a part of the input data using a regular expression (regex), and run all subsequent operations on each match separately.<br><br>You can use up to one capture group, where the recipe will only be run on the data in the capture group. If there's more than one capture group, only the first one will be operated on.";
|
|
25
|
+
this.description = "Select a part of the input data using a regular expression (regex), and run all subsequent operations on each match separately.<br><br>You can use up to one capture group, where the recipe will only be run on the data in the capture group. If there's more than one capture group, only the first one will be operated on.<br><br>Use the Merge operation to reset the effects of subsection.";
|
|
26
26
|
this.infoURL = "";
|
|
27
27
|
this.inputType = "string";
|
|
28
28
|
this.outputType = "string";
|
|
@@ -220,6 +220,7 @@ import PGPEncrypt from "./PGPEncrypt.mjs";
|
|
|
220
220
|
import PGPEncryptAndSign from "./PGPEncryptAndSign.mjs";
|
|
221
221
|
import PGPVerify from "./PGPVerify.mjs";
|
|
222
222
|
import PHPDeserialize from "./PHPDeserialize.mjs";
|
|
223
|
+
import PLISTViewer from "./PLISTViewer.mjs";
|
|
223
224
|
import PadLines from "./PadLines.mjs";
|
|
224
225
|
import ParseASN1HexString from "./ParseASN1HexString.mjs";
|
|
225
226
|
import ParseColourCode from "./ParseColourCode.mjs";
|
|
@@ -594,6 +595,7 @@ export {
|
|
|
594
595
|
PGPEncryptAndSign,
|
|
595
596
|
PGPVerify,
|
|
596
597
|
PHPDeserialize,
|
|
598
|
+
PLISTViewer,
|
|
597
599
|
PadLines,
|
|
598
600
|
ParseASN1HexString,
|
|
599
601
|
ParseColourCode,
|
package/src/node/index.mjs
CHANGED
|
@@ -221,6 +221,7 @@ import {
|
|
|
221
221
|
PGPEncryptAndSign as core_PGPEncryptAndSign,
|
|
222
222
|
PGPVerify as core_PGPVerify,
|
|
223
223
|
PHPDeserialize as core_PHPDeserialize,
|
|
224
|
+
PLISTViewer as core_PLISTViewer,
|
|
224
225
|
PadLines as core_PadLines,
|
|
225
226
|
ParseASN1HexString as core_ParseASN1HexString,
|
|
226
227
|
ParseColourCode as core_ParseColourCode,
|
|
@@ -595,6 +596,7 @@ function generateChef() {
|
|
|
595
596
|
"PGPEncryptAndSign": _wrap(core_PGPEncryptAndSign),
|
|
596
597
|
"PGPVerify": _wrap(core_PGPVerify),
|
|
597
598
|
"PHPDeserialize": _wrap(core_PHPDeserialize),
|
|
599
|
+
"PLISTViewer": _wrap(core_PLISTViewer),
|
|
598
600
|
"padLines": _wrap(core_PadLines),
|
|
599
601
|
"parseASN1HexString": _wrap(core_ParseASN1HexString),
|
|
600
602
|
"parseColourCode": _wrap(core_ParseColourCode),
|
|
@@ -986,6 +988,7 @@ const PGPEncrypt = chef.PGPEncrypt;
|
|
|
986
988
|
const PGPEncryptAndSign = chef.PGPEncryptAndSign;
|
|
987
989
|
const PGPVerify = chef.PGPVerify;
|
|
988
990
|
const PHPDeserialize = chef.PHPDeserialize;
|
|
991
|
+
const PLISTViewer = chef.PLISTViewer;
|
|
989
992
|
const padLines = chef.padLines;
|
|
990
993
|
const parseASN1HexString = chef.parseASN1HexString;
|
|
991
994
|
const parseColourCode = chef.parseColourCode;
|
|
@@ -1362,6 +1365,7 @@ const operations = [
|
|
|
1362
1365
|
PGPEncryptAndSign,
|
|
1363
1366
|
PGPVerify,
|
|
1364
1367
|
PHPDeserialize,
|
|
1368
|
+
PLISTViewer,
|
|
1365
1369
|
padLines,
|
|
1366
1370
|
parseASN1HexString,
|
|
1367
1371
|
parseColourCode,
|
|
@@ -1742,6 +1746,7 @@ export {
|
|
|
1742
1746
|
PGPEncryptAndSign,
|
|
1743
1747
|
PGPVerify,
|
|
1744
1748
|
PHPDeserialize,
|
|
1749
|
+
PLISTViewer,
|
|
1745
1750
|
padLines,
|
|
1746
1751
|
parseASN1HexString,
|
|
1747
1752
|
parseColourCode,
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import Chef from "../../src/core/Chef.mjs";
|
|
13
13
|
import Utils from "../../src/core/Utils.mjs";
|
|
14
14
|
import cliProgress from "cli-progress";
|
|
15
|
+
import log from "loglevel";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Object to store and run the list of tests.
|
|
@@ -50,6 +51,9 @@ class TestRegister {
|
|
|
50
51
|
* Runs all the tests in the register.
|
|
51
52
|
*/
|
|
52
53
|
async runTests () {
|
|
54
|
+
// Turn off logging to avoid messy errors
|
|
55
|
+
log.setLevel("silent", false);
|
|
56
|
+
|
|
53
57
|
const progBar = new cliProgress.SingleBar({
|
|
54
58
|
format: formatter,
|
|
55
59
|
stopOnComplete: true
|
|
@@ -84,7 +88,17 @@ class TestRegister {
|
|
|
84
88
|
|
|
85
89
|
if (result.error) {
|
|
86
90
|
if (test.expectedError) {
|
|
87
|
-
|
|
91
|
+
if (result.error.displayStr === test.expectedOutput) {
|
|
92
|
+
ret.status = "passing";
|
|
93
|
+
} else {
|
|
94
|
+
ret.status = "failing";
|
|
95
|
+
ret.output = [
|
|
96
|
+
"Expected",
|
|
97
|
+
"\t" + test.expectedOutput.replace(/\n/g, "\n\t"),
|
|
98
|
+
"Received",
|
|
99
|
+
"\t" + result.error.displayStr.replace(/\n/g, "\n\t"),
|
|
100
|
+
].join("\n");
|
|
101
|
+
}
|
|
88
102
|
} else {
|
|
89
103
|
ret.status = "erroring";
|
|
90
104
|
ret.output = result.error.displayStr;
|
|
@@ -118,6 +132,9 @@ class TestRegister {
|
|
|
118
132
|
progBar.increment();
|
|
119
133
|
}
|
|
120
134
|
|
|
135
|
+
// Turn logging back on
|
|
136
|
+
log.setLevel("info", false);
|
|
137
|
+
|
|
121
138
|
return testResults;
|
|
122
139
|
}
|
|
123
140
|
|
|
@@ -24,6 +24,7 @@ import "./tests/Base45.mjs";
|
|
|
24
24
|
import "./tests/Base58.mjs";
|
|
25
25
|
import "./tests/Base64.mjs";
|
|
26
26
|
import "./tests/Base62.mjs";
|
|
27
|
+
import "./tests/Base85.mjs";
|
|
27
28
|
import "./tests/BitwiseOp.mjs";
|
|
28
29
|
import "./tests/ByteRepr.mjs";
|
|
29
30
|
import "./tests/CartesianProduct.mjs";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base85 tests
|
|
3
|
+
*
|
|
4
|
+
* @author john19696
|
|
5
|
+
* @copyright Crown Copyright 2019
|
|
6
|
+
* @license Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
import TestRegister from "../../lib/TestRegister.mjs";
|
|
9
|
+
|
|
10
|
+
// Example from Wikipedia
|
|
11
|
+
const wpExample = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
|
|
12
|
+
// Escape newline, quote & backslash
|
|
13
|
+
const wpOutput = "9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,O<\
|
|
14
|
+
DJ+*.@<*K0@<6L(Df-\\0Ec5e;DffZ(EZee.Bl.9pF\"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKYi(\
|
|
15
|
+
DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(\
|
|
16
|
+
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
|
17
|
+
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
|
18
|
+
|
|
19
|
+
TestRegister.addTests([
|
|
20
|
+
{
|
|
21
|
+
name: "To Base85",
|
|
22
|
+
input: wpExample,
|
|
23
|
+
expectedOutput: wpOutput,
|
|
24
|
+
recipeConfig: [
|
|
25
|
+
{ "op": "To Base85",
|
|
26
|
+
"args": ["!-u"] }
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "From Base85",
|
|
31
|
+
input: wpOutput + "\n",
|
|
32
|
+
expectedOutput: wpExample,
|
|
33
|
+
recipeConfig: [
|
|
34
|
+
{ "op": "From Base85",
|
|
35
|
+
"args": ["!-u", true] }
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "From Base85",
|
|
40
|
+
input: wpOutput + "v",
|
|
41
|
+
expectedError: true,
|
|
42
|
+
expectedOutput: "From Base85 - Invalid character 'v' at index 337",
|
|
43
|
+
recipeConfig: [
|
|
44
|
+
{ "op": "From Base85",
|
|
45
|
+
"args": ["!-u", false] }
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
]);
|