mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
040229418e | ||
|
|
c259963542 | ||
|
|
ca75f7fa0b | ||
|
|
4b22a409e7 | ||
|
|
55806db00f | ||
|
|
2a4c9afdf2 | ||
|
|
ab76933158 | ||
|
|
d4d7bcab7a | ||
|
|
146a307b59 | ||
|
|
875946b4e8 | ||
|
|
81f2a460ed | ||
|
|
6698a2ac13 | ||
|
|
9161cc693d | ||
|
|
be689e293d | ||
|
|
53c22d5e29 | ||
|
|
5c0c80829e | ||
|
|
55aedfe901 | ||
|
|
4b87d66131 | ||
|
|
fc9497f067 | ||
|
|
3186335f47 | ||
|
|
31bfd8664a | ||
|
|
ab1c9e27dc | ||
|
|
c07cc913c8 | ||
|
|
b8fb5493c5 | ||
|
|
e8e5eb9c53 | ||
|
|
a15034b03e | ||
|
|
1435acdc28 | ||
|
|
37f164f11c | ||
|
|
7a2f071269 | ||
|
|
9ee0964d0e | ||
|
|
33ecbfa95b | ||
|
|
559c13a003 | ||
|
|
8f00345430 | ||
|
|
7a56af8ffa | ||
|
|
ed2bfbd27c | ||
|
|
e0905255ba | ||
|
|
de80db73f2 | ||
|
|
90ed62add2 | ||
|
|
d46e279933 | ||
|
|
77e074efc2 | ||
|
|
bd000d2d2c | ||
|
|
5f1c88104d | ||
|
|
a61df0832f | ||
|
|
58361e58f8 | ||
|
|
96b4361b31 | ||
|
|
c773edceb9 | ||
|
|
bcaef8ba54 | ||
|
|
c7d0b0ccc5 | ||
|
|
38792a0f02 | ||
|
|
cda557e1b9 | ||
|
|
8d09f7c7eb | ||
|
|
4845a56435 | ||
|
|
f164dcdd70 | ||
|
|
6c8da6b070 | ||
|
|
09df753ca9 | ||
|
|
72ec9df1b1 | ||
|
|
086d5272ac | ||
|
|
2555de7712 | ||
|
|
645e540c66 | ||
|
|
d16e1a4451 | ||
|
|
7c5dd2bd78 | ||
|
|
2f0121f0e4 | ||
|
|
7e310a8de7 | ||
|
|
c460c2bf6b | ||
|
|
2400de337b | ||
|
|
85d41085de | ||
|
|
48d45d026e | ||
|
|
183c57643b | ||
|
|
e7cea889ab | ||
|
|
61c799447b | ||
|
|
ad25daf206 | ||
|
|
4143bba89f | ||
|
|
8eb7d65b74 | ||
|
|
51798553e1 | ||
|
|
323928ff86 | ||
|
|
fe3aeabd0a | ||
|
|
ec7a55dba6 | ||
|
|
b4fe708d70 | ||
|
|
c3469bd545 | ||
|
|
92018b761d | ||
|
|
bb45ff0515 | ||
|
|
df1405e998 | ||
|
|
62ec018bb2 | ||
|
|
14b7c4bf23 | ||
|
|
5c774a3ce2 | ||
|
|
246480daef | ||
|
|
91c6f682e7 | ||
|
|
a417a6469c | ||
|
|
2821bdd52b | ||
|
|
d37300be39 | ||
|
|
15b83072bb | ||
|
|
6d2e2259db | ||
|
|
5b70614212 | ||
|
|
4363da534d | ||
|
|
685f7a4f00 | ||
|
|
213ec028b8 | ||
|
|
fadd7158ed |
6
.babelrc
6
.babelrc
@@ -4,9 +4,11 @@
|
||||
"targets": {
|
||||
"chrome": 40,
|
||||
"firefox": 35,
|
||||
"edge": 14
|
||||
"edge": 14,
|
||||
"node": "6.5",
|
||||
},
|
||||
"modules": false
|
||||
"modules": false,
|
||||
"useBuiltIns": true
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -93,6 +96,7 @@
|
||||
"moment": false,
|
||||
|
||||
"COMPILE_TIME": false,
|
||||
"COMPILE_MSG": false
|
||||
"COMPILE_MSG": false,
|
||||
"PKG_VERSION": false
|
||||
}
|
||||
}
|
||||
|
||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at oss@gchq.gov.uk. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -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) {
|
||||
@@ -164,7 +165,8 @@ module.exports = function (grunt) {
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
COMPILE_TIME: JSON.stringify(compileTime),
|
||||
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || "")
|
||||
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
|
||||
PKG_VERSION: JSON.stringify(pkg.version)
|
||||
}),
|
||||
new ExtractTextPlugin("styles.css"),
|
||||
],
|
||||
@@ -227,6 +229,9 @@ module.exports = function (grunt) {
|
||||
stats: {
|
||||
children: false,
|
||||
warningsFilter: /source-map/
|
||||
},
|
||||
node: {
|
||||
fs: "empty"
|
||||
}
|
||||
},
|
||||
webDev: {
|
||||
@@ -293,6 +298,7 @@ module.exports = function (grunt) {
|
||||
tests: {
|
||||
target: "node",
|
||||
entry: "./test/index.js",
|
||||
externals: [NodeExternals()],
|
||||
output: {
|
||||
filename: "index.js",
|
||||
path: __dirname + "/build/test"
|
||||
@@ -301,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",
|
||||
|
||||
30
README.md
30
README.md
@@ -6,9 +6,9 @@
|
||||
|
||||
#### *The Cyber Swiss Army Knife*
|
||||
|
||||
CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include creating hexdumps, simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, data compression and decompression, calculating hashes and checksums, IPv6 and X.509 parsing, and much more.
|
||||
CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, creating binary and hexdumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
|
||||
|
||||
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years. Every effort has been made to structure the code in a readable and extendable format, however it should be noted that the analyst is not a professional developer and the code has not been peer-reviewed for compliance with a formal specification.
|
||||
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years. Every effort has been made to structure the code in a readable and extendable format, however it should be noted that the analyst is not a professional developer.
|
||||
|
||||
## Live demo
|
||||
|
||||
@@ -24,9 +24,9 @@ Cryptographic operations in CyberChef should not be relied upon to provide secur
|
||||
There are four main areas in CyberChef:
|
||||
|
||||
1. The **input** box in the top right, where you can paste, type or drag the data you want to operate on.
|
||||
2. The **output** box in the bottom right, where the outcome of the specified processing will be displayed.
|
||||
2. The **output** box in the bottom right, where the outcome of your processing will be displayed.
|
||||
3. The **operations** list on the far left, where you can find all the operations that CyberChef is capable of in categorised lists, or by searching.
|
||||
4. The **recipe** area in the middle, where you drag the operations that you want to use and specify arguments and options.
|
||||
4. The **recipe** area in the middle, where you can drag the operations that you want to use and specify arguments and options.
|
||||
|
||||
You can use as many operations as you like in simple or complex ways. Some examples are as follows:
|
||||
|
||||
@@ -66,12 +66,16 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||
|
||||
## Browser support
|
||||
|
||||
CyberChef is built to support Google Chrome 40+, Mozilla Firefox 35+ and Microsoft Edge 14+.
|
||||
CyberChef is built to support
|
||||
|
||||
- Google Chrome 40+
|
||||
- Mozilla Firefox 35+
|
||||
- Microsoft Edge 14+
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
An installation walkthrough, how-to guides for adding new operations, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
|
||||
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
|
||||
|
||||
- Sign the [GCHQ Contributor Licence Agreement](https://github.com/gchq/Gaffer/wiki/GCHQ-OSS-Contributor-License-Agreement-V1.0)
|
||||
- Push your changes to your fork.
|
||||
@@ -84,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=%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
|
||||
|
||||
8010
package-lock.json
generated
Normal file
8010
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "5.10.3",
|
||||
"version": "5.15.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,64 @@
|
||||
"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",
|
||||
"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",
|
||||
|
||||
@@ -73,7 +73,7 @@ Ingredient.prepare = function(data, type) {
|
||||
case "byteArray":
|
||||
if (typeof data == "string") {
|
||||
data = data.replace(/\s+/g, "");
|
||||
return Utils.hexToByteArray(data);
|
||||
return Utils.fromHex(data);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -23,6 +23,16 @@ const Utils = {
|
||||
* Utils.chr(97);
|
||||
*/
|
||||
chr: function(o) {
|
||||
// Detect astral symbols
|
||||
// Thanks to @mathiasbynens for this solution
|
||||
// https://mathiasbynens.be/notes/javascript-unicode
|
||||
if (o > 0xffff) {
|
||||
o -= 0x10000;
|
||||
const high = String.fromCharCode(o >>> 10 & 0x3ff | 0xd800);
|
||||
o = 0xdc00 | o & 0x3ff;
|
||||
return high + String.fromCharCode(o);
|
||||
}
|
||||
|
||||
return String.fromCharCode(o);
|
||||
},
|
||||
|
||||
@@ -38,6 +48,18 @@ const Utils = {
|
||||
* Utils.ord('a');
|
||||
*/
|
||||
ord: function(c) {
|
||||
// Detect astral symbols
|
||||
// Thanks to @mathiasbynens for this solution
|
||||
// https://mathiasbynens.be/notes/javascript-unicode
|
||||
if (c.length === 2) {
|
||||
const high = c.charCodeAt(0);
|
||||
const low = c.charCodeAt(1);
|
||||
if (high >= 0xd800 && high < 0xdc00 &&
|
||||
low >= 0xdc00 && low < 0xe000) {
|
||||
return (high - 0xd800) * 0x400 + low - 0xdc00 + 0x10000;
|
||||
}
|
||||
}
|
||||
|
||||
return c.charCodeAt(0);
|
||||
},
|
||||
|
||||
@@ -216,7 +238,7 @@ const Utils = {
|
||||
str = Utils.byteArrayToChars(Utils.strToByteArray(str));
|
||||
}
|
||||
|
||||
const re = /[\0-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BB-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]/g;
|
||||
const re = /[\0-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BB-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]/g;
|
||||
const wsRe = /[\x09-\x10\x0D\u2028\u2029]/g;
|
||||
|
||||
str = str.replace(re, ".");
|
||||
@@ -271,7 +293,7 @@ const Utils = {
|
||||
* Utils.escapeRegex("[example]");
|
||||
*/
|
||||
escapeRegex: function(str) {
|
||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
||||
return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, "\\$1");
|
||||
},
|
||||
|
||||
|
||||
@@ -318,48 +340,6 @@ const Utils = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Translates a hex string into an array of bytes.
|
||||
*
|
||||
* @param {string} hexStr
|
||||
* @returns {byteArray}
|
||||
*
|
||||
* @example
|
||||
* // returns [0xfe, 0x09, 0xa7]
|
||||
* Utils.hexToByteArray("fe09a7");
|
||||
*/
|
||||
hexToByteArray: function(hexStr) {
|
||||
// TODO: Handle errors i.e. input string is not hex
|
||||
if (!hexStr) return [];
|
||||
hexStr = hexStr.replace(/\s+/g, "");
|
||||
const byteArray = [];
|
||||
for (let i = 0; i < hexStr.length; i += 2) {
|
||||
byteArray.push(parseInt(hexStr.substr(i, 2), 16));
|
||||
}
|
||||
return byteArray;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Translates an array of bytes to a hex string.
|
||||
*
|
||||
* @param {byteArray} byteArray
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns "fe09a7"
|
||||
* Utils.byteArrayToHex([0xfe, 0x09, 0xa7]);
|
||||
*/
|
||||
byteArrayToHex: function(byteArray) {
|
||||
if (!byteArray) return "";
|
||||
let hexStr = "";
|
||||
for (let i = 0; i < byteArray.length; i++) {
|
||||
hexStr += Utils.hex(byteArray[i]) + " ";
|
||||
}
|
||||
return hexStr.slice(0, hexStr.length-1);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts a string to a byte array.
|
||||
* Treats the string as UTF-8 if any values are over 255.
|
||||
@@ -412,7 +392,7 @@ const Utils = {
|
||||
|
||||
|
||||
/**
|
||||
* Converts a string to a charcode array
|
||||
* Converts a string to a unicode charcode array
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {byteArray}
|
||||
@@ -425,12 +405,23 @@ const Utils = {
|
||||
* Utils.strToCharcode("你好");
|
||||
*/
|
||||
strToCharcode: function(str) {
|
||||
const byteArray = new Array(str.length);
|
||||
let i = str.length;
|
||||
while (i--) {
|
||||
byteArray[i] = str.charCodeAt(i);
|
||||
const charcode = new Array();
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let ord = str.charCodeAt(i);
|
||||
|
||||
// Detect and merge astral symbols
|
||||
if (i < str.length - 1 && ord >= 0xd800 && ord < 0xdc00) {
|
||||
const low = str[i + 1].charCodeAt(0);
|
||||
if (low >= 0xdc00 && low < 0xe000) {
|
||||
ord = Utils.ord(str[i] + str[++i]);
|
||||
}
|
||||
}
|
||||
|
||||
charcode.push(ord);
|
||||
}
|
||||
return byteArray;
|
||||
|
||||
return charcode;
|
||||
},
|
||||
|
||||
|
||||
@@ -601,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, "");
|
||||
}
|
||||
|
||||
@@ -793,7 +784,7 @@ const Utils = {
|
||||
if (removeScriptAndStyle) {
|
||||
htmlStr = htmlStr.replace(/<(script|style)[^>]*>.*<\/(script|style)>/gmi, "");
|
||||
}
|
||||
return htmlStr.replace(/<[^>\n]+>/g, "");
|
||||
return htmlStr.replace(/<[^>]+>/g, "");
|
||||
},
|
||||
|
||||
|
||||
@@ -819,7 +810,7 @@ const Utils = {
|
||||
"`": "`"
|
||||
};
|
||||
|
||||
return str.replace(/[&<>"'\/`]/g, function (match) {
|
||||
return str.replace(/[&<>"'/`]/g, function (match) {
|
||||
return HTML_CHARS[match];
|
||||
});
|
||||
},
|
||||
@@ -910,17 +901,20 @@ const Utils = {
|
||||
* @param {Object[]} files
|
||||
* @returns {html}
|
||||
*/
|
||||
displayFilesAsHTML: function(files){
|
||||
displayFilesAsHTML: function(files) {
|
||||
/* <NL> and <SP> used to denote newlines and spaces in HTML markup.
|
||||
* If a non-html operation is used, all markup will be removed but these
|
||||
* whitespace chars will remain for formatting purposes.
|
||||
*/
|
||||
|
||||
const formatDirectory = function(file) {
|
||||
const html = "<div class='panel panel-default'>" +
|
||||
"<div class='panel-heading' role='tab'>" +
|
||||
"<h4 class='panel-title'>" +
|
||||
file.fileName +
|
||||
// The following line is for formatting when HTML is stripped
|
||||
"<span style='display: none'>\n0 bytes\n</span>" +
|
||||
"</h4>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
const html = `<div class='panel panel-default' style='white-space: normal;'>
|
||||
<div class='panel-heading' role='tab'>
|
||||
<h4 class='panel-title'>
|
||||
<NL>${Utils.escapeHtml(file.fileName)}
|
||||
</h4>
|
||||
</div>
|
||||
</div>`;
|
||||
return html;
|
||||
};
|
||||
|
||||
@@ -931,45 +925,52 @@ const Utils = {
|
||||
);
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
|
||||
const downloadAnchorElem = "<a href='" + blobUrl + "' " +
|
||||
"title='Download " + Utils.escapeHtml(file.fileName) + "' " +
|
||||
"download='" + Utils.escapeHtml(file.fileName) + "'>\u21B4</a>";
|
||||
const viewFileElem = `<a href='#collapse${i}'
|
||||
class='collapsed'
|
||||
data-toggle='collapse'
|
||||
aria-expanded='true'
|
||||
aria-controls='collapse${i}'
|
||||
title="Show/hide contents of '${Utils.escapeHtml(file.fileName)}'">👁️</a>`;
|
||||
|
||||
const expandFileContentsElem = "<a href='#collapse" + i + "' " +
|
||||
"class='collapsed' " +
|
||||
"data-toggle='collapse' " +
|
||||
"aria-expanded='true' " +
|
||||
"aria-controls='collapse" + i + "' " +
|
||||
"title=\"Show/hide contents of '" + Utils.escapeHtml(file.fileName) + "'\">🔍</a>";
|
||||
const downloadFileElem = `<a href='${blobUrl}'
|
||||
title='Download ${Utils.escapeHtml(file.fileName)}'
|
||||
download='${Utils.escapeHtml(file.fileName)}'>💾</a>`;
|
||||
|
||||
const html = "<div class='panel panel-default'>" +
|
||||
"<div class='panel-heading' role='tab' id='heading" + i + "'>" +
|
||||
"<h4 class='panel-title'>" +
|
||||
"<div>" +
|
||||
Utils.escapeHtml(file.fileName) +
|
||||
" " + expandFileContentsElem +
|
||||
" " + downloadAnchorElem +
|
||||
"<span class='pull-right'>" +
|
||||
// These are for formatting when stripping HTML
|
||||
"<span style='display: none'>\n</span>" +
|
||||
file.size.toLocaleString() + " bytes" +
|
||||
"<span style='display: none'>\n</span>" +
|
||||
"</span>" +
|
||||
"</div>" +
|
||||
"</h4>" +
|
||||
"</div>" +
|
||||
"<div id='collapse" + i + "' class='panel-collapse collapse' " +
|
||||
"role='tabpanel' aria-labelledby='heading" + i + "'>" +
|
||||
"<div class='panel-body'>" +
|
||||
"<pre><code>" + Utils.escapeHtml(file.contents) + "</pre></code></div>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
const hexFileData = Utils.toHexFast(new Uint8Array(file.bytes));
|
||||
|
||||
const switchToInputElem = `<a href='#switchFileToInput${i}'
|
||||
class='file-switch'
|
||||
title='Move file to input as hex'
|
||||
fileValue='${hexFileData}'>⇧</a>`;
|
||||
|
||||
const html = `<div class='panel panel-default' style='white-space: normal;'>
|
||||
<div class='panel-heading' role='tab' id='heading${i}'>
|
||||
<h4 class='panel-title'>
|
||||
<div>
|
||||
${Utils.escapeHtml(file.fileName)}<NL>
|
||||
${viewFileElem}<SP>
|
||||
${downloadFileElem}<SP>
|
||||
${switchToInputElem}<SP>
|
||||
<span class='pull-right'>
|
||||
<NL>${file.size.toLocaleString()} bytes
|
||||
</span>
|
||||
</div>
|
||||
</h4>
|
||||
</div>
|
||||
<div id='collapse${i}' class='panel-collapse collapse'
|
||||
role='tabpanel' aria-labelledby='heading${i}'>
|
||||
<div class='panel-body'>
|
||||
<NL><NL><pre><code>${Utils.escapeHtml(file.contents)}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
return html;
|
||||
};
|
||||
|
||||
let html = "<div style='padding: 5px;'>" +
|
||||
files.length +
|
||||
" file(s) found</div>\n";
|
||||
let html = `<div style='padding: 5px; white-space: normal;'>
|
||||
${files.length} file(s) found<NL>
|
||||
</div>`;
|
||||
|
||||
files.forEach(function(file, i) {
|
||||
if (typeof file.contents !== "undefined") {
|
||||
html += formatFile(file, i);
|
||||
@@ -977,7 +978,10 @@ const Utils = {
|
||||
html += formatDirectory(file);
|
||||
}
|
||||
});
|
||||
return html;
|
||||
|
||||
return html.replace(/(?:(<pre>(?:\n|.)*<\/pre>)|\s{2,})/g, "$1") // Remove whitespace from markup
|
||||
.replace(/<NL>/g, "\n") // Replace <NP> with newlines
|
||||
.replace(/<SP>/g, " "); // Replace <SP> with spaces
|
||||
},
|
||||
|
||||
|
||||
@@ -996,9 +1000,14 @@ const Utils = {
|
||||
if (paramStr === "") return {};
|
||||
|
||||
// Cut off ? or # and split on &
|
||||
const params = paramStr.substr(1).split("&");
|
||||
if (paramStr[0] === "?" ||
|
||||
paramStr[0] === "#") {
|
||||
paramStr = paramStr.substr(1);
|
||||
}
|
||||
|
||||
const params = paramStr.split("&");
|
||||
const result = {};
|
||||
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
const param = params[i].split("=");
|
||||
if (param.length !== 2) {
|
||||
@@ -1015,7 +1024,7 @@ const Utils = {
|
||||
/**
|
||||
* Actual modulo function, since % is actually the remainder function in JS.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @returns {number}
|
||||
@@ -1028,7 +1037,7 @@ const Utils = {
|
||||
/**
|
||||
* Finds the greatest common divisor of two numbers.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @returns {number}
|
||||
@@ -1044,7 +1053,7 @@ const Utils = {
|
||||
/**
|
||||
* Finds the modular inverse of two values.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @returns {number}
|
||||
|
||||
@@ -46,6 +46,8 @@ const Categories = [
|
||||
"From Base58",
|
||||
"To Base",
|
||||
"From Base",
|
||||
"To BCD",
|
||||
"From BCD",
|
||||
"To HTML Entity",
|
||||
"From HTML Entity",
|
||||
"URL Encode",
|
||||
@@ -89,6 +91,8 @@ const Categories = [
|
||||
"Vigenère Decode",
|
||||
"To Morse Code",
|
||||
"From Morse Code",
|
||||
"Bifid Cipher Encode",
|
||||
"Bifid Cipher Decode",
|
||||
"Affine Cipher Encode",
|
||||
"Affine Cipher Decode",
|
||||
"Atbash Cipher",
|
||||
@@ -169,7 +173,6 @@ const Categories = [
|
||||
"Tail",
|
||||
"Count occurrences",
|
||||
"Expand alphabet range",
|
||||
"Parse escaped string",
|
||||
"Drop bytes",
|
||||
"Take bytes",
|
||||
"Pad lines",
|
||||
@@ -184,6 +187,8 @@ const Categories = [
|
||||
"Parse UNIX file permissions",
|
||||
"Swap endianness",
|
||||
"Parse colour code",
|
||||
"Escape string",
|
||||
"Unescape string",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -211,6 +216,7 @@ const Categories = [
|
||||
"Extract dates",
|
||||
"Regular expression",
|
||||
"XPath expression",
|
||||
"JPath expression",
|
||||
"CSS selector",
|
||||
"Extract EXIF",
|
||||
]
|
||||
@@ -274,6 +280,7 @@ const Categories = [
|
||||
"CSS Beautify",
|
||||
"CSS Minify",
|
||||
"XPath expression",
|
||||
"JPath expression",
|
||||
"CSS selector",
|
||||
"Strip HTML tags",
|
||||
"Diff",
|
||||
|
||||
@@ -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";
|
||||
@@ -330,30 +331,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 +359,11 @@ const OperationConfig = {
|
||||
name: "Output as hex",
|
||||
type: "boolean",
|
||||
value: BitwiseOp.XOR_BRUTE_OUTPUT_HEX
|
||||
},
|
||||
{
|
||||
name: "Crib (known plaintext string)",
|
||||
type: "binaryString",
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -605,7 +606,7 @@ const OperationConfig = {
|
||||
args: []
|
||||
},
|
||||
"To Hexdump": {
|
||||
description: "Creates a hexdump of the input data, displaying both the hexademinal values of each byte and an ASCII representation alongside.",
|
||||
description: "Creates a hexdump of the input data, displaying both the hexadecimal values of each byte and an ASCII representation alongside.",
|
||||
run: Hexdump.runTo,
|
||||
highlight: Hexdump.highlightTo,
|
||||
highlightReverse: Hexdump.highlightFrom,
|
||||
@@ -1512,6 +1513,36 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"Bifid Cipher Encode": {
|
||||
description: "The Bifid cipher is a cipher which uses a Polybius square in conjunction with transposition, which can be fairly difficult to decipher without knowing the alphabet keyword.",
|
||||
run: Cipher.runBifidEnc,
|
||||
highlight: true,
|
||||
highlightReverse: true,
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Keyword",
|
||||
type: "string",
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"Bifid Cipher Decode": {
|
||||
description: "The Bifid cipher is a cipher which uses a Polybius square in conjunction with transposition, which can be fairly difficult to decipher without knowing the alphabet keyword.",
|
||||
run: Cipher.runBifidDec,
|
||||
highlight: true,
|
||||
highlightReverse: true,
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Keyword",
|
||||
type: "string",
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"Affine Cipher Encode": {
|
||||
description: "The Affine cipher is a type of monoalphabetic substitution cipher, wherein each letter in an alphabet is mapped to its numeric equivalent, encrypted using simple mathematical function, <code>(ax + b) % 26</code>, and converted back to a letter.",
|
||||
run: Cipher.runAffineEnc,
|
||||
@@ -2212,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,
|
||||
@@ -2261,7 +2310,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",
|
||||
@@ -2271,10 +2320,15 @@ const OperationConfig = {
|
||||
name: "Output units",
|
||||
type: "option",
|
||||
value: DateTime.UNITS
|
||||
},
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: DateTime.FILETIME_FORMATS
|
||||
}
|
||||
]
|
||||
},
|
||||
"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",
|
||||
@@ -2284,6 +2338,11 @@ const OperationConfig = {
|
||||
name: "Input units",
|
||||
type: "option",
|
||||
value: DateTime.UNITS
|
||||
},
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: DateTime.FILETIME_FORMATS
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3165,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,
|
||||
@@ -3196,8 +3248,8 @@ const OperationConfig = {
|
||||
"Substitute": {
|
||||
description: "A substitution cipher allowing you to specify bytes to replace with other byte values. This can be used to create Caesar ciphers but is more powerful as any byte value can be substituted, not just letters, and the substitution values need not be in order.<br><br>Enter the bytes you want to replace in the Plaintext field and the bytes to replace them with in the Ciphertext field.<br><br>Non-printable bytes can be specified using string escape notation. For example, a line feed character can be written as either <code>\\n</code> or <code>\\x0a</code>.<br><br>Byte ranges can be specified using a hyphen. For example, the sequence <code>0123456789</code> can be written as <code>0-9</code>.",
|
||||
run: Cipher.runSubstitute,
|
||||
inputType: "byteArray",
|
||||
outputType: "byteArray",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Plaintext",
|
||||
@@ -3211,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,
|
||||
@@ -3467,6 +3533,64 @@ 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
|
||||
}
|
||||
]
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
export default OperationConfig;
|
||||
|
||||
214
src/core/operations/BCD.js
Executable file
214
src/core/operations/BCD.js
Executable 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;
|
||||
@@ -221,15 +221,15 @@ const Base64 = {
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 2) + "</span>";
|
||||
"<span class='hl5'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset0.substr(offset0.length - 2) + "</span>";
|
||||
} else if (len0 % 4 === 3) {
|
||||
staticSection = offset0.slice(0, -2);
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 1) + "</span>";
|
||||
"<span class='hl5'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset0.substr(offset0.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset0;
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
@@ -243,23 +243,23 @@ const Base64 = {
|
||||
|
||||
|
||||
// Highlight offset 1
|
||||
padding = "<span class='hlred'>" + offset1.substr(0, 1) + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(1, 1) + "</span>";
|
||||
padding = "<span class='hl3'>" + offset1.substr(0, 1) + "</span>" +
|
||||
"<span class='hl5'>" + offset1.substr(1, 1) + "</span>";
|
||||
offset1 = offset1.substr(2);
|
||||
if (len1 % 4 === 2) {
|
||||
staticSection = offset1.slice(0, -3);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 2) + "</span>";
|
||||
"<span class='hl5'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset1.substr(offset1.length - 2) + "</span>";
|
||||
} else if (len1 % 4 === 3) {
|
||||
staticSection = offset1.slice(0, -2);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 1) + "</span>";
|
||||
"<span class='hl5'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset1.substr(offset1.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset1;
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
@@ -272,23 +272,23 @@ const Base64 = {
|
||||
}
|
||||
|
||||
// Highlight offset 2
|
||||
padding = "<span class='hlred'>" + offset2.substr(0, 2) + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(2, 1) + "</span>";
|
||||
padding = "<span class='hl3'>" + offset2.substr(0, 2) + "</span>" +
|
||||
"<span class='hl5'>" + offset2.substr(2, 1) + "</span>";
|
||||
offset2 = offset2.substr(3);
|
||||
if (len2 % 4 === 2) {
|
||||
staticSection = offset2.slice(0, -3);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 2) + "</span>";
|
||||
"<span class='hl5'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset2.substr(offset2.length - 2) + "</span>";
|
||||
} else if (len2 % 4 === 3) {
|
||||
staticSection = offset2.slice(0, -2);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 1) + "</span>";
|
||||
"<span class='hl5'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset2.substr(offset2.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset2;
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
@@ -300,8 +300,8 @@ const Base64 = {
|
||||
offset2 = staticSection;
|
||||
}
|
||||
|
||||
return (showVariable ? "Characters highlighted in <span class='hlgreen'>green</span> could change if the input is surrounded by more data." +
|
||||
"\nCharacters highlighted in <span class='hlred'>red</span> are for padding purposes only." +
|
||||
return (showVariable ? "Characters highlighted in <span class='hl5'>green</span> could change if the input is surrounded by more data." +
|
||||
"\nCharacters highlighted in <span class='hl3'>red</span> are for padding purposes only." +
|
||||
"\nUnhighlighted characters are <span data-toggle='tooltip' data-placement='top' title='Tooltip on left'>static</span>." +
|
||||
"\nHover over the static sections to see what they decode to on their own.\n" +
|
||||
"\nOffset 0: " + offset0 +
|
||||
|
||||
@@ -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.hexToByteArray(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.byteArrayToHex(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;
|
||||
|
||||
@@ -58,7 +58,7 @@ const ByteRepr = {
|
||||
/**
|
||||
* To Octal operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
@@ -72,7 +72,7 @@ const ByteRepr = {
|
||||
/**
|
||||
* From Octal operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
@@ -108,8 +108,9 @@ const ByteRepr = {
|
||||
throw "Error: Base argument must be between 2 and 36";
|
||||
}
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
ordinal = Utils.ord(input[i]);
|
||||
const charcode = Utils.strToCharcode(input);
|
||||
for (let i = 0; i < charcode.length; i++) {
|
||||
ordinal = charcode[i];
|
||||
|
||||
if (base === 16) {
|
||||
if (ordinal < 256) padding = 2;
|
||||
|
||||
@@ -407,7 +407,7 @@ const Cipher = {
|
||||
/**
|
||||
* Vigenère Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
@@ -454,7 +454,7 @@ const Cipher = {
|
||||
/**
|
||||
* Vigenère Decode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
@@ -508,7 +508,7 @@ const Cipher = {
|
||||
/**
|
||||
* Affine Cipher Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
@@ -540,9 +540,9 @@ const Cipher = {
|
||||
|
||||
|
||||
/**
|
||||
* Affine Cipher Encode operation.
|
||||
* Affine Cipher Decode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
@@ -584,7 +584,7 @@ const Cipher = {
|
||||
/**
|
||||
* Atbash Cipher Encode operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
@@ -594,6 +594,159 @@ const Cipher = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generates a polybius square for the given keyword
|
||||
*
|
||||
* @private
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} keyword - Must be upper case
|
||||
* @returns {string}
|
||||
*/
|
||||
_genPolybiusSquare: function (keyword) {
|
||||
const alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
|
||||
const polArray = `${keyword}${alpha}`.split("").unique();
|
||||
let polybius = [];
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
polybius[i] = polArray.slice(i*5, i*5 + 5);
|
||||
}
|
||||
|
||||
return polybius;
|
||||
},
|
||||
|
||||
/**
|
||||
* Bifid Cipher Encode operation
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBifidEnc: function (input, args) {
|
||||
const keywordStr = args[0].toUpperCase().replace("J", "I"),
|
||||
keyword = keywordStr.split("").unique(),
|
||||
alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
|
||||
|
||||
let output = "",
|
||||
xCo = [],
|
||||
yCo = [],
|
||||
structure = [],
|
||||
count = 0;
|
||||
|
||||
if (keyword.length > 25)
|
||||
return "The alphabet keyword must be less than 25 characters.";
|
||||
|
||||
if (!/^[a-zA-Z]+$/.test(keywordStr) && keyword.length > 0)
|
||||
return "The key must consist only of letters";
|
||||
|
||||
const polybius = Cipher._genPolybiusSquare(keywordStr);
|
||||
|
||||
input.replace("J", "I").split("").forEach(letter => {
|
||||
let alpInd = alpha.split("").indexOf(letter.toLocaleUpperCase()) >= 0,
|
||||
polInd;
|
||||
|
||||
if (alpInd) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
polInd = polybius[i].indexOf(letter.toLocaleUpperCase());
|
||||
if (polInd >= 0) {
|
||||
xCo.push(polInd);
|
||||
yCo.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha.split("").indexOf(letter) >= 0) {
|
||||
structure.push(true);
|
||||
} else if (alpInd) {
|
||||
structure.push(false);
|
||||
}
|
||||
} else {
|
||||
structure.push(letter);
|
||||
}
|
||||
});
|
||||
|
||||
const trans = `${yCo.join("")}${xCo.join("")}`;
|
||||
|
||||
structure.forEach(pos => {
|
||||
if (typeof pos === "boolean") {
|
||||
let coords = trans.substr(2*count, 2).split("");
|
||||
|
||||
output += pos ?
|
||||
polybius[coords[0]][coords[1]] :
|
||||
polybius[coords[0]][coords[1]].toLocaleLowerCase();
|
||||
count++;
|
||||
} else {
|
||||
output += pos;
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
/**
|
||||
* Bifid Cipher Decode operation
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runBifidDec: function (input, args) {
|
||||
const keywordStr = args[0].toUpperCase().replace("J", "I"),
|
||||
keyword = keywordStr.split("").unique(),
|
||||
alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
|
||||
|
||||
let output = "",
|
||||
structure = [],
|
||||
count = 0,
|
||||
trans = "";
|
||||
|
||||
if (keyword.length > 25)
|
||||
return "The alphabet keyword must be less than 25 characters.";
|
||||
|
||||
if (!/^[a-zA-Z]+$/.test(keywordStr) && keyword.length > 0)
|
||||
return "The key must consist only of letters";
|
||||
|
||||
const polybius = Cipher._genPolybiusSquare(keywordStr);
|
||||
|
||||
input.replace("J", "I").split("").forEach((letter) => {
|
||||
let alpInd = alpha.split("").indexOf(letter.toLocaleUpperCase()) >= 0,
|
||||
polInd;
|
||||
|
||||
if (alpInd) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
polInd = polybius[i].indexOf(letter.toLocaleUpperCase());
|
||||
if (polInd >= 0) {
|
||||
trans += `${i}${polInd}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha.split("").indexOf(letter) >= 0) {
|
||||
structure.push(true);
|
||||
} else if (alpInd) {
|
||||
structure.push(false);
|
||||
}
|
||||
} else {
|
||||
structure.push(letter);
|
||||
}
|
||||
});
|
||||
|
||||
structure.forEach(pos => {
|
||||
if (typeof pos === "boolean") {
|
||||
let coords = [trans[count], trans[count+trans.length/2]];
|
||||
|
||||
output += pos ?
|
||||
polybius[coords[0]][coords[1]] :
|
||||
polybius[coords[0]][coords[1]].toLocaleLowerCase();
|
||||
count++;
|
||||
} else {
|
||||
output += pos;
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -608,23 +761,23 @@ const Cipher = {
|
||||
/**
|
||||
* Substitute operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
* @returns {string}
|
||||
*/
|
||||
runSubstitute: function (input, args) {
|
||||
let plaintext = Utils.strToByteArray(Utils.expandAlphRange(args[0]).join()),
|
||||
ciphertext = Utils.strToByteArray(Utils.expandAlphRange(args[1]).join()),
|
||||
output = [],
|
||||
let plaintext = Utils.expandAlphRange(args[0]).join(),
|
||||
ciphertext = Utils.expandAlphRange(args[1]).join(),
|
||||
output = "",
|
||||
index = -1;
|
||||
|
||||
if (plaintext.length !== ciphertext.length) {
|
||||
output = Utils.strToByteArray("Warning: Plaintext and Ciphertext lengths differ\n\n");
|
||||
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
||||
}
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
index = plaintext.indexOf(input[i]);
|
||||
output.push(index > -1 && index < ciphertext.length ? ciphertext[index] : input[i]);
|
||||
output += index > -1 && index < ciphertext.length ? ciphertext[index] : input[i];
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,8 +89,17 @@ const DateTime = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFromFiletimeToUnix: function(input, args) {
|
||||
let units = args[0];
|
||||
input = new BigInteger(input).subtract(new BigInteger("116444736000000000"));
|
||||
let units = args[0],
|
||||
format = args[1];
|
||||
|
||||
if (format === "Hex") {
|
||||
input = new BigInteger(input, 16);
|
||||
} else {
|
||||
input = new BigInteger(input);
|
||||
}
|
||||
|
||||
input = input.subtract(new BigInteger("116444736000000000"));
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.divide(new BigInteger("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
@@ -102,6 +111,7 @@ const DateTime = {
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
return input.toString();
|
||||
},
|
||||
|
||||
@@ -115,8 +125,11 @@ const DateTime = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToFiletimeFromUnix: function(input, args) {
|
||||
let units = args[0];
|
||||
let units = args[0],
|
||||
format = args[1];
|
||||
|
||||
input = new BigInteger(input);
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.multiply(new BigInteger("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
@@ -128,10 +141,24 @@ const DateTime = {
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
return input.add(new BigInteger("116444736000000000")).toString();
|
||||
|
||||
input = input.add(new BigInteger("116444736000000000"));
|
||||
|
||||
if (format === "Hex"){
|
||||
return input.toString(16);
|
||||
} else {
|
||||
return input.toString();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FILETIME_FORMATS: ["Decimal", "Hex"],
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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";
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
@@ -283,7 +283,7 @@ const IP = {
|
||||
baIp.push(decimal & 255);
|
||||
break;
|
||||
case "Hex":
|
||||
baIp = Utils.hexToByteArray(lines[i]);
|
||||
baIp = Utils.fromHex(lines[i]);
|
||||
break;
|
||||
default:
|
||||
throw "Unsupported input IP format";
|
||||
@@ -516,7 +516,7 @@ const IP = {
|
||||
"<tr><td>Destination IP address</td><td>" + IP._ipv4ToStr(dstIP) + "</td></tr>";
|
||||
|
||||
if (ihl > 5) {
|
||||
output += "<tr><td>Options</td><td>" + Utils.byteArrayToHex(options) + "</td></tr>";
|
||||
output += "<tr><td>Options</td><td>" + Utils.toHex(options) + "</td></tr>";
|
||||
}
|
||||
|
||||
return output + "</table>";
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -135,7 +135,7 @@ const Rotate = {
|
||||
/**
|
||||
* ROT47 operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -73,7 +75,9 @@ App.prototype.loaded = function() {
|
||||
}, 1000);
|
||||
|
||||
// Clear the loading message interval
|
||||
clearInterval(window.loadingMsgInt);
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -400,7 +396,12 @@ App.prototype.addFavourite = function(name) {
|
||||
*/
|
||||
App.prototype.loadURIParams = function() {
|
||||
// Load query string or hash from URI (depending on which is populated)
|
||||
const params = window.location.search || window.location.hash;
|
||||
// We prefer getting the hash by splitting the href rather than referencing
|
||||
// location.hash as some browsers (Firefox) automatically URL decode it,
|
||||
// which cause issues.
|
||||
const params = window.location.search ||
|
||||
window.location.href.split("#")[1] ||
|
||||
window.location.hash;
|
||||
this.uriParams = Utils.parseURIParams(params);
|
||||
|
||||
// Pause auto-bake while loading but don't modify `this.autoBake_`
|
||||
@@ -463,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();
|
||||
};
|
||||
|
||||
|
||||
@@ -475,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++) {
|
||||
@@ -530,15 +528,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;
|
||||
};
|
||||
|
||||
@@ -663,10 +670,20 @@ 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) {
|
||||
title = `${recipeConfig.length} operations - ${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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -678,9 +695,7 @@ App.prototype.stateChange = function(e) {
|
||||
* @param {event} e
|
||||
*/
|
||||
App.prototype.popState = function(e) {
|
||||
if (window.location.href.split("#")[0] !== this.lastStateUrl) {
|
||||
this.loadURIParams();
|
||||
}
|
||||
this.loadURIParams();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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}=${encodeURIComponent(value)}`)
|
||||
.join("&");
|
||||
|
||||
if (hash) {
|
||||
return `${link}#${hash}`;
|
||||
@@ -288,7 +288,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 +310,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 +325,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);
|
||||
@@ -351,13 +351,18 @@ ControlsWaiter.prototype.loadButtonClick = function() {
|
||||
|
||||
/**
|
||||
* Populates the bug report information box with useful technical info.
|
||||
*
|
||||
* @param {event} e
|
||||
*/
|
||||
ControlsWaiter.prototype.supportButtonClick = function() {
|
||||
ControlsWaiter.prototype.supportButtonClick = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const reportBugInfo = document.getElementById("report-bug-info");
|
||||
const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
|
||||
|
||||
if (reportBugInfo) {
|
||||
reportBugInfo.innerHTML = "* CyberChef compile time: " + COMPILE_TIME + "\n" +
|
||||
reportBugInfo.innerHTML = "* Version: " + PKG_VERSION + "\n" +
|
||||
"* Compile time: " + COMPILE_TIME + "\n" +
|
||||
"* User-Agent: \n" + navigator.userAgent + "\n" +
|
||||
"* [Link to reproduce](" + saveLink + ")\n\n";
|
||||
}
|
||||
|
||||
@@ -493,13 +493,14 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
|
||||
//if (colour) cssClass += "-"+colour;
|
||||
|
||||
// Remove HTML tags
|
||||
text = text.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\n/g, " ")
|
||||
// Convert placeholders to tags
|
||||
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
|
||||
.replace(endPlaceholderRegex, "</span>") + " ";
|
||||
text = text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\n/g, " ")
|
||||
// Convert placeholders to tags
|
||||
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
|
||||
.replace(endPlaceholderRegex, "</span>") + " ";
|
||||
|
||||
// Adjust width to allow for scrollbars
|
||||
highlighter.style.width = textarea.clientWidth + "px";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -145,6 +149,7 @@ Manager.prototype.initialiseEventListeners = function() {
|
||||
document.getElementById("output-html").addEventListener("mousemove", this.highlighter.outputHtmlMousemove.bind(this.highlighter));
|
||||
this.addMultiEventListener("#output-text", "mousedown dblclick select", this.highlighter.outputMousedown, this.highlighter);
|
||||
this.addMultiEventListener("#output-html", "mousedown dblclick select", this.highlighter.outputHtmlMousedown, this.highlighter);
|
||||
this.addDynamicListener(".file-switch", "click", this.output.fileSwitch, this.output);
|
||||
|
||||
// Options
|
||||
document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -57,8 +57,11 @@ OptionsWaiter.prototype.load = function(options) {
|
||||
/**
|
||||
* Handler for options click events.
|
||||
* Dispays the options pane.
|
||||
*
|
||||
* @param {event} e
|
||||
*/
|
||||
OptionsWaiter.prototype.optionsClick = function() {
|
||||
OptionsWaiter.prototype.optionsClick = function(e) {
|
||||
e.preventDefault();
|
||||
$("#options-modal").modal();
|
||||
};
|
||||
|
||||
|
||||
@@ -167,6 +167,17 @@ OutputWaiter.prototype.undoSwitchClick = function() {
|
||||
document.getElementById("undo-switch").disabled = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for file switch click events.
|
||||
* Moves a files data for items created via Utils.displayFilesAsHTML to the input.
|
||||
*/
|
||||
OutputWaiter.prototype.fileSwitch = function(e) {
|
||||
e.preventDefault();
|
||||
this.switchOrigData = this.manager.input.get();
|
||||
this.app.setInput(e.target.getAttribute("fileValue"));
|
||||
document.getElementById("undo-switch").disabled = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for maximise output click events.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -26,14 +26,18 @@
|
||||
<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') %>" />
|
||||
|
||||
<script type="application/javascript">
|
||||
"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 = [
|
||||
@@ -44,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
|
||||
@@ -58,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 -->
|
||||
@@ -87,23 +101,29 @@
|
||||
</div>
|
||||
<div id="content-wrapper">
|
||||
<div id="banner">
|
||||
<% if (htmlWebpackPlugin.options.inline) { %>
|
||||
<span style="float: left; margin-left: 10px;">Compile time: <%= htmlWebpackPlugin.options.compileTime %></span>
|
||||
<% } else { %>
|
||||
<a href="cyberchef.htm" style="float: left; margin-left: 10px; margin-right: 80px;" download>Download CyberChef<img aria-hidden="true" src="<%- require('../static/images/download-24x24.png') %>" alt="Download Icon"/></a>
|
||||
<% } %>
|
||||
<span id="notice">
|
||||
<script type="text/javascript">
|
||||
// Must be text/javascript rather than application/javascript otherwise IE won't recognise it...
|
||||
if (navigator.userAgent && navigator.userAgent.match(/MSIE \d\d?\./)) {
|
||||
document.write("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
||||
alert("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
||||
}
|
||||
</script>
|
||||
<noscript>JavaScript is not enabled. Good luck.</noscript>
|
||||
</span>
|
||||
<a href="#" id="support" class="banner-right" data-toggle="modal" data-target="#support-modal">About / Support<img aria-hidden="true" src="<%- require('../static/images/help-22x22.png') %>" alt="Question Mark Icon"/></a>
|
||||
<a href="#" id="options" class="banner-right">Options<img aria-hidden="true" src="<%- require('../static/images/settings-22x22.png') %>" alt="Settings Icon"/></a>
|
||||
<div class="col-md-4" style="text-align: left; padding-left: 10px;">
|
||||
<% if (htmlWebpackPlugin.options.inline) { %>
|
||||
<span>Version <%= htmlWebpackPlugin.options.version %></span>
|
||||
<% } else { %>
|
||||
<a href="cyberchef.htm" download>Download CyberChef<img aria-hidden="true" src="<%- require('../static/images/download-24x24.png') %>" alt="Download Icon"/></a>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="col-md-4" style="text-align: center;">
|
||||
<span id="notice">
|
||||
<script type="text/javascript">
|
||||
// Must be text/javascript rather than application/javascript otherwise IE won't recognise it...
|
||||
if (navigator.userAgent && navigator.userAgent.match(/MSIE \d\d?\./)) {
|
||||
document.write("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
||||
alert("Internet Explorer is not supported, please use Firefox or Chrome instead");
|
||||
}
|
||||
</script>
|
||||
<noscript>JavaScript is not enabled. Good luck.</noscript>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-4" style="text-align: right; padding-right: 0;">
|
||||
<a href="#" id="options">Options<img aria-hidden="true" src="<%- require('../static/images/settings-22x22.png') %>" alt="Settings Icon"/></a>
|
||||
<a href="#" id="support" data-toggle="modal" data-target="#support-modal">About / Support<img aria-hidden="true" src="<%- require('../static/images/help-22x22.png') %>" alt="Question Mark Icon"/></a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="workspace-wrapper">
|
||||
<div id="operations" class="split split-horizontal no-select">
|
||||
@@ -260,36 +280,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">
|
||||
@@ -341,7 +362,7 @@
|
||||
Compile time: <%= htmlWebpackPlugin.options.compileTime %>
|
||||
</p>
|
||||
<p>© Crown Copyright 2016.</p>
|
||||
<p>Licenced under the Apache Licence, Version 2.0.</p>
|
||||
<p>Released under the Apache Licence, Version 2.0.</p>
|
||||
<br>
|
||||
<br>
|
||||
<div>
|
||||
@@ -368,14 +389,14 @@
|
||||
</a>
|
||||
</blockquote>
|
||||
<div class="collapse" id="faq-examples">
|
||||
<p>There are well over 100 operations in CyberChef allowing you to carry simple and complex tasks easily. Here are some examples:</p>
|
||||
<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=%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>
|
||||
</ul>
|
||||
</div>
|
||||
<blockquote>
|
||||
@@ -395,7 +416,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=%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>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="report-bug">
|
||||
@@ -407,21 +428,25 @@
|
||||
<a class="btn btn-primary" href="https://github.com/gchq/CyberChef/issues/new" role="button">Raise issue on GitHub</a>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="about" style="padding: 20px;">
|
||||
<h4>What</h4>
|
||||
<p>A simple, intuitive web app for analysing and decoding data without having to deal with complex tools or programming languages. CyberChef encourages both technical and non-technical people to explore data formats, encryption and compression.</p>
|
||||
<h5><strong>What</strong></h5>
|
||||
<p>A simple, intuitive web app for analysing and decoding data without having to deal with complex tools or programming languages. CyberChef encourages both technical and non-technical people to explore data formats, encryption and compression.</p><br>
|
||||
|
||||
<h4>Why</h4>
|
||||
<p>Digital data comes in all shapes, sizes and formats in the modern world – CyberChef helps to make sense of this data all on one easy-to-use platform.</p>
|
||||
<h5><strong>Why</strong></h5>
|
||||
<p>Digital data comes in all shapes, sizes and formats in the modern world – CyberChef helps to make sense of this data all on one easy-to-use platform.</p><br>
|
||||
|
||||
|
||||
<h4>How</h4>
|
||||
<h5><strong>How</strong></h5>
|
||||
<p>The interface is designed with simplicity at its heart. Complex techniques are now as trivial as drag-and-drop. Simple functions can be combined to build up a "recipe", potentially resulting in complex analysis, which can be shared with other users and used with their input.</p>
|
||||
<p>For those comfortable writing code, CyberChef is a quick and efficient way to prototype solutions to a problem which can then be scripted once proven to work.</p>
|
||||
<p>For those comfortable writing code, CyberChef is a quick and efficient way to prototype solutions to a problem which can then be scripted once proven to work.</p><br>
|
||||
|
||||
|
||||
<h4>Who</h4>
|
||||
<p>It is expected that CyberChef will be useful for cybersecurity and antivirus companies. It should also appeal to the academic world and any individuals or companies involved in the analysis of digital data, be that software developers, analysts, mathematicians or casual puzzle solvers.</p>
|
||||
<h5><strong>Who</strong></h5>
|
||||
<p>It is expected that CyberChef will be useful for cybersecurity and antivirus companies. It should also appeal to the academic world and any individuals or companies involved in the analysis of digital data, be that software developers, analysts, mathematicians or casual puzzle solvers.</p><br>
|
||||
|
||||
|
||||
<h4>Aim</h4>
|
||||
<p>It is hoped that by releasing CyberChef through <a href="https://github.com/gchq/cyberchef">GitHub</a>, contributions can be added which can be rolled out into future versions of the tool.</p>
|
||||
<h5><strong>Aim</strong></h5>
|
||||
<p>It is hoped that by releasing CyberChef through <a href="https://github.com/gchq/CyberChef">GitHub</a>, contributions can be added which can be rolled out into future versions of the tool.</p><br>
|
||||
|
||||
|
||||
<br>
|
||||
<p>There are around 150 useful operations in CyberChef for anyone working on anything vaguely Internet-related, whether you just want to convert a timestamp to a different format, decompress gzipped data, create a SHA3 hash, or parse an X.509 certificate to find out who issued it.</p>
|
||||
|
||||
@@ -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);
|
||||
|
||||
23
src/web/static/structuredData.json
Normal file
23
src/web/static/structuredData.json
Normal 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"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -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 {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
/* Themes */
|
||||
@import "./themes/_classic.css";
|
||||
@import "./themes/_dark.css";
|
||||
@import "./themes/_geocities.css";
|
||||
|
||||
/* Utilities */
|
||||
@import "./utils/_overrides.css";
|
||||
|
||||
@@ -10,19 +10,15 @@
|
||||
position: absolute;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
border-bottom: 1px solid var(--primary-border-colour);
|
||||
color: var(--banner-font-colour);
|
||||
background-color: var(--banner-bg-colour);
|
||||
}
|
||||
|
||||
.banner-right {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#banner img {
|
||||
margin-bottom: 2px;
|
||||
margin-left: 8px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.option-item label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.option-item input[type=number] {
|
||||
margin: 15px 10px;
|
||||
width: 80px;
|
||||
|
||||
@@ -37,20 +37,24 @@
|
||||
#preloader:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
border: 3px solid transparent;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#preloader:before {
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
border-top-color: #e74c3c;
|
||||
animation: spin 3s linear infinite;
|
||||
}
|
||||
|
||||
#preloader:after {
|
||||
top: 13px;
|
||||
left: 13px;
|
||||
right: 13px;
|
||||
bottom: 13px;
|
||||
border-top-color: #f9c922;
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
@@ -58,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;
|
||||
|
||||
115
src/web/stylesheets/themes/_geocities.css
Executable file
115
src/web/stylesheets/themes/_geocities.css
Executable 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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -202,6 +206,11 @@ optgroup {
|
||||
border-color: var(--primary-border-colour);
|
||||
}
|
||||
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default {
|
||||
background-color: var(--primary-border-colour);
|
||||
color: var(--primary-font-colour);
|
||||
}
|
||||
|
||||
|
||||
/* Sortable */
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -12,8 +12,10 @@ import "babel-polyfill";
|
||||
|
||||
import TestRegister from "./TestRegister.js";
|
||||
import "./tests/operations/Base58.js";
|
||||
import "./tests/operations/BCD.js";
|
||||
import "./tests/operations/ByteRepr.js";
|
||||
import "./tests/operations/CharEnc.js";
|
||||
import "./tests/operations/Cipher.js";
|
||||
import "./tests/operations/Code.js";
|
||||
import "./tests/operations/Compress.js";
|
||||
import "./tests/operations/DateTime.js";
|
||||
|
||||
103
test/tests/operations/BCD.js
Normal file
103
test/tests/operations/BCD.js
Normal 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"]
|
||||
}
|
||||
]
|
||||
},
|
||||
]);
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ByteRepr tests.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
78
test/tests/operations/Cipher.js
Normal file
78
test/tests/operations/Cipher.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Cipher tests.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
*
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Bifid Cipher Encode: no input",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Bifid Cipher Encode",
|
||||
"args": ["nothing"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bifid Cipher Encode: no key",
|
||||
input: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
|
||||
expectedOutput: "Vq daqcliho rmltofvlnc qbdhlcr nt qdq Fbm-Rdkkm vuoottnoi aitp al axf tdtmvt owppkaodtx.",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Bifid Cipher Encode",
|
||||
"args": [""]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bifid Cipher Encode: normal",
|
||||
input: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
|
||||
expectedOutput: "Wc snpsigdd cpfrrcxnfi hikdnnp dm crc Fcb-Pdeug vueageacc vtyl sa zxm crebzp lyoeuaiwpv.",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Bifid Cipher Encode",
|
||||
"args": ["Schrodinger"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bifid Cipher Decode: no input",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Bifid Cipher Decode",
|
||||
"args": ["nothing"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bifid Cipher Decode: no key",
|
||||
input: "Vq daqcliho rmltofvlnc qbdhlcr nt qdq Fbm-Rdkkm vuoottnoi aitp al axf tdtmvt owppkaodtx.",
|
||||
expectedOutput: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Bifid Cipher Decode",
|
||||
"args": [""]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bifid Cipher Decode: normal",
|
||||
input: "Wc snpsigdd cpfrrcxnfi hikdnnp dm crc Fcb-Pdeug vueageacc vtyl sa zxm crebzp lyoeuaiwpv.",
|
||||
expectedOutput: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Bifid Cipher Decode",
|
||||
"args": ["Schrodinger"]
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -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"]
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -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": []
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Windows Filetime to UNIX Timestamp",
|
||||
args: ["Nanoseconds (ns)"],
|
||||
args: ["Nanoseconds (ns)", "Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -27,7 +27,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "UNIX Timestamp to Windows Filetime",
|
||||
args: ["Nanoseconds (ns)"],
|
||||
args: ["Nanoseconds (ns)", "Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -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+/="]}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": []
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user