2
0
mirror of https://github.com/gchq/CyberChef synced 2025-12-05 23:53:27 +00:00

Compare commits

...

96 Commits

Author SHA1 Message Date
n1474335
04c1adc5f0 5.19.0 2017-09-05 17:59:16 +00:00
n1474335
8e8f6a0284 Merge branch 'feature-otp' 2017-09-05 17:59:02 +00:00
n1474335
68bf1d123e Added 'Generate HOTP' and 'Generate TOTP' operations 2017-09-05 17:53:54 +00:00
n1474335
2c03689195 5.18.1 2017-09-05 17:26:29 +00:00
n1474335
45f41b1140 Merge branch 'bug-number-input-change' 2017-09-05 17:21:49 +00:00
n1474335
8fa6f3f45c Fixed bug where clicking up and down arrows on numeric inputs would not trigger an auto-bake 2017-09-05 16:51:57 +00:00
n1474335
78a842deb7 5.18.0 2017-09-05 15:37:18 +00:00
n1474335
3657ff4f79 Merge branch 'feature-bitshift' 2017-09-05 15:37:10 +00:00
n1474335
d4d12c3db0 Whitespace is now removed from hex and binary even when the delimiter is set to 'None' 2017-09-05 14:30:06 +00:00
n1474335
1b628ac213 Added 'Bit shift left' and 'Bit shift right' operations 2017-09-05 14:26:09 +00:00
n1474335
5fcc259efb Merge branch 'Synchro-master' 2017-09-04 15:22:17 +00:00
Marcus Bointon
9545205f19 Optimise PNGs 2017-09-04 12:22:12 +02:00
n1474335
4f403d4450 5.17.0 2017-08-30 15:57:58 +00:00
n1474335
f2d8f930fb Merge branch 'bwhitn-vbe' 2017-08-30 15:57:18 +00:00
n1474335
4a86340d50 Tidied up 'Microsoft Script Decoder' operation 2017-08-30 15:56:51 +00:00
bwhitn
f8e9e9ba85 added sample to description 2017-08-29 12:04:15 -07:00
bwhitn
934ed1af09 Fixed spelling errors, syntax errors, and improved the test for script decoding 2017-08-29 10:46:34 -07:00
bwhitn
0fc2a219a7 Changed the name. Small logic change. Changed from split join to regex replace. 2017-08-28 17:55:54 -04:00
bwhitn
aa5939c051 Took out logging call. My bad. 2017-08-27 20:53:53 -04:00
bwhitn
9c5f06101e Fixed the replace statements 2017-08-27 18:45:42 -04:00
bwhitn
2a7c0252a0 Fixed regex issue 2017-08-27 11:49:28 -04:00
bwhitn
414726ecd4 Fixed small syntax error 2017-08-27 09:44:26 -04:00
bwhitn
fdc8a15595 Added Decode VBE 2017-08-27 09:29:26 -04:00
n1474335
d012fd3a65 5.16.3 2017-08-25 11:53:08 +00:00
n1474335
a5ed824674 Merge branch 'bug-substitute' 2017-08-25 11:50:07 +00:00
n1474335
d6705c682f Fixed bug in Substitute where commas would not encode correctly 2017-08-25 11:44:31 +00:00
n1474335
33b606d48f 5.16.2 2017-08-21 15:25:41 +00:00
n1474335
cc44be7ef9 Fixed recipe saving 2017-08-21 15:25:35 +00:00
n1474335
e0eb972a54 Operations with no arguments can now be added to the recipe without causing errors 2017-08-18 16:12:49 +00:00
n1474335
19c54a99cd Improved web app title construction 2017-08-18 16:01:55 +00:00
n1474335
9d60ec22ee Updated links in index.html 2017-08-18 15:55:04 +01:00
n1474335
cb4eeccfd3 Updated links in README 2017-08-18 15:47:38 +01:00
n1474335
62e50caa99 5.16.1 2017-08-16 14:11:55 +00:00
n1474335
0192566d19 Improved recipe config generation for complex objects. Fixes #180 2017-08-16 14:11:50 +00:00
n1474335
8a8b70f2ab 5.16.0 2017-08-16 13:01:50 +00:00
n1474335
af311001cf Merge branch 'feature-pretty-recipe-format' 2017-08-16 13:01:08 +00:00
n1474335
040229418e 5.15.0 2017-08-15 17:32:31 +00:00
n1474335
c259963542 Fixed string escape test configs 2017-08-15 17:32:21 +00:00
n1474335
ca75f7fa0b Merge branch 'artemisbot-features/string_escape_unescape' 2017-08-15 17:30:12 +00:00
n1474335
4b22a409e7 Tidied up string escape operations 2017-08-15 17:29:48 +00:00
n1474335
55806db00f Merge branch 'features/string_escape_unescape' of https://github.com/artemisbot/CyberChef into artemisbot-features/string_escape_unescape 2017-08-15 17:16:39 +00:00
n1474335
83c757ebd4 Lint 2017-08-15 17:12:09 +00:00
n1474335
a19b02aa8c Updated URL regexes to match more unescaped special characters 2017-08-15 16:44:45 +00:00
n1474335
cf1ba60a10 Added new 'pretty' recipe format to make URLs more readable 2017-08-15 16:26:42 +00:00
n1474335
2a4c9afdf2 5.14.0 2017-08-10 12:42:00 +00:00
n1474335
ab76933158 Merge branch 'feature-themes' 2017-08-10 12:41:18 +00:00
n1474335
d4d7bcab7a Added GeoCities theme 2017-08-10 12:35:30 +00:00
n1474335
146a307b59 5.13.1 2017-08-08 14:47:55 +00:00
n1474335
875946b4e8 Modified babel to target Node 6.5 2017-08-08 14:47:48 +00:00
n1474335
81f2a460ed Added apploaded event to signify when the app has completed loading 2017-08-08 13:08:06 +00:00
Matt C
6698a2ac13 Added tests + fixes for PR
- actually removed prev func
- shuffled some stuff around
2017-08-07 16:08:50 +01:00
Matt C
9161cc693d Removes need for runParseEscapedString
- Fixes examples
- Actually makes it work
2017-08-04 15:54:00 +01:00
n1474335
be689e293d Removed dev commands from PublicKey.js 2017-08-04 14:44:12 +00:00
n1474335
53c22d5e29 5.13.0 2017-08-04 14:00:24 +00:00
n1474335
5c0c80829e Merge branch 'artemisbot-features/jpath' 2017-08-04 14:00:05 +00:00
n1474335
55aedfe901 Jsonpath lib now imported from npm with workaround instead of serving locally. 2017-08-04 13:59:32 +00:00
n1474335
4b87d66131 Merge branch 'features/jpath' of https://github.com/artemisbot/CyberChef into artemisbot-features/jpath 2017-08-04 13:36:03 +00:00
n1474335
fc9497f067 Updated dependencies 2017-08-04 13:35:52 +00:00
Matt C
3186335f47 Merge Vel0z/string_escaping_unescaping
Updated to new project format
2017-08-04 11:50:45 +01:00
Matt C
31bfd8664a Added JSONPath tests & changed lib 2017-08-03 14:50:16 +01:00
n1474335
ab1c9e27dc Added more loading messages 2017-08-03 10:57:54 +00:00
n1474335
c07cc913c8 5.12.4 2017-08-01 19:27:24 +00:00
n1474335
b8fb5493c5 Merge branch 'artemisbot-bug/text-overflow' 2017-08-01 19:25:04 +00:00
n1474335
e8e5eb9c53 Fixed some edge cases for popover triggering 2017-08-01 19:23:30 +00:00
n1474335
a15034b03e Merge branch 'bug/text-overflow' of https://github.com/artemisbot/CyberChef into artemisbot-bug/text-overflow 2017-08-01 15:40:31 +00:00
n1474335
1435acdc28 5.12.3 2017-08-01 14:42:52 +00:00
n1474335
37f164f11c Merge branch 'master' of github.com:gchq/CyberChef 2017-08-01 14:42:17 +00:00
n1474335
7a2f071269 Dependencies in the node version are now kept external in the webpack build 2017-08-01 14:42:09 +00:00
Matt C
9ee0964d0e Fixed hover issue - now allows scrolling 2017-07-29 00:45:41 +01:00
Matt C
33ecbfa95b Fixed arrow issue 2017-07-28 21:47:47 +01:00
n1474335
559c13a003 5.12.2 2017-07-28 16:44:48 +01:00
n1474335
8f00345430 Merge branch 'seo-structured-data' 2017-07-28 16:44:28 +01:00
n1474335
7a56af8ffa Page title changes to reflect recipe 2017-07-27 15:33:24 +00:00
n1474335
ed2bfbd27c Added structured data to help search engines 2017-07-27 15:33:01 +00:00
Matt C
e0905255ba Forgot about package-lock.json
oops
2017-07-25 16:36:01 +01:00
Matt C
de80db73f2 Adds initial JPath functionality 2017-07-25 16:27:59 +01:00
Matt C
90ed62add2 Fixes gchq/CyberChef#137
Changes data-trigger to focus so scrolling works and sets max height.
2017-07-25 11:49:23 +01:00
n1474335
d46e279933 Added link to 'Last build' notice showing commits since last release 2017-07-24 16:38:38 +00:00
n1474335
77e074efc2 5.12.1 2017-07-24 15:27:14 +00:00
n1474335
bd000d2d2c Merge branch 'lib-update' 2017-07-24 15:26:12 +00:00
n1474335
5f1c88104d Introduced key-spacing eslint rule 2017-07-24 14:55:48 +00:00
n1474335
a61df0832f Updated dependencies and linted 2017-07-24 13:49:16 +00:00
n1474335
58361e58f8 5.12.0 2017-07-19 16:03:24 +00:00
n1474335
96b4361b31 Merge branch 'feature-bcd' 2017-07-19 15:55:36 +00:00
n1474335
c773edceb9 Added BCD operations with tests 2017-07-19 15:29:37 +00:00
n1474335
bcaef8ba54 5.11.7 2017-07-18 16:17:59 +00:00
n1474335
c7d0b0ccc5 Merge branch 'feature-xor-brute-scheme' 2017-07-18 16:17:13 +00:00
n1474335
38792a0f02 Added differential schemes to 'XOR Brute Force' operation 2017-07-18 16:09:22 +00:00
n1474335
cda557e1b9 Removed sessionStorage as it is no longer used and marginally affects performance 2017-07-18 14:28:51 +00:00
n1474335
8d09f7c7eb 5.11.6 2017-07-17 13:31:37 +00:00
n1474335
4845a56435 Fixed Diff test for new higlighting class 2017-07-17 13:31:28 +00:00
n1474335
f164dcdd70 Fixed Diff highlighting classes 2017-07-17 13:19:08 +00:00
n1474335
6c8da6b070 Added ellipsis to overflowing args 2017-07-13 15:11:21 +00:00
n1474335
09df753ca9 5.11.5 2017-07-12 14:34:50 +00:00
n1474335
72ec9df1b1 Fixed option naming conventions 2017-07-12 14:34:45 +00:00
Dale Myers
fadd7158ed Add string escape/unescape operations
These operations are useful for taking the contents of a string, and making it
suitable for use as a stand alone string. For example, in an IDE you might see
a string which is represented as: "Say \"Hello\"". The escaped double quotes
are shown to make it clear that they do not end the string, despite the fact
that they are not truly part of the string. In order to get the raw string, you
would need to copy this, then manually remove the backslashes. The new
String_.run_unescape operation does this automatically.

The String_.run_escape is the inverse. It allows you to take a string like the
one above, and paste it between two quotes without having to manually escape
it.
2017-01-23 21:39:08 +00:00
98 changed files with 7127 additions and 3274 deletions

View File

@@ -4,9 +4,11 @@
"targets": {
"chrome": 40,
"firefox": 35,
"edge": 14
"edge": 14,
"node": "6.5",
},
"modules": false
"modules": false,
"useBuiltIns": true
}]
]
}

View File

@@ -52,6 +52,9 @@
"no-trailing-spaces": "warn",
"eol-last": "error",
"func-call-spacing": "error",
"key-spacing": ["warn", {
"mode": "minimum"
}],
"indent": ["error", 4, {
"ArrayExpression": "first",
"SwitchCase": 1

View File

@@ -1,6 +1,7 @@
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const NodeExternals = require("webpack-node-externals");
const Inliner = require("web-resource-inliner");
module.exports = function (grunt) {
@@ -228,6 +229,9 @@ module.exports = function (grunt) {
stats: {
children: false,
warningsFilter: /source-map/
},
node: {
fs: "empty"
}
},
webDev: {
@@ -294,6 +298,7 @@ module.exports = function (grunt) {
tests: {
target: "node",
entry: "./test/index.js",
externals: [NodeExternals()],
output: {
filename: "index.js",
path: __dirname + "/build/test"
@@ -302,6 +307,7 @@ module.exports = function (grunt) {
node: {
target: "node",
entry: "./src/node/index.js",
externals: [NodeExternals()],
output: {
filename: "CyberChef.js",
path: __dirname + "/build/node",

View File

@@ -88,10 +88,10 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
[1]: https://gchq.github.io/CyberChef
[2]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
[3]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA
[4]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
[5]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
[6]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
[7]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
[8]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22XOR%22%2C%22args%22%3A%5B%7B%22option%22%3A%22Hex%22%2C%22string%22%3A%223a%22%7D%2Cfalse%2Cfalse%5D%7D%2C%7B%22op%22%3A%22To%20Hexdump%22%2C%22args%22%3A%5B%2216%22%2Cfalse%2Cfalse%5D%7D%5D&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
[2]: https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
[3]: https://gchq.github.io/CyberChef/#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA
[4]: https://gchq.github.io/CyberChef/#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
[5]: https://gchq.github.io/CyberChef/#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
[6]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
[8]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4

5225
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "5.11.4",
"version": "5.19.0",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -31,62 +31,65 @@
"bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^6.4.0",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.2.2",
"css-loader": "^0.27.3",
"babel-loader": "^7.1.1",
"babel-preset-env": "^1.6.0",
"css-loader": "^0.28.4",
"exports-loader": "^0.6.4",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.10.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.2",
"grunt": ">=0.4.5",
"grunt-accessibility": "~5.0.0",
"grunt-chmod": "~1.1.1",
"grunt-contrib-clean": "~1.0.0",
"grunt-contrib-clean": "~1.1.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-eslint": "^19.0.0",
"grunt-exec": "~1.0.1",
"grunt-eslint": "^20.0.0",
"grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.1.0",
"grunt-webpack": "^2.0.1",
"html-webpack-plugin": "^2.28.0",
"grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"imports-loader": "^0.7.1",
"ink-docstrap": "^1.1.4",
"jsdoc-babel": "^0.3.0",
"less": "^2.7.2",
"less-loader": "^4.0.3",
"less-loader": "^4.0.5",
"postcss-css-variables": "^0.7.0",
"postcss-import": "^10.0.0",
"postcss-loader": "^2.0.5",
"style-loader": "^0.15.0",
"style-loader": "^0.18.2",
"url-loader": "^0.5.8",
"web-resource-inliner": "^4.1.0",
"webpack": "^2.2.1"
"webpack": "^3.4.1",
"webpack-node-externals": "^1.6.0"
},
"dependencies": {
"babel-polyfill": "^6.23.0",
"bootstrap": "^3.3.7",
"bootstrap-colorpicker": "^2.5.1",
"bootstrap-switch": "^3.3.4",
"crypto-api": "^0.6.2",
"crypto-js": "^3.1.9-1",
"diff": "^3.2.0",
"diff": "^3.3.0",
"escodegen": "^1.8.1",
"esmangle": "^1.0.1",
"esprima": "^3.1.3",
"exif-parser": "^0.1.9",
"esprima": "^4.0.0",
"exif-parser": "^0.1.12",
"google-code-prettify": "^1.0.5",
"jquery": "^3.1.1",
"jsbn": "^1.1.0",
"jsrsasign": "7.1.3",
"jsonpath": "^0.2.12",
"jsrsasign": "8.0.3",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
"otp": "^0.1.3",
"sladex-blowfish": "^0.8.1",
"sortablejs": "^1.5.1",
"split.js": "^1.2.0",
"vkbeautify": "^0.99.1",
"vkbeautify": "^0.99.3",
"xmldom": "^0.1.27",
"xpath": "0.0.24",
"zlibjs": "^0.2.0"
"zlibjs": "^0.3.1"
},
"scripts": {
"build": "grunt prod",

View File

@@ -164,10 +164,10 @@ Recipe.prototype.execute = async function(dish, startFrom) {
if (op.isFlowControl()) {
// Package up the current state
let state = {
"progress" : i,
"dish" : dish,
"opList" : this.opList,
"numJumps" : numJumps
"progress": i,
"dish": dish,
"opList": this.opList,
"numJumps": numJumps
};
state = await op.run(state);

View File

@@ -293,7 +293,7 @@ const Utils = {
* Utils.escapeRegex("[example]");
*/
escapeRegex: function(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, "\\$1");
},
@@ -592,7 +592,7 @@ const Utils = {
i = 0;
if (removeNonAlphChars) {
const re = new RegExp("[^" + alphabet.replace(/[\[\]\\\-^$]/g, "\\$&") + "]", "g");
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
data = data.replace(re, "");
}
@@ -810,7 +810,7 @@ const Utils = {
"`": "&#x60;"
};
return str.replace(/[&<>"'\/`]/g, function (match) {
return str.replace(/[&<>"'/`]/g, function (match) {
return HTML_CHARS[match];
});
},
@@ -843,6 +843,139 @@ const Utils = {
},
/**
* Encodes a URI fragment (#) or query (?) using a minimal amount of percent-encoding.
*
* RFC 3986 defines legal characters for the fragment and query parts of a URL to be as follows:
*
* fragment = *( pchar / "/" / "?" )
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*
* Meaning that the list of characters that need not be percent-encoded are alphanumeric plus:
* -._~!$&'()*+,;=:@/?
*
* & and = are still escaped as they are used to serialise the key-value pairs in CyberChef
* fragments. + is also escaped so as to prevent it being decoded to a space.
*
* @param {string} str
* @returns {string}
*/
encodeURIFragment: function(str) {
const LEGAL_CHARS = {
"%2D": "-",
"%2E": ".",
"%5F": "_",
"%7E": "~",
"%21": "!",
"%24": "$",
//"%26": "&",
"%27": "'",
"%28": "(",
"%29": ")",
"%2A": "*",
//"%2B": "+",
"%2C": ",",
"%3B": ";",
//"%3D": "=",
"%3A": ":",
"%40": "@",
"%2F": "/",
"%3F": "?"
};
str = encodeURIComponent(str);
return str.replace(/%[0-9A-F]{2}/g, function (match) {
return LEGAL_CHARS[match] || match;
});
},
/**
* Generates a "pretty" recipe format from a recipeConfig object.
*
* "Pretty" CyberChef recipe formats are designed to be included in the fragment (#) or query (?)
* parts of the URL. They can also be loaded into CyberChef through the 'Load' interface. In order
* to make this format as readable as possible, various special characters are used unescaped. This
* reduces the amount of percent-encoding included in the URL which is typically difficult to read,
* as well as substantially increasing the overall length. These characteristics can be quite
* offputting for users.
*
* @param {Object[]} recipeConfig
* @param {boolean} newline - whether to add a newline after each operation
* @returns {string}
*/
generatePrettyRecipe: function(recipeConfig, newline) {
let prettyConfig = "",
name = "",
args = "",
disabled = "",
bp = "";
recipeConfig.forEach(op => {
name = op.op.replace(/ /g, "_");
args = JSON.stringify(op.args)
.slice(1, -1) // Remove [ and ] as they are implied
// We now need to switch double-quoted (") strings to single-quotes (') as these do not
// need to be percent-encoded.
.replace(/'/g, "\\'") // Escape single quotes
.replace(/\\"/g, '"') // Unescape double quotes
.replace(/(^|,|{|:)"/g, "$1'") // Replace opening " with '
.replace(/"(,|:|}|$)/g, "'$1"); // Replace closing " with '
disabled = op.disabled ? "/disabled": "";
bp = op.breakpoint ? "/breakpoint" : "";
prettyConfig += `${name}(${args}${disabled}${bp})`;
if (newline) prettyConfig += "\n";
});
return prettyConfig;
},
/**
* Converts a recipe string to the JSON representation of the recipe.
* Accepts either stringified JSON or bespoke "pretty" recipe format.
*
* @param {string} recipe
* @returns {Object[]}
*/
parseRecipeConfig: function(recipe) {
recipe = recipe.trim();
if (recipe.length === 0) return [];
if (recipe[0] === "[") return JSON.parse(recipe);
// Parse bespoke recipe format
recipe = recipe.replace(/\n/g, "");
let m,
recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/])*)(\/[^)]+)?\)/g,
recipeConfig = [],
args;
while ((m = recipeRegex.exec(recipe))) {
// Translate strings in args back to double-quotes
args = m[2]
.replace(/"/g, '\\"') // Escape double quotes
.replace(/(^|,|{|:)'/g, '$1"') // Replace opening ' with "
.replace(/([^\\])'(,|:|}|$)/g, '$1"$2') // Replace closing ' with "
.replace(/\\'/g, "'"); // Unescape single quotes
args = "[" + args + "]";
let op = {
op: m[1].replace(/_/g, " "),
args: JSON.parse(args)
};
if (m[3] && m[3].indexOf("disabled") > 0) op.disabled = true;
if (m[3] && m[3].indexOf("breakpoint") > 0) op.breakpoint = true;
recipeConfig.push(op);
}
return recipeConfig;
},
/**
* Expresses a number of milliseconds in a human readable format.
*
@@ -1102,7 +1235,8 @@ const Utils = {
"Forward slash": /\//g,
"Backslash": /\\/g,
"0x": /0x/g,
"\\x": /\\x/g
"\\x": /\\x/g,
"None": /\s+/g // Included here to remove whitespace when there shouldn't be any
},

View File

@@ -46,6 +46,8 @@ const Categories = [
"From Base58",
"To Base",
"From Base",
"To BCD",
"From BCD",
"To HTML Entity",
"From HTML Entity",
"URL Encode",
@@ -120,6 +122,8 @@ const Categories = [
"AND",
"ADD",
"SUB",
"Bit shift left",
"Bit shift right",
"Rotate left",
"Rotate right",
"ROT13",
@@ -171,7 +175,6 @@ const Categories = [
"Tail",
"Count occurrences",
"Expand alphabet range",
"Parse escaped string",
"Drop bytes",
"Take bytes",
"Pad lines",
@@ -186,6 +189,8 @@ const Categories = [
"Parse UNIX file permissions",
"Swap endianness",
"Parse colour code",
"Escape string",
"Unescape string",
]
},
{
@@ -213,6 +218,7 @@ const Categories = [
"Extract dates",
"Regular expression",
"XPath expression",
"JPath expression",
"CSS selector",
"Extract EXIF",
]
@@ -276,7 +282,9 @@ const Categories = [
"CSS Beautify",
"CSS Minify",
"XPath expression",
"JPath expression",
"CSS selector",
"Microsoft Script Decoder",
"Strip HTML tags",
"Diff",
"To Snake case",
@@ -292,6 +300,8 @@ const Categories = [
"Detect File Type",
"Scan for Embedded Files",
"Generate UUID",
"Generate TOTP",
"Generate HOTP",
"Render Image",
"Remove EXIF",
"Extract EXIF",

View File

@@ -2,6 +2,7 @@ import FlowControl from "../FlowControl.js";
import Base from "../operations/Base.js";
import Base58 from "../operations/Base58.js";
import Base64 from "../operations/Base64.js";
import BCD from "../operations/BCD.js";
import BitwiseOp from "../operations/BitwiseOp.js";
import ByteRepr from "../operations/ByteRepr.js";
import CharEnc from "../operations/CharEnc.js";
@@ -24,9 +25,11 @@ import IP from "../operations/IP.js";
import JS from "../operations/JS.js";
import MAC from "../operations/MAC.js";
import MorseCode from "../operations/MorseCode.js";
import MS from "../operations/MS.js";
import NetBIOS from "../operations/NetBIOS.js";
import Numberwang from "../operations/Numberwang.js";
import OS from "../operations/OS.js";
import OTP from "../operations/OTP.js";
import PublicKey from "../operations/PublicKey.js";
import Punycode from "../operations/Punycode.js";
import QuotedPrintable from "../operations/QuotedPrintable.js";
@@ -330,30 +333,25 @@ const OperationConfig = {
value: BitwiseOp.XOR_BRUTE_KEY_LENGTH
},
{
name: "Length of sample",
name: "Sample length",
type: "number",
value: BitwiseOp.XOR_BRUTE_SAMPLE_LENGTH
},
{
name: "Offset of sample",
name: "Sample offset",
type: "number",
value: BitwiseOp.XOR_BRUTE_SAMPLE_OFFSET
},
{
name: "Scheme",
type: "option",
value: BitwiseOp.XOR_SCHEME
},
{
name: "Null preserving",
type: "boolean",
value: BitwiseOp.XOR_PRESERVE_NULLS
},
{
name: "Differential",
type: "boolean",
value: BitwiseOp.XOR_DIFFERENTIAL
},
{
name: "Crib (known plaintext string)",
type: "binaryString",
value: ""
},
{
name: "Print key",
type: "boolean",
@@ -363,6 +361,11 @@ const OperationConfig = {
name: "Output as hex",
type: "boolean",
value: BitwiseOp.XOR_BRUTE_OUTPUT_HEX
},
{
name: "Crib (known plaintext string)",
type: "binaryString",
value: ""
}
]
},
@@ -519,6 +522,7 @@ const OperationConfig = {
}
]
},
"To Charcode": {
description: "Converts text to its unicode character code equivalent.<br><br>e.g. <code>Γειά σου</code> becomes <code>0393 03b5 03b9 03ac 20 03c3 03bf 03c5</code>",
run: ByteRepr.runToCharcode,
@@ -1592,7 +1596,7 @@ const OperationConfig = {
args: []
},
"Rotate right": {
description: "Rotates each byte to the right by the number of bits specified. Currently only supports 8-bit values.",
description: "Rotates each byte to the right by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.",
run: Rotate.runRotr,
highlight: true,
highlightReverse: true,
@@ -1600,19 +1604,19 @@ const OperationConfig = {
outputType: "byteArray",
args: [
{
name: "Number of bits",
name: "Amount",
type: "number",
value: Rotate.ROTATE_AMOUNT
},
{
name: "Rotate as a whole",
name: "Carry through",
type: "boolean",
value: Rotate.ROTATE_WHOLE
value: Rotate.ROTATE_CARRY
}
]
},
"Rotate left": {
description: "Rotates each byte to the left by the number of bits specified. Currently only supports 8-bit values.",
description: "Rotates each byte to the left by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.",
run: Rotate.runRotl,
highlight: true,
highlightReverse: true,
@@ -1620,14 +1624,14 @@ const OperationConfig = {
outputType: "byteArray",
args: [
{
name: "Number of bits",
name: "Amount",
type: "number",
value: Rotate.ROTATE_AMOUNT
},
{
name: "Rotate as a whole",
name: "Carry through",
type: "boolean",
value: Rotate.ROTATE_WHOLE
value: Rotate.ROTATE_CARRY
}
]
},
@@ -2242,6 +2246,24 @@ const OperationConfig = {
}
]
},
"JPath expression": {
description: "Extract information from a JSON object with a JPath query.",
run: Code.runJpath,
inputType: "string",
outputType: "string",
args: [
{
name: "Query",
type: "string",
value: Code.JPATH_INITIAL
},
{
name: "Result delimiter",
type: "binaryShortString",
value: Code.JPATH_DELIMITER
}
]
},
"CSS selector": {
description: "Extract information from an HTML document with a CSS selector",
run: Code.runCSSQuery,
@@ -2291,7 +2313,7 @@ const OperationConfig = {
}
]
},
"Windows Filetime to UNIX Timestamp":{
"Windows Filetime to UNIX Timestamp": {
description: "Converts a Windows Filetime value to a UNIX timestamp.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.",
run: DateTime.runFromFiletimeToUnix,
inputType: "string",
@@ -2309,7 +2331,7 @@ const OperationConfig = {
}
]
},
"UNIX Timestamp to Windows Filetime":{
"UNIX Timestamp to Windows Filetime": {
description: "Converts a UNIX timestamp to a Windows Filetime value.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.",
run: DateTime.runToFiletimeFromUnix,
inputType: "string",
@@ -3185,6 +3207,13 @@ const OperationConfig = {
}
]
},
"Microsoft Script Decoder": {
description: "Decodes Microsoft Encoded Script files that have been encoded with Microsoft's custom encoding. These are often VBS (Visual Basic Script) files that are encoded and renamed with a '.vbe' extention or JS (JScript) files renamed with a '.jse' extention.<br><br><b>Sample</b><br><br>Encoded:<br><code>#@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&amp;@*eEI@#@&amp;@#@&amp;.jm.raY 214Wv:zms/obI0xEAAA==^#~@</code><br><br>Decoded:<br><code>var my_msg = &#34;Testing <1><2><3>!&#34;;\n\nVScript.Echo(my_msg);</code>",
run: MS.runDecodeScript,
inputType: "string",
outputType: "string",
args: []
},
"Syntax highlighter": {
description: "Adds syntax highlighting to a range of source code languages. Note that this will not indent the code. Use one of the 'Beautify' operations for that.",
run: Code.runSyntaxHighlight,
@@ -3205,13 +3234,6 @@ const OperationConfig = {
}
]
},
"Parse escaped string": {
description: "Replaces escaped characters with the bytes they represent.<br><br>e.g.<code>Hello\\nWorld</code> becomes <code>Hello<br>World</code>",
run: StrUtils.runParseEscapedString,
inputType: "string",
outputType: "string",
args: []
},
"TCP/IP Checksum": {
description: "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes.",
run: Checksum.runTCPIP,
@@ -3251,6 +3273,20 @@ const OperationConfig = {
}
]
},
"Escape string": {
description: "Escapes special characters in a string so that they do not cause conflicts. For example, <code>Don't stop me now</code> becomes <code>Don\\'t stop me now</code>.",
run: StrUtils.runEscape,
inputType: "string",
outputType: "string",
args: []
},
"Unescape string": {
description: "Unescapes characters in a string that have been escaped. For example, <code>Don\\'t stop me now</code> becomes <code>Don't stop me now</code>.",
run: StrUtils.runUnescape,
inputType: "string",
outputType: "string",
args: []
},
"To Morse Code": {
description: "Translates alphanumeric characters into International Morse Code.<br><br>Ignores non-Morse characters.<br><br>e.g. <code>SOS</code> becomes <code>... --- ...</code>",
run: MorseCode.runTo,
@@ -3507,6 +3543,160 @@ const OperationConfig = {
}
]
},
"From BCD": {
description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign.",
run: BCD.runFromBCD,
inputType: "string",
outputType: "number",
args: [
{
name: "Scheme",
type: "option",
value: BCD.ENCODING_SCHEME
},
{
name: "Packed",
type: "boolean",
value: true
},
{
name: "Signed",
type: "boolean",
value: false
},
{
name: "Input format",
type: "option",
value: BCD.FORMAT
}
]
},
"To BCD": {
description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign",
run: BCD.runToBCD,
inputType: "number",
outputType: "string",
args: [
{
name: "Scheme",
type: "option",
value: BCD.ENCODING_SCHEME
},
{
name: "Packed",
type: "boolean",
value: true
},
{
name: "Signed",
type: "boolean",
value: false
},
{
name: "Output format",
type: "option",
value: BCD.FORMAT
}
]
},
"Bit shift left": {
description: "Shifts the bits in each byte towards the left by the specified amount.",
run: BitwiseOp.runBitShiftLeft,
inputType: "byteArray",
outputType: "byteArray",
highlight: true,
highlightReverse: true,
args: [
{
name: "Amount",
type: "number",
value: 1
},
]
},
"Bit shift right": {
description: "Shifts the bits in each byte towards the right by the specified amount.<br><br><i>Logical shifts</i> replace the leftmost bits with zeros.<br><i>Arithmetic shifts</i> preserve the most significant bit (MSB) of the original byte keeping the sign the same (positive or negative).",
run: BitwiseOp.runBitShiftRight,
inputType: "byteArray",
outputType: "byteArray",
highlight: true,
highlightReverse: true,
args: [
{
name: "Amount",
type: "number",
value: 1
},
{
name: "Type",
type: "option",
value: BitwiseOp.BIT_SHIFT_TYPE
}
]
},
"Generate TOTP": {
description: "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. T0 and T1 are in seconds.",
run: OTP.runTOTP,
inputType: "byteArray",
outputType: "string",
args: [
{
name: "Name",
type: "string",
value: ""
},
{
name: "Key size",
type: "number",
value: 32
},
{
name: "Code length",
type: "number",
value: 6
},
{
name: "Epoch offset (T0)",
type: "number",
value: 0
},
{
name: "Interval (T1)",
type: "number",
value: 30
}
]
},
"Generate HOTP": {
description: "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated.",
run: OTP.runHOTP,
inputType: "string",
outputType: "string",
args: [
{
name: "Name",
type: "string",
value: ""
},
{
name: "Key size",
type: "number",
value: 32
},
{
name: "Code length",
type: "number",
value: 6
},
{
name: "Counter",
type: "number",
value: 0
}
]
},
};
export default OperationConfig;

214
src/core/operations/BCD.js Executable file
View File

@@ -0,0 +1,214 @@
import Utils from "../Utils.js";
/**
* Binary-Coded Decimal operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const BCD = {
/**
* @constant
* @default
*/
ENCODING_SCHEME: [
"8 4 2 1",
"7 4 2 1",
"4 2 2 1",
"2 4 2 1",
"8 4 -2 -1",
"Excess-3",
"IBM 8 4 2 1",
],
/**
* Lookup table for the binary value of each digit representation.
*
* I wrote a very nice algorithm to generate 8 4 2 1 encoding programatically,
* but unfortunately it's much easier (if less elegant) to use lookup tables
* when supporting multiple encoding schemes.
*
* "Practicality beats purity" - PEP 20
*
* In some schemes it is possible to represent the same value in multiple ways.
* For instance, in 4 2 2 1 encoding, 0100 and 0010 both represent 2. Support
* has not yet been added for this.
*
* @constant
*/
ENCODING_LOOKUP: {
"8 4 2 1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
"7 4 2 1": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10],
"4 2 2 1": [0, 1, 4, 5, 8, 9, 12, 13, 14, 15],
"2 4 2 1": [0, 1, 2, 3, 4, 11, 12, 13, 14, 15],
"8 4 -2 -1": [0, 7, 6, 5, 4, 11, 10, 9, 8, 15],
"Excess-3": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
"IBM 8 4 2 1": [10, 1, 2, 3, 4, 5, 6, 7, 8, 9],
},
/**
* @default
* @constant
*/
FORMAT: ["Nibbles", "Bytes", "Raw"],
/**
* To BCD operation.
*
* @param {number} input
* @param {Object[]} args
* @returns {string}
*/
runToBCD: function(input, args) {
if (isNaN(input))
return "Invalid input";
if (Math.floor(input) !== input)
return "Fractional values are not supported by BCD";
const encoding = BCD.ENCODING_LOOKUP[args[0]],
packed = args[1],
signed = args[2],
outputFormat = args[3];
// Split input number up into separate digits
const digits = input.toString().split("");
if (digits[0] === "-" || digits[0] === "+") {
digits.shift();
}
let nibbles = [];
digits.forEach(d => {
const n = parseInt(d, 10);
nibbles.push(encoding[n]);
});
if (signed) {
if (packed && digits.length % 2 === 0) {
// If there are an even number of digits, we add a leading 0 so
// that the sign nibble doesn't sit in its own byte, leading to
// ambiguity around whether the number ends with a 0 or not.
nibbles.unshift(encoding[0]);
}
nibbles.push(input > 0 ? 12 : 13);
// 12 ("C") for + (credit)
// 13 ("D") for - (debit)
}
let bytes = [];
if (packed) {
let encoded = 0,
little = false;
nibbles.forEach(n => {
encoded ^= little ? n : (n << 4);
if (little) {
bytes.push(encoded);
encoded = 0;
}
little = !little;
});
if (little) bytes.push(encoded);
} else {
bytes = nibbles;
// Add null high nibbles
nibbles = nibbles.map(n => {
return [0, n];
}).reduce((a, b) => {
return a.concat(b);
});
}
// Output
switch (outputFormat) {
case "Nibbles":
return nibbles.map(n => {
return Utils.padLeft(n.toString(2), 4);
}).join(" ");
case "Bytes":
return bytes.map(b => {
return Utils.padLeft(b.toString(2), 8);
}).join(" ");
case "Raw":
default:
return Utils.byteArrayToChars(bytes);
}
},
/**
* From BCD operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {number}
*/
runFromBCD: function(input, args) {
const encoding = BCD.ENCODING_LOOKUP[args[0]],
packed = args[1],
signed = args[2],
inputFormat = args[3];
let nibbles = [],
output = "",
byteArray;
// Normalise the input
switch (inputFormat) {
case "Nibbles":
case "Bytes":
input = input.replace(/\s/g, "");
for (let i = 0; i < input.length; i += 4) {
nibbles.push(parseInt(input.substr(i, 4), 2));
}
break;
case "Raw":
default:
byteArray = Utils.strToByteArray(input);
byteArray.forEach(b => {
nibbles.push(b >>> 4);
nibbles.push(b & 15);
});
break;
}
if (!packed) {
// Discard each high nibble
for (let i = 0; i < nibbles.length; i++) {
nibbles.splice(i, 1);
}
}
if (signed) {
const sign = nibbles.pop();
if (sign === 13 ||
sign === 11) {
// Negative
output += "-";
}
}
nibbles.forEach(n => {
if (isNaN(n)) throw "Invalid input";
let val = encoding.indexOf(n);
if (val < 0) throw `Value ${Utils.bin(n, 4)} not in encoding scheme`;
output += val.toString();
});
return parseInt(output, 10);
},
};
export default BCD;

View File

@@ -36,7 +36,9 @@ const BitwiseOp = {
o = input[i];
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
result.push(x);
if (scheme !== "Standard" && !(nullPreserving && (o === 0 || o === k))) {
if (scheme &&
scheme !== "Standard" &&
!(nullPreserving && (o === 0 || o === k))) {
switch (scheme) {
case "Input differential":
key[i % key.length] = x;
@@ -120,19 +122,19 @@ const BitwiseOp = {
* @returns {string}
*/
runXorBrute: function (input, args) {
let keyLength = parseInt(args[0], 10),
const keyLength = parseInt(args[0], 10),
sampleLength = args[1],
sampleOffset = args[2],
nullPreserving = args[3],
differential = args[4],
crib = args[5],
printKey = args[6],
outputHex = args[7],
regex;
scheme = args[3],
nullPreserving = args[4],
printKey = args[5],
outputHex = args[6],
crib = args[7];
let output = "",
result,
resultUtf8;
resultUtf8,
regex;
input = input.slice(sampleOffset, sampleOffset + sampleLength);
@@ -142,14 +144,12 @@ const BitwiseOp = {
for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) {
result = BitwiseOp._bitOp(input, Utils.fromHex(key.toString(16)), BitwiseOp._xor, nullPreserving, differential);
result = BitwiseOp._bitOp(input, Utils.fromHex(key.toString(16)), BitwiseOp._xor, nullPreserving, scheme);
resultUtf8 = Utils.byteArrayToUtf8(result);
if (crib !== "" && resultUtf8.search(regex) === -1) continue;
if (printKey) output += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
if (outputHex)
output += Utils.toHex(result) + "\n";
else
output += Utils.printable(resultUtf8, false) + "\n";
if (outputHex) output += Utils.toHex(result) + "\n";
else output += Utils.printable(resultUtf8, false) + "\n";
if (printKey) output += "\n";
}
return output;
@@ -228,6 +228,46 @@ const BitwiseOp = {
},
/**
* Bit shift left operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
runBitShiftLeft: function(input, args) {
const amount = args[0];
return input.map(b => {
return (b << amount) & 0xff;
});
},
/**
* @constant
* @default
*/
BIT_SHIFT_TYPE: ["Logical shift", "Arithmetic shift"],
/**
* Bit shift right operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
runBitShiftRight: function(input, args) {
const amount = args[0],
type = args[1],
mask = type === "Logical shift" ? 0 : 0x80;
return input.map(b => {
return (b >>> amount) ^ (b & mask);
});
},
/**
* XOR bitwise calculation.
*

View File

@@ -196,7 +196,7 @@ const ByteRepr = {
/**
* Highlight to hex
* Highlight from hex
*
* @param {Object[]} pos
* @param {number} pos[].start
@@ -288,10 +288,8 @@ const ByteRepr = {
* @returns {byteArray}
*/
runFromBinary: function(input, args) {
if (args[0] !== "None") {
const delimRegex = Utils.regexRep[args[0] || "Space"];
input = input.replace(delimRegex, "");
}
const delimRegex = Utils.regexRep[args[0] || "Space"];
input = input.replace(delimRegex, "");
const output = [];
const byteLen = 8;

View File

@@ -766,8 +766,8 @@ const Cipher = {
* @returns {string}
*/
runSubstitute: function (input, args) {
let plaintext = Utils.expandAlphRange(args[0]).join(),
ciphertext = Utils.expandAlphRange(args[1]).join(),
let plaintext = Utils.expandAlphRange(args[0]).join(""),
ciphertext = Utils.expandAlphRange(args[1]).join(""),
output = "",
index = -1;

View File

@@ -4,6 +4,7 @@ import Utils from "../Utils.js";
import vkbeautify from "vkbeautify";
import {DOMParser as dom} from "xmldom";
import xpath from "xpath";
import jpath from "jsonpath";
import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js";
@@ -228,19 +229,19 @@ const Code = {
}
code = code
// Create newlines after ;
.replace(/;/g, ";\n")
// Create newlines after { and around }
.replace(/{/g, "{\n")
.replace(/}/g, "\n}\n")
// Remove carriage returns
.replace(/\r/g, "")
// Remove all indentation
.replace(/^\s+/g, "")
.replace(/\n\s+/g, "\n")
// Remove trailing spaces
.replace(/\s*$/g, "")
.replace(/\n{/g, "{");
// Create newlines after ;
.replace(/;/g, ";\n")
// Create newlines after { and around }
.replace(/{/g, "{\n")
.replace(/}/g, "\n}\n")
// Remove carriage returns
.replace(/\r/g, "")
// Remove all indentation
.replace(/^\s+/g, "")
.replace(/\n\s+/g, "\n")
// Remove trailing spaces
.replace(/\s*$/g, "")
.replace(/\n{/g, "{");
// Indent
let i = 0,
@@ -265,27 +266,27 @@ const Code = {
}
code = code
// Add strategic spaces
.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ")
.replace(/\s*<([=]?)\s*/g, " <$1 ")
.replace(/\s*>([=]?)\s*/g, " >$1 ")
.replace(/([^+])\+([^+=])/g, "$1 + $2")
.replace(/([^-])-([^-=])/g, "$1 - $2")
.replace(/([^*])\*([^*=])/g, "$1 * $2")
.replace(/([^/])\/([^/=])/g, "$1 / $2")
.replace(/\s*,\s*/g, ", ")
.replace(/\s*{/g, " {")
.replace(/}\n/g, "}\n\n")
// Hacky horribleness
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3")
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3")
.replace(/else\s*\n([^{])/gim, "else\n $1")
.replace(/else\s+([^{])/gim, "else $1")
// Remove strategic spaces
.replace(/\s+;/g, ";")
.replace(/\{\s+\}/g, "{}")
.replace(/\[\s+\]/g, "[]")
.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
// Add strategic spaces
.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ")
.replace(/\s*<([=]?)\s*/g, " <$1 ")
.replace(/\s*>([=]?)\s*/g, " >$1 ")
.replace(/([^+])\+([^+=])/g, "$1 + $2")
.replace(/([^-])-([^-=])/g, "$1 - $2")
.replace(/([^*])\*([^*=])/g, "$1 * $2")
.replace(/([^/])\/([^/=])/g, "$1 / $2")
.replace(/\s*,\s*/g, ", ")
.replace(/\s*{/g, " {")
.replace(/}\n/g, "}\n\n")
// Hacky horribleness
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3")
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3")
.replace(/else\s*\n([^{])/gim, "else\n $1")
.replace(/else\s+([^{])/gim, "else $1")
// Remove strategic spaces
.replace(/\s+;/g, ";")
.replace(/\{\s+\}/g, "{}")
.replace(/\[\s+\]/g, "[]")
.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
// Replace preserved tokens
const ptokens = /###preservedToken(\d+)###/g;
@@ -329,7 +330,7 @@ const Code = {
* @param {Object[]} args
* @returns {string}
*/
runXpath:function(input, args) {
runXpath: function(input, args) {
let query = args[0],
delimiter = args[1];
@@ -355,6 +356,48 @@ const Code = {
},
/**
* @constant
* @default
*/
JPATH_INITIAL: "",
/**
* @constant
* @default
*/
JPATH_DELIMITER: "\\n",
/**
* JPath expression operation.
*
* @author Matt C (matt@artemisbot.uk)
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runJpath: function(input, args) {
let query = args[0],
delimiter = args[1],
results,
obj;
try {
obj = JSON.parse(input);
} catch (err) {
return "Invalid input JSON: " + err.message;
}
try {
results = jpath.query(obj, query);
} catch (err) {
return "Invalid JPath expression: " + err.message;
}
return results.map(result => JSON.stringify(result)).join(delimiter);
},
/**
* @constant
* @default

View File

@@ -9,12 +9,12 @@ import bzip2 from "exports-loader?bzip2!../lib/bzip2.js";
const Zlib = {
RawDeflate: rawdeflate.Zlib.RawDeflate,
RawInflate: rawinflate.Zlib.RawInflate,
Deflate: zlibAndGzip.Zlib.Deflate,
Inflate: zlibAndGzip.Zlib.Inflate,
Gzip: zlibAndGzip.Zlib.Gzip,
Gunzip: zlibAndGzip.Zlib.Gunzip,
Zip: zip.Zlib.Zip,
Unzip: unzip.Zlib.Unzip,
Deflate: zlibAndGzip.Zlib.Deflate,
Inflate: zlibAndGzip.Zlib.Inflate,
Gzip: zlibAndGzip.Zlib.Gzip,
Gunzip: zlibAndGzip.Zlib.Gunzip,
Zip: zip.Zlib.Zip,
Unzip: unzip.Zlib.Unzip,
};
@@ -54,9 +54,9 @@ const Compress = {
* @default
*/
RAW_COMPRESSION_TYPE_LOOKUP: {
"Fixed Huffman Coding" : Zlib.RawDeflate.CompressionType.FIXED,
"Dynamic Huffman Coding" : Zlib.RawDeflate.CompressionType.DYNAMIC,
"None (Store)" : Zlib.RawDeflate.CompressionType.NONE,
"Fixed Huffman Coding": Zlib.RawDeflate.CompressionType.FIXED,
"Dynamic Huffman Coding": Zlib.RawDeflate.CompressionType.DYNAMIC,
"None (Store)": Zlib.RawDeflate.CompressionType.NONE,
},
/**
@@ -99,8 +99,8 @@ const Compress = {
* @default
*/
RAW_BUFFER_TYPE_LOOKUP: {
"Adaptive" : Zlib.RawInflate.BufferType.ADAPTIVE,
"Block" : Zlib.RawInflate.BufferType.BLOCK,
"Adaptive": Zlib.RawInflate.BufferType.ADAPTIVE,
"Block": Zlib.RawInflate.BufferType.BLOCK,
},
/**
@@ -150,9 +150,9 @@ const Compress = {
* @default
*/
ZLIB_COMPRESSION_TYPE_LOOKUP: {
"Fixed Huffman Coding" : Zlib.Deflate.CompressionType.FIXED,
"Dynamic Huffman Coding" : Zlib.Deflate.CompressionType.DYNAMIC,
"None (Store)" : Zlib.Deflate.CompressionType.NONE,
"Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED,
"Dynamic Huffman Coding": Zlib.Deflate.CompressionType.DYNAMIC,
"None (Store)": Zlib.Deflate.CompressionType.NONE,
},
/**
@@ -175,8 +175,8 @@ const Compress = {
* @default
*/
ZLIB_BUFFER_TYPE_LOOKUP: {
"Adaptive" : Zlib.Inflate.BufferType.ADAPTIVE,
"Block" : Zlib.Inflate.BufferType.BLOCK,
"Adaptive": Zlib.Inflate.BufferType.ADAPTIVE,
"Block": Zlib.Inflate.BufferType.BLOCK,
},
/**
@@ -264,17 +264,17 @@ const Compress = {
* @default
*/
ZIP_COMPRESSION_METHOD_LOOKUP: {
"Deflate" : Zlib.Zip.CompressionMethod.DEFLATE,
"None (Store)" : Zlib.Zip.CompressionMethod.STORE
"Deflate": Zlib.Zip.CompressionMethod.DEFLATE,
"None (Store)": Zlib.Zip.CompressionMethod.STORE
},
/**
* @constant
* @default
*/
ZIP_OS_LOOKUP: {
"MSDOS" : Zlib.Zip.OperatingSystem.MSDOS,
"Unix" : Zlib.Zip.OperatingSystem.UNIX,
"Macintosh" : Zlib.Zip.OperatingSystem.MACINTOSH
"MSDOS": Zlib.Zip.OperatingSystem.MSDOS,
"Unix": Zlib.Zip.OperatingSystem.UNIX,
"Macintosh": Zlib.Zip.OperatingSystem.MACINTOSH
},
/**

View File

@@ -25,36 +25,36 @@ const Convert = {
* @default
*/
DISTANCE_FACTOR: { // Multiples of a metre
"Nanometres (nm)" : 1e-9,
"Micrometres (µm)" : 1e-6,
"Millimetres (mm)" : 1e-3,
"Centimetres (cm)" : 1e-2,
"Metres (m)" : 1,
"Kilometers (km)" : 1e3,
"Nanometres (nm)": 1e-9,
"Micrometres (µm)": 1e-6,
"Millimetres (mm)": 1e-3,
"Centimetres (cm)": 1e-2,
"Metres (m)": 1,
"Kilometers (km)": 1e3,
"Thou (th)" : 0.0000254,
"Inches (in)" : 0.0254,
"Feet (ft)" : 0.3048,
"Yards (yd)" : 0.9144,
"Chains (ch)" : 20.1168,
"Furlongs (fur)" : 201.168,
"Miles (mi)" : 1609.344,
"Leagues (lea)" : 4828.032,
"Thou (th)": 0.0000254,
"Inches (in)": 0.0254,
"Feet (ft)": 0.3048,
"Yards (yd)": 0.9144,
"Chains (ch)": 20.1168,
"Furlongs (fur)": 201.168,
"Miles (mi)": 1609.344,
"Leagues (lea)": 4828.032,
"Fathoms (ftm)" : 1.853184,
"Cables" : 185.3184,
"Nautical miles" : 1853.184,
"Fathoms (ftm)": 1.853184,
"Cables": 185.3184,
"Nautical miles": 1853.184,
"Cars (4m)" : 4,
"Buses (8.4m)" : 8.4,
"Cars (4m)": 4,
"Buses (8.4m)": 8.4,
"American football fields (91m)": 91,
"Football pitches (105m)": 105,
"Earth-to-Moons" : 380000000,
"Earth's equators" : 40075016.686,
"Earth-to-Moons": 380000000,
"Earth's equators": 40075016.686,
"Astronomical units (au)": 149597870700,
"Light-years (ly)" : 9460730472580800,
"Parsecs (pc)" : 3.0856776e16
"Light-years (ly)": 9460730472580800,
"Parsecs (pc)": 3.0856776e16
},
/**
@@ -90,52 +90,52 @@ const Convert = {
* @default
*/
DATA_FACTOR: { // Multiples of a bit
"Bits (b)" : 1,
"Nibbles" : 4,
"Octets" : 8,
"Bytes (B)" : 8,
"Bits (b)": 1,
"Nibbles": 4,
"Octets": 8,
"Bytes (B)": 8,
// Binary bits (2^n)
"Kibibits (Kib)" : 1024,
"Mebibits (Mib)" : 1048576,
"Gibibits (Gib)" : 1073741824,
"Tebibits (Tib)" : 1099511627776,
"Pebibits (Pib)" : 1125899906842624,
"Exbibits (Eib)" : 1152921504606846976,
"Zebibits (Zib)" : 1180591620717411303424,
"Yobibits (Yib)" : 1208925819614629174706176,
"Kibibits (Kib)": 1024,
"Mebibits (Mib)": 1048576,
"Gibibits (Gib)": 1073741824,
"Tebibits (Tib)": 1099511627776,
"Pebibits (Pib)": 1125899906842624,
"Exbibits (Eib)": 1152921504606846976,
"Zebibits (Zib)": 1180591620717411303424,
"Yobibits (Yib)": 1208925819614629174706176,
// Decimal bits (10^n)
"Decabits" : 10,
"Hectobits" : 100,
"Kilobits (Kb)" : 1e3,
"Megabits (Mb)" : 1e6,
"Gigabits (Gb)" : 1e9,
"Terabits (Tb)" : 1e12,
"Petabits (Pb)" : 1e15,
"Exabits (Eb)" : 1e18,
"Zettabits (Zb)" : 1e21,
"Yottabits (Yb)" : 1e24,
"Decabits": 10,
"Hectobits": 100,
"Kilobits (Kb)": 1e3,
"Megabits (Mb)": 1e6,
"Gigabits (Gb)": 1e9,
"Terabits (Tb)": 1e12,
"Petabits (Pb)": 1e15,
"Exabits (Eb)": 1e18,
"Zettabits (Zb)": 1e21,
"Yottabits (Yb)": 1e24,
// Binary bytes (8 x 2^n)
"Kibibytes (KiB)" : 8192,
"Mebibytes (MiB)" : 8388608,
"Gibibytes (GiB)" : 8589934592,
"Tebibytes (TiB)" : 8796093022208,
"Pebibytes (PiB)" : 9007199254740992,
"Exbibytes (EiB)" : 9223372036854775808,
"Zebibytes (ZiB)" : 9444732965739290427392,
"Yobibytes (YiB)" : 9671406556917033397649408,
"Kibibytes (KiB)": 8192,
"Mebibytes (MiB)": 8388608,
"Gibibytes (GiB)": 8589934592,
"Tebibytes (TiB)": 8796093022208,
"Pebibytes (PiB)": 9007199254740992,
"Exbibytes (EiB)": 9223372036854775808,
"Zebibytes (ZiB)": 9444732965739290427392,
"Yobibytes (YiB)": 9671406556917033397649408,
// Decimal bytes (8 x 10^n)
"Kilobytes (KB)" : 8e3,
"Megabytes (MB)" : 8e6,
"Gigabytes (GB)" : 8e9,
"Terabytes (TB)" : 8e12,
"Petabytes (PB)" : 8e15,
"Exabytes (EB)" : 8e18,
"Zettabytes (ZB)" : 8e21,
"Yottabytes (YB)" : 8e24,
"Kilobytes (KB)": 8e3,
"Megabytes (MB)": 8e6,
"Gigabytes (GB)": 8e9,
"Terabytes (TB)": 8e12,
"Petabytes (PB)": 8e15,
"Exabytes (EB)": 8e18,
"Zettabytes (ZB)": 8e21,
"Yottabytes (YB)": 8e24,
},
/**
@@ -171,51 +171,51 @@ const Convert = {
*/
AREA_FACTOR: { // Multiples of a square metre
// Metric
"Square metre (sq m)" : 1,
"Square kilometre (sq km)" : 1e6,
"Square metre (sq m)": 1,
"Square kilometre (sq km)": 1e6,
"Centiare (ca)" : 1,
"Deciare (da)" : 10,
"Are (a)" : 100,
"Decare (daa)" : 1e3,
"Hectare (ha)" : 1e4,
"Centiare (ca)": 1,
"Deciare (da)": 10,
"Are (a)": 100,
"Decare (daa)": 1e3,
"Hectare (ha)": 1e4,
// Imperial
"Square inch (sq in)" : 0.00064516,
"Square foot (sq ft)" : 0.09290304,
"Square yard (sq yd)" : 0.83612736,
"Square mile (sq mi)" : 2589988.110336,
"Perch (sq per)" : 42.21,
"Rood (ro)" : 1011,
"International acre (ac)" : 4046.8564224,
"Square inch (sq in)": 0.00064516,
"Square foot (sq ft)": 0.09290304,
"Square yard (sq yd)": 0.83612736,
"Square mile (sq mi)": 2589988.110336,
"Perch (sq per)": 42.21,
"Rood (ro)": 1011,
"International acre (ac)": 4046.8564224,
// US customary units
"US survey acre (ac)" : 4046.87261,
"US survey square mile (sq mi)" : 2589998.470305239,
"US survey township" : 93239944.9309886,
"US survey acre (ac)": 4046.87261,
"US survey square mile (sq mi)": 2589998.470305239,
"US survey township": 93239944.9309886,
// Nuclear physics
"Yoctobarn (yb)" : 1e-52,
"Zeptobarn (zb)" : 1e-49,
"Attobarn (ab)" : 1e-46,
"Femtobarn (fb)" : 1e-43,
"Picobarn (pb)" : 1e-40,
"Nanobarn (nb)" : 1e-37,
"Microbarn (μb)" : 1e-34,
"Millibarn (mb)" : 1e-31,
"Barn (b)" : 1e-28,
"Kilobarn (kb)" : 1e-25,
"Megabarn (Mb)" : 1e-22,
"Yoctobarn (yb)": 1e-52,
"Zeptobarn (zb)": 1e-49,
"Attobarn (ab)": 1e-46,
"Femtobarn (fb)": 1e-43,
"Picobarn (pb)": 1e-40,
"Nanobarn (nb)": 1e-37,
"Microbarn (μb)": 1e-34,
"Millibarn (mb)": 1e-31,
"Barn (b)": 1e-28,
"Kilobarn (kb)": 1e-25,
"Megabarn (Mb)": 1e-22,
"Planck area" : 2.6e-70,
"Shed" : 1e-52,
"Outhouse" : 1e-34,
"Planck area": 2.6e-70,
"Shed": 1e-52,
"Outhouse": 1e-34,
// Comparisons
"Washington D.C." : 176119191.502848,
"Isle of Wight" : 380000000,
"Wales" : 20779000000,
"Texas" : 696241000000,
"Washington D.C.": 176119191.502848,
"Isle of Wight": 380000000,
"Wales": 20779000000,
"Texas": 696241000000,
},
/**
@@ -252,81 +252,81 @@ const Convert = {
*/
MASS_FACTOR: { // Multiples of a gram
// Metric
"Yoctogram (yg)" : 1e-24,
"Zeptogram (zg)" : 1e-21,
"Attogram (ag)" : 1e-18,
"Femtogram (fg)" : 1e-15,
"Picogram (pg)" : 1e-12,
"Nanogram (ng)" : 1e-9,
"Microgram (μg)" : 1e-6,
"Milligram (mg)" : 1e-3,
"Centigram (cg)" : 1e-2,
"Decigram (dg)" : 1e-1,
"Gram (g)" : 1,
"Decagram (dag)" : 10,
"Hectogram (hg)" : 100,
"Kilogram (kg)" : 1000,
"Megagram (Mg)" : 1e6,
"Tonne (t)" : 1e6,
"Gigagram (Gg)" : 1e9,
"Teragram (Tg)" : 1e12,
"Petagram (Pg)" : 1e15,
"Exagram (Eg)" : 1e18,
"Zettagram (Zg)" : 1e21,
"Yottagram (Yg)" : 1e24,
"Yoctogram (yg)": 1e-24,
"Zeptogram (zg)": 1e-21,
"Attogram (ag)": 1e-18,
"Femtogram (fg)": 1e-15,
"Picogram (pg)": 1e-12,
"Nanogram (ng)": 1e-9,
"Microgram (μg)": 1e-6,
"Milligram (mg)": 1e-3,
"Centigram (cg)": 1e-2,
"Decigram (dg)": 1e-1,
"Gram (g)": 1,
"Decagram (dag)": 10,
"Hectogram (hg)": 100,
"Kilogram (kg)": 1000,
"Megagram (Mg)": 1e6,
"Tonne (t)": 1e6,
"Gigagram (Gg)": 1e9,
"Teragram (Tg)": 1e12,
"Petagram (Pg)": 1e15,
"Exagram (Eg)": 1e18,
"Zettagram (Zg)": 1e21,
"Yottagram (Yg)": 1e24,
// Imperial Avoirdupois
"Grain (gr)" : 64.79891e-3,
"Dram (dr)" : 1.7718451953125,
"Ounce (oz)" : 28.349523125,
"Pound (lb)" : 453.59237,
"Nail" : 3175.14659,
"Stone (st)" : 6.35029318e3,
"Quarter (gr)" : 12700.58636,
"Tod" : 12700.58636,
"US hundredweight (cwt)" : 45.359237e3,
"Imperial hundredweight (cwt)" : 50.80234544e3,
"US ton (t)" : 907.18474e3,
"Imperial ton (t)" : 1016.0469088e3,
"Grain (gr)": 64.79891e-3,
"Dram (dr)": 1.7718451953125,
"Ounce (oz)": 28.349523125,
"Pound (lb)": 453.59237,
"Nail": 3175.14659,
"Stone (st)": 6.35029318e3,
"Quarter (gr)": 12700.58636,
"Tod": 12700.58636,
"US hundredweight (cwt)": 45.359237e3,
"Imperial hundredweight (cwt)": 50.80234544e3,
"US ton (t)": 907.18474e3,
"Imperial ton (t)": 1016.0469088e3,
// Imperial Troy
"Pennyweight (dwt)" : 1.55517384,
"Troy dram (dr t)" : 3.8879346,
"Troy ounce (oz t)" : 31.1034768,
"Troy pound (lb t)" : 373.2417216,
"Mark" : 248.8278144,
"Pennyweight (dwt)": 1.55517384,
"Troy dram (dr t)": 3.8879346,
"Troy ounce (oz t)": 31.1034768,
"Troy pound (lb t)": 373.2417216,
"Mark": 248.8278144,
// Archaic
"Wey" : 76.5e3,
"Wool wey" : 101.7e3,
"Suffolk wey" : 161.5e3,
"Wool sack" : 153000,
"Coal sack" : 50.80234544e3,
"Load" : 918000,
"Last" : 1836000,
"Flax or feather last" : 770e3,
"Gunpowder last" : 1090e3,
"Picul" : 60.478982e3,
"Rice last" : 1200e3,
"Wey": 76.5e3,
"Wool wey": 101.7e3,
"Suffolk wey": 161.5e3,
"Wool sack": 153000,
"Coal sack": 50.80234544e3,
"Load": 918000,
"Last": 1836000,
"Flax or feather last": 770e3,
"Gunpowder last": 1090e3,
"Picul": 60.478982e3,
"Rice last": 1200e3,
// Comparisons
"Big Ben (14 tonnes)" : 14e6,
"Blue whale (180 tonnes)" : 180e6,
"International Space Station (417 tonnes)" : 417e6,
"Space Shuttle (2,041 tonnes)" : 2041e6,
"RMS Titanic (52,000 tonnes)" : 52000e6,
"Great Pyramid of Giza (6,000,000 tonnes)" : 6e12,
"Earth's oceans (1.4 yottagrams)" : 1.4e24,
"Big Ben (14 tonnes)": 14e6,
"Blue whale (180 tonnes)": 180e6,
"International Space Station (417 tonnes)": 417e6,
"Space Shuttle (2,041 tonnes)": 2041e6,
"RMS Titanic (52,000 tonnes)": 52000e6,
"Great Pyramid of Giza (6,000,000 tonnes)": 6e12,
"Earth's oceans (1.4 yottagrams)": 1.4e24,
// Astronomical
"A teaspoon of neutron star (5,500 million tonnes)" : 5.5e15,
"Lunar mass (ML)" : 7.342e25,
"Earth mass (M⊕)" : 5.97219e27,
"Jupiter mass (MJ)" : 1.8981411476999997e30,
"Solar mass (M☉)" : 1.98855e33,
"Sagittarius A* (7.5 x 10^36 kgs-ish)" : 7.5e39,
"Milky Way galaxy (1.2 x 10^42 kgs)" : 1.2e45,
"The observable universe (1.45 x 10^53 kgs)" : 1.45e56,
"A teaspoon of neutron star (5,500 million tonnes)": 5.5e15,
"Lunar mass (ML)": 7.342e25,
"Earth mass (M⊕)": 5.97219e27,
"Jupiter mass (MJ)": 1.8981411476999997e30,
"Solar mass (M☉)": 1.98855e33,
"Sagittarius A* (7.5 x 10^36 kgs-ish)": 7.5e39,
"Milky Way galaxy (1.2 x 10^42 kgs)": 1.2e45,
"The observable universe (1.45 x 10^53 kgs)": 1.45e56,
},
/**
@@ -361,37 +361,37 @@ const Convert = {
*/
SPEED_FACTOR: { // Multiples of m/s
// Metric
"Metres per second (m/s)" : 1,
"Kilometres per hour (km/h)" : 0.2778,
"Metres per second (m/s)": 1,
"Kilometres per hour (km/h)": 0.2778,
// Imperial
"Miles per hour (mph)" : 0.44704,
"Knots (kn)" : 0.5144,
"Miles per hour (mph)": 0.44704,
"Knots (kn)": 0.5144,
// Comparisons
"Human hair growth rate" : 4.8e-9,
"Bamboo growth rate" : 1.4e-5,
"World's fastest snail" : 0.00275,
"Usain Bolt's top speed" : 12.42,
"Jet airliner cruising speed" : 250,
"Concorde" : 603,
"SR-71 Blackbird" : 981,
"Space Shuttle" : 1400,
"International Space Station" : 7700,
"Human hair growth rate": 4.8e-9,
"Bamboo growth rate": 1.4e-5,
"World's fastest snail": 0.00275,
"Usain Bolt's top speed": 12.42,
"Jet airliner cruising speed": 250,
"Concorde": 603,
"SR-71 Blackbird": 981,
"Space Shuttle": 1400,
"International Space Station": 7700,
// Scientific
"Sound in standard atmosphere" : 340.3,
"Sound in water" : 1500,
"Lunar escape velocity" : 2375,
"Earth escape velocity" : 11200,
"Earth's solar orbit" : 29800,
"Solar system's Milky Way orbit" : 200000,
"Milky Way relative to the cosmic microwave background" : 552000,
"Solar escape velocity" : 617700,
"Neutron star escape velocity (0.3c)" : 100000000,
"Light in a diamond (0.4136c)" : 124000000,
"Signal in an optical fibre (0.667c)" : 200000000,
"Light (c)" : 299792458,
"Sound in standard atmosphere": 340.3,
"Sound in water": 1500,
"Lunar escape velocity": 2375,
"Earth escape velocity": 11200,
"Earth's solar orbit": 29800,
"Solar system's Milky Way orbit": 200000,
"Milky Way relative to the cosmic microwave background": 552000,
"Solar escape velocity": 617700,
"Neutron star escape velocity (0.3c)": 100000000,
"Light in a diamond (0.4136c)": 124000000,
"Signal in an optical fibre (0.667c)": 200000000,
"Light (c)": 299792458,
},
/**

View File

@@ -170,9 +170,9 @@ const Extract = {
protocol = "[A-Z]+://",
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
port = ":\\d+",
path = "/[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]*";
path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
path += "(?:[.!,?]+[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]+)*";
path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
const regex = new RegExp(protocol + hostname + "(?:" + port +
")?(?:" + path + ")?", "ig");
return Extract._search(input, regex, null, displayTotal);

File diff suppressed because it is too large Load Diff

View File

@@ -125,30 +125,30 @@ const HTTP = {
}
return fetch(url, config)
.then(r => {
if (r.status === 0 && r.type === "opaque") {
return "Error: Null response. Try setting the connection mode to CORS.";
}
if (showResponseMetadata) {
let headers = "";
for (let pair of r.headers.entries()) {
headers += " " + pair[0] + ": " + pair[1] + "\n";
.then(r => {
if (r.status === 0 && r.type === "opaque") {
return "Error: Null response. Try setting the connection mode to CORS.";
}
return r.text().then(b => {
return "####\n Status: " + r.status + " " + r.statusText +
"\n Exposed headers:\n" + headers + "####\n\n" + b;
});
}
return r.text();
})
.catch(e => {
return e.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid URL\n" +
" - Making a request to an insecure resource (HTTP) from a secure source (HTTPS)\n" +
" - Making a cross-origin request to a server which does not support CORS\n";
});
if (showResponseMetadata) {
let headers = "";
for (let pair of r.headers.entries()) {
headers += " " + pair[0] + ": " + pair[1] + "\n";
}
return r.text().then(b => {
return "####\n Status: " + r.status + " " + r.statusText +
"\n Exposed headers:\n" + headers + "####\n\n" + b;
});
}
return r.text();
})
.catch(e => {
return e.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid URL\n" +
" - Making a request to an insecure resource (HTTP) from a secure source (HTTPS)\n" +
" - Making a cross-origin request to a server which does not support CORS\n";
});
},
};

View File

@@ -1,4 +1,4 @@
import esprima from "esprima";
import * as esprima from "esprima";
import escodegen from "escodegen";
import esmangle from "esmangle";
@@ -62,7 +62,7 @@ const JS = {
tolerant: parseTolerant
};
result = esprima.parse(input, options);
result = esprima.parseScript(input, options);
return JSON.stringify(result, null, 2);
},
@@ -104,7 +104,7 @@ const JS = {
AST;
try {
AST = esprima.parse(input, {
AST = esprima.parseScript(input, {
range: true,
tokens: true,
comment: true
@@ -142,7 +142,7 @@ const JS = {
*/
runMinify: function(input, args) {
let result = "",
AST = esprima.parse(input),
AST = esprima.parseScript(input),
optimisedAST = esmangle.optimize(AST, null),
mangledAST = esmangle.mangle(optimisedAST);

213
src/core/operations/MS.js Normal file
View File

@@ -0,0 +1,213 @@
/**
* Microsoft operations.
*
* @author bmwhitn [brian.m.whitney@outlook.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const MS = {
/**
* @constant
* @default
*/
D_DECODE: [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"\x57\x6E\x7B",
"\x4A\x4C\x41",
"\x0B\x0B\x0B",
"\x0C\x0C\x0C",
"\x4A\x4C\x41",
"\x0E\x0E\x0E",
"\x0F\x0F\x0F",
"\x10\x10\x10",
"\x11\x11\x11",
"\x12\x12\x12",
"\x13\x13\x13",
"\x14\x14\x14",
"\x15\x15\x15",
"\x16\x16\x16",
"\x17\x17\x17",
"\x18\x18\x18",
"\x19\x19\x19",
"\x1A\x1A\x1A",
"\x1B\x1B\x1B",
"\x1C\x1C\x1C",
"\x1D\x1D\x1D",
"\x1E\x1E\x1E",
"\x1F\x1F\x1F",
"\x2E\x2D\x32",
"\x47\x75\x30",
"\x7A\x52\x21",
"\x56\x60\x29",
"\x42\x71\x5B",
"\x6A\x5E\x38",
"\x2F\x49\x33",
"\x26\x5C\x3D",
"\x49\x62\x58",
"\x41\x7D\x3A",
"\x34\x29\x35",
"\x32\x36\x65",
"\x5B\x20\x39",
"\x76\x7C\x5C",
"\x72\x7A\x56",
"\x43\x7F\x73",
"\x38\x6B\x66",
"\x39\x63\x4E",
"\x70\x33\x45",
"\x45\x2B\x6B",
"\x68\x68\x62",
"\x71\x51\x59",
"\x4F\x66\x78",
"\x09\x76\x5E",
"\x62\x31\x7D",
"\x44\x64\x4A",
"\x23\x54\x6D",
"\x75\x43\x71",
"\x4A\x4C\x41",
"\x7E\x3A\x60",
"\x4A\x4C\x41",
"\x5E\x7E\x53",
"\x40\x4C\x40",
"\x77\x45\x42",
"\x4A\x2C\x27",
"\x61\x2A\x48",
"\x5D\x74\x72",
"\x22\x27\x75",
"\x4B\x37\x31",
"\x6F\x44\x37",
"\x4E\x79\x4D",
"\x3B\x59\x52",
"\x4C\x2F\x22",
"\x50\x6F\x54",
"\x67\x26\x6A",
"\x2A\x72\x47",
"\x7D\x6A\x64",
"\x74\x39\x2D",
"\x54\x7B\x20",
"\x2B\x3F\x7F",
"\x2D\x38\x2E",
"\x2C\x77\x4C",
"\x30\x67\x5D",
"\x6E\x53\x7E",
"\x6B\x47\x6C",
"\x66\x34\x6F",
"\x35\x78\x79",
"\x25\x5D\x74",
"\x21\x30\x43",
"\x64\x23\x26",
"\x4D\x5A\x76",
"\x52\x5B\x25",
"\x63\x6C\x24",
"\x3F\x48\x2B",
"\x7B\x55\x28",
"\x78\x70\x23",
"\x29\x69\x41",
"\x28\x2E\x34",
"\x73\x4C\x09",
"\x59\x21\x2A",
"\x33\x24\x44",
"\x7F\x4E\x3F",
"\x6D\x50\x77",
"\x55\x09\x3B",
"\x53\x56\x55",
"\x7C\x73\x69",
"\x3A\x35\x61",
"\x5F\x61\x63",
"\x65\x4B\x50",
"\x46\x58\x67",
"\x58\x3B\x51",
"\x31\x57\x49",
"\x69\x22\x4F",
"\x6C\x6D\x46",
"\x5A\x4D\x68",
"\x48\x25\x7C",
"\x27\x28\x36",
"\x5C\x46\x70",
"\x3D\x4A\x6E",
"\x24\x32\x7A",
"\x79\x41\x2F",
"\x37\x3D\x5F",
"\x60\x5F\x4B",
"\x51\x4F\x5A",
"\x20\x42\x2C",
"\x36\x65\x57"
],
/**
* @constant
* @default
*/
D_COMBINATION: [
0, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 2, 0, 0, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1,
0, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 2, 1
],
/**
* Decodes Microsoft Encoded Script files that can be read and executed by cscript.exe/wscript.exe.
* This is a conversion of a Python script that was originally created by Didier Stevens
* (https://DidierStevens.com).
*
* @private
* @param {string} data
* @returns {string}
*/
_decode: function (data) {
let result = [];
let index = -1;
data = data.replace(/@&/g, String.fromCharCode(10))
.replace(/@#/g, String.fromCharCode(13))
.replace(/@\*/g, ">")
.replace(/@!/g, "<")
.replace(/@\$/g, "@");
for (let i = 0; i < data.length; i++) {
let byte = data.charCodeAt(i);
let char = data.charAt(i);
if (byte < 128) {
index++;
}
if ((byte === 9 || byte > 31 && byte < 128) &&
byte !== 60 &&
byte !== 62 &&
byte !== 64) {
char = MS.D_DECODE[byte].charAt(MS.D_COMBINATION[index % 64]);
}
result.push(char);
}
return result.join("");
},
/**
* Microsoft Script Decoder operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runDecodeScript: function (input, args) {
let matcher = /#@~\^.{6}==(.+).{6}==\^#~@/;
let encodedData = matcher.exec(input);
if (encodedData){
return MS._decode(encodedData[1]);
} else {
return "";
}
}
};
export default MS;

View File

@@ -18,25 +18,25 @@ const OS = {
*/
runParseUnixPerms: function(input, args) {
let perms = {
d : false, // directory
sl : false, // symbolic link
np : false, // named pipe
s : false, // socket
cd : false, // character device
bd : false, // block device
dr : false, // door
sb : false, // sticky bit
su : false, // setuid
sg : false, // setgid
ru : false, // read user
wu : false, // write user
eu : false, // execute user
rg : false, // read group
wg : false, // write group
eg : false, // execute group
ro : false, // read other
wo : false, // write other
eo : false // execute other
d: false, // directory
sl: false, // symbolic link
np: false, // named pipe
s: false, // socket
cd: false, // character device
bd: false, // block device
dr: false, // door
sb: false, // sticky bit
su: false, // setuid
sg: false, // setgid
ru: false, // read user
wu: false, // write user
eu: false, // execute user
rg: false, // read group
wg: false, // write group
eg: false, // execute group
ro: false, // read other
wo: false, // write other
eo: false // execute other
},
d = 0,
u = 0,

55
src/core/operations/OTP.js Executable file
View File

@@ -0,0 +1,55 @@
import otp from "otp";
import Base64 from "./Base64.js";
/**
* One-Time Password operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const OTP = {
/**
* Generate TOTP operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runTOTP: function(input, args) {
const otpObj = otp({
name: args[0],
keySize: args[1],
codeLength: args[2],
secret: Base64.runTo32(input, []),
epoch: args[3],
timeSlice: args[4]
});
return `URI: ${otpObj.totpURL}\n\nPassword: ${otpObj.totp()}`;
},
/**
* Generate HOTP operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runHOTP: function(input, args) {
const otpObj = otp({
name: args[0],
keySize: args[1],
codeLength: args[2],
secret: Base64.runTo32(input, []),
});
const counter = args[3];
return `URI: ${otpObj.hotpURL}\n\nPassword: ${otpObj.hotp(counter)}`;
},
};
export default OTP;

File diff suppressed because it is too large Load Diff

View File

@@ -61,7 +61,7 @@ const QuotedPrintable = {
* @returns {byteArray}
*/
runFrom: function (input, args) {
const str = input.replace(/\=(?:\r?\n|$)/g, "");
const str = input.replace(/=(?:\r?\n|$)/g, "");
return QuotedPrintable.mimeDecode(str);
},
@@ -73,7 +73,7 @@ const QuotedPrintable = {
* @returns {byteArray}
*/
mimeDecode: function(str) {
let encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length,
let encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length,
bufferLength = str.length - encodedBytesCount * 2,
chr, hex,
buffer = new Array(bufferLength),
@@ -219,21 +219,21 @@ const QuotedPrintable = {
result += line;
pos += line.length;
continue;
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t\.,!\?][^ \t\.,!\?]*$/))) {
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t.,!?][^ \t.,!?]*$/))) {
// truncate to nearest space
line = line.substr(0, line.length - (match[0].length - 1));
} else if (line.substr(-1) === "\r") {
line = line.substr(0, line.length - 1);
} else {
if (line.match(/\=[\da-f]{0,2}$/i)) {
if (line.match(/=[\da-f]{0,2}$/i)) {
// push incomplete encoding sequences to the next line
if ((match = line.match(/\=[\da-f]{0,1}$/i))) {
if ((match = line.match(/=[\da-f]{0,1}$/i))) {
line = line.substr(0, line.length - match[0].length);
}
// ensure that utf-8 sequences are not split
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/ig))) {
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/=[\da-f]{2}$/ig))) {
code = parseInt(match[0].substr(1, 2), 16);
if (code < 128) {
break;
@@ -250,7 +250,7 @@ const QuotedPrintable = {
}
if (pos + line.length < len && line.substr(-1) !== "\n") {
if (line.length === 76 && line.match(/\=[\da-f]{2}$/i)) {
if (line.length === 76 && line.match(/=[\da-f]{2}$/i)) {
line = line.substr(0, line.length - 3);
} else if (line.length === 76) {
line = line.substr(0, line.length - 1);

View File

@@ -20,7 +20,7 @@ const Rotate = {
* @constant
* @default
*/
ROTATE_WHOLE: false,
ROTATE_CARRY: false,
/**
* Runs rotation operations across the input data.
@@ -53,7 +53,7 @@ const Rotate = {
*/
runRotr: function(input, args) {
if (args[1]) {
return Rotate._rotrWhole(input, args[0]);
return Rotate._rotrCarry(input, args[0]);
} else {
return Rotate._rot(input, args[0], Rotate._rotr);
}
@@ -69,7 +69,7 @@ const Rotate = {
*/
runRotl: function(input, args) {
if (args[1]) {
return Rotate._rotlWhole(input, args[0]);
return Rotate._rotlCarry(input, args[0]);
} else {
return Rotate._rot(input, args[0], Rotate._rotl);
}
@@ -197,7 +197,7 @@ const Rotate = {
* @param {number} amount
* @returns {byteArray}
*/
_rotrWhole: function(data, amount) {
_rotrCarry: function(data, amount) {
let carryBits = 0,
newByte,
result = [];
@@ -223,7 +223,7 @@ const Rotate = {
* @param {number} amount
* @returns {byteArray}
*/
_rotlWhole: function(data, amount) {
_rotlCarry: function(data, amount) {
let carryBits = 0,
newByte,
result = [];

View File

@@ -36,7 +36,7 @@ const StrUtils = {
},
{
name: "URL",
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
},
{
name: "Domain",
@@ -193,17 +193,17 @@ const StrUtils = {
* @constant
* @default
*/
FIND_REPLACE_GLOBAL : true,
FIND_REPLACE_GLOBAL: true,
/**
* @constant
* @default
*/
FIND_REPLACE_CASE : false,
FIND_REPLACE_CASE: false,
/**
* @constant
* @default
*/
FIND_REPLACE_MULTILINE : true,
FIND_REPLACE_MULTILINE: true,
/**
* Find / Replace operation.
@@ -359,9 +359,9 @@ const StrUtils = {
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hlgreen'>" + Utils.escapeHtml(diff[i].value) + "</span>";
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hlred'>" + Utils.escapeHtml(diff[i].value) + "</span>";
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else {
output += Utils.escapeHtml(diff[i].value);
}
@@ -424,7 +424,7 @@ const StrUtils = {
}
if (match && !inMatch) {
outputs[s] += "<span class='hlgreen'>" + Utils.escapeHtml(samples[s][i]);
outputs[s] += "<span class='hl5'>" + Utils.escapeHtml(samples[s][i]);
if (samples[s].length === i + 1) outputs[s] += "</span>";
if (s === samples.length - 1) inMatch = true;
} else if (!match && inMatch) {
@@ -450,14 +450,84 @@ const StrUtils = {
/**
* Parse escaped string operation.
* @constant
* @default
*/
ESCAPE_REPLACEMENTS: [
{"escaped": "\\\\", "unescaped": "\\"}, // Must be first
{"escaped": "\\'", "unescaped": "'"},
{"escaped": "\\\"", "unescaped": "\""},
{"escaped": "\\n", "unescaped": "\n"},
{"escaped": "\\r", "unescaped": "\r"},
{"escaped": "\\t", "unescaped": "\t"},
{"escaped": "\\b", "unescaped": "\b"},
{"escaped": "\\f", "unescaped": "\f"},
],
/**
* Escape string operation.
*
* @author Vel0x [dalemy@microsoft.com]
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*
* @example
* StrUtils.runUnescape("Don't do that", [])
* > "Don\'t do that"
* StrUtils.runUnescape(`Hello
* World`, [])
* > "Hello\nWorld"
*/
runParseEscapedString: function(input, args) {
return Utils.parseEscapedChars(input);
runEscape: function(input, args) {
return StrUtils._replaceByKeys(input, "unescaped", "escaped");
},
/**
* Unescape string operation.
*
* @author Vel0x [dalemy@microsoft.com]
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*
* @example
* StrUtils.runUnescape("Don\'t do that", [])
* > "Don't do that"
* StrUtils.runUnescape("Hello\nWorld", [])
* > `Hello
* World`
*/
runUnescape: function(input, args) {
return StrUtils._replaceByKeys(input, "escaped", "unescaped");
},
/**
* Replaces all matching tokens in ESCAPE_REPLACEMENTS with the correction. The
* ordering is determined by the patternKey and the replacementKey.
*
* @author Vel0x [dalemy@microsoft.com]
* @author Matt C [matt@artemisbot.uk]
*
* @param {string} input
* @param {string} pattern_key
* @param {string} replacement_key
* @returns {string}
*/
_replaceByKeys: function(input, patternKey, replacementKey) {
let output = input;
// Catch the \\x encoded characters
if (patternKey === "escaped") output = Utils.parseEscapedChars(input);
StrUtils.ESCAPE_REPLACEMENTS.forEach(replacement => {
output = output.split(replacement[patternKey]).join(replacement[replacementKey]);
});
return output;
},
@@ -476,16 +546,16 @@ const StrUtils = {
const splitInput = input.split(delimiter);
return splitInput
.filter((line, lineIndex) => {
lineIndex += 1;
.filter((line, lineIndex) => {
lineIndex += 1;
if (number < 0) {
return lineIndex <= splitInput.length + number;
} else {
return lineIndex <= number;
}
})
.join(delimiter);
if (number < 0) {
return lineIndex <= splitInput.length + number;
} else {
return lineIndex <= number;
}
})
.join(delimiter);
},
@@ -504,16 +574,16 @@ const StrUtils = {
const splitInput = input.split(delimiter);
return splitInput
.filter((line, lineIndex) => {
lineIndex += 1;
.filter((line, lineIndex) => {
lineIndex += 1;
if (number < 0) {
return lineIndex > -number;
} else {
return lineIndex > splitInput.length - number;
}
})
.join(delimiter);
if (number < 0) {
return lineIndex > -number;
} else {
return lineIndex > splitInput.length - number;
}
})
.join(delimiter);
},

View File

@@ -16,32 +16,32 @@ const Tidy = {
* @constant
* @default
*/
REMOVE_SPACES : true,
REMOVE_SPACES: true,
/**
* @constant
* @default
*/
REMOVE_CARIAGE_RETURNS : true,
REMOVE_CARIAGE_RETURNS: true,
/**
* @constant
* @default
*/
REMOVE_LINE_FEEDS : true,
REMOVE_LINE_FEEDS: true,
/**
* @constant
* @default
*/
REMOVE_TABS : true,
REMOVE_TABS: true,
/**
* @constant
* @default
*/
REMOVE_FORM_FEEDS : true,
REMOVE_FORM_FEEDS: true,
/**
* @constant
* @default
*/
REMOVE_FULL_STOPS : false,
REMOVE_FULL_STOPS: false,
/**
* Remove whitespace operation.
@@ -89,17 +89,17 @@ const Tidy = {
* @constant
* @default
*/
APPLY_TO_EACH_LINE : false,
APPLY_TO_EACH_LINE: false,
/**
* @constant
* @default
*/
DROP_START : 0,
DROP_START: 0,
/**
* @constant
* @default
*/
DROP_LENGTH : 5,
DROP_LENGTH: 5,
/**
* Drop bytes operation.
@@ -200,17 +200,17 @@ const Tidy = {
* @constant
* @default
*/
PAD_POSITION : ["Start", "End"],
PAD_POSITION: ["Start", "End"],
/**
* @constant
* @default
*/
PAD_LENGTH : 5,
PAD_LENGTH: 5,
/**
* @constant
* @default
*/
PAD_CHAR : " ",
PAD_CHAR: " ",
/**
* Pad lines operation.

View File

@@ -127,7 +127,7 @@ const URL_ = {
.replace(/\(/g, "%28")
.replace(/\)/g, "%29")
.replace(/\*/g, "%2A")
.replace(/\-/g, "%2D")
.replace(/-/g, "%2D")
.replace(/\./g, "%2E")
.replace(/_/g, "%5F")
.replace(/~/g, "%7E");

View File

@@ -14,12 +14,12 @@ const CyberChef = module.exports = {
bake: function(input, recipeConfig) {
this.chef = new Chef();
return this.chef.bake(
input,
recipeConfig,
{},
0,
false
);
input,
recipeConfig,
{},
0,
false
);
}
};

View File

@@ -60,6 +60,8 @@ App.prototype.setup = function() {
/**
* Fires once all setup activities have completed.
*
* @fires Manager#apploaded
*/
App.prototype.loaded = function() {
// Trigger CSS animations to remove preloader
@@ -74,6 +76,8 @@ App.prototype.loaded = function() {
// Clear the loading message interval
clearInterval(window.loadingMsgsInt);
document.dispatchEvent(this.manager.apploaded);
};
@@ -200,13 +204,7 @@ App.prototype.silentBake = function() {
* @returns {string}
*/
App.prototype.getInput = function() {
const input = this.manager.input.get();
// Save to session storage in case we need to restore it later
sessionStorage.setItem("inputLength", input.length);
sessionStorage.setItem("input", input);
return input;
return this.manager.input.get();
};
@@ -216,8 +214,6 @@ App.prototype.getInput = function() {
* @param {string} input - The string to set the input to
*/
App.prototype.setInput = function(input) {
sessionStorage.setItem("inputLength", input.length);
sessionStorage.setItem("input", input);
this.manager.input.set(input);
};
@@ -415,7 +411,7 @@ App.prototype.loadURIParams = function() {
// Read in recipe from URI params
if (this.uriParams.recipe) {
try {
const recipeConfig = JSON.parse(this.uriParams.recipe);
const recipeConfig = Utils.parseRecipeConfig(this.uriParams.recipe);
this.setRecipeConfig(recipeConfig);
} catch (err) {}
} else if (this.uriParams.op) {
@@ -468,9 +464,7 @@ App.prototype.nextIngId = function() {
* @returns {Object[]}
*/
App.prototype.getRecipeConfig = function() {
const recipeConfig = this.manager.recipe.getConfig();
sessionStorage.setItem("recipeConfig", JSON.stringify(recipeConfig));
return recipeConfig;
return this.manager.recipe.getConfig();
};
@@ -480,7 +474,6 @@ App.prototype.getRecipeConfig = function() {
* @param {Object[]} recipeConfig - The recipe configuration
*/
App.prototype.setRecipeConfig = function(recipeConfig) {
sessionStorage.setItem("recipeConfig", JSON.stringify(recipeConfig));
document.getElementById("rec-list").innerHTML = null;
for (let i = 0; i < recipeConfig.length; i++) {
@@ -489,6 +482,7 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
// Populate arguments
const args = item.querySelectorAll(".arg");
for (let j = 0; j < args.length; j++) {
if (recipeConfig[i].args[j] === undefined) continue;
if (args[j].getAttribute("type") === "checkbox") {
// checkbox
args[j].checked = recipeConfig[i].args[j];
@@ -535,15 +529,24 @@ App.prototype.resetLayout = function() {
App.prototype.setCompileMessage = function() {
// Display time since last build and compile message
let now = new Date(),
timeSinceCompile = Utils.fuzzyTime(now.getTime() - window.compileTime),
compileInfo = "<span style=\"font-weight: normal\">Last build: " +
timeSinceCompile.substr(0, 1).toUpperCase() + timeSinceCompile.substr(1) + " ago";
timeSinceCompile = Utils.fuzzyTime(now.getTime() - window.compileTime);
// Calculate previous version to compare to
let prev = PKG_VERSION.split(".").map(n => {
return parseInt(n, 10);
});
if (prev[2] > 0) prev[2]--;
else if (prev[1] > 0) prev[1]--;
else prev[0]--;
const compareURL = `https://github.com/gchq/CyberChef/compare/v${prev.join(".")}...v${PKG_VERSION}`;
let compileInfo = `<a href='${compareURL}'>Last build: ${timeSinceCompile.substr(0, 1).toUpperCase() + timeSinceCompile.substr(1)} ago</a>`;
if (window.compileMessage !== "") {
compileInfo += " - " + window.compileMessage;
}
compileInfo += "</span>";
document.getElementById("notice").innerHTML = compileInfo;
};
@@ -668,10 +671,27 @@ App.prototype.alertCloseClick = function() {
App.prototype.stateChange = function(e) {
this.autoBake();
// Set title
const recipeConfig = this.getRecipeConfig();
let title = "CyberChef";
if (recipeConfig.length === 1) {
title = `${recipeConfig[0].op} - ${title}`;
} else if (recipeConfig.length > 1) {
// See how long the full recipe is
const ops = recipeConfig.map(op => op.op).join(", ");
if (ops.length < 45) {
title = `${ops} - ${title}`;
} else {
// If it's too long, just use the first one and say how many more there are
title = `${recipeConfig[0].op}, ${recipeConfig.length - 1} more - ${title}`;
}
}
document.title = title;
// Update the current history state (not creating a new one)
if (this.options.updateUrl) {
this.lastStateUrl = this.manager.controls.generateStateUrl(true, true);
window.history.replaceState({}, "CyberChef", this.lastStateUrl);
this.lastStateUrl = this.manager.controls.generateStateUrl(true, true, recipeConfig);
window.history.replaceState({}, title, this.lastStateUrl);
}
};

View File

@@ -170,7 +170,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
const link = baseURL || window.location.protocol + "//" +
window.location.host +
window.location.pathname;
const recipeStr = JSON.stringify(recipeConfig);
const recipeStr = Utils.generatePrettyRecipe(recipeConfig);
const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
includeRecipe = includeRecipe && (recipeConfig.length > 0);
@@ -183,9 +183,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
];
const hash = params
.filter(v => v)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("&");
.filter(v => v)
.map(([key, value]) => `${key}=${Utils.encodeURIFragment(value)}`)
.join("&");
if (hash) {
return `${link}#${hash}`;
@@ -198,9 +198,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
/**
* Handler for changes made to the save dialog text area. Re-initialises the save link.
*/
ControlsWaiter.prototype.saveTextChange = function() {
ControlsWaiter.prototype.saveTextChange = function(e) {
try {
const recipeConfig = JSON.parse(document.getElementById("save-text").value);
const recipeConfig = Utils.parseRecipeConfig(e.target.value);
this.initialiseSaveLink(recipeConfig);
} catch (err) {}
};
@@ -211,9 +211,16 @@ ControlsWaiter.prototype.saveTextChange = function() {
*/
ControlsWaiter.prototype.saveClick = function() {
const recipeConfig = this.app.getRecipeConfig();
const recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
const recipeStr = JSON.stringify(recipeConfig);
document.getElementById("save-text").value = recipeStr;
document.getElementById("save-text-chef").value = Utils.generatePrettyRecipe(recipeConfig, true);
document.getElementById("save-text-clean").value = JSON.stringify(recipeConfig, null, 2)
.replace(/{\n\s+"/g, "{ \"")
.replace(/\[\n\s{3,}/g, "[")
.replace(/\n\s{3,}]/g, "]")
.replace(/\s*\n\s*}/g, " }")
.replace(/\n\s{6,}/g, " ");
document.getElementById("save-text-compact").value = recipeStr;
this.initialiseSaveLink(recipeConfig);
$("#save-modal").modal();
@@ -250,7 +257,7 @@ ControlsWaiter.prototype.loadClick = function() {
*/
ControlsWaiter.prototype.saveButtonClick = function() {
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
const recipeStr = document.getElementById("save-text").value;
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
if (!recipeName) {
this.app.alert("Please enter a recipe name", "danger", 2000);
@@ -288,7 +295,7 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
// Add recipes to select
const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
JSON.parse(localStorage.savedRecipes) : [];
for (i = 0; i < savedRecipes.length; i++) {
const opt = document.createElement("option");
@@ -310,7 +317,7 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
ControlsWaiter.prototype.loadDeleteClick = function() {
const id = parseInt(document.getElementById("load-name").value, 10);
const rawSavedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
JSON.parse(localStorage.savedRecipes) : [];
const savedRecipes = rawSavedRecipes.filter(r => r.id !== id);
@@ -325,7 +332,7 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
ControlsWaiter.prototype.loadNameChange = function(e) {
const el = e.target;
const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
JSON.parse(localStorage.savedRecipes) : [];
const id = parseInt(el.value, 10);
const recipe = savedRecipes.find(r => r.id === id);
@@ -339,7 +346,7 @@ ControlsWaiter.prototype.loadNameChange = function(e) {
*/
ControlsWaiter.prototype.loadButtonClick = function() {
try {
const recipeConfig = JSON.parse(document.getElementById("load-text").value);
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
this.app.setRecipeConfig(recipeConfig);
$("#rec-list [data-toggle=popover]").popover();

View File

@@ -493,13 +493,14 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
//if (colour) cssClass += "-"+colour;
// Remove HTML tags
text = text.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/\n/g, "&#10;")
// Convert placeholders to tags
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
.replace(endPlaceholderRegex, "</span>") + "&nbsp;";
text = text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/\n/g, "&#10;")
// Convert placeholders to tags
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
.replace(endPlaceholderRegex, "</span>") + "&nbsp;";
// Adjust width to allow for scrollbars
highlighter.style.width = textarea.clientWidth + "px";

View File

@@ -166,7 +166,7 @@ InputWaiter.prototype.inputDrop = function(e) {
this.set(inputCharcode);
const recipeConfig = this.app.getRecipeConfig();
if (!recipeConfig[0] || recipeConfig[0].op !== "From Hex") {
recipeConfig.unshift({op:"From Hex", args:["Space"]});
recipeConfig.unshift({op: "From Hex", args: ["Space"]});
this.app.setRecipeConfig(recipeConfig);
}

View File

@@ -27,6 +27,10 @@ const Manager = function(app) {
* @event Manager#appstart
*/
this.appstart = new CustomEvent("appstart", {bubbles: true});
/**
* @event Manager#apploaded
*/
this.apploaded = new CustomEvent("apploaded", {bubbles: true});
/**
* @event Manager#operationadd
*/
@@ -98,7 +102,7 @@ Manager.prototype.initialiseEventListeners = function() {
document.getElementById("load-name").addEventListener("change", this.controls.loadNameChange.bind(this.controls));
document.getElementById("load-button").addEventListener("click", this.controls.loadButtonClick.bind(this.controls));
document.getElementById("support").addEventListener("click", this.controls.supportButtonClick.bind(this.controls));
this.addMultiEventListener("#save-text", "keyup paste", this.controls.saveTextChange, this.controls);
this.addMultiEventListeners("#save-texts textarea", "keyup paste", this.controls.saveTextChange, this.controls);
// Operations
this.addMultiEventListener("#search", "keyup paste search", this.ops.searchOperations, this.ops);
@@ -114,6 +118,7 @@ Manager.prototype.initialiseEventListeners = function() {
// Recipe
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".arg", "change", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".arg", "input", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe);
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);

View File

@@ -155,7 +155,35 @@ OperationsWaiter.prototype.getSelectedOp = function(ops) {
*/
OperationsWaiter.prototype.opListCreate = function(e) {
this.manager.recipe.createSortableSeedList(e.target);
$("[data-toggle=popover]").popover();
this.enableOpsListPopovers(e.target);
};
/**
* Sets up popovers, allowing the popover itself to gain focus which enables scrolling
* and other interactions.
*
* @param {Element} el - The element to start selecting from
*/
OperationsWaiter.prototype.enableOpsListPopovers = function(el) {
$(el).find("[data-toggle=popover]").addBack("[data-toggle=popover]")
.popover({trigger: "manual"})
.on("mouseenter", function() {
const _this = this;
$(this).popover("show");
$(".popover").on("mouseleave", function () {
$(_this).popover("hide");
});
}).on("mouseleave", function () {
const _this = this;
setTimeout(function() {
// Determine if the popover associated with this element is being hovered over
if ($(_this).data("bs.popover") &&
!$(_this).data("bs.popover").$tip.is(":hover")) {
$(_this).popover("hide");
}
}, 50);
});
};

View File

@@ -93,7 +93,7 @@ RecipeWaiter.prototype.createSortableSeedList = function(listEl) {
// Removes popover element and event bindings from the dragged operation but not the
// event bindings from the one left in the operations list. Without manually removing
// these bindings, we cannot re-initialise the popover on the stub operation.
$(evt.item).popover("destroy");
$(evt.item).popover("destroy").removeData("bs.popover").off("mouseenter").off("mouseleave");
$(evt.clone).off(".popover").removeData("bs.popover");
evt.item.setAttribute("data-toggle", "popover-disabled");
},
@@ -120,8 +120,7 @@ RecipeWaiter.prototype.opSortEnd = function(evt) {
// Reinitialise the popover on the original element in the ops list because for some reason it
// gets destroyed and recreated.
$(evt.clone).popover();
$(evt.clone).children("[data-toggle=popover]").popover();
this.manager.ops.enableOpsListPopovers(evt.clone);
if (evt.item.parentNode.id !== "rec-list") {
return;
@@ -296,6 +295,9 @@ RecipeWaiter.prototype.getConfig = function() {
option: ingList[j].previousSibling.children[0].textContent.slice(0, -1),
string: ingList[j].value
};
} else if (ingList[j].getAttribute("type") === "number") {
// number
ingredients[j] = parseFloat(ingList[j].value, 10);
} else {
// all others
ingredients[j] = ingList[j].value;

View File

@@ -26,7 +26,7 @@
<title>CyberChef</title>
<meta name="copyright" content="Crown Copyright 2016" />
<meta name="description" content="The Cyber Swiss Army Knife" />
<meta name="description" content="The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis" />
<meta name="keywords" content="base64, hex, decode, encode, encrypt, decrypt, compress, decompress, regex, regular expressions, hash, crypt, hexadecimal, user agent, url, certificate, x.509, parser, JSON, gzip, md5, sha1, aes, des, blowfish, xor" />
<link rel="icon" type="image/ico" href="<%- require('../static/images/favicon.ico') %>" />
@@ -35,7 +35,9 @@
"use strict";
// Load theme before the preloader is shown
document.querySelector(":root").className = JSON.parse(localStorage.getItem("options")).theme;
try {
document.querySelector(":root").className = JSON.parse(localStorage.getItem("options")).theme;
} catch (e) {}
// Define loading messages
const loadingMsgs = [
@@ -46,10 +48,15 @@
"Initialising Skynet...",
"[REDACTED]",
"Downloading more RAM...",
"Loading more loading messages...",
"Ordering 1s and 0s...",
"Navigating neural network...",
"Importing machine learning..."
"Importing machine learning...",
"Issuing Alice and Bob one-time pads...",
"Mining bitcoin cash...",
"Generating key material by trying to escape vim...",
"for i in range(additional): Pylon()",
"(creating unresolved tension...",
"Symlinking emacs and vim to ed...",
];
// Shuffle array using Durstenfeld algorithm
@@ -60,20 +67,25 @@
loadingMsgs[j] = temp;
}
// Show next loading message then move it to the end of the array
// Show next loading message and move it to the end of the array
function changeLoadingMsg() {
const msg = loadingMsgs.shift();
loadingMsgs.push(msg);
try {
const el = document.getElementById("preloader-msg");
el.className = "loading"; // Causes CSS transition on first message
el.innerHTML = msg;
} catch (err) {} // Ignore errors if DOM not yet ready
loadingMsgs.push(msg);
}
changeLoadingMsg();
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 1000) + 1000);
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 2000) + 1500);
</script>
<% if (!htmlWebpackPlugin.options.inline) { %>
<script type="application/ld+json">
<% print(JSON.stringify(require("../static/structuredData.json"))); %>
</script>
<% } %>
</head>
<body>
<!-- Preloader overlay -->
@@ -203,7 +215,22 @@
<div class="modal-body">
<div class="form-group">
<label for="save-text">Save your recipe to local storage or copy the following string to load later</label>
<textarea class="form-control" id="save-text" rows="5"></textarea>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#chef-format" role="tab" data-toggle="tab">Chef format</a></li>
<li role="presentation"><a href="#clean-json" role="tab" data-toggle="tab">Clean JSON</a></li>
<li role="presentation"><a href="#compact-json" role="tab" data-toggle="tab">Compact JSON</a></li>
</ul>
<div class="tab-content" id="save-texts">
<div role="tabpanel" class="tab-pane active" id="chef-format">
<textarea class="form-control" id="save-text-chef" rows="5"></textarea>
</div>
<div role="tabpanel" class="tab-pane" id="clean-json">
<textarea class="form-control" id="save-text-clean" rows="5"></textarea>
</div>
<div role="tabpanel" class="tab-pane" id="compact-json">
<textarea class="form-control" id="save-text-compact" rows="5"></textarea>
</div>
</div>
</div>
<div class="form-group">
<label for="save-name">Recipe name</label>
@@ -268,36 +295,37 @@
<select option="theme" id="theme">
<option value="classic">Classic</option>
<option value="dark">Dark</option>
<option value="geocities">GeoCities</option>
</select>
<label for="theme"> Theme (only supported in modern browsers)</label>
</div>
<div class="option-item">
<input type="checkbox" option="update_url" id="update_url" checked />
<label for="update_url"> Update the URL when the input or recipe changes </label>
<input type="checkbox" option="updateUrl" id="updateUrl" checked />
<label for="updateUrl"> Update the URL when the input or recipe changes </label>
</div>
<div class="option-item">
<input type="checkbox" option="show_highlighter" id="show_highlighter" checked />
<label for="show_highlighter"> Highlight selected bytes in output and input (when possible) </label>
<input type="checkbox" option="showHighlighter" id="showHighlighter" checked />
<label for="showHighlighter"> Highlight selected bytes in output and input (when possible) </label>
</div>
<div class="option-item">
<input type="checkbox" option="treat_as_utf8" id="treat_as_utf8" checked />
<label for="treat_as_utf8"> Treat output as UTF-8 if possible </label>
<input type="checkbox" option="treatAsUtf8" id="treatAsUtf8" checked />
<label for="treatAsUtf8"> Treat output as UTF-8 if possible </label>
</div>
<div class="option-item">
<input type="checkbox" option="word_wrap" id="word_wrap" checked />
<label for="word_wrap"> Word wrap the input and output </label>
<input type="checkbox" option="wordWrap" id="wordWrap" checked />
<label for="wordWrap"> Word wrap the input and output </label>
</div>
<div class="option-item">
<input type="checkbox" option="show_errors" id="show_errors" checked />
<label for="show_errors"> Operation error reporting (recommended) </label>
<input type="checkbox" option="showErrors" id="showErrors" checked />
<label for="showErrors"> Operation error reporting (recommended) </label>
</div>
<div class="option-item">
<input type="number" option="error_timeout" id="error_timeout" />
<label for="error_timeout"> Operation error timeout in ms (0 for never) </label>
<input type="number" option="errorTimeout" id="errorTimeout" />
<label for="errorTimeout"> Operation error timeout in ms (0 for never) </label>
</div>
<div class="option-item">
<input type="number" option="auto_bake_threshold" id="auto_bake_threshold"/>
<label for="auto_bake_threshold"> Auto Bake threshold in ms </label>
<input type="number" option="autoBakeThreshold" id="autoBakeThreshold"/>
<label for="autoBakeThreshold"> Auto Bake threshold in ms </label>
</div>
</div>
<div class="modal-footer">
@@ -378,12 +406,12 @@
<div class="collapse" id="faq-examples">
<p>There are around 200 operations in CyberChef allowing you to carry out simple and complex tasks easily. Here are some examples:</p>
<ul>
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
<li><a href="#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
<li><a href="#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
<li><a href="#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
<li><a href="#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
</ul>
</div>
<blockquote>
@@ -403,7 +431,7 @@
<div class="collapse" id="faq-fork">
<p>Maybe you have 10 timestamps that you want to parse or 16 encoded strings that all have the same key.</p>
<p>The 'Fork' operation (found in the 'Flow control' category) splits up the input line by line and runs all subsequent operations on each line separately. Each output is then displayed on a separate line. These delimiters can be changed, so if your inputs are separated by commas, you can change the split delimiter to a comma instead.</p>
<p><a href='#recipe=%5B%7B"op"%3A"Fork"%2C"args"%3A%5B"%5C%5Cn"%2C"%5C%5Cn"%5D%7D%2C%7B"op"%3A"From%20UNIX%20Timestamp"%2C"args"%3A%5B"Seconds%20(s)"%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA%3D%3D'>Click here</a> for an example.</p>
<p><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Click here</a> for an example.</p>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="report-bug">

View File

@@ -38,15 +38,15 @@ function main() {
];
const defaultOptions = {
updateUrl : true,
showHighlighter : true,
treatAsUtf8 : true,
wordWrap : true,
showErrors : true,
errorTimeout : 4000,
autoBakeThreshold : 200,
attemptHighlight : true,
theme : "classic",
updateUrl: true,
showHighlighter: true,
treatAsUtf8: true,
wordWrap: true,
showErrors: true,
errorTimeout: 4000,
autoBakeThreshold: 200,
attemptHighlight: true,
theme: "classic",
};
document.removeEventListener("DOMContentLoaded", main, false);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 773 B

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 445 B

View File

@@ -0,0 +1,23 @@
[
{
"@context": "http://schema.org",
"@type": "Organization",
"url": "https://gchq.github.io/CyberChef/",
"logo": "https://gchq.github.io/CyberChef/images/cyberchef-128x128.png",
"sameAs": [
"https://github.com/gchq/CyberChef",
"https://www.npmjs.com/package/cyberchef"
]
},
{
"@context": "http://schema.org",
"@type": "WebSite",
"url": "https://gchq.github.io/CyberChef/",
"name": "CyberChef",
"potentialAction": {
"@type": "SearchAction",
"target": "https://gchq.github.io/CyberChef/?op={operation_search_term}",
"query-input": "required name=operation_search_term"
}
}
]

View File

@@ -59,6 +59,7 @@
background-color: var(--arg-background);
border: 1px solid var(--arg-border-colour);
font-family: var(--fixed-width-font-family);
text-overflow: ellipsis;
}
.short-string {

View File

@@ -9,6 +9,7 @@
/* Themes */
@import "./themes/_classic.css";
@import "./themes/_dark.css";
@import "./themes/_geocities.css";
/* Utilities */
@import "./utils/_overrides.css";

View File

@@ -78,7 +78,13 @@
font-family: var(--primary-font-family);
}
#save-text,
#save-texts textarea,
#load-text {
font-family: var(--fixed-width-font-family);
}
#save-texts textarea {
border-top: none;
box-shadow: none;
height: 200px;
}

View File

@@ -62,8 +62,8 @@
#preloader-msg {
display: block;
position: relative;
width: 300px;
left: calc(50% - 150px);
width: 400px;
left: calc(50% - 200px);
top: calc(50% + 50px);
text-align: center;
margin-top: 50px;

View File

@@ -0,0 +1,115 @@
/**
* GeoCities theme definitions
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
:root.geocities {
--primary-font-family: "Comic Sans", "Comic Sans MS", "Chalkboard", "ChalkboardSE-Regular", "Marker Felt", "Purisa", "URW Chancery L", cursive, sans-serif;
--primary-font-colour: black;
--primary-font-size: 14px;
--primary-line-height: 20px;
--fixed-width-font-family: "Courier New", Courier, monospace;
--fixed-width-font-colour: yellow;
--fixed-width-font-size: inherit;
--subtext-font-colour: darkgrey;
--subtext-font-size: 13px;
--primary-background-colour: #00f;
--secondary-background-colour: #f00;
--primary-border-colour: pink;
--secondary-border-colour: springgreen;
--title-colour: red;
--title-weight: bold;
--title-background-colour: yellow;
--banner-font-colour: white;
--banner-bg-colour: maroon;
/* Operation colours */
--op-list-operation-font-colour: blue;
--op-list-operation-bg-colour: yellow;
--op-list-operation-border-colour: green;
--rec-list-operation-font-colour: white;
--rec-list-operation-bg-colour: purple;
--rec-list-operation-border-colour: green;
--selected-operation-font-color: white;
--selected-operation-bg-colour: pink;
--selected-operation-border-colour: blue;
--breakpoint-font-colour: white;
--breakpoint-bg-colour: red;
--breakpoint-border-colour: blue;
--disabled-font-colour: grey;
--disabled-bg-colour: black;
--disabled-border-colour: grey;
--fc-operation-font-colour: sienna;
--fc-operation-bg-colour: pink;
--fc-operation-border-colour: yellow;
--fc-breakpoint-operation-font-colour: darkgrey;
--fc-breakpoint-operation-bg-colour: deeppink;
--fc-breakpoint-operation-border-colour: yellowgreen;
/* Operation arguments */
--arg-title-font-weight: bold;
--arg-input-height: 34px;
--arg-input-line-height: 20px;
--arg-input-font-size: 15px;
--arg-font-colour: white;
--arg-background: black;
--arg-border-colour: lime;
--arg-disabled-background: grey;
/* Buttons */
--btn-default-font-colour: black;
--btn-default-bg-colour: white;
--btn-default-border-colour: grey;
--btn-default-hover-font-colour: black;
--btn-default-hover-bg-colour: white;
--btn-default-hover-border-colour: grey;
--btn-success-font-colour: white;
--btn-success-bg-colour: lawngreen;
--btn-success-border-colour: grey;
--btn-success-hover-font-colour: white;
--btn-success-hover-bg-colour: lime;
--btn-success-hover-border-colour: grey;
/* Highlighter colours */
--hl1: #fff000;
--hl2: #95dfff;
--hl3: #ffb6b6;
--hl4: #fcf8e3;
--hl5: #8de768;
/* Scrollbar */
--scrollbar-track: lightsteelblue;
--scrollbar-thumb: lightslategrey;
--scrollbar-hover: grey;
/* Misc. */
--drop-file-border-colour: purple;
--popover-background: turquoise;
--popover-border-colour: violet;
--code-background: black;
--code-font-colour: limegreen;
}

View File

@@ -142,6 +142,10 @@ optgroup {
border-color: var(--popover-border-colour);
}
.popover-content {
max-height: 90vh;
overflow-y: auto;
}
.popover.right>.arrow {
border-right-color: var(--popover-border-colour);

View File

@@ -46,8 +46,7 @@ import Chef from "../src/core/Chef.js";
{},
0,
false
)
.then(function(result) {
).then(function(result) {
const ret = {
test: test,
status: null,

View File

@@ -12,6 +12,8 @@ import "babel-polyfill";
import TestRegister from "./TestRegister.js";
import "./tests/operations/Base58.js";
import "./tests/operations/BCD.js";
import "./tests/operations/BitwiseOp.js";
import "./tests/operations/ByteRepr.js";
import "./tests/operations/CharEnc.js";
import "./tests/operations/Cipher.js";
@@ -21,9 +23,11 @@ import "./tests/operations/DateTime.js";
import "./tests/operations/FlowControl.js";
import "./tests/operations/Image.js";
import "./tests/operations/MorseCode.js";
import "./tests/operations/MS.js";
import "./tests/operations/StrUtils.js";
import "./tests/operations/SeqUtils.js";
let allTestsPassing = true;
const testStatusCounts = {
total: 0,

View File

@@ -0,0 +1,103 @@
/**
* BCD tests
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "To BCD: default 0",
input: "0",
expectedOutput: "0000",
recipeConfig: [
{
"op": "To BCD",
"args": ["8 4 2 1", true, false, "Nibbles"]
}
]
},
{
name: "To BCD: unpacked nibbles",
input: "1234567890",
expectedOutput: "0000 0001 0000 0010 0000 0011 0000 0100 0000 0101 0000 0110 0000 0111 0000 1000 0000 1001 0000 0000",
recipeConfig: [
{
"op": "To BCD",
"args": ["8 4 2 1", false, false, "Nibbles"]
}
]
},
{
name: "To BCD: packed, signed bytes",
input: "1234567890",
expectedOutput: "00000001 00100011 01000101 01100111 10001001 00001100",
recipeConfig: [
{
"op": "To BCD",
"args": ["8 4 2 1", true, true, "Bytes"]
}
]
},
{
name: "To BCD: packed, signed nibbles, 8 4 -2 -1",
input: "-1234567890",
expectedOutput: "0000 0111 0110 0101 0100 1011 1010 1001 1000 1111 0000 1101",
recipeConfig: [
{
"op": "To BCD",
"args": ["8 4 -2 -1", true, true, "Nibbles"]
}
]
},
{
name: "From BCD: default 0",
input: "0000",
expectedOutput: "0",
recipeConfig: [
{
"op": "From BCD",
"args": ["8 4 2 1", true, false, "Nibbles"]
}
]
},
{
name: "From BCD: packed, signed bytes",
input: "00000001 00100011 01000101 01100111 10001001 00001101",
expectedOutput: "-1234567890",
recipeConfig: [
{
"op": "From BCD",
"args": ["8 4 2 1", true, true, "Bytes"]
}
]
},
{
name: "From BCD: Excess-3, unpacked, unsigned",
input: "00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00000011",
expectedOutput: "1234567890",
recipeConfig: [
{
"op": "From BCD",
"args": ["Excess-3", false, false, "Nibbles"]
}
]
},
{
name: "BCD: raw 4 2 2 1, packed, signed",
input: "1234567890",
expectedOutput: "1234567890",
recipeConfig: [
{
"op": "To BCD",
"args": ["4 2 2 1", true, true, "Raw"]
},
{
"op": "From BCD",
"args": ["4 2 2 1", true, true, "Raw"]
}
]
},
]);

View File

@@ -0,0 +1,50 @@
/**
* BitwiseOp tests
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "Bit shift left",
input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100",
expectedOutput: "10101010 01010100 11111110 00000000 11100000 00011110 01100110 10011000",
recipeConfig: [
{ "op": "From Binary",
"args": ["Space"] },
{ "op": "Bit shift left",
"args": [1] },
{ "op": "To Binary",
"args": ["Space"] }
]
},
{
name: "Bit shift right: Logical shift",
input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100",
expectedOutput: "00101010 01010101 01111111 00000000 01111000 00000111 00011001 01100110",
recipeConfig: [
{ "op": "From Binary",
"args": ["Space"] },
{ "op": "Bit shift right",
"args": [1, "Logical shift"] },
{ "op": "To Binary",
"args": ["Space"] }
]
},
{
name: "Bit shift right: Arithmetic shift",
input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100",
expectedOutput: "00101010 11010101 11111111 00000000 11111000 00000111 00011001 11100110",
recipeConfig: [
{ "op": "From Binary",
"args": ["Space"] },
{ "op": "Bit shift right",
"args": [1, "Arithmetic shift"] },
{ "op": "To Binary",
"args": ["Space"] }
]
},
]);

View File

@@ -2,12 +2,54 @@
* Code tests.
*
* @author tlwr [toby@toby.codes]
* @author Matt C [matt@artemisbot.uk]
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
const JPATH_TEST_DATA = {
"store": {
"book": [{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
}, {
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}, {
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}, {
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}],
"bicycle": {
"color": "red",
"price": 19.95
},
"newspaper": [{
"format": "broadsheet",
"title": "Financial Times",
"price": 2.75
}, {
"format": "tabloid",
"title": "The Guardian",
"price": 2.00
}]
}
};
TestRegister.addTests([
{
name: "To Camel case (dumb)",
@@ -129,4 +171,143 @@ TestRegister.addTests([
}
],
},
{
name: "JPath Expression: Empty JSON",
input: "",
expectedOutput: "Invalid input JSON: Unexpected end of JSON input",
recipeConfig: [
{
"op": "JPath expression",
"args": ["", "\n"]
}
],
},
{
name: "JPath Expression: Empty expression",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: "Invalid JPath expression: we need a path",
recipeConfig: [
{
"op": "JPath expression",
"args": ["", "\n"]
}
],
},
{
name: "JPath Expression: Fetch of values from specific object",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"\"Nigel Rees\"",
"\"Evelyn Waugh\"",
"\"Herman Melville\"",
"\"J. R. R. Tolkien\""
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$.store.book[*].author", "\n"]
}
],
},
{
name: "JPath Expression: Fetch of all values with matching key",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"\"Sayings of the Century\"",
"\"Sword of Honour\"",
"\"Moby Dick\"",
"\"The Lord of the Rings\"",
"\"Financial Times\"",
"\"The Guardian\""
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..title", "\n"]
}
],
},
{
name: "JPath Expression: All data in object",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}]",
"{\"color\":\"red\",\"price\":19.95}",
"[{\"format\":\"broadsheet\",\"title\":\"Financial Times\",\"price\":2.75},{\"format\":\"tabloid\",\"title\":\"The Guardian\",\"price\":2}]"
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$.store.*", "\n"]
}
],
},
{
name: "JPath Expression: Last element in array",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: "{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}",
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[-1:]", "\n"]
}
],
},
{
name: "JPath Expression: First 2 elements in array",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95}",
"{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99}"
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[:2]", "\n"]
}
],
},
{
name: "JPath Expression: All elements in array with property",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}",
"{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}"
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[?(@.isbn)]", "\n"]
}
],
},
{
name: "JPath Expression: All elements in array which meet condition",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99}",
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}",
"{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}"
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[?(@.price<30 && @.category==\"fiction\")]", "\n"]
}
],
},
{
name: "JPath Expression: All elements in object",
input: JSON.stringify(JPATH_TEST_DATA),
expectedOutput: [
"{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95}",
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}"
].join("\n"),
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[?(@.price<10)]", "\n"]
}
],
},
]);

View File

@@ -14,12 +14,12 @@ TestRegister.addTests([
expectedOutput: "The cat sat on the mat.",
recipeConfig: [
{
"op" : "From Hex",
"args" : ["Space"]
"op": "From Hex",
"args": ["Space"]
},
{
"op" : "Bzip2 Decompress",
"args" : []
"op": "Bzip2 Decompress",
"args": []
}
],
},

View File

@@ -59,11 +59,11 @@ TestRegister.addTests([
input: "Some data with a 1 in it\nSome data with a 2 in it",
expectedOutput: "U29tZSBkYXRhIHdpdGggYSAxIGluIGl0\n53 6f 6d 65 20 64 61 74 61 20 77 69 74 68 20 61 20 32 20 69 6e 20 69 74\n",
recipeConfig: [
{"op":"Fork", "args":["\\n", "\\n", false]},
{"op":"Conditional Jump", "args":["1", "2", "10"]},
{"op":"To Hex", "args":["Space"]},
{"op":"Return", "args":[]},
{"op":"To Base64", "args":["A-Za-z0-9+/="]}
{"op": "Fork", "args": ["\\n", "\\n", false]},
{"op": "Conditional Jump", "args": ["1", "2", "10"]},
{"op": "To Hex", "args": ["Space"]},
{"op": "Return", "args": []},
{"op": "To Base64", "args": ["A-Za-z0-9+/="]}
]
},
{

View File

@@ -73,11 +73,11 @@ TestRegister.addTests([
"",
"Make: SONY",
"Model: DSC-H5",
"XResolution: 72",
"YResolution: 72",
"XResolution: 70",
"YResolution: 70",
"ResolutionUnit: 2",
"Software: Pictomio 1.2.31.0",
"ModifyDate: 2010:07:04 23:31:13",
"ModifyDate: 1278286273",
"ExposureTime: 0.008",
"FNumber: 3.7",
"ExposureProgram: 3",

View File

@@ -0,0 +1,22 @@
/**
* MS tests.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "Microsoft Script Decoder",
input: "#@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&@*eEI@#@&@#@&\x7fjm.raY 214Wv:zms/obI0xEAAA==^#~@",
expectedOutput: "var my_msg = \"Testing <1><2><3>!\";\r\n\r\nWScript.Echo(my_msg);",
recipeConfig: [
{
"op": "Microsoft Script Decoder",
"args": []
},
],
},
]);

View File

@@ -26,7 +26,7 @@ TestRegister.addTests([
{
name: "Diff, basic usage",
input: "testing23\n\ntesting123",
expectedOutput: "testing<span class='hlgreen'>1</span>23",
expectedOutput: "testing<span class='hl5'>1</span>23",
recipeConfig: [
{
"op": "Diff",
@@ -232,4 +232,48 @@ TestRegister.addTests([
}
],
},
{
name: "Escape String: quotes",
input: "Hello \"World\"! Escape 'these' quotes.",
expectedOutput: "Hello \\\"World\\\"! Escape \\'these\\' quotes.",
recipeConfig: [
{
"op": "Escape string",
"args": []
}
],
},
{
name: "Escape String: special characters",
input: "Fizz & buzz\n\ttabbed newline\rcarriage returned line\nbackspace character: \"\" form feed character: \" \"",
expectedOutput: "Fizz & buzz\\n\\ttabbed newline\\rcarriage returned line\\nbackspace character: \\\"\\b\\\" form feed character: \\\"\\f\\\"",
recipeConfig: [
{
"op": "Escape string",
"args": []
}
],
},
{
name: "Unescape String: quotes",
input: "Hello \\\"World\\\"! Escape \\'these\\' quotes.",
expectedOutput: "Hello \"World\"! Escape 'these' quotes.",
recipeConfig: [
{
"op": "Unescape string",
"args": []
}
],
},
{
name: "Unescape String: special characters",
input: "Fizz \x26 buzz\\n\\ttabbed newline\\rcarriage returned line\\nbackspace character: \\\"\\b\\\" form feed character: \\\"\\f\\\"",
expectedOutput: "Fizz & buzz\n\ttabbed newline\rcarriage returned line\nbackspace character: \"\" form feed character: \" \"",
recipeConfig: [
{
"op": "Unescape string",
"args": []
}
],
},
]);