Compare commits

..

48 Commits

Author SHA1 Message Date
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
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
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
25 changed files with 1198 additions and 198 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

@@ -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

565
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "5.12.2",
"version": "5.13.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -153,13 +153,13 @@
"dev": true
},
"anymatch": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz",
"integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
"integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
"dev": true,
"requires": {
"arrify": "1.0.1",
"micromatch": "2.3.11"
"micromatch": "2.3.11",
"normalize-path": "2.1.1"
}
},
"argparse": {
@@ -865,7 +865,6 @@
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz",
"integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=",
"dev": true,
"requires": {
"babel-runtime": "6.23.0",
"core-js": "2.4.1",
@@ -929,7 +928,6 @@
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz",
"integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=",
"dev": true,
"requires": {
"core-js": "2.4.1",
"regenerator-runtime": "0.10.5"
@@ -1012,9 +1010,9 @@
"dev": true
},
"binary-extensions": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz",
"integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=",
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.9.0.tgz",
"integrity": "sha1-ZlBsFs5vTWkopbPNajPKQelB43s=",
"dev": true
},
"bluebird": {
@@ -1318,7 +1316,7 @@
"integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
"dev": true,
"requires": {
"anymatch": "1.3.0",
"anymatch": "1.3.2",
"async-each": "1.0.1",
"glob-parent": "2.0.0",
"inherits": "2.0.3",
@@ -1344,6 +1342,11 @@
"integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=",
"dev": true
},
"cjson": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/cjson/-/cjson-0.2.1.tgz",
"integrity": "sha1-c82KrWXZ4VBfmvF0TTt5wVJ2gqU="
},
"clap": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/clap/-/clap-1.2.0.tgz",
@@ -1557,8 +1560,7 @@
"core-js": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
"dev": true
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4="
},
"core-util-is": {
"version": "1.0.2",
@@ -1662,7 +1664,7 @@
"create-hmac": "1.1.6",
"diffie-hellman": "5.0.2",
"inherits": "2.0.3",
"pbkdf2": "3.0.12",
"pbkdf2": "3.0.13",
"public-encrypt": "4.0.0",
"randombytes": "2.0.5"
}
@@ -1836,7 +1838,7 @@
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
"dev": true,
"requires": {
"es5-ext": "0.10.24"
"es5-ext": "0.10.26"
}
},
"dashdash": {
@@ -2033,6 +2035,12 @@
}
}
},
"dom-walk": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
"integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=",
"dev": true
},
"domain-browser": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
@@ -2064,6 +2072,11 @@
"domelementtype": "1.3.0"
}
},
"ebnf-parser": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz",
"integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE="
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
@@ -2111,15 +2124,15 @@
"dev": true
},
"enhanced-resolve": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.3.0.tgz",
"integrity": "sha512-2qbxE7ek3YxPJ1ML6V+satHkzHpJQKWkRHmRx6mfAoW59yP8YH8BFplbegSP+u2hBd6B6KCOpvJQ3dZAP+hkpg==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
"integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"memory-fs": "0.4.1",
"object-assign": "4.1.1",
"tapable": "0.2.7"
"tapable": "0.2.8"
}
},
"entities": {
@@ -2147,9 +2160,9 @@
}
},
"es5-ext": {
"version": "0.10.24",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz",
"integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=",
"version": "0.10.26",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.26.tgz",
"integrity": "sha1-UbISilMbcMT2dkCTpzy+u4IYY3I=",
"dev": true,
"requires": {
"es6-iterator": "2.0.1",
@@ -2163,7 +2176,7 @@
"dev": true,
"requires": {
"d": "1.0.0",
"es5-ext": "0.10.24",
"es5-ext": "0.10.26",
"es6-symbol": "3.1.1"
}
},
@@ -2174,7 +2187,7 @@
"dev": true,
"requires": {
"d": "1.0.0",
"es5-ext": "0.10.24",
"es5-ext": "0.10.26",
"es6-iterator": "2.0.1",
"es6-set": "0.1.5",
"es6-symbol": "3.1.1",
@@ -2194,7 +2207,7 @@
"dev": true,
"requires": {
"d": "1.0.0",
"es5-ext": "0.10.24",
"es5-ext": "0.10.26",
"es6-iterator": "2.0.1",
"es6-symbol": "3.1.1",
"event-emitter": "0.3.5"
@@ -2207,7 +2220,7 @@
"dev": true,
"requires": {
"d": "1.0.0",
"es5-ext": "0.10.24"
"es5-ext": "0.10.26"
}
},
"es6-weak-map": {
@@ -2217,7 +2230,7 @@
"dev": true,
"requires": {
"d": "1.0.0",
"es5-ext": "0.10.24",
"es5-ext": "0.10.26",
"es6-iterator": "2.0.1",
"es6-symbol": "3.1.1"
}
@@ -2569,7 +2582,7 @@
"dev": true,
"requires": {
"d": "1.0.0",
"es5-ext": "0.10.24"
"es5-ext": "0.10.26"
}
},
"eventemitter2": {
@@ -2593,6 +2606,34 @@
"create-hash": "1.1.3"
}
},
"execa": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
"integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
"dev": true,
"requires": {
"cross-spawn": "5.1.0",
"get-stream": "3.0.0",
"is-stream": "1.1.0",
"npm-run-path": "2.0.2",
"p-finally": "1.0.0",
"signal-exit": "3.0.2",
"strip-eof": "1.0.0"
},
"dependencies": {
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "4.1.1",
"shebang-command": "1.2.0",
"which": "1.2.14"
}
}
}
},
"exif-parser": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
@@ -2957,6 +2998,12 @@
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
"dev": true
},
"get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true
},
"getobject": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
@@ -3013,6 +3060,24 @@
"is-glob": "2.0.1"
}
},
"global": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
"integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=",
"dev": true,
"requires": {
"min-document": "2.19.0",
"process": "0.5.2"
},
"dependencies": {
"process": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
"integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=",
"dev": true
}
}
},
"globals": {
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
@@ -3044,12 +3109,6 @@
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"dev": true
},
"graceful-readlink": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
"dev": true
},
"grunt": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
@@ -3170,9 +3229,9 @@
}
},
"grunt-exec": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-2.0.0.tgz",
"integrity": "sha1-pXWmILHaRBbCksAd9WTJKWuAqyM=",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-3.0.0.tgz",
"integrity": "sha512-cgAlreXf3muSYS5LzW0Cc4xHK03BjFOYk0MqCQ/MZ3k1Xz2GU7D+IAJg4UKicxpO+XdONJdx/NJ6kpy2wI+uHg==",
"dev": true
},
"grunt-execute": {
@@ -3433,40 +3492,29 @@
}
},
"html-minifier": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.2.tgz",
"integrity": "sha1-1zvD/0SJQkCIGM5gm/P7DqfvTrc=",
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.3.tgz",
"integrity": "sha512-iKRzQQDuTCsq0Ultbi/mfJJnR0D3AdZKTq966Gsp92xkmAPCV4Xi08qhJ0Dl3ZAWemSgJ7qZK+UsZc0gFqK6wg==",
"dev": true,
"requires": {
"camel-case": "3.0.0",
"clean-css": "4.1.7",
"commander": "2.9.0",
"commander": "2.11.0",
"he": "1.1.1",
"ncname": "1.0.0",
"param-case": "2.1.1",
"relateurl": "0.2.7",
"uglify-js": "3.0.25"
},
"dependencies": {
"commander": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
"integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
"dev": true,
"requires": {
"graceful-readlink": "1.0.1"
}
}
"uglify-js": "3.0.27"
}
},
"html-webpack-plugin": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.29.0.tgz",
"integrity": "sha1-6Yf0IYU9O2k4yMTIFxhC5f0XryM=",
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz",
"integrity": "sha1-f5xCG36pHsRg9WUn1430hO51N9U=",
"dev": true,
"requires": {
"bluebird": "3.5.0",
"html-minifier": "3.5.2",
"html-minifier": "3.5.3",
"loader-utils": "0.2.17",
"lodash": "4.17.4",
"pretty-error": "2.1.1",
@@ -3829,7 +3877,7 @@
"integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
"dev": true,
"requires": {
"binary-extensions": "1.8.0"
"binary-extensions": "1.9.0"
}
},
"is-buffer": {
@@ -4048,6 +4096,52 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"jison": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz",
"integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=",
"requires": {
"cjson": "0.2.1",
"ebnf-parser": "0.1.10",
"escodegen": "0.0.21",
"esprima": "1.0.4",
"jison-lex": "0.2.1",
"JSONSelect": "0.4.0",
"lex-parser": "0.1.4",
"nomnom": "1.5.2"
},
"dependencies": {
"escodegen": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.21.tgz",
"integrity": "sha1-U9ZSz6EDA4gnlFilJmxf/HCcY8M=",
"requires": {
"esprima": "1.0.4",
"estraverse": "0.0.4",
"source-map": "0.2.0"
}
},
"esprima": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
"integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0="
},
"estraverse": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-0.0.4.tgz",
"integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI="
}
}
},
"jison-lex": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.2.1.tgz",
"integrity": "sha1-rEuBXozOUTLrErXfz+jXB7iETf4=",
"requires": {
"lex-parser": "0.1.4",
"nomnom": "1.5.2"
}
},
"jquery": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz",
@@ -4183,9 +4277,9 @@
"dev": true
},
"json-loader": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.4.tgz",
"integrity": "sha1-i6oTZaYy9Yo8RtIBdfxgAsluN94=",
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
"integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==",
"dev": true
},
"json-schema": {
@@ -4236,12 +4330,40 @@
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"dev": true
},
"jsonpath": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-0.2.12.tgz",
"integrity": "sha1-W/nZEftGFsHjNwvs658NskrjTNI=",
"requires": {
"esprima": "1.2.2",
"jison": "0.4.13",
"static-eval": "0.2.3",
"underscore": "1.7.0"
},
"dependencies": {
"esprima": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz",
"integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs="
},
"underscore": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
"integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk="
}
}
},
"jsonpointer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
"dev": true
},
"JSONSelect": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz",
"integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40="
},
"jsprim": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz",
@@ -4359,6 +4481,11 @@
"type-check": "0.3.2"
}
},
"lex-parser": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz",
"integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA="
},
"load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
@@ -4502,6 +4629,15 @@
"integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=",
"dev": true
},
"mem": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
"integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
"dev": true,
"requires": {
"mimic-fn": "1.1.0"
}
},
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -4602,6 +4738,15 @@
"integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
"dev": true
},
"min-document": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
"integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
"dev": true,
"requires": {
"dom-walk": "0.1.1"
}
},
"minimalistic-assert": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
@@ -4711,13 +4856,34 @@
"stream-browserify": "2.0.1",
"stream-http": "2.7.2",
"string_decoder": "0.10.31",
"timers-browserify": "2.0.2",
"timers-browserify": "2.0.3",
"tty-browserify": "0.0.0",
"url": "0.11.0",
"util": "0.10.3",
"vm-browserify": "0.0.4"
}
},
"nomnom": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz",
"integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=",
"requires": {
"colors": "0.5.1",
"underscore": "1.1.7"
},
"dependencies": {
"colors": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz",
"integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q="
},
"underscore": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz",
"integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA="
}
}
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -4766,6 +4932,15 @@
"sort-keys": "1.1.2"
}
},
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
"dev": true,
"requires": {
"path-key": "2.0.1"
}
},
"nth-check": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
@@ -4859,12 +5034,14 @@
"dev": true
},
"os-locale": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
"dev": true,
"requires": {
"lcid": "1.0.0"
"execa": "0.7.0",
"lcid": "1.0.0",
"mem": "1.1.0"
}
},
"os-tmpdir": {
@@ -4873,6 +5050,12 @@
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
"p-limit": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz",
@@ -4913,7 +5096,7 @@
"browserify-aes": "1.0.6",
"create-hash": "1.1.3",
"evp_bytestokey": "1.0.0",
"pbkdf2": "3.0.12"
"pbkdf2": "3.0.13"
}
},
"parse-glob": {
@@ -4967,6 +5150,12 @@
"integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
"dev": true
},
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
"dev": true
},
"path-type": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
@@ -4979,9 +5168,9 @@
}
},
"pbkdf2": {
"version": "3.0.12",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz",
"integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=",
"version": "3.0.13",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz",
"integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==",
"dev": true,
"requires": {
"create-hash": "1.1.3",
@@ -6208,8 +6397,7 @@
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
"dev": true
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
},
"regenerator-transform": {
"version": "0.9.11",
@@ -6571,6 +6759,21 @@
"inherits": "2.0.3"
}
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
"dev": true,
"requires": {
"shebang-regex": "1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
"shelljs": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz",
@@ -6718,6 +6921,36 @@
}
}
},
"static-eval": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.3.tgz",
"integrity": "sha1-Aj8XrJ/uQm6niMEuo5IG3Bdfiyo=",
"requires": {
"escodegen": "0.0.28"
},
"dependencies": {
"escodegen": {
"version": "0.0.28",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz",
"integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=",
"requires": {
"esprima": "1.0.4",
"estraverse": "1.3.2",
"source-map": "0.2.0"
}
},
"esprima": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
"integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0="
},
"estraverse": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz",
"integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI="
}
}
},
"stream-browserify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
@@ -6836,6 +7069,12 @@
"is-utf8": "0.2.1"
}
},
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"strip-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
@@ -6921,9 +7160,9 @@
"dev": true
},
"tapable": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.7.tgz",
"integrity": "sha1-5GwNqsuyuKmLmwzqD0BSEFgX7Vw=",
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
"integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=",
"dev": true
},
"text-table": {
@@ -6945,11 +7184,12 @@
"dev": true
},
"timers-browserify": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.2.tgz",
"integrity": "sha1-q0iDz1l9zVCvIRNJoA+8pWrIa4Y=",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.3.tgz",
"integrity": "sha512-+JAqyNgg+M8+gXIrq2EeUr4kZqRz47Ysco7X5QKRGScRE9HIHckyHD1asozSFGeqx2nmPCgA8T5tIGVO0ML7/w==",
"dev": true,
"requires": {
"global": "4.3.2",
"setimmediate": "1.0.5"
}
},
@@ -7050,24 +7290,15 @@
"dev": true
},
"uglify-js": {
"version": "3.0.25",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.25.tgz",
"integrity": "sha512-JO1XE0WZ9m6UpDkN7WCyPNAWI6EN3K0g40ekcoJKejViYmryJ0BaLxXjvra1IsAeIlJfq72scTbhl0jknsT2GA==",
"version": "3.0.27",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.27.tgz",
"integrity": "sha512-HD8CmxPXUI62v5tweiulMcP/apAtx1DXGcNZkhKQZyC+MTrTsoCBb8yPAwVrbvpgw3EpRU76bRe6axjIiCYcQg==",
"dev": true,
"requires": {
"commander": "2.9.0",
"commander": "2.11.0",
"source-map": "0.5.6"
},
"dependencies": {
"commander": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
"integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
"dev": true,
"requires": {
"graceful-readlink": "1.0.1"
}
},
"source-map": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
@@ -7291,9 +7522,9 @@
}
},
"vkbeautify": {
"version": "0.99.2",
"resolved": "https://registry.npmjs.org/vkbeautify/-/vkbeautify-0.99.2.tgz",
"integrity": "sha1-212WXsvEneSFvyF6e/kXiDZB2e4="
"version": "0.99.3",
"resolved": "https://registry.npmjs.org/vkbeautify/-/vkbeautify-0.99.3.tgz",
"integrity": "sha512-2ozZEFfmVvQcHWoHLNuiKlUfDKlhh4KGsy54U0UrlLMR1SO+XKAIDqBxtBwHgNrekurlJwE8A9K6L49T78ZQ9Q=="
},
"vm-browserify": {
"version": "0.0.4",
@@ -7362,9 +7593,9 @@
"dev": true
},
"webpack": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.3.0.tgz",
"integrity": "sha1-zi+eB2Vmq6kfdIhxM6iD/X2hh7w=",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.4.1.tgz",
"integrity": "sha1-TD9PP7MYFVpNsMtqNv8FxWl0GPQ=",
"dev": true,
"requires": {
"acorn": "5.1.1",
@@ -7372,10 +7603,10 @@
"ajv": "5.2.2",
"ajv-keywords": "2.1.0",
"async": "2.5.0",
"enhanced-resolve": "3.3.0",
"enhanced-resolve": "3.4.1",
"escope": "3.6.0",
"interpret": "1.0.3",
"json-loader": "0.5.4",
"json-loader": "0.5.7",
"json5": "0.5.1",
"loader-runner": "2.3.0",
"loader-utils": "1.1.0",
@@ -7383,12 +7614,12 @@
"mkdirp": "0.5.1",
"node-libs-browser": "2.0.0",
"source-map": "0.5.6",
"supports-color": "3.2.3",
"tapable": "0.2.7",
"supports-color": "4.2.1",
"tapable": "0.2.8",
"uglifyjs-webpack-plugin": "0.4.6",
"watchpack": "1.4.0",
"webpack-sources": "1.0.1",
"yargs": "6.6.0"
"yargs": "8.0.2"
},
"dependencies": {
"acorn": {
@@ -7421,6 +7652,12 @@
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
"dev": true
},
"has-flag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
"dev": true
},
"source-map": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
@@ -7428,16 +7665,22 @@
"dev": true
},
"supports-color": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz",
"integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==",
"dev": true,
"requires": {
"has-flag": "1.0.0"
"has-flag": "2.0.0"
}
}
}
},
"webpack-node-externals": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-1.6.0.tgz",
"integrity": "sha1-Iyxi7GCSsQBjWj0p2DwXRxKN+b0=",
"dev": true
},
"webpack-sources": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.0.1.tgz",
@@ -7513,9 +7756,9 @@
}
},
"which-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
"window-size": {
@@ -7623,30 +7866,30 @@
"dev": true
},
"yargs": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
"integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz",
"integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
"dev": true,
"requires": {
"camelcase": "3.0.0",
"camelcase": "4.1.0",
"cliui": "3.2.0",
"decamelize": "1.2.0",
"get-caller-file": "1.0.2",
"os-locale": "1.4.0",
"read-pkg-up": "1.0.1",
"os-locale": "2.1.0",
"read-pkg-up": "2.0.0",
"require-directory": "2.1.1",
"require-main-filename": "1.0.1",
"set-blocking": "2.0.0",
"string-width": "1.0.2",
"which-module": "1.0.0",
"string-width": "2.1.1",
"which-module": "2.0.0",
"y18n": "3.2.1",
"yargs-parser": "4.2.1"
"yargs-parser": "7.0.0"
},
"dependencies": {
"camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
"integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
"dev": true
},
"cliui": {
@@ -7658,6 +7901,19 @@
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wrap-ansi": "2.1.0"
},
"dependencies": {
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
}
}
},
"is-fullwidth-code-point": {
@@ -7669,32 +7925,69 @@
"number-is-nan": "1.0.1"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
"graceful-fs": "4.1.11",
"parse-json": "2.2.0",
"pify": "2.3.0",
"strip-bom": "3.0.0"
}
},
"path-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
"integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
"dev": true,
"requires": {
"pify": "2.3.0"
}
},
"read-pkg": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
"integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
"dev": true,
"requires": {
"load-json-file": "2.0.0",
"normalize-package-data": "2.4.0",
"path-type": "2.0.0"
}
},
"read-pkg-up": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
"integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
"dev": true,
"requires": {
"find-up": "2.1.0",
"read-pkg": "2.0.0"
}
},
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"dev": true
}
}
},
"yargs-parser": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
"integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
"integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
"dev": true,
"requires": {
"camelcase": "3.0.0"
"camelcase": "4.1.0"
},
"dependencies": {
"camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
"integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
"dev": true
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "5.12.2",
"version": "5.16.2",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -32,7 +32,6 @@
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^7.1.1",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.6.0",
"css-loader": "^0.28.4",
"exports-loader": "^0.6.4",
@@ -44,11 +43,11 @@
"grunt-contrib-clean": "~1.1.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-eslint": "^20.0.0",
"grunt-exec": "~2.0.0",
"grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.1.0",
"grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.29.0",
"html-webpack-plugin": "^2.30.1",
"imports-loader": "^0.7.1",
"ink-docstrap": "^1.1.4",
"jsdoc-babel": "^0.3.0",
@@ -60,9 +59,11 @@
"style-loader": "^0.18.2",
"url-loader": "^0.5.8",
"web-resource-inliner": "^4.1.0",
"webpack": "^3.3.0"
"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",
@@ -76,6 +77,7 @@
"google-code-prettify": "^1.0.5",
"jquery": "^3.1.1",
"jsbn": "^1.1.0",
"jsonpath": "^0.2.12",
"jsrsasign": "8.0.3",
"lodash": "^4.17.4",
"moment": "^2.17.1",
@@ -83,7 +85,7 @@
"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.3.1"

View File

@@ -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.
*

View File

@@ -173,7 +173,6 @@ const Categories = [
"Tail",
"Count occurrences",
"Expand alphabet range",
"Parse escaped string",
"Drop bytes",
"Take bytes",
"Pad lines",
@@ -188,6 +187,8 @@ const Categories = [
"Parse UNIX file permissions",
"Swap endianness",
"Parse colour code",
"Escape string",
"Unescape string",
]
},
{
@@ -215,6 +216,7 @@ const Categories = [
"Extract dates",
"Regular expression",
"XPath expression",
"JPath expression",
"CSS selector",
"Extract EXIF",
]
@@ -278,6 +280,7 @@ const Categories = [
"CSS Beautify",
"CSS Minify",
"XPath expression",
"JPath expression",
"CSS selector",
"Strip HTML tags",
"Diff",

View File

@@ -2243,6 +2243,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,
@@ -3206,13 +3224,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,
@@ -3252,6 +3263,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,

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";
@@ -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

@@ -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);

View File

@@ -61,8 +61,6 @@ const PublicKey = {
sig = cert.getSignatureValueHex(),
sigStr = "",
extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0];
window.cert = cert;
window.r = r;
// Public Key fields
pkFields.push({

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",
@@ -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;
},

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);
};
@@ -407,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) {
@@ -478,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];
@@ -672,7 +677,14 @@ App.prototype.stateChange = function(e) {
if (recipeConfig.length === 1) {
title = `${recipeConfig[0].op} - ${title}`;
} else if (recipeConfig.length > 1) {
title = `${recipeConfig.length} operations - ${title}`;
// 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;

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);
@@ -184,7 +184,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
const hash = params
.filter(v => v)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.map(([key, value]) => `${key}=${Utils.encodeURIFragment(value)}`)
.join("&");
if (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);
@@ -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

@@ -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);

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

@@ -48,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
@@ -62,19 +67,19 @@
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">
@@ -210,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>
@@ -275,6 +295,7 @@
<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>
@@ -385,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>
@@ -410,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

@@ -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

@@ -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

@@ -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": []
}
],
},
]);