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

Compare commits

...

119 Commits

Author SHA1 Message Date
n1474335
6e26f25418 5.10.3 2017-06-16 11:26:03 +00:00
n1474335
d8051ce9a2 Merge branch 'feature-hashurls' 2017-06-16 11:23:16 +00:00
n1474335
00e7d8a390 The recipe and input are now stored in the hash part of the URL 2017-06-16 11:04:35 +00:00
n1474335
61951e76ac 5.10.2 2017-06-15 14:25:03 +00:00
n1474335
47cf763b3f Merge branch 'bug-findreplace' 2017-06-15 14:23:35 +00:00
n1474335
04aac03d6e Fixed global matching for simple strings in 'Find / Replace' operation. Closes #25. 2017-06-15 14:21:30 +00:00
n1474335
3faef2c9c9 5.10.1 2017-06-13 16:31:00 +00:00
n1474335
eda17d1671 Added mixed content note to 'HTTP request' error message. 2017-06-13 16:30:55 +00:00
n1474335
fbd6ead6b7 5.10.0 2017-06-13 15:34:36 +00:00
n1474335
bf2950abdd Merge branch 'bwhitn-master' 2017-06-13 15:33:59 +00:00
n1474335
3eacc325a3 Improved descriptions for timestamp operations. 2017-06-13 15:33:37 +00:00
n1474335
15decd9cd9 Merge branch 'master' of https://github.com/bwhitn/CyberChef into bwhitn-master 2017-06-13 14:12:20 +00:00
Bwhit1
c0142adba9 changed error to conform with the rest of the functions and simplified repetative math. 2017-06-12 15:39:54 -04:00
bwhitn
ec01333c83 removed decimal.min.js 2017-06-12 05:48:22 -07:00
bwhitn
8110384ea2 Fixed the names under the DateTime Category 2017-06-12 05:33:24 -07:00
bwhitn
0c2c0d7b8b Added DateTime test, added filetime functions to Catagories, and removed unused variables. 2017-06-12 05:28:41 -07:00
Bwhit1
ae38bb0927 Completion of simple filetime conversion 2017-06-11 20:05:30 -04:00
Bwhit1
003e076b00 modifications to FILETIME 2017-06-10 23:42:02 -04:00
n1474335
2c2a0eb7d9 5.9.2 2017-06-09 15:36:53 +00:00
n1474335
e7f5b17184 Manual bake now triggers when recipes are loaded from the URL. Fixes #93. 2017-06-09 15:36:15 +00:00
n1474335
69e12b1067 5.9.1 2017-06-09 15:21:45 +00:00
n1474335
fef446687a Loading messages won't repeat as often and cycle more slowly 2017-06-09 15:21:39 +00:00
n1474335
3affce8f98 5.9.0 2017-06-09 14:54:27 +00:00
n1474335
0b91468edc Merge branch 'tlwr-feature-http-request' 2017-06-09 14:53:39 +00:00
n1474335
127364e8a4 Added error handling for non-CORS requests. 2017-06-09 14:53:15 +00:00
bwhitn
a144f65dcf Create DateTime.js 2017-06-08 08:28:21 -07:00
bwhitn
96ec3a869b Use decimal.min.js and add the file. 2017-06-08 08:19:26 -07:00
n1474335
52426bc1a4 Merge branch 'master' into feature-http-request 2017-06-08 16:08:20 +01:00
n1474335
cbab995c6d Added error handling and CORS support 2017-06-08 15:03:55 +00:00
bwhitn
d27fa43120 Add conversions for from/to Windows Filetime to UNIX Epoch. Decimal.js is used to prevent rounding errors during conversion. 2017-06-08 07:23:11 -07:00
n1474335
45a9da5b30 5.8.0 2017-06-08 11:10:35 +00:00
n1474335
aed22aebb2 Merge branch 'davejm-feature-remove-exif' 2017-06-08 11:09:53 +00:00
n1474335
369d213da5 Tidying 'Remove EXIF' 2017-06-08 11:09:31 +00:00
n1474335
e92775eec2 Merge branch 'feature-remove-exif' of https://github.com/davejm/CyberChef into davejm-feature-remove-exif 2017-06-08 10:56:06 +00:00
bwhitn
2c0f48f4e5 Merge pull request #1 from gchq/master
update
2017-06-07 23:55:41 -04:00
toby
a5f1c430a3 Add "HTTP request" operation 2017-06-07 22:46:05 -04:00
David Moodie
e4a91b5397 Use functions from utils 2017-06-07 21:41:02 +01:00
David Moodie
cbcd45cd70 Do nothing if input is empty for removeEXIF operation 2017-06-07 20:01:45 +01:00
David Moodie
0968912954 Only reference JPEGs in removeEXIF description to be more clear 2017-06-07 19:51:09 +01:00
David Moodie
3bfe22c0f7 Remove piexifjs dep and extract removeEXIF to lib module 2017-06-07 19:49:44 +01:00
David Moodie
6cf64d794f Change == to === 2017-06-04 17:23:53 +01:00
David Moodie
6741ba0783 Add remove EXIF operation 2017-06-04 17:08:39 +01:00
n1474335
f1e7bc3363 5.7.3 2017-06-01 10:24:38 +00:00
n1474335
2dbe2d044e Merge branch 'qistoph-numsort' 2017-06-01 10:23:49 +00:00
n1474335
ea3630e018 Tidied _numericSort and added @author tag 2017-06-01 10:21:10 +00:00
Chris van Marle
c6391d958d Add numeric sorting tests 2017-05-30 08:53:18 +02:00
Chris van Marle
71aa4033a4 Add numeric sorting 2017-05-29 15:24:41 +02:00
n1474335
57dcd961d5 Option selects now default to the first option if not previously set 2017-05-24 10:29:47 +01:00
n1474335
83878d6b05 Update ControlsWaiter.js 2017-05-23 16:53:37 +01:00
n1474335
9055fc72d2 Added Boostrap grid CSS 2017-05-23 13:09:55 +01:00
n1474335
fb4ab56b47 Merge pull request #141 from tlwr/master
Add repo option to Travis
2017-05-21 19:36:12 +01:00
toby
51e195ed17 Add repo option to Travis 2017-05-20 23:56:58 -04:00
n1474335
9947c574d2 5.7.2 2017-05-20 13:49:29 +01:00
n1474335
693abdacf6 Merge branch 'tlwr-master' 2017-05-20 13:49:17 +01:00
toby
dd3b42fb53 Fix bug with UTF16LE in Encode/Decode ops 2017-05-19 16:11:08 -04:00
n1474335
8e72d7d0d6 5.7.1 2017-05-19 16:28:43 +00:00
n1474335
a6317212d9 Merge branch 'feature-loading-messages' 2017-05-19 16:25:30 +00:00
n1474335
347adf688a Added loading messages to preloader 2017-05-19 16:23:52 +00:00
n1474335
3ee67927a5 Moved bootstrap from devDependencies to dependencies and removed bootstrap-sass. 2017-05-19 14:17:34 +00:00
n1474335
7ecd36efcf Cleaned up extraneous character encoding functions in Utils.js 2017-05-19 14:05:57 +00:00
n1474335
714ce8a8a3 5.7.0 2017-05-19 13:45:30 +00:00
n1474335
7b18a2f46f Merge branch 'tlwr-feature-ebcdic' 2017-05-19 13:44:18 +00:00
n1474335
19103a64e5 Tidied up character encoding names 2017-05-19 13:43:55 +00:00
n1474335
a13f1d27e2 Merge branch 'feature-ebcdic' of https://github.com/tlwr/CyberChef into tlwr-feature-ebcdic 2017-05-19 13:16:54 +00:00
n1474335
9a6e4b1e85 5.6.0 2017-05-19 13:12:04 +00:00
n1474335
67b78fc230 Merge branch 'feature-render-images' 2017-05-19 13:11:12 +00:00
n1474335
5e79187176 Added ico and removed tiff from supported image types 2017-05-19 12:58:42 +00:00
n1474335
491a82cd67 Added 'Render Image' operation 2017-05-19 11:15:48 +00:00
n1474335
87c2ec678f 5.5.0 2017-05-19 00:22:50 +01:00
n1474335
70135ab3ea Really fix compile message formatting 2017-05-19 00:22:41 +01:00
n1474335
ad18d84f14 Fix option defaults and compile message formatting 2017-05-19 00:10:36 +01:00
n1474335
77e47e3fa4 Merge branch 'feature-sass' 2017-05-18 23:51:29 +01:00
n1474335
04432385b3 Merge branch 'master' into feature-sass 2017-05-18 23:50:43 +01:00
n1474335
cbdc24d869 Travis CI now adds a compile message 2017-05-18 23:46:03 +01:00
n1474335
2b3e471f96 Added version number to About/Support pane 2017-05-18 23:40:53 +01:00
n1474335
488d54493a Added modern browser warning for theme support 2017-05-18 23:29:04 +01:00
n1474335
a418f63a44 Added postcss-loader to provide fallbacks for older browsers 2017-05-18 23:24:24 +01:00
toby
0e285151f3 Add codepage numbers to CharEnc IO_FORMAT 2017-05-17 18:22:04 -04:00
n1474335
e4ad7768d5 Finalised the dark theme 2017-05-17 23:02:52 +01:00
toby
f800fab1a3 Add author tags to Encode text & Decode text ops 2017-05-17 17:31:28 -04:00
toby
dc61aeeeb8 Improve format of en/decoding text descriptions 2017-05-17 17:18:08 -04:00
toby
4b1d0fd011 Merge branch 'feature-ebcdic' of github.com:tlwr/CyberChef into feature-ebcdic 2017-05-17 11:30:20 -04:00
toby
2b7ba594fc Split "Text encoding" op into two ops
This commit splits "Text encoding" into two operations:
+ Encode text `string -> byteArray`
+ Decode text `byteArray -> string`

Base64 and Hex support are removed "Encode text" and "Decode text" as
they have their own operations.

Encode and decode operations now have support for the following
encodings:
+ IBM EBCDIC US-Canada
+ IBM EBCDIC International
+ Windows-874 Thai
+ Japanese Shift-JIS
+ Simplified Chinese GBK
+ Korean
+ Traditional Chinese Big5
+ UTF-16, little endian
+ UTF-16, big endian
+ Windows-1250 Central European
+ Windows-1251 Cyrillic
+ Windows-1252 Latin
+ Windows-1253 Greek
+ Windows-1254 Turkish
+ Windows-1255 Hebrew
+ Windows-1256 Arabic
+ Windows-1257 Baltic
+ Windows-1258 Vietnam
+ US-ASCII
+ Russian Cyrillic KOI8-R
+ Simplified Chinese GB2312
+ KOI8-U Ukrainian Cyrillic
+ ISO-8859-1 Latin 1 (Western European)
+ ISO-8859-2 Latin 2 (Central European)
+ ISO-8859-3 Latin 3
+ ISO-8859-4 Baltic
+ ISO-8859-5 Cyrillic
+ ISO-8859-6 Arabic
+ ISO-8859-7 Greek
+ ISO-8859-8 Hebrew
+ ISO-8859-9 Turkish
+ ISO-8859-10 Latin 6
+ ISO-8859-11 Latin (Thai)
+ ISO-8859-13 Latin 7 (Estonian)
+ ISO-8859-14 Latin 8 (Celtic)
+ ISO-8859-15 Latin 9
+ ISO-8859-16 Latin 10
+ ISO-2022 JIS Japanese
+ EUC Japanese
+ EUC Korean
+ Simplified Chinese GB18030
+ UTF-7
+ UTF-8
2017-05-17 11:17:11 -04:00
n1474335
d87b14af13 5.4.1 2017-05-17 14:45:19 +00:00
n1474335
83623d23cf Merge branch 'bug-timestamp' 2017-05-17 14:45:10 +00:00
n1474335
07fba53b73 'To UNIX Timestamp' operation now defaults to UTC instead of your local timezone. 2017-05-17 14:37:36 +00:00
n1474335
823b276ef5 Changed bootstrap-sass back to bootstrap (with less). Theme now loads before the preloader is shown. 2017-05-13 16:45:19 +01:00
n1474335
0e72d78731 5.4.0 2017-05-13 16:10:26 +01:00
n1474335
768609e357 Whitespace 2017-05-13 16:09:32 +01:00
n1474335
526a157421 Merge branch 'tlwr-feature-exif' 2017-05-13 16:08:39 +01:00
n1474335
62154309fb Newlines 2017-05-13 16:08:14 +01:00
n1474335
ad74e6c475 Merge branch 'feature-exif' of https://github.com/tlwr/CyberChef into tlwr-feature-exif 2017-05-13 15:59:48 +01:00
toby
82d28242cc Add JSDoc to the runEXIF function in Image.js 2017-05-09 15:34:18 -04:00
toby
60fddf837d Change let to const in "Extract EXIF" 2017-05-08 12:49:13 -04:00
toby
ee25df0c28 Add desc and fix error message for "Extract EXIF" 2017-05-08 12:48:43 -04:00
toby
478af40359 Fix "Extract EXIF" tests 2017-05-08 12:45:42 -04:00
Toby Lorne
6bf06a9629 Merge branch 'master' into feature-ebcdic 2017-05-07 18:21:30 -04:00
toby
3c15bd9e29 Add "{To,From} EBCDIC" operations
This adds operations
+ "To EBCDIC"
+ "From EBCDIC"

This makes use of the npm codepage package but it is not installed as a
dependency.

Instead I used the `make.sh` script to export pages 37 and 500.

To my knowledge there is no way currently to only import individual code pages
from the npm package (hence the included script).

If we were to import the package directly it increases the build size by
2.7MB.
2017-05-07 18:07:56 -04:00
toby
71796e3dbf Merge remote-tracking branch 'upstream/master' into feature-exif 2017-05-06 23:38:04 -04:00
n1474335
280f1ee2df Dark theme tweaks and improvements 2017-05-07 01:13:47 +01:00
n1474335
0dc72d8301 Merged master 2017-05-06 16:22:25 +01:00
n1474335
c43b67ea90 5.3.5 2017-05-06 16:15:29 +01:00
n1474335
244421b69e Merge branch 'graingert-prefer-const' 2017-05-06 16:14:58 +01:00
n1474335
1adedff61a Filter out source-map warnings in webpack output 2017-05-06 16:14:30 +01:00
n1474335
6abd10f9e2 Tidying codebase 2017-05-06 16:12:09 +01:00
n1474335
5efe9bd91d Merge branch 'prefer-const' of https://github.com/graingert/CyberChef into graingert-prefer-const 2017-05-06 14:11:38 +01:00
n1474335
dc7a7267c9 5.3.4 2017-05-06 14:00:41 +01:00
Thomas Grainger
b365ce3195 fix the first 100 prefer-const errors 2017-05-03 00:41:01 +01:00
Thomas Grainger
0a3233d289 move spider images to .json file 2017-05-03 00:41:01 +01:00
Thomas Grainger
15aea9e9ea auto-fix prefer-const 2017-05-03 00:41:01 +01:00
n1474335
80cdf0c014 Merge conflict 2017-05-02 23:03:28 +01:00
n1474335
d1d394eec7 Fix search-results layout bug. 2017-05-02 20:56:57 +01:00
toby
1b8a25ec88 Add "Extract EXIF" operation 2017-04-29 16:06:16 -04:00
n1474335
2e4076bb75 Added option to change the theme. 2017-04-25 00:21:38 +01:00
n1474335
d71ac2e894 Moved from Sass to CSS with custom properties, allowing for dynamic theme changes. 2017-04-24 23:59:35 +01:00
n1474335
e3f41fea9c Developing a dark theme. 2017-04-23 17:09:12 +01:00
n1474335
a4d93f23d6 Added preloader to hide elements before they are correctly rendered 2017-04-15 20:46:57 +01:00
n1474335
e0e5670d0e Styles rewritten in a modular format with themable properties stored in variables. 2017-04-13 17:59:37 +01:00
n1474335
e120422b05 Styles now imported through Sass. Less removed. 2017-04-09 14:06:59 +01:00
63 changed files with 5368 additions and 1400 deletions

View File

@@ -9,7 +9,7 @@ script:
- grunt test
- grunt docs
- grunt node
- grunt prod
- grunt prod --msg="$COMPILE_MSG"
before_deploy:
- grunt copy:ghPages
deploy:
@@ -19,6 +19,7 @@ deploy:
local_dir: build/prod/
target_branch: gh-pages
on:
repo: gchq/CyberChef
branch: master
- provider: releases
skip_cleaup: true

View File

@@ -54,7 +54,7 @@ module.exports = function (grunt) {
// Project configuration
const compileTime = grunt.template.today("dd/mm/yyyy HH:MM:ss") + " UTC",
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
banner = "/**\n" +
"* CyberChef - The Cyber Swiss Army Knife\n" +
"*\n" +
@@ -74,7 +74,8 @@ module.exports = function (grunt) {
"* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
"* See the License for the specific language governing permissions and\n" +
"* limitations under the License.\n" +
"*/\n";
"*/\n",
pkg = grunt.file.readJSON("package.json");
/**
* Compiles a production build of CyberChef into a single, portable web page.
@@ -182,7 +183,10 @@ module.exports = function (grunt) {
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: "css-loader?minimize"
use: [
{ loader: "css-loader?minimize" },
{ loader: "postcss-loader" },
]
})
},
{
@@ -190,6 +194,7 @@ module.exports = function (grunt) {
use: ExtractTextPlugin.extract({
use: [
{ loader: "css-loader?minimize" },
{ loader: "postcss-loader" },
{ loader: "less-loader" }
]
})
@@ -220,7 +225,8 @@ module.exports = function (grunt) {
]
},
stats: {
children: false
children: false,
warningsFilter: /source-map/
}
},
webDev: {
@@ -234,7 +240,8 @@ module.exports = function (grunt) {
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/web/html/index.html",
compileTime: compileTime
compileTime: compileTime,
version: pkg.version,
})
],
watch: true
@@ -260,6 +267,7 @@ module.exports = function (grunt) {
filename: "index.html",
template: "./src/web/html/index.html",
compileTime: compileTime,
version: pkg.version,
minify: {
removeComments: true,
collapseWhitespace: true,
@@ -271,6 +279,7 @@ module.exports = function (grunt) {
filename: "cyberchef.htm",
template: "./src/web/html/index.html",
compileTime: compileTime,
version: pkg.version,
inline: true,
minify: {
removeComments: true,

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "5.3.4",
"version": "5.10.3",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -53,7 +53,10 @@
"ink-docstrap": "^1.1.4",
"jsdoc-babel": "^0.3.0",
"less": "^2.7.2",
"less-loader": "^4.0.2",
"less-loader": "^4.0.3",
"postcss-css-variables": "^0.7.0",
"postcss-import": "^10.0.0",
"postcss-loader": "^2.0.5",
"style-loader": "^0.15.0",
"url-loader": "^0.5.8",
"web-resource-inliner": "^4.1.0",
@@ -69,6 +72,7 @@
"escodegen": "^1.8.1",
"esmangle": "^1.0.1",
"esprima": "^3.1.3",
"exif-parser": "^0.1.9",
"google-code-prettify": "^1.0.5",
"jquery": "^3.1.1",
"jsbn": "^1.1.0",

15
postcss.config.js Normal file
View File

@@ -0,0 +1,15 @@
module.exports = {
plugins: [
require("postcss-import"),
require("autoprefixer")({
browsers: [
"Chrome >= 40",
"Firefox >= 35",
"Edge >= 14"
]
}),
require("postcss-css-variables")({
preserve: true
}),
]
};

View File

@@ -259,6 +259,22 @@ const Utils = {
},
/**
* Escape a string containing regex control characters so that it can be safely
* used in a regex without causing unintended behaviours.
*
* @param {string} str
* @returns {string}
*
* @example
* // returns "\[example\]"
* Utils.escapeRegex("[example]");
*/
escapeRegex: function(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
},
/**
* Expand an alphabet range string into a list of the characters in that range.
*
@@ -498,127 +514,6 @@ const Utils = {
},
/**
* Mapping of Unicode code points to Windows-1251
* @private
* @constant
*/
UNIC_WIN1251_MAP: {
0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13,
14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24,
25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35,
36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46,
47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57,
58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68,
69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79,
80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90,
91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99, 100: 100, 101: 101,
102: 102, 103: 103, 104: 104, 105: 105, 106: 106, 107: 107, 108: 108, 109: 109, 110: 110,
111: 111, 112: 112, 113: 113, 114: 114, 115: 115, 116: 116, 117: 117, 118: 118, 119: 119,
120: 120, 121: 121, 122: 122, 123: 123, 124: 124, 125: 125, 126: 126, 127: 127, 1027: 129,
8225: 135, 1046: 198, 8222: 132, 1047: 199, 1168: 165, 1048: 200, 1113: 154, 1049: 201,
1045: 197, 1050: 202, 1028: 170, 160: 160, 1040: 192, 1051: 203, 164: 164, 166: 166,
167: 167, 169: 169, 171: 171, 172: 172, 173: 173, 174: 174, 1053: 205, 176: 176, 177: 177,
1114: 156, 181: 181, 182: 182, 183: 183, 8221: 148, 187: 187, 1029: 189, 1056: 208,
1057: 209, 1058: 210, 8364: 136, 1112: 188, 1115: 158, 1059: 211, 1060: 212, 1030: 178,
1061: 213, 1062: 214, 1063: 215, 1116: 157, 1064: 216, 1065: 217, 1031: 175, 1066: 218,
1067: 219, 1068: 220, 1069: 221, 1070: 222, 1032: 163, 8226: 149, 1071: 223, 1072: 224,
8482: 153, 1073: 225, 8240: 137, 1118: 162, 1074: 226, 1110: 179, 8230: 133, 1075: 227,
1033: 138, 1076: 228, 1077: 229, 8211: 150, 1078: 230, 1119: 159, 1079: 231, 1042: 194,
1080: 232, 1034: 140, 1025: 168, 1081: 233, 1082: 234, 8212: 151, 1083: 235, 1169: 180,
1084: 236, 1052: 204, 1085: 237, 1035: 142, 1086: 238, 1087: 239, 1088: 240, 1089: 241,
1090: 242, 1036: 141, 1041: 193, 1091: 243, 1092: 244, 8224: 134, 1093: 245, 8470: 185,
1094: 246, 1054: 206, 1095: 247, 1096: 248, 8249: 139, 1097: 249, 1098: 250, 1044: 196,
1099: 251, 1111: 191, 1055: 207, 1100: 252, 1038: 161, 8220: 147, 1101: 253, 8250: 155,
1102: 254, 8216: 145, 1103: 255, 1043: 195, 1105: 184, 1039: 143, 1026: 128, 1106: 144,
8218: 130, 1107: 131, 8217: 146, 1108: 186, 1109: 190
},
/**
* Mapping of Windows-1251 code points to Unicode
* @private
* @constant
*/
WIN1251_UNIC_MAP: {
0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13,
14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24,
25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35,
36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46,
47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57,
58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68,
69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79,
80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90,
91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99, 100: 100, 101: 101,
102: 102, 103: 103, 104: 104, 105: 105, 106: 106, 107: 107, 108: 108, 109: 109, 110: 110,
111: 111, 112: 112, 113: 113, 114: 114, 115: 115, 116: 116, 117: 117, 118: 118, 119: 119,
120: 120, 121: 121, 122: 122, 123: 123, 124: 124, 125: 125, 126: 126, 127: 127, 160: 160,
164: 164, 166: 166, 167: 167, 169: 169, 171: 171, 172: 172, 173: 173, 174: 174, 176: 176,
177: 177, 181: 181, 182: 182, 183: 183, 187: 187, 168: 1025, 128: 1026, 129: 1027,
170: 1028, 189: 1029, 178: 1030, 175: 1031, 163: 1032, 138: 1033, 140: 1034, 142: 1035,
141: 1036, 161: 1038, 143: 1039, 192: 1040, 193: 1041, 194: 1042, 195: 1043, 196: 1044,
197: 1045, 198: 1046, 199: 1047, 200: 1048, 201: 1049, 202: 1050, 203: 1051, 204: 1052,
205: 1053, 206: 1054, 207: 1055, 208: 1056, 209: 1057, 210: 1058, 211: 1059, 212: 1060,
213: 1061, 214: 1062, 215: 1063, 216: 1064, 217: 1065, 218: 1066, 219: 1067, 220: 1068,
221: 1069, 222: 1070, 223: 1071, 224: 1072, 225: 1073, 226: 1074, 227: 1075, 228: 1076,
229: 1077, 230: 1078, 231: 1079, 232: 1080, 233: 1081, 234: 1082, 235: 1083, 236: 1084,
237: 1085, 238: 1086, 239: 1087, 240: 1088, 241: 1089, 242: 1090, 243: 1091, 244: 1092,
245: 1093, 246: 1094, 247: 1095, 248: 1096, 249: 1097, 250: 1098, 251: 1099, 252: 1100,
253: 1101, 254: 1102, 255: 1103, 184: 1105, 144: 1106, 131: 1107, 186: 1108, 190: 1109,
179: 1110, 191: 1111, 188: 1112, 154: 1113, 156: 1114, 158: 1115, 157: 1116, 162: 1118,
159: 1119, 165: 1168, 180: 1169, 150: 8211, 151: 8212, 145: 8216, 146: 8217, 130: 8218,
147: 8220, 148: 8221, 132: 8222, 134: 8224, 135: 8225, 149: 8226, 133: 8230, 137: 8240,
139: 8249, 155: 8250, 136: 8364, 185: 8470, 153: 8482
},
/**
* Converts a Unicode string to Windows-1251 encoding
*
* @param {string} unicStr
* @returns {string} String encoded in Windows-1251
*
* @example
* // returns "îáíîâëåííàÿ òåõíè÷êà ïî Áîèíãó. îðèãèíàë ó ìåíÿ. çàáåðåòå êîãäà áóäåòå â ÊÈ"
* Utils.unicodeToWin1251("обновленная техничка по Боингу. оригинал у меня. заберете когда будете в КИ");
*/
unicodeToWin1251: function(unicStr) {
const res = [];
for (let i = 0; i < unicStr.length; i++) {
const ord = unicStr.charCodeAt(i);
if (!(ord in Utils.UNIC_WIN1251_MAP))
throw "Character '" + unicStr.charAt(i) + "' isn't supported by Windows-1251";
res.push(String.fromCharCode(Utils.UNIC_WIN1251_MAP[ord]));
}
return res.join("");
},
/**
* Converts a Windows-1251 string to Unicode encoding
*
* @param {string} win1251Str
* @returns {string} String encoded in Unicode
*
* @example
* // returns "обновленная техничка по Боингу. оригинал у меня. заберете когда будете в КИ"
* Utils.unicodeToWin1251("îáíîâëåííàÿ òåõíè÷êà ïî Áîèíãó. îðèãèíàë ó ìåíÿ. çàáåðåòå êîãäà áóäåòå â ÊÈ");
*/
win1251ToUnicode: function(win1251Str) {
const res = [];
for (let i = 0; i < win1251Str.length; i++) {
const ord = win1251Str.charCodeAt(i);
if (!(ord in Utils.WIN1251_UNIC_MAP))
throw "Character '" + win1251Str.charAt(i) + "' isn't supported by Windows-1251";
res.push(String.fromCharCode(Utils.WIN1251_UNIC_MAP[ord]));
}
return res.join("");
},
/**
* Base64's the input byte array using the given alphabet, returning a string.
*
@@ -1086,6 +981,37 @@ const Utils = {
},
/**
* Parses URI parameters into a JSON object.
*
* @param {string} paramStr - The serialised query or hash section of a URI
* @returns {object}
*
* @example
* // returns {a: 'abc', b: '123'}
* Utils.parseURIParams("?a=abc&b=123")
* Utils.parseURIParams("#a=abc&b=123")
*/
parseURIParams: function(paramStr) {
if (paramStr === "") return {};
// Cut off ? or # and split on &
const params = paramStr.substr(1).split("&");
const result = {};
for (let i = 0; i < params.length; i++) {
const param = params[i].split("=");
if (param.length !== 2) {
result[params[i]] = true;
} else {
result[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "));
}
}
return result;
},
/**
* Actual modulo function, since % is actually the remainder function in JS.
*

View File

@@ -61,7 +61,8 @@ const Categories = [
"Hex to PEM",
"Parse ASN.1 hex string",
"Change IP format",
"Text encoding",
"Encode text",
"Decode text",
"Swap endianness",
]
},
@@ -125,6 +126,7 @@ const Categories = [
{
name: "Networking",
ops: [
"HTTP request",
"Strip HTTP headers",
"Parse User Agent",
"Parse IP range",
@@ -143,7 +145,8 @@ const Categories = [
{
name: "Language",
ops: [
"Text encoding",
"Encode text",
"Decode text",
"Unescape Unicode Characters",
]
},
@@ -190,6 +193,8 @@ const Categories = [
"Translate DateTime Format",
"From UNIX Timestamp",
"To UNIX Timestamp",
"Windows Filetime to UNIX Timestamp",
"UNIX Timestamp to Windows Filetime",
"Extract dates",
]
},
@@ -207,6 +212,7 @@ const Categories = [
"Regular expression",
"XPath expression",
"CSS selector",
"Extract EXIF",
]
},
{
@@ -284,6 +290,9 @@ const Categories = [
"Detect File Type",
"Scan for Embedded Files",
"Generate UUID",
"Render Image",
"Remove EXIF",
"Extract EXIF",
"Numberwang",
]
},

View File

@@ -15,6 +15,7 @@ import Endian from "../operations/Endian.js";
import Entropy from "../operations/Entropy.js";
import Extract from "../operations/Extract.js";
import FileType from "../operations/FileType.js";
import Image from "../operations/Image.js";
import Hash from "../operations/Hash.js";
import Hexdump from "../operations/Hexdump.js";
import HTML from "../operations/HTML.js";
@@ -886,21 +887,43 @@ const OperationConfig = {
}
]
},
"Text encoding": {
description: "Translates the data between different character encodings.<br><br>Supported charsets are:<ul><li>UTF8</li><li>UTF16</li><li>UTF16LE (little-endian)</li><li>UTF16BE (big-endian)</li><li>Hex</li><li>Base64</li><li>Latin1 (ISO-8859-1)</li><li>Windows-1251</li></ul>",
run: CharEnc.run,
"Encode text": {
description: [
"Encodes text into the chosen character encoding.",
"<br><br>",
"Supported charsets are:",
"<ul>",
Object.keys(CharEnc.IO_FORMAT).map(e => `<li>${e}</li>`).join("\n"),
"</ul>",
].join("\n"),
run: CharEnc.runEncode,
inputType: "string",
outputType: "byteArray",
args: [
{
name: "Encoding",
type: "option",
value: Object.keys(CharEnc.IO_FORMAT),
},
]
},
"Decode text": {
description: [
"Decodes text from the chosen character encoding.",
"<br><br>",
"Supported charsets are:",
"<ul>",
Object.keys(CharEnc.IO_FORMAT).map(e => `<li>${e}</li>`).join("\n"),
"</ul>",
].join("\n"),
run: CharEnc.runDecode,
inputType: "byteArray",
outputType: "string",
args: [
{
name: "Input type",
name: "Encoding",
type: "option",
value: CharEnc.IO_FORMAT
},
{
name: "Output type",
type: "option",
value: CharEnc.IO_FORMAT
value: Object.keys(CharEnc.IO_FORMAT),
},
]
},
@@ -921,7 +944,6 @@ const OperationConfig = {
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{
name: "Salt",
@@ -968,7 +990,6 @@ const OperationConfig = {
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{
name: "Salt",
@@ -1898,7 +1919,7 @@ const OperationConfig = {
args: []
},
"Find / Replace": {
description: "Replaces all occurrences of the first string with the second.<br><br>The three match options are only relevant to regex search strings.",
description: "Replaces all occurrences of the first string with the second.<br><br> Includes support for regular expressions (regex), simple strings and extended strings (which support \\n, \\r, \\t, \\b, \\f and escaped hex bytes using \\x notation, e.g. \\x00 for a null byte).",
run: StrUtils.runFindReplace,
manualBake: true,
inputType: "string",
@@ -2210,7 +2231,7 @@ const OperationConfig = {
]
},
"From UNIX Timestamp": {
description: "Converts a UNIX timestamp to a datetime string.<br><br>e.g. <code>978346800</code> becomes <code>Mon 1 January 2001 11:00:00 UTC</code>",
description: "Converts a UNIX timestamp to a datetime string.<br><br>e.g. <code>978346800</code> becomes <code>Mon 1 January 2001 11:00:00 UTC</code><br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).",
run: DateTime.runFromUnixTimestamp,
inputType: "number",
outputType: "string",
@@ -2223,7 +2244,7 @@ const OperationConfig = {
]
},
"To UNIX Timestamp": {
description: "Parses a datetime string and returns the corresponding UNIX timestamp.<br><br>e.g. <code>Mon 1 January 2001 11:00:00 UTC</code> becomes <code>978346800</code>",
description: "Parses a datetime string in UTC and returns the corresponding UNIX timestamp.<br><br>e.g. <code>Mon 1 January 2001 11:00:00</code> becomes <code>978346800</code><br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).",
run: DateTime.runToUnixTimestamp,
inputType: "string",
outputType: "number",
@@ -2232,6 +2253,37 @@ const OperationConfig = {
name: "Units",
type: "option",
value: DateTime.UNITS
},
{
name: "Treat as UTC",
type: "boolean",
value: DateTime.TREAT_AS_UTC
}
]
},
"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",
outputType: "string",
args: [
{
name: "Output units",
type: "option",
value: DateTime.UNITS
}
]
},
"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",
outputType: "string",
args: [
{
name: "Input units",
type: "option",
value: DateTime.UNITS
}
]
},
@@ -3336,6 +3388,85 @@ const OperationConfig = {
},
]
},
"Extract EXIF": {
description: [
"Extracts EXIF data from an image.",
"<br><br>",
"EXIF data is metadata embedded in images (JPEG, JPG, TIFF) and audio files.",
"<br><br>",
"EXIF data from photos usually contains information about the image file itself as well as the device used to create it.",
].join("\n"),
run: Image.runExtractEXIF,
inputType: "byteArray",
outputType: "string",
args: [],
},
"Render Image": {
description: "Displays the input as an image. Supports the following formats:<br><br><ul><li>jpg/jpeg</li><li>png</li><li>gif</li><li>webp</li><li>bmp</li><li>ico</li></ul>",
run: Image.runRenderImage,
inputType: "string",
outputType: "html",
args: [
{
name: "Input format",
type: "option",
value: Image.INPUT_FORMAT
}
]
},
"Remove EXIF": {
description: [
"Removes EXIF data from a JPEG image.",
"<br><br>",
"EXIF data embedded in photos usually contains information about the image file itself as well as the device used to create it.",
].join("\n"),
run: Image.runRemoveEXIF,
inputType: "byteArray",
outputType: "byteArray",
args: []
},
"HTTP request": {
description: [
"Makes an HTTP request and returns the response.",
"<br><br>",
"This operation supports different HTTP verbs like GET, POST, PUT, etc.",
"<br><br>",
"You can add headers line by line in the format <code>Key: Value</code>",
"<br><br>",
"The status code of the response, along with a limited selection of exposed headers, can be viewed by checking the 'Show response metadata' option. Only a limited set of response headers are exposed by the browser for security reasons.",
].join("\n"),
run: HTTP.runHTTPRequest,
inputType: "string",
outputType: "string",
manualBake: true,
args: [
{
name: "Method",
type: "option",
value: HTTP.METHODS,
},
{
name: "URL",
type: "string",
value: "",
},
{
name: "Headers",
type: "text",
value: "",
},
{
name: "Mode",
type: "option",
value: HTTP.MODE,
},
{
name: "Show response metadata",
type: "boolean",
value: false,
}
]
},
};
export default OperationConfig;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,515 @@
/* cputils.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ft=javascript: */
/*jshint newcap: false */
(function(root, factory) {
"use strict";
if(typeof cptable === "undefined") {
if(typeof require !== "undefined"){
var cpt = require('./cptable');
if (typeof module !== 'undefined' && module.exports) module.exports = factory(cpt);
else root.cptable = factory(cpt);
} else throw new Error("cptable not found");
} else cptable = factory(cptable);
}(this, function(cpt){
"use strict";
var magic = {
"1200":"utf16le",
"1201":"utf16be",
"12000":"utf32le",
"12001":"utf32be",
"16969":"utf64le",
"20127":"ascii",
"65000":"utf7",
"65001":"utf8"
};
var sbcs_cache = [874,1250,1251,1252,1253,1254,1255,1256,10000];
var dbcs_cache = [932,936,949,950];
var magic_cache = [65001];
var magic_decode = {};
var magic_encode = {};
var cpdcache = {};
var cpecache = {};
var sfcc = function sfcc(x) { return String.fromCharCode(x); };
var cca = function cca(x) { return x.charCodeAt(0); };
var has_buf = (typeof Buffer !== 'undefined');
if(has_buf) {
var mdl = 1024, mdb = new Buffer(mdl);
var make_EE = function make_EE(E){
var EE = new Buffer(65536);
for(var i = 0; i < 65536;++i) EE[i] = 0;
var keys = Object.keys(E), len = keys.length;
for(var ee = 0, e = keys[ee]; ee < len; ++ee) {
if(!(e = keys[ee])) continue;
EE[e.charCodeAt(0)] = E[e];
}
return EE;
};
var sbcs_encode = function make_sbcs_encode(cp) {
var EE = make_EE(cpt[cp].enc);
return function sbcs_e(data, ofmt) {
var len = data.length;
var out, i=0, j=0, D=0, w=0;
if(typeof data === 'string') {
out = new Buffer(len);
for(i = 0; i < len; ++i) out[i] = EE[data.charCodeAt(i)];
} else if(Buffer.isBuffer(data)) {
out = new Buffer(2*len);
j = 0;
for(i = 0; i < len; ++i) {
D = data[i];
if(D < 128) out[j++] = EE[D];
else if(D < 224) { out[j++] = EE[((D&31)<<6)+(data[i+1]&63)]; ++i; }
else if(D < 240) { out[j++] = EE[((D&15)<<12)+((data[i+1]&63)<<6)+(data[i+2]&63)]; i+=2; }
else {
w = ((D&7)<<18)+((data[i+1]&63)<<12)+((data[i+2]&63)<<6)+(data[i+3]&63); i+=3;
if(w < 65536) out[j++] = EE[w];
else { w -= 65536; out[j++] = EE[0xD800 + ((w>>10)&1023)]; out[j++] = EE[0xDC00 + (w&1023)]; }
}
}
out = out.slice(0,j);
} else {
out = new Buffer(len);
for(i = 0; i < len; ++i) out[i] = EE[data[i].charCodeAt(0)];
}
if(!ofmt || ofmt === 'buf') return out;
if(ofmt !== 'arr') return out.toString('binary');
return [].slice.call(out);
};
};
var sbcs_decode = function make_sbcs_decode(cp) {
var D = cpt[cp].dec;
var DD = new Buffer(131072), d=0, c="";
for(d=0;d<D.length;++d) {
if(!(c=D[d])) continue;
var w = c.charCodeAt(0);
DD[2*d] = w&255; DD[2*d+1] = w>>8;
}
return function sbcs_d(data) {
var len = data.length, i=0, j=0;
if(2 * len > mdl) { mdl = 2 * len; mdb = new Buffer(mdl); }
if(Buffer.isBuffer(data)) {
for(i = 0; i < len; i++) {
j = 2*data[i];
mdb[2*i] = DD[j]; mdb[2*i+1] = DD[j+1];
}
} else if(typeof data === "string") {
for(i = 0; i < len; i++) {
j = 2*data.charCodeAt(i);
mdb[2*i] = DD[j]; mdb[2*i+1] = DD[j+1];
}
} else {
for(i = 0; i < len; i++) {
j = 2*data[i];
mdb[2*i] = DD[j]; mdb[2*i+1] = DD[j+1];
}
}
return mdb.slice(0, 2 * len).toString('ucs2');
};
};
var dbcs_encode = function make_dbcs_encode(cp) {
var E = cpt[cp].enc;
var EE = new Buffer(131072);
for(var i = 0; i < 131072; ++i) EE[i] = 0;
var keys = Object.keys(E);
for(var ee = 0, e = keys[ee]; ee < keys.length; ++ee) {
if(!(e = keys[ee])) continue;
var f = e.charCodeAt(0);
EE[2*f] = E[e] & 255; EE[2*f+1] = E[e]>>8;
}
return function dbcs_e(data, ofmt) {
var len = data.length, out = new Buffer(2*len), i=0, j=0, jj=0, k=0, D=0;
if(typeof data === 'string') {
for(i = k = 0; i < len; ++i) {
j = data.charCodeAt(i)*2;
out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
}
out = out.slice(0,k);
} else if(Buffer.isBuffer(data)) {
for(i = k = 0; i < len; ++i) {
D = data[i];
if(D < 128) j = D;
else if(D < 224) { j = ((D&31)<<6)+(data[i+1]&63); ++i; }
else if(D < 240) { j = ((D&15)<<12)+((data[i+1]&63)<<6)+(data[i+2]&63); i+=2; }
else { j = ((D&7)<<18)+((data[i+1]&63)<<12)+((data[i+2]&63)<<6)+(data[i+3]&63); i+=3; }
if(j<65536) { j*=2; out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j]; }
else { jj = j-65536;
j=2*(0xD800 + ((jj>>10)&1023)); out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
j=2*(0xDC00 + (jj&1023)); out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
}
}
out = out.slice(0,k);
} else {
for(i = k = 0; i < len; i++) {
j = data[i].charCodeAt(0)*2;
out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
}
}
if(!ofmt || ofmt === 'buf') return out;
if(ofmt !== 'arr') return out.toString('binary');
return [].slice.call(out);
};
};
var dbcs_decode = function make_dbcs_decode(cp) {
var D = cpt[cp].dec;
var DD = new Buffer(131072), d=0, c, w=0, j=0, i=0;
for(i = 0; i < 65536; ++i) { DD[2*i] = 0xFF; DD[2*i+1] = 0xFD;}
for(d = 0; d < D.length; ++d) {
if(!(c=D[d])) continue;
w = c.charCodeAt(0);
j = 2*d;
DD[j] = w&255; DD[j+1] = w>>8;
}
return function dbcs_d(data) {
var len = data.length, out = new Buffer(2*len), i=0, j=0, k=0;
if(Buffer.isBuffer(data)) {
for(i = 0; i < len; i++) {
j = 2*data[i];
if(DD[j]===0xFF && DD[j+1]===0xFD) { j=2*((data[i]<<8)+data[i+1]); ++i; }
out[k++] = DD[j]; out[k++] = DD[j+1];
}
} else if(typeof data === "string") {
for(i = 0; i < len; i++) {
j = 2*data.charCodeAt(i);
if(DD[j]===0xFF && DD[j+1]===0xFD) { j=2*((data.charCodeAt(i)<<8)+data.charCodeAt(i+1)); ++i; }
out[k++] = DD[j]; out[k++] = DD[j+1];
}
} else {
for(i = 0; i < len; i++) {
j = 2*data[i];
if(DD[j]===0xFF && DD[j+1]===0xFD) { j=2*((data[i]<<8)+data[i+1]); ++i; }
out[k++] = DD[j]; out[k++] = DD[j+1];
}
}
return out.slice(0,k).toString('ucs2');
};
};
magic_decode[65001] = function utf8_d(data) {
if(typeof data === "string") return utf8_d(data.split("").map(cca));
var len = data.length, w = 0, ww = 0;
if(4 * len > mdl) { mdl = 4 * len; mdb = new Buffer(mdl); }
var i = 0;
if(len >= 3 && data[0] == 0xEF) if(data[1] == 0xBB && data[2] == 0xBF) i = 3;
for(var j = 1, k = 0, D = 0; i < len; i+=j) {
j = 1; D = data[i];
if(D < 128) w = D;
else if(D < 224) { w=(D&31)*64+(data[i+1]&63); j=2; }
else if(D < 240) { w=((D&15)<<12)+(data[i+1]&63)*64+(data[i+2]&63); j=3; }
else { w=(D&7)*262144+((data[i+1]&63)<<12)+(data[i+2]&63)*64+(data[i+3]&63); j=4; }
if(w < 65536) { mdb[k++] = w&255; mdb[k++] = w>>8; }
else {
w -= 65536; ww = 0xD800 + ((w>>10)&1023); w = 0xDC00 + (w&1023);
mdb[k++] = ww&255; mdb[k++] = ww>>>8; mdb[k++] = w&255; mdb[k++] = (w>>>8)&255;
}
}
return mdb.slice(0,k).toString('ucs2');
};
magic_encode[65001] = function utf8_e(data, ofmt) {
if(has_buf && Buffer.isBuffer(data)) {
if(!ofmt || ofmt === 'buf') return data;
if(ofmt !== 'arr') return data.toString('binary');
return [].slice.call(data);
}
var len = data.length, w = 0, ww = 0, j = 0;
var direct = typeof data === "string";
if(4 * len > mdl) { mdl = 4 * len; mdb = new Buffer(mdl); }
for(var i = 0; i < len; ++i) {
w = direct ? data.charCodeAt(i) : data[i].charCodeAt(0);
if(w <= 0x007F) mdb[j++] = w;
else if(w <= 0x07FF) {
mdb[j++] = 192 + (w >> 6);
mdb[j++] = 128 + (w&63);
} else if(w >= 0xD800 && w <= 0xDFFF) {
w -= 0xD800; ++i;
ww = (direct ? data.charCodeAt(i) : data[i].charCodeAt(0)) - 0xDC00 + (w << 10);
mdb[j++] = 240 + ((ww>>>18) & 0x07);
mdb[j++] = 144 + ((ww>>>12) & 0x3F);
mdb[j++] = 128 + ((ww>>>6) & 0x3F);
mdb[j++] = 128 + (ww & 0x3F);
} else {
mdb[j++] = 224 + (w >> 12);
mdb[j++] = 128 + ((w >> 6)&63);
mdb[j++] = 128 + (w&63);
}
}
if(!ofmt || ofmt === 'buf') return mdb.slice(0,j);
if(ofmt !== 'arr') return mdb.slice(0,j).toString('binary');
return [].slice.call(mdb, 0, j);
};
}
var encache = function encache() {
if(has_buf) {
if(cpdcache[sbcs_cache[0]]) return;
var i=0, s=0;
for(i = 0; i < sbcs_cache.length; ++i) {
s = sbcs_cache[i];
if(cpt[s]) {
cpdcache[s] = sbcs_decode(s);
cpecache[s] = sbcs_encode(s);
}
}
for(i = 0; i < dbcs_cache.length; ++i) {
s = dbcs_cache[i];
if(cpt[s]) {
cpdcache[s] = dbcs_decode(s);
cpecache[s] = dbcs_encode(s);
}
}
for(i = 0; i < magic_cache.length; ++i) {
s = magic_cache[i];
if(magic_decode[s]) cpdcache[s] = magic_decode[s];
if(magic_encode[s]) cpecache[s] = magic_encode[s];
}
}
};
var null_enc = function(data, ofmt) { return ""; };
var cp_decache = function cp_decache(cp) { delete cpdcache[cp]; delete cpecache[cp]; };
var decache = function decache() {
if(has_buf) {
if(!cpdcache[sbcs_cache[0]]) return;
sbcs_cache.forEach(cp_decache);
dbcs_cache.forEach(cp_decache);
magic_cache.forEach(cp_decache);
}
last_enc = null_enc; last_cp = 0;
};
var cache = {
encache: encache,
decache: decache,
sbcs: sbcs_cache,
dbcs: dbcs_cache
};
encache();
var BM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var SetD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?";
var last_enc = null_enc, last_cp = 0;
var encode = function encode(cp, data, ofmt) {
if(cp === last_cp && last_enc) { return last_enc(data, ofmt); }
if(cpecache[cp]) { last_enc = cpecache[last_cp=cp]; return last_enc(data, ofmt); }
if(has_buf && Buffer.isBuffer(data)) data = data.toString('utf8');
var len = data.length;
var out = has_buf ? new Buffer(4*len) : [], w=0, i=0, j = 0, ww=0;
var C = cpt[cp], E, M = "";
var isstr = typeof data === 'string';
if(C && (E=C.enc)) for(i = 0; i < len; ++i, ++j) {
w = E[isstr? data.charAt(i) : data[i]];
if(w > 255) {
out[j] = w>>8;
out[++j] = w&255;
} else out[j] = w&255;
}
else if((M=magic[cp])) switch(M) {
case "utf8":
if(has_buf && isstr) { out = new Buffer(data, M); j = out.length; break; }
for(i = 0; i < len; ++i, ++j) {
w = isstr ? data.charCodeAt(i) : data[i].charCodeAt(0);
if(w <= 0x007F) out[j] = w;
else if(w <= 0x07FF) {
out[j] = 192 + (w >> 6);
out[++j] = 128 + (w&63);
} else if(w >= 0xD800 && w <= 0xDFFF) {
w -= 0xD800;
ww = (isstr ? data.charCodeAt(++i) : data[++i].charCodeAt(0)) - 0xDC00 + (w << 10);
out[j] = 240 + ((ww>>>18) & 0x07);
out[++j] = 144 + ((ww>>>12) & 0x3F);
out[++j] = 128 + ((ww>>>6) & 0x3F);
out[++j] = 128 + (ww & 0x3F);
} else {
out[j] = 224 + (w >> 12);
out[++j] = 128 + ((w >> 6)&63);
out[++j] = 128 + (w&63);
}
}
break;
case "ascii":
if(has_buf && typeof data === "string") { out = new Buffer(data, M); j = out.length; break; }
for(i = 0; i < len; ++i, ++j) {
w = isstr ? data.charCodeAt(i) : data[i].charCodeAt(0);
if(w <= 0x007F) out[j] = w;
else throw new Error("bad ascii " + w);
}
break;
case "utf16le":
if(has_buf && typeof data === "string") { out = new Buffer(data, M); j = out.length; break; }
for(i = 0; i < len; ++i) {
w = isstr ? data.charCodeAt(i) : data[i].charCodeAt(0);
out[j++] = w&255;
out[j++] = w>>8;
}
break;
case "utf16be":
for(i = 0; i < len; ++i) {
w = isstr ? data.charCodeAt(i) : data[i].charCodeAt(0);
out[j++] = w>>8;
out[j++] = w&255;
}
break;
case "utf32le":
for(i = 0; i < len; ++i) {
w = isstr ? data.charCodeAt(i) : data[i].charCodeAt(0);
if(w >= 0xD800 && w <= 0xDFFF) w = 0x10000 + ((w - 0xD800) << 10) + (data[++i].charCodeAt(0) - 0xDC00);
out[j++] = w&255; w >>= 8;
out[j++] = w&255; w >>= 8;
out[j++] = w&255; w >>= 8;
out[j++] = w&255;
}
break;
case "utf32be":
for(i = 0; i < len; ++i) {
w = isstr ? data.charCodeAt(i) : data[i].charCodeAt(0);
if(w >= 0xD800 && w <= 0xDFFF) w = 0x10000 + ((w - 0xD800) << 10) + (data[++i].charCodeAt(0) - 0xDC00);
out[j+3] = w&255; w >>= 8;
out[j+2] = w&255; w >>= 8;
out[j+1] = w&255; w >>= 8;
out[j] = w&255;
j+=4;
}
break;
case "utf7":
for(i = 0; i < len; i++) {
var c = isstr ? data.charAt(i) : data[i].charAt(0);
if(c === "+") { out[j++] = 0x2b; out[j++] = 0x2d; continue; }
if(SetD.indexOf(c) > -1) { out[j++] = c.charCodeAt(0); continue; }
var tt = encode(1201, c);
out[j++] = 0x2b;
out[j++] = BM.charCodeAt(tt[0]>>2);
out[j++] = BM.charCodeAt(((tt[0]&0x03)<<4) + ((tt[1]||0)>>4));
out[j++] = BM.charCodeAt(((tt[1]&0x0F)<<2) + ((tt[2]||0)>>6));
out[j++] = 0x2d;
}
break;
default: throw new Error("Unsupported magic: " + cp + " " + magic[cp]);
}
else throw new Error("Unrecognized CP: " + cp);
out = out.slice(0,j);
if(!has_buf) return (ofmt == 'str') ? (out).map(sfcc).join("") : out;
if(!ofmt || ofmt === 'buf') return out;
if(ofmt !== 'arr') return out.toString('binary');
return [].slice.call(out);
};
var decode = function decode(cp, data) {
var F; if((F=cpdcache[cp])) return F(data);
if(typeof data === "string") return decode(cp, data.split("").map(cca));
var len = data.length, out = new Array(len), s="", w=0, i=0, j=1, k=0, ww=0;
var C = cpt[cp], D, M="";
if(C && (D=C.dec)) {
for(i = 0; i < len; i+=j) {
j = 2;
s = D[(data[i]<<8)+ data[i+1]];
if(!s) {
j = 1;
s = D[data[i]];
}
if(!s) throw new Error('Unrecognized code: ' + data[i] + ' ' + data[i+j-1] + ' ' + i + ' ' + j + ' ' + D[data[i]]);
out[k++] = s;
}
}
else if((M=magic[cp])) switch(M) {
case "utf8":
if(len >= 3 && data[0] == 0xEF) if(data[1] == 0xBB && data[2] == 0xBF) i = 3;
for(; i < len; i+=j) {
j = 1;
if(data[i] < 128) w = data[i];
else if(data[i] < 224) { w=(data[i]&31)*64+(data[i+1]&63); j=2; }
else if(data[i] < 240) { w=((data[i]&15)<<12)+(data[i+1]&63)*64+(data[i+2]&63); j=3; }
else { w=(data[i]&7)*262144+((data[i+1]&63)<<12)+(data[i+2]&63)*64+(data[i+3]&63); j=4; }
if(w < 65536) { out[k++] = String.fromCharCode(w); }
else {
w -= 65536; ww = 0xD800 + ((w>>10)&1023); w = 0xDC00 + (w&1023);
out[k++] = String.fromCharCode(ww); out[k++] = String.fromCharCode(w);
}
}
break;
case "ascii":
if(has_buf && Buffer.isBuffer(data)) return data.toString(M);
for(i = 0; i < len; i++) out[i] = String.fromCharCode(data[i]);
k = len; break;
case "utf16le":
if(len >= 2 && data[0] == 0xFF) if(data[1] == 0xFE) i = 2;
if(has_buf && Buffer.isBuffer(data)) return data.toString(M);
j = 2;
for(; i+1 < len; i+=j) {
out[k++] = String.fromCharCode((data[i+1]<<8) + data[i]);
}
break;
case "utf16be":
if(len >= 2 && data[0] == 0xFE) if(data[1] == 0xFF) i = 2;
j = 2;
for(; i+1 < len; i+=j) {
out[k++] = String.fromCharCode((data[i]<<8) + data[i+1]);
}
break;
case "utf32le":
if(len >= 4 && data[0] == 0xFF) if(data[1] == 0xFE && data[2] === 0 && data[3] === 0) i = 4;
j = 4;
for(; i < len; i+=j) {
w = (data[i+3]<<24) + (data[i+2]<<16) + (data[i+1]<<8) + (data[i]);
if(w > 0xFFFF) {
w -= 0x10000;
out[k++] = String.fromCharCode(0xD800 + ((w >> 10) & 0x3FF));
out[k++] = String.fromCharCode(0xDC00 + (w & 0x3FF));
}
else out[k++] = String.fromCharCode(w);
}
break;
case "utf32be":
if(len >= 4 && data[3] == 0xFF) if(data[2] == 0xFE && data[1] === 0 && data[0] === 0) i = 4;
j = 4;
for(; i < len; i+=j) {
w = (data[i]<<24) + (data[i+1]<<16) + (data[i+2]<<8) + (data[i+3]);
if(w > 0xFFFF) {
w -= 0x10000;
out[k++] = String.fromCharCode(0xD800 + ((w >> 10) & 0x3FF));
out[k++] = String.fromCharCode(0xDC00 + (w & 0x3FF));
}
else out[k++] = String.fromCharCode(w);
}
break;
case "utf7":
if(len >= 4 && data[0] == 0x2B && data[1] == 0x2F && data[2] == 0x76) {
if(len >= 5 && data[3] == 0x38 && data[4] == 0x2D) i = 5;
else if(data[3] == 0x38 || data[3] == 0x39 || data[3] == 0x2B || data[3] == 0x2F) i = 4;
}
for(; i < len; i+=j) {
if(data[i] !== 0x2b) { j=1; out[k++] = String.fromCharCode(data[i]); continue; }
j=1;
if(data[i+1] === 0x2d) { j = 2; out[k++] = "+"; continue; }
while(String.fromCharCode(data[i+j]).match(/[A-Za-z0-9+\/]/)) j++;
var dash = 0;
if(data[i+j] === 0x2d) { ++j; dash=1; }
var tt = [];
var o64 = "";
var c1=0, c2=0, c3=0;
var e1=0, e2=0, e3=0, e4=0;
for(var l = 1; l < j - dash;) {
e1 = BM.indexOf(String.fromCharCode(data[i+l++]));
e2 = BM.indexOf(String.fromCharCode(data[i+l++]));
c1 = e1 << 2 | e2 >> 4;
tt.push(c1);
e3 = BM.indexOf(String.fromCharCode(data[i+l++]));
if(e3 === -1) break;
c2 = (e2 & 15) << 4 | e3 >> 2;
tt.push(c2);
e4 = BM.indexOf(String.fromCharCode(data[i+l++]));
if(e4 === -1) break;
c3 = (e3 & 3) << 6 | e4;
if(e4 < 64) tt.push(c3);
}
o64 = decode(1201, tt);
for(l = 0; l < o64.length; ++l) out[k++] = o64.charAt(l);
}
break;
default: throw new Error("Unsupported magic: " + cp + " " + magic[cp]);
}
else throw new Error("Unrecognized CP: " + cp);
return out.slice(0,k).join("");
};
var hascp = function hascp(cp) { return !!(cpt[cp] || magic[cp]); };
cpt.utils = { decode: decode, encode: encode, hascp: hascp, magic: magic, cache:cache };
return cpt;
}));

153
src/core/lib/remove-exif.js Normal file
View File

@@ -0,0 +1,153 @@
/* piexifjs
The MIT License (MIT)
Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Utils from "../Utils.js";
// Param jpeg should be a binaryArray
function removeEXIF(jpeg) {
// Convert binaryArray to char string
jpeg = Utils.byteArrayToChars(jpeg);
if (jpeg.slice(0, 2) != "\xff\xd8") {
throw ("Given data is not jpeg.");
}
var segments = splitIntoSegments(jpeg);
if (segments[1].slice(0, 2) == "\xff\xe1" &&
segments[1].slice(4, 10) == "Exif\x00\x00") {
segments = [segments[0]].concat(segments.slice(2));
} else if (segments[2].slice(0, 2) == "\xff\xe1" &&
segments[2].slice(4, 10) == "Exif\x00\x00") {
segments = segments.slice(0, 2).concat(segments.slice(3));
} else {
throw ("Exif not found.");
}
var new_data = segments.join("");
// Convert back to binaryArray
new_data = Utils.strToCharcode(new_data);
return new_data;
};
function splitIntoSegments(data) {
if (data.slice(0, 2) != "\xff\xd8") {
throw ("Given data isn't JPEG.");
}
var head = 2;
var segments = ["\xff\xd8"];
while (true) {
if (data.slice(head, head + 2) == "\xff\xda") {
segments.push(data.slice(head));
break;
} else {
var length = unpack(">H", data.slice(head + 2, head + 4))[0];
var endPoint = head + length + 2;
segments.push(data.slice(head, endPoint));
head = endPoint;
}
if (head >= data.length) {
throw ("Wrong JPEG data.");
}
}
return segments;
}
function unpack(mark, str) {
if (typeof(str) != "string") {
throw ("'unpack' error. Got invalid type argument.");
}
var l = 0;
for (var markPointer = 1; markPointer < mark.length; markPointer++) {
if (mark[markPointer].toLowerCase() == "b") {
l += 1;
} else if (mark[markPointer].toLowerCase() == "h") {
l += 2;
} else if (mark[markPointer].toLowerCase() == "l") {
l += 4;
} else {
throw ("'unpack' error. Got invalid mark.");
}
}
if (l != str.length) {
throw ("'unpack' error. Mismatch between symbol and string length. " + l + ":" + str.length);
}
var littleEndian;
if (mark[0] == "<") {
littleEndian = true;
} else if (mark[0] == ">") {
littleEndian = false;
} else {
throw ("'unpack' error.");
}
var unpacked = [];
var strPointer = 0;
var p = 1;
var val = null;
var c = null;
var length = null;
var sliced = "";
while (c = mark[p]) {
if (c.toLowerCase() == "b") {
length = 1;
sliced = str.slice(strPointer, strPointer + length);
val = sliced.charCodeAt(0);
if ((c == "b") && (val >= 0x80)) {
val -= 0x100;
}
} else if (c == "H") {
length = 2;
sliced = str.slice(strPointer, strPointer + length);
if (littleEndian) {
sliced = sliced.split("").reverse().join("");
}
val = sliced.charCodeAt(0) * 0x100 +
sliced.charCodeAt(1);
} else if (c.toLowerCase() == "l") {
length = 4;
sliced = str.slice(strPointer, strPointer + length);
if (littleEndian) {
sliced = sliced.split("").reverse().join("");
}
val = sliced.charCodeAt(0) * 0x1000000 +
sliced.charCodeAt(1) * 0x10000 +
sliced.charCodeAt(2) * 0x100 +
sliced.charCodeAt(3);
if ((c == "l") && (val >= 0x80000000)) {
val -= 0x100000000;
}
} else {
throw ("'unpack' error. " + c);
}
unpacked.push(val);
strPointer += length;
p += 1;
}
return unpacked;
}
export default removeEXIF;

View File

@@ -1,3 +1,4 @@
import cptable from "../lib/js-codepage/cptable.js";
import Utils from "../Utils.js";
import CryptoJS from "crypto-js";
@@ -17,34 +18,82 @@ const CharEnc = {
* @constant
* @default
*/
IO_FORMAT: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Windows-1251", "Hex", "Base64"],
IO_FORMAT: {
"UTF-8 (65001)": 65001,
"UTF-7 (65000)": 65000,
"UTF16LE (1200)": 1200,
"UTF16BE (1201)": 1201,
"UTF16 (1201)": 1201,
"IBM EBCDIC International (500)": 500,
"IBM EBCDIC US-Canada (37)": 37,
"Windows-874 Thai (874)": 874,
"Japanese Shift-JIS (932)": 932,
"Simplified Chinese GBK (936)": 936,
"Korean (949)": 949,
"Traditional Chinese Big5 (950)": 950,
"Windows-1250 Central European (1250)": 1250,
"Windows-1251 Cyrillic (1251)": 1251,
"Windows-1252 Latin (1252)": 1252,
"Windows-1253 Greek (1253)": 1253,
"Windows-1254 Turkish (1254)": 1254,
"Windows-1255 Hebrew (1255)": 1255,
"Windows-1256 Arabic (1256)": 1256,
"Windows-1257 Baltic (1257)": 1257,
"Windows-1258 Vietnam (1258)": 1258,
"US-ASCII (20127)": 20127,
"Simplified Chinese GB2312 (20936)": 20936,
"KOI8-R Russian Cyrillic (20866)": 20866,
"KOI8-U Ukrainian Cyrillic (21866)": 21866,
"ISO-8859-1 Latin 1 Western European (28591)": 28591,
"ISO-8859-2 Latin 2 Central European (28592)": 28592,
"ISO-8859-3 Latin 3 South European (28593)": 28593,
"ISO-8859-4 Latin 4 North European (28594)": 28594,
"ISO-8859-5 Latin/Cyrillic (28595)": 28595,
"ISO-8859-6 Latin/Arabic (28596)": 28596,
"ISO-8859-7 Latin/Greek (28597)": 28597,
"ISO-8859-8 Latin/Hebrew (28598)": 28598,
"ISO-8859-9 Latin 5 Turkish (28599)": 28599,
"ISO-8859-10 Latin 6 Nordic (28600)": 28600,
"ISO-8859-11 Latin/Thai (28601)": 28601,
"ISO-8859-13 Latin 7 Baltic Rim (28603)": 28603,
"ISO-8859-14 Latin 8 Celtic (28604)": 28604,
"ISO-8859-15 Latin 9 (28605)": 28605,
"ISO-8859-16 Latin 10 (28606)": 28606,
"ISO-2022 JIS Japanese (50222)": 50222,
"EUC Japanese (51932)": 51932,
"EUC Korean (51949)": 51949,
"Simplified Chinese GB18030 (54936)": 54936,
},
/**
* Text encoding operation.
* Encode text operation.
* @author tlwr [toby@toby.codes]
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
* @returns {byteArray}
*/
run: function(input, args) {
let inputFormat = args[0],
outputFormat = args[1];
if (inputFormat === "Windows-1251") {
input = Utils.win1251ToUnicode(input);
input = CryptoJS.enc.Utf8.parse(input);
} else {
input = Utils.format[inputFormat].parse(input);
}
if (outputFormat === "Windows-1251") {
input = CryptoJS.enc.Utf8.stringify(input);
return Utils.unicodeToWin1251(input);
} else {
return Utils.format[outputFormat].stringify(input);
}
runEncode: function(input, args) {
const format = CharEnc.IO_FORMAT[args[0]];
let encoded = cptable.utils.encode(format, input);
encoded = Array.from(encoded);
return encoded;
},
/**
* Decode text operation.
* @author tlwr [toby@toby.codes]
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runDecode: function(input, args) {
const format = CharEnc.IO_FORMAT[args[0]];
let decoded = cptable.utils.decode(format, input);
return decoded;
},
};
export default CharEnc;

View File

@@ -426,7 +426,7 @@ const Code = {
* @returns {string}
*/
_replaceVariableNames(input, replacer) {
let tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig;
const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig;
return input.replace(tokenRegex, (...args) => {
let match = args[0],
@@ -450,7 +450,7 @@ const Code = {
*
*/
runToSnakeCase(input, args) {
let smart = args[0];
const smart = args[0];
if (smart) {
return Code._replaceVariableNames(input, snakeCase);
@@ -469,7 +469,7 @@ const Code = {
*
*/
runToCamelCase(input, args) {
let smart = args[0];
const smart = args[0];
if (smart) {
return Code._replaceVariableNames(input, camelCase);
@@ -488,7 +488,7 @@ const Code = {
*
*/
runToKebabCase(input, args) {
let smart = args[0];
const smart = args[0];
if (smart) {
return Code._replaceVariableNames(input, kebabCase);

View File

@@ -1,3 +1,5 @@
import {BigInteger} from "jsbn";
/**
* Date and time operations.
*
@@ -46,6 +48,12 @@ const DateTime = {
},
/**
* @constant
* @default
*/
TREAT_AS_UTC: true,
/**
* To UNIX Timestamp operation.
*
@@ -55,7 +63,8 @@ const DateTime = {
*/
runToUnixTimestamp: function(input, args) {
let units = args[0],
d = moment(input);
treatAsUTC = args[1],
d = treatAsUTC ? moment.utc(input) : moment(input);
if (units === "Seconds (s)") {
return d.unix();
@@ -71,6 +80,58 @@ const DateTime = {
},
/**
* Windows Filetime to Unix Timestamp operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFromFiletimeToUnix: function(input, args) {
let units = args[0];
input = new BigInteger(input).subtract(new BigInteger("116444736000000000"));
if (units === "Seconds (s)"){
input = input.divide(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.divide(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.divide(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.multiply(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
return input.toString();
},
/**
* Unix Timestamp to Windows Filetime operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runToFiletimeFromUnix: function(input, args) {
let units = args[0];
input = new BigInteger(input);
if (units === "Seconds (s)"){
input = input.multiply(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.multiply(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.multiply(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.divide(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
return input.add(new BigInteger("116444736000000000")).toString();
},
/**
* @constant
* @default

View File

@@ -20,7 +20,7 @@ const FileType = {
* @returns {string}
*/
runDetect: function(input, args) {
const type = FileType._magicType(input);
const type = FileType.magicType(input);
if (!type) {
return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
@@ -59,7 +59,7 @@ const FileType = {
numCommonFound = 0;
for (let i = 0; i < input.length; i++) {
type = FileType._magicType(input.slice(i));
type = FileType.magicType(input.slice(i));
if (type) {
if (ignoreCommon && commonExts.indexOf(type.ext) > -1) {
numCommonFound++;
@@ -96,14 +96,13 @@ const FileType = {
* Given a buffer, detects magic byte sequences at specific positions and returns the
* extension and mime type.
*
* @private
* @param {byteArray} buf
* @returns {Object} type
* @returns {string} type.ext - File extension
* @returns {string} type.mime - Mime type
* @returns {string} [type.desc] - Description
*/
_magicType: function (buf) {
magicType: function (buf) {
if (!(buf && buf.length > 1)) {
return null;
}

View File

@@ -12,6 +12,17 @@ import {UAS_parser as UAParser} from "../lib/uas_parser.js";
*/
const HTTP = {
/**
* @constant
* @default
*/
METHODS: [
"GET", "POST", "HEAD",
"PUT", "PATCH", "DELETE",
"CONNECT", "TRACE", "OPTIONS"
],
/**
* Strip HTTP headers operation.
*
@@ -51,6 +62,95 @@ const HTTP = {
"Device Type: " + ua.deviceType + "\n";
},
/**
* @constant
* @default
*/
MODE: [
"Cross-Origin Resource Sharing",
"No CORS (limited to HEAD, GET or POST)",
],
/**
* Lookup table for HTTP modes
*
* @private
* @constant
*/
_modeLookup: {
"Cross-Origin Resource Sharing": "cors",
"No CORS (limited to HEAD, GET or POST)": "no-cors",
},
/**
* HTTP request operation.
*
* @author tlwr [toby@toby.codes]
* @author n1474335 [n1474335@gmail.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runHTTPRequest(input, args) {
const method = args[0],
url = args[1],
headersText = args[2],
mode = args[3],
showResponseMetadata = args[4];
if (url.length === 0) return "";
let headers = new Headers();
headersText.split(/\r?\n/).forEach(line => {
line = line.trim();
if (line.length === 0) return;
let split = line.split(":");
if (split.length !== 2) throw `Could not parse header in line: ${line}`;
headers.set(split[0].trim(), split[1].trim());
});
let config = {
method: method,
headers: headers,
mode: HTTP._modeLookup[mode],
cache: "no-cache",
};
if (method !== "GET" && method !== "HEAD") {
config.body = input;
}
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";
}
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";
});
},
};
export default HTTP;

View File

@@ -0,0 +1,124 @@
import * as ExifParser from "exif-parser";
import removeEXIF from "../lib/remove-exif.js";
import Utils from "../Utils.js";
import FileType from "./FileType.js";
/**
* Image operations.
*
* @author tlwr [toby@toby.codes]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const Image = {
/**
* Extract EXIF operation.
*
* Extracts EXIF data from a byteArray, representing a JPG or a TIFF image.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runExtractEXIF(input, args) {
try {
const bytes = Uint8Array.from(input);
const parser = ExifParser.create(bytes.buffer);
const result = parser.parse();
let lines = [];
for (let tagName in result.tags) {
let value = result.tags[tagName];
lines.push(`${tagName}: ${value}`);
}
const numTags = lines.length;
lines.unshift(`Found ${numTags} tags.\n`);
return lines.join("\n");
} catch (err) {
throw "Could not extract EXIF data from image: " + err;
}
},
/**
* Remove EXIF operation.
*
* Removes EXIF data from a byteArray, representing a JPG.
*
* @author David Moodie [davidmoodie12@gmail.com]
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runRemoveEXIF(input, args) {
// Do nothing if input is empty
if (input.length === 0) return input;
try {
return removeEXIF(input);
} catch (err) {
// Simply return input if no EXIF data is found
if (err === "Exif not found.") return input;
throw "Could not remove EXIF data from image: " + err;
}
},
/**
* @constant
* @default
*/
INPUT_FORMAT: ["Raw", "Base64", "Hex"],
/**
* Render Image operation.
*
* @author n1474335 [n1474335@gmail.com]
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runRenderImage(input, args) {
const inputFormat = args[0];
let dataURI = "data:";
if (!input.length) return "";
// Convert input to raw bytes
switch (inputFormat) {
case "Hex":
input = Utils.fromHex(input);
break;
case "Base64":
// Don't trust the Base64 entered by the user.
// Unwrap it first, then re-encode later.
input = Utils.fromBase64(input, null, "byteArray");
break;
case "Raw":
default:
input = Utils.strToByteArray(input);
break;
}
// Determine file type
const type = FileType.magicType(input);
if (type && type.mime.indexOf("image") === 0) {
dataURI += type.mime + ";";
} else {
throw "Invalid file type";
}
// Add image data to URI
dataURI += "base64," + Utils.toBase64(input);
return "<img src='" + dataURI + "'>";
},
};
export default Image;

View File

@@ -26,7 +26,7 @@ const SeqUtils = {
* @constant
* @default
*/
SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address"],
SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"],
/**
* Sort operation.
@@ -47,6 +47,8 @@ const SeqUtils = {
sorted = sorted.sort(SeqUtils._caseInsensitiveSort);
} else if (order === "IP address") {
sorted = sorted.sort(SeqUtils._ipSort);
} else if (order === "Numeric") {
sorted = sorted.sort(SeqUtils._numericSort);
}
if (sortReverse) sorted.reverse();
@@ -221,6 +223,35 @@ const SeqUtils = {
return a_ - b_;
},
/**
* Comparison operation for sorting of numeric values.
*
* @author Chris van Marle
* @private
* @param {string} a
* @param {string} b
* @returns {number}
*/
_numericSort: function _numericSort(a, b) {
let a_ = a.split(/([^\d]+)/),
b_ = b.split(/([^\d]+)/);
for (let i = 0; i < a_.length && i < b.length; ++i) {
if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
if (isNaN(a_[i]) && isNaN(b_[i])) {
let ret = a_[i].localeCompare(b_[i]); // Compare strings
if (ret !== 0) return ret;
}
if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
}
}
return 0;
},
};
export default SeqUtils;

View File

@@ -227,14 +227,16 @@ const StrUtils = {
if (type === "Regex") {
find = new RegExp(find, modifiers);
} else if (type.indexOf("Extended") === 0) {
return input.replace(find, replace);
}
if (type.indexOf("Extended") === 0) {
find = Utils.parseEscapedChars(find);
}
return input.replace(find, replace, modifiers);
// Non-standard addition of flags in the third argument. This will work in Firefox but
// probably nowhere else. The purpose is to allow global matching when the `find` parameter
// is just a string.
find = new RegExp(Utils.escapeRegex(find), modifiers);
return input.replace(find, replace);
},
@@ -471,7 +473,7 @@ const StrUtils = {
number = args[1];
delimiter = Utils.charRep[delimiter];
let splitInput = input.split(delimiter);
const splitInput = input.split(delimiter);
return splitInput
.filter((line, lineIndex) => {
@@ -499,7 +501,7 @@ const StrUtils = {
number = args[1];
delimiter = Utils.charRep[delimiter];
let splitInput = input.split(delimiter);
const splitInput = input.split(delimiter);
return splitInput
.filter((line, lineIndex) => {

View File

@@ -21,21 +21,22 @@ import Split from "split.js";
* @param {Object} options - Default setting for app options.
*/
const App = function(categories, operations, defaultFavourites, defaultOptions) {
this.categories = categories;
this.operations = operations;
this.dfavourites = defaultFavourites;
this.doptions = defaultOptions;
this.options = Utils.extend({}, defaultOptions);
this.categories = categories;
this.operations = operations;
this.dfavourites = defaultFavourites;
this.doptions = defaultOptions;
this.options = Utils.extend({}, defaultOptions);
this.chef = new Chef();
this.manager = new Manager(this);
this.chef = new Chef();
this.manager = new Manager(this);
this.baking = false;
this.autoBake_ = false;
this.progress = 0;
this.ingId = 0;
this.baking = false;
this.autoBake_ = false;
this.autoBakePause = false;
this.progress = 0;
this.ingId = 0;
window.chef = this.chef;
window.chef = this.chef;
};
@@ -53,6 +54,26 @@ App.prototype.setup = function() {
this.resetLayout();
this.setCompileMessage();
this.loadURIParams();
this.loaded();
};
/**
* Fires once all setup activities have completed.
*/
App.prototype.loaded = function() {
// Trigger CSS animations to remove preloader
document.body.classList.add("loaded");
// Wait for animations to complete then remove the preloader and loaded style
// so that the animations for existing elements don't play again.
setTimeout(function() {
document.getElementById("loader-wrapper").remove();
document.body.classList.remove("loaded");
}, 1000);
// Clear the loading message interval
clearInterval(window.loadingMsgInt);
};
@@ -146,7 +167,7 @@ App.prototype.bake = async function(step) {
* Runs Auto Bake if it is set.
*/
App.prototype.autoBake = function() {
if (this.autoBake_) {
if (this.autoBake_ && !this.autoBakePause) {
this.bake();
}
};
@@ -378,39 +399,28 @@ App.prototype.addFavourite = function(name) {
* Checks for input and recipe in the URI parameters and loads them if present.
*/
App.prototype.loadURIParams = function() {
// Load query string from URI
this.queryString = (function(a) {
if (a === "") return {};
const b = {};
for (let i = 0; i < a.length; i++) {
const p = a[i].split("=");
if (p.length !== 2) {
b[a[i]] = true;
} else {
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
}
return b;
})(window.location.search.substr(1).split("&"));
// Load query string or hash from URI (depending on which is populated)
const params = window.location.search || window.location.hash;
this.uriParams = Utils.parseURIParams(params);
// Turn off auto-bake while loading
const autoBakeVal = this.autoBake_;
this.autoBake_ = false;
// Pause auto-bake while loading but don't modify `this.autoBake_`
// otherwise `manualBake` cannot trigger.
this.autoBakePause = true;
// Read in recipe from query string
if (this.queryString.recipe) {
// Read in recipe from URI params
if (this.uriParams.recipe) {
try {
const recipeConfig = JSON.parse(this.queryString.recipe);
const recipeConfig = JSON.parse(this.uriParams.recipe);
this.setRecipeConfig(recipeConfig);
} catch (err) {}
} else if (this.queryString.op) {
} else if (this.uriParams.op) {
// If there's no recipe, look for single operations
this.manager.recipe.clearRecipe();
try {
this.manager.recipe.addOperation(this.queryString.op);
this.manager.recipe.addOperation(this.uriParams.op);
} catch (err) {
// If no exact match, search for nearest match and add that
const matchedOps = this.manager.ops.filterOperations(this.queryString.op, false);
const matchedOps = this.manager.ops.filterOperations(this.uriParams.op, false);
if (matchedOps.length) {
this.manager.recipe.addOperation(matchedOps[0].name);
}
@@ -418,21 +428,21 @@ App.prototype.loadURIParams = function() {
// Populate search with the string
const search = document.getElementById("search");
search.value = this.queryString.op;
search.value = this.uriParams.op;
search.dispatchEvent(new Event("search"));
}
}
// Read in input data from query string
if (this.queryString.input) {
// Read in input data from URI params
if (this.uriParams.input) {
try {
const inputData = Utils.fromBase64(this.queryString.input);
const inputData = Utils.fromBase64(this.uriParams.input);
this.setInput(inputData);
} catch (err) {}
}
// Restore auto-bake state
this.autoBake_ = autoBakeVal;
// Unpause auto-bake
this.autoBakePause = false;
this.autoBake();
};

View File

@@ -23,14 +23,14 @@ const ControlsWaiter = function(app, manager) {
* without wrapping or overflowing.
*/
ControlsWaiter.prototype.adjustWidth = function() {
let controls = document.getElementById("controls"),
step = document.getElementById("step"),
clrBreaks = document.getElementById("clr-breaks"),
saveImg = document.querySelector("#save img"),
loadImg = document.querySelector("#load img"),
stepImg = document.querySelector("#step img"),
clrRecipImg = document.querySelector("#clr-recipe img"),
clrBreaksImg = document.querySelector("#clr-breaks img");
const controls = document.getElementById("controls");
const step = document.getElementById("step");
const clrBreaks = document.getElementById("clr-breaks");
const saveImg = document.querySelector("#save img");
const loadImg = document.querySelector("#load img");
const stepImg = document.querySelector("#step img");
const clrRecipImg = document.querySelector("#clr-recipe img");
const clrBreaksImg = document.querySelector("#clr-breaks img");
if (controls.clientWidth < 470) {
step.childNodes[1].nodeValue = " Step";
@@ -100,17 +100,17 @@ ControlsWaiter.prototype.stepClick = function() {
* Handler for changes made to the Auto Bake checkbox.
*/
ControlsWaiter.prototype.autoBakeChange = function() {
let autoBakeLabel = document.getElementById("auto-bake-label"),
autoBakeCheckbox = document.getElementById("auto-bake");
const autoBakeLabel = document.getElementById("auto-bake-label");
const autoBakeCheckbox = document.getElementById("auto-bake");
this.app.autoBake_ = autoBakeCheckbox.checked;
if (autoBakeCheckbox.checked) {
autoBakeLabel.classList.remove("btn-default");
autoBakeLabel.classList.add("btn-success");
autoBakeLabel.classList.remove("btn-default");
} else {
autoBakeLabel.classList.remove("btn-success");
autoBakeLabel.classList.add("btn-default");
autoBakeLabel.classList.remove("btn-success");
}
};
@@ -145,10 +145,10 @@ ControlsWaiter.prototype.clearBreaksClick = function() {
ControlsWaiter.prototype.initialiseSaveLink = function(recipeConfig) {
recipeConfig = recipeConfig || this.app.getRecipeConfig();
let includeRecipe = document.getElementById("save-link-recipe-checkbox").checked,
includeInput = document.getElementById("save-link-input-checkbox").checked,
saveLinkEl = document.getElementById("save-link"),
saveLink = this.generateStateUrl(includeRecipe, includeInput, recipeConfig);
const includeRecipe = document.getElementById("save-link-recipe-checkbox").checked;
const includeInput = document.getElementById("save-link-input-checkbox").checked;
const saveLinkEl = document.getElementById("save-link");
const saveLink = this.generateStateUrl(includeRecipe, includeInput, recipeConfig);
saveLinkEl.innerHTML = Utils.truncate(saveLink, 120);
saveLinkEl.setAttribute("href", saveLink);
@@ -167,23 +167,28 @@ ControlsWaiter.prototype.initialiseSaveLink = function(recipeConfig) {
ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput, recipeConfig, baseURL) {
recipeConfig = recipeConfig || this.app.getRecipeConfig();
let link = baseURL || window.location.protocol + "//" +
window.location.host +
window.location.pathname,
recipeStr = JSON.stringify(recipeConfig),
inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
const link = baseURL || window.location.protocol + "//" +
window.location.host +
window.location.pathname;
const recipeStr = JSON.stringify(recipeConfig);
const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
includeRecipe = includeRecipe && (recipeConfig.length > 0);
includeInput = includeInput && (inputStr.length > 0) && (inputStr.length < 8000);
// Only inlcude input if it is less than 50KB (51200 * 4/3 as it is Base64 encoded)
includeInput = includeInput && (inputStr.length > 0) && (inputStr.length <= 68267);
if (includeRecipe) {
link += "?recipe=" + encodeURIComponent(recipeStr);
}
const params = [
includeRecipe ? ["recipe", recipeStr] : undefined,
includeInput ? ["input", inputStr] : undefined,
];
if (includeRecipe && includeInput) {
link += "&input=" + encodeURIComponent(inputStr);
} else if (includeInput) {
link += "?input=" + encodeURIComponent(inputStr);
const hash = params
.filter(v => v)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("&");
if (hash) {
return `${link}#${hash}`;
}
return link;
@@ -205,8 +210,8 @@ ControlsWaiter.prototype.saveTextChange = function() {
* Handler for the 'Save' command. Pops up the save dialog box.
*/
ControlsWaiter.prototype.saveClick = function() {
let recipeConfig = this.app.getRecipeConfig(),
recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
const recipeConfig = this.app.getRecipeConfig();
const recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
document.getElementById("save-text").value = recipeStr;
@@ -244,8 +249,8 @@ ControlsWaiter.prototype.loadClick = function() {
* Saves the recipe specified in the save textarea to local storage.
*/
ControlsWaiter.prototype.saveButtonClick = function() {
let recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
let recipeStr = document.getElementById("save-text").value;
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
const recipeStr = document.getElementById("save-text").value;
if (!recipeName) {
this.app.alert("Please enter a recipe name", "danger", 2000);
@@ -303,13 +308,11 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
* Removes the currently selected recipe from local storage.
*/
ControlsWaiter.prototype.loadDeleteClick = function() {
let id = parseInt(document.getElementById("load-name").value, 10),
savedRecipes = localStorage.savedRecipes ?
const id = parseInt(document.getElementById("load-name").value, 10);
const rawSavedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
savedRecipes = savedRecipes.filter(function(r) {
return r.id !== id;
});
const savedRecipes = rawSavedRecipes.filter(r => r.id !== id);
localStorage.savedRecipes = JSON.stringify(savedRecipes);
this.populateLoadRecipesList();
@@ -320,14 +323,12 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
* Displays the selected recipe in the load text box.
*/
ControlsWaiter.prototype.loadNameChange = function(e) {
let el = e.target,
savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [],
id = parseInt(el.value, 10);
const el = e.target;
const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
const id = parseInt(el.value, 10);
const recipe = savedRecipes.filter(function(r) {
return r.id === id;
})[0];
const recipe = savedRecipes.find(r => r.id === id);
document.getElementById("load-text").value = recipe.recipe;
};
@@ -352,12 +353,14 @@ ControlsWaiter.prototype.loadButtonClick = function() {
* Populates the bug report information box with useful technical info.
*/
ControlsWaiter.prototype.supportButtonClick = function() {
let reportBugInfo = document.getElementById("report-bug-info"),
saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
const reportBugInfo = document.getElementById("report-bug-info");
const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
reportBugInfo.innerHTML = "* CyberChef compile time: " + COMPILE_TIME + "\n" +
"* User-Agent: \n" + navigator.userAgent + "\n" +
"* [Link to reproduce](" + saveLink + ")\n\n";
if (reportBugInfo) {
reportBugInfo.innerHTML = "* CyberChef compile time: " + COMPILE_TIME + "\n" +
"* User-Agent: \n" + navigator.userAgent + "\n" +
"* [Link to reproduce](" + saveLink + ")\n\n";
}
};
export default ControlsWaiter;

View File

@@ -158,13 +158,12 @@ HTMLIngredient.prototype.toHtml = function() {
* @param {event} e
*/
HTMLIngredient.prototype.toggleDisableArgs = function(e) {
let el = e.target,
op = el.parentNode.parentNode,
args = op.querySelectorAll(".arg-group"),
els;
const el = e.target;
const op = el.parentNode.parentNode;
const args = op.querySelectorAll(".arg-group");
for (let i = 0; i < this.disableArgs.length; i++) {
els = args[this.disableArgs[i]].querySelectorAll("input, select, button");
const els = args[this.disableArgs[i]].querySelectorAll("input, select, button");
for (let j = 0; j < els.length; j++) {
if (els[j].getAttribute("disabled")) {
@@ -186,9 +185,9 @@ HTMLIngredient.prototype.toggleDisableArgs = function(e) {
* @param {event} e
*/
HTMLIngredient.prototype.populateOptionChange = function(e) {
let el = e.target,
op = el.parentNode.parentNode,
target = op.querySelectorAll(".arg-group")[this.target].querySelector("input, select, textarea");
const el = e.target;
const op = el.parentNode.parentNode;
const target = op.querySelectorAll(".arg-group")[this.target].querySelector("input, select, textarea");
target.value = el.childNodes[el.selectedIndex].getAttribute("populate-value");

View File

@@ -64,8 +64,8 @@ HighlighterWaiter.prototype._isSelectionBackwards = function() {
* @returns {number}
*/
HighlighterWaiter.prototype._getOutputHtmlOffset = function(node, offset) {
let sel = window.getSelection(),
range = document.createRange();
const sel = window.getSelection();
const range = document.createRange();
range.selectNodeContents(document.getElementById("output-html"));
range.setEnd(node, offset);
@@ -85,8 +85,8 @@ HighlighterWaiter.prototype._getOutputHtmlOffset = function(node, offset) {
* @returns {number} pos.end
*/
HighlighterWaiter.prototype._getOutputHtmlSelectionOffsets = function() {
let sel = window.getSelection(),
range,
const sel = window.getSelection();
let range,
start = 0,
end = 0,
backwards = false;
@@ -151,9 +151,9 @@ HighlighterWaiter.prototype.inputMousedown = function(e) {
this.mouseTarget = HighlighterWaiter.INPUT;
this.removeHighlights();
let el = e.target,
start = el.selectionStart,
end = el.selectionEnd;
const el = e.target;
const start = el.selectionStart;
const end = el.selectionEnd;
if (start !== 0 || end !== 0) {
document.getElementById("input-selection-info").innerHTML = this.selectionInfo(start, end);
@@ -173,9 +173,9 @@ HighlighterWaiter.prototype.outputMousedown = function(e) {
this.mouseTarget = HighlighterWaiter.OUTPUT;
this.removeHighlights();
let el = e.target,
start = el.selectionStart,
end = el.selectionEnd;
const el = e.target;
const start = el.selectionStart;
const end = el.selectionEnd;
if (start !== 0 || end !== 0) {
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(start, end);
@@ -244,9 +244,9 @@ HighlighterWaiter.prototype.inputMousemove = function(e) {
this.mouseTarget !== HighlighterWaiter.INPUT)
return;
let el = e.target,
start = el.selectionStart,
end = el.selectionEnd;
const el = e.target;
const start = el.selectionStart;
const end = el.selectionEnd;
if (start !== 0 || end !== 0) {
document.getElementById("input-selection-info").innerHTML = this.selectionInfo(start, end);
@@ -268,9 +268,9 @@ HighlighterWaiter.prototype.outputMousemove = function(e) {
this.mouseTarget !== HighlighterWaiter.OUTPUT)
return;
let el = e.target,
start = el.selectionStart,
end = el.selectionEnd;
const el = e.target;
const start = el.selectionStart;
const end = el.selectionEnd;
if (start !== 0 || end !== 0) {
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(start, end);
@@ -308,11 +308,11 @@ HighlighterWaiter.prototype.outputHtmlMousemove = function(e) {
* @returns {string}
*/
HighlighterWaiter.prototype.selectionInfo = function(start, end) {
let width = end.toString().length;
width = width < 2 ? 2 : width;
let startStr = Utils.pad(start.toString(), width, " ").replace(/ /g, "&nbsp;"),
endStr = Utils.pad(end.toString(), width, " ").replace(/ /g, "&nbsp;"),
lenStr = Utils.pad((end-start).toString(), width, " ").replace(/ /g, "&nbsp;");
const len = end.toString().length;
const width = len < 2 ? 2 : len;
const startStr = Utils.pad(start.toString(), width, " ").replace(/ /g, "&nbsp;");
const endStr = Utils.pad(end.toString(), width, " ").replace(/ /g, "&nbsp;");
const lenStr = Utils.pad((end-start).toString(), width, " ").replace(/ /g, "&nbsp;");
return "start: " + startStr + "<br>end: " + endStr + "<br>length: " + lenStr;
};
@@ -339,8 +339,8 @@ HighlighterWaiter.prototype.removeHighlights = function() {
* @returns {Object[]} highlights[].args
*/
HighlighterWaiter.prototype.generateHighlightList = function() {
let recipeConfig = this.app.getRecipeConfig(),
highlights = [];
const recipeConfig = this.app.getRecipeConfig();
const highlights = [];
for (let i = 0; i < recipeConfig.length; i++) {
if (recipeConfig[i].disabled) continue;
@@ -452,11 +452,11 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
// be displayed by the HTML textarea and will mess up highlighting offsets.
if (!this.app.dishStr || this.app.dishStr.indexOf("\r") >= 0) return false;
let startPlaceholder = "[startHighlight]",
startPlaceholderRegex = /\[startHighlight\]/g,
endPlaceholder = "[endHighlight]",
endPlaceholderRegex = /\[endHighlight\]/g,
text = textarea.value;
const startPlaceholder = "[startHighlight]";
const startPlaceholderRegex = /\[startHighlight\]/g;
const endPlaceholder = "[endHighlight]";
const endPlaceholderRegex = /\[endHighlight\]/g;
let text = textarea.value;
// Put placeholders in position
// If there's only one value, select that

View File

@@ -92,8 +92,8 @@ InputWaiter.prototype.inputChange = function(e) {
this.app.progress = 0;
// Update the input metadata info
let inputText = this.get(),
lines = inputText.count("\n") + 1;
const inputText = this.get();
const lines = inputText.count("\n") + 1;
this.setInputInfo(inputText.length, lines);
@@ -149,13 +149,13 @@ InputWaiter.prototype.inputDrop = function(e) {
e.stopPropagation();
e.preventDefault();
let el = e.target,
file = e.dataTransfer.files[0],
text = e.dataTransfer.getData("Text"),
reader = new FileReader(),
inputCharcode = "",
offset = 0,
CHUNK_SIZE = 20480; // 20KB
const el = e.target;
const file = e.dataTransfer.files[0];
const text = e.dataTransfer.getData("Text");
const reader = new FileReader();
let inputCharcode = "";
let offset = 0;
const CHUNK_SIZE = 20480; // 20KB
const setInput = function() {
if (inputCharcode.length > 100000 && this.app.autoBake_) {

View File

@@ -154,6 +154,7 @@ Manager.prototype.initialiseEventListeners = function() {
this.addDynamicListener(".option-item input[type=number]", "keyup", this.options.numberChange, this.options);
this.addDynamicListener(".option-item input[type=number]", "change", this.options.numberChange, this.options);
this.addDynamicListener(".option-item select", "change", this.options.selectChange, this.options);
document.getElementById("theme").addEventListener("change", this.options.themeChange.bind(this.options));
// Misc
document.getElementById("alert-close").addEventListener("click", this.app.alertCloseClick.bind(this.app));
@@ -261,15 +262,16 @@ Manager.prototype.addDynamicListener = function(selector, eventType, callback, s
* @param {Event} e - The event to be handled
*/
Manager.prototype.dynamicListenerHandler = function(e) {
let handlers = this.dynamicHandlers[e.type],
matches = e.target.matches ||
e.target.webkitMatchesSelector ||
e.target.mozMatchesSelector ||
e.target.msMatchesSelector ||
e.target.oMatchesSelector;
const { type, target } = e;
const handlers = this.dynamicHandlers[type];
const matches = target.matches ||
target.webkitMatchesSelector ||
target.mozMatchesSelector ||
target.msMatchesSelector ||
target.oMatchesSelector;
for (let i = 0; i < handlers.length; i++) {
if (matches && e.target[matches.name](handlers[i].selector)) {
if (matches && matches.call(target, handlers[i].selector)) {
handlers[i].callback(e);
}
}

View File

@@ -68,9 +68,9 @@ OperationsWaiter.prototype.searchOperations = function(e) {
ops[selected-1].classList.add("selected-op");
}
} else {
let searchResultsEl = document.getElementById("search-results"),
el = e.target,
str = el.value;
const searchResultsEl = document.getElementById("search-results");
const el = e.target;
const str = el.value;
while (searchResultsEl.firstChild) {
try {
@@ -81,12 +81,10 @@ OperationsWaiter.prototype.searchOperations = function(e) {
$("#categories .in").collapse("hide");
if (str) {
let matchedOps = this.filterOperations(str, true),
matchedOpsHtml = "";
for (let i = 0; i < matchedOps.length; i++) {
matchedOpsHtml += matchedOps[i].toStubHtml();
}
const matchedOps = this.filterOperations(str, true);
const matchedOpsHtml = matchedOps
.map(v => v.toStubHtml())
.join("");
searchResultsEl.innerHTML = matchedOpsHtml;
searchResultsEl.dispatchEvent(this.manager.oplistcreate);
@@ -103,16 +101,16 @@ OperationsWaiter.prototype.searchOperations = function(e) {
* name and description
* @returns {string[]}
*/
OperationsWaiter.prototype.filterOperations = function(searchStr, highlight) {
let matchedOps = [],
matchedDescs = [];
OperationsWaiter.prototype.filterOperations = function(inStr, highlight) {
const matchedOps = [];
const matchedDescs = [];
searchStr = searchStr.toLowerCase();
const searchStr = inStr.toLowerCase();
for (const opName in this.app.operations) {
let op = this.app.operations[opName],
namePos = opName.toLowerCase().indexOf(searchStr),
descPos = op.description.toLowerCase().indexOf(searchStr);
const op = this.app.operations[opName];
const namePos = opName.toLowerCase().indexOf(searchStr);
const descPos = op.description.toLowerCase().indexOf(searchStr);
if (namePos >= 0 || descPos >= 0) {
const operation = new HTMLOperation(opName, this.app.operations[opName], this.app, this.manager);
@@ -236,12 +234,8 @@ OperationsWaiter.prototype.editFavouritesClick = function(e) {
* Saves the selected favourites and reloads them.
*/
OperationsWaiter.prototype.saveFavouritesClick = function() {
let favouritesList = [],
favs = document.querySelectorAll("#edit-favourites-list li");
for (let i = 0; i < favs.length; i++) {
favouritesList.push(favs[i].textContent);
}
const favs = document.querySelectorAll("#edit-favourites-list li");
const favouritesList = Array.from(favs, e => e.textContent);
this.app.saveFavourites(favouritesList);
this.app.loadFavourites();
@@ -281,8 +275,8 @@ OperationsWaiter.prototype.opIconMouseover = function(e) {
* @param {event} e
*/
OperationsWaiter.prototype.opIconMouseleave = function(e) {
let opEl = e.target.parentNode,
toEl = e.toElement || e.relatedElement;
const opEl = e.target.parentNode;
const toEl = e.toElement || e.relatedElement;
if (e.target.getAttribute("data-toggle") === "popover" && toEl === opEl) {
$(opEl).popover("show");

View File

@@ -43,8 +43,13 @@ OptionsWaiter.prototype.load = function(options) {
const selects = document.querySelectorAll("#options-body select");
for (i = 0; i < selects.length; i++) {
selects[i].value = this.app.options[selects[i].getAttribute("option")];
selects[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
const val = this.app.options[selects[i].getAttribute("option")];
if (val) {
selects[i].value = val;
selects[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
} else {
selects[i].selectedIndex = 0;
}
}
};
@@ -75,8 +80,8 @@ OptionsWaiter.prototype.resetOptionsClick = function() {
* @param {boolean} state
*/
OptionsWaiter.prototype.switchChange = function(e, state) {
let el = e.target,
option = el.getAttribute("option");
const el = e.target;
const option = el.getAttribute("option");
this.app.options[option] = state;
localStorage.setItem("options", JSON.stringify(this.app.options));
@@ -90,8 +95,8 @@ OptionsWaiter.prototype.switchChange = function(e, state) {
* @param {event} e
*/
OptionsWaiter.prototype.numberChange = function(e) {
let el = e.target,
option = el.getAttribute("option");
const el = e.target;
const option = el.getAttribute("option");
this.app.options[option] = parseInt(el.value, 10);
localStorage.setItem("options", JSON.stringify(this.app.options));
@@ -105,8 +110,8 @@ OptionsWaiter.prototype.numberChange = function(e) {
* @param {event} e
*/
OptionsWaiter.prototype.selectChange = function(e) {
let el = e.target,
option = el.getAttribute("option");
const el = e.target;
const option = el.getAttribute("option");
this.app.options[option] = el.value;
localStorage.setItem("options", JSON.stringify(this.app.options));
@@ -132,4 +137,14 @@ OptionsWaiter.prototype.setWordWrap = function() {
}
};
/**
* Changes the theme by setting the class of the <html> element.
*/
OptionsWaiter.prototype.themeChange = function (e) {
const themeClass = e.target.value;
document.querySelector(":root").className = themeClass;
};
export default OptionsWaiter;

View File

@@ -36,10 +36,10 @@ OutputWaiter.prototype.get = function() {
* @param {number} duration - The length of time (ms) it took to generate the output
*/
OutputWaiter.prototype.set = function(dataStr, type, duration) {
let outputText = document.getElementById("output-text"),
outputHtml = document.getElementById("output-html"),
outputHighlighter = document.getElementById("output-highlighter"),
inputHighlighter = document.getElementById("input-highlighter");
const outputText = document.getElementById("output-text");
const outputHtml = document.getElementById("output-html");
const outputHighlighter = document.getElementById("output-highlighter");
const inputHighlighter = document.getElementById("input-highlighter");
if (type === "html") {
outputText.style.display = "none";
@@ -103,11 +103,11 @@ OutputWaiter.prototype.setOutputInfo = function(length, lines, duration) {
* without wrapping or overflowing.
*/
OutputWaiter.prototype.adjustWidth = function() {
let output = document.getElementById("output"),
saveToFile = document.getElementById("save-to-file"),
switchIO = document.getElementById("switch"),
undoSwitch = document.getElementById("undo-switch"),
maximiseOutput = document.getElementById("maximise-output");
const output = document.getElementById("output");
const saveToFile = document.getElementById("save-to-file");
const switchIO = document.getElementById("switch");
const undoSwitch = document.getElementById("undo-switch");
const maximiseOutput = document.getElementById("maximise-output");
if (output.clientWidth < 680) {
saveToFile.childNodes[1].nodeValue = "";
@@ -129,8 +129,8 @@ OutputWaiter.prototype.adjustWidth = function() {
* Saves the current output to a file, downloaded as a URL octet stream.
*/
OutputWaiter.prototype.saveClick = function() {
let data = Utils.toBase64(this.app.dishStr),
filename = window.prompt("Please enter a filename:", "download.dat");
const data = Utils.toBase64(this.app.dishStr);
const filename = window.prompt("Please enter a filename:", "download.dat");
if (filename) {
const el = document.createElement("a");

View File

@@ -60,8 +60,8 @@ RecipeWaiter.prototype.initialiseOperationDragNDrop = function() {
}.bind(this));
Sortable.utils.on(recList, "touchend", function(e) {
let loc = e.changedTouches[0],
target = document.elementFromPoint(loc.clientX, loc.clientY);
const loc = e.changedTouches[0];
const target = document.elementFromPoint(loc.clientX, loc.clientY);
this.removeIntent = !recList.contains(target);
}.bind(this));
@@ -276,8 +276,9 @@ RecipeWaiter.prototype.operationChildDblclick = function(e) {
* @returns {recipeConfig}
*/
RecipeWaiter.prototype.getConfig = function() {
let config = [], ingredients, ingList, disabled, bp, item,
operations = document.querySelectorAll("#rec-list li.operation");
const config = [];
let ingredients, ingList, disabled, bp, item;
const operations = document.querySelectorAll("#rec-list li.operation");
for (let i = 0; i < operations.length; i++) {
ingredients = [];
@@ -353,8 +354,7 @@ RecipeWaiter.prototype.buildRecipeOperation = function(el) {
el.classList.add("flow-control-op");
}
// Disable auto-bake if this is a manual op - this should be moved to the 'operationadd'
// handler after event restructuring
// Disable auto-bake if this is a manual op
if (op.manualBake && this.app.autoBake_) {
this.manager.controls.setAutoBake(false);
this.app.alert("Auto-Bake is disabled by default when using this operation.", "info", 5000);
@@ -402,8 +402,8 @@ RecipeWaiter.prototype.clearRecipe = function() {
* @param {event} e
*/
RecipeWaiter.prototype.dropdownToggleClick = function(e) {
let el = e.target,
button = el.parentNode.parentNode.previousSibling;
const el = e.target;
const button = el.parentNode.parentNode.previousSibling;
button.innerHTML = el.textContent + " <span class='caret'></span>";
this.ingChange();

View File

@@ -19,69 +19,12 @@ const SeasonalWaiter = function(app, manager) {
* Loads all relevant items depending on the current date.
*/
SeasonalWaiter.prototype.load = function() {
//var now = new Date();
// SpiderChef
// if (now.getMonth() === 3 && now.getDate() === 1) { // Apr 1
// this.insertSpiderIcons();
// this.insertSpiderText();
// }
// Konami code
this.kkeys = [];
window.addEventListener("keydown", this.konamiCodeListener.bind(this));
};
/**
* Replaces chef icons with spider icons.
* #spiderchef
*/
SeasonalWaiter.prototype.insertSpiderIcons = function() {
let spider16 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3UlEQVQ4y2NgGJaAmYGBgVnf0oKJgYGBobWtXamqqoYTn2I4CI+LTzM2NTulpKbu+vPHz2dV5RWlluZmi3j5+KqFJSSEzpw8uQPdAEYYIzo5Kfjrl28rWFlZzjAzMYuEBQao3Lh+g+HGvbsMzExMDN++fWf4/PXLBzY2tqYNK1f2+4eHM2xcuRLigsT09Igf3384MTExbf767etBI319jU8fPsi+//jx/72HDxh5uLkZ7ty7y/Dz1687Avz8n2UUFR3Z2NjOySoqfmdhYGBg+PbtuwI7O8e5H79+8X379t357PnzYo+ePP7y6cuXc9++f69nYGRsvf/w4XdtLS2R799/bBUWFHr57sP7Jbs3b/ZkzswvUP3165fZ7z9//r988WIVAyPDr8tXr576+u3bpb9//7YwMjKeV1dV41NWVGoVEhDgPH761DJREeHaz1+/lqlpafUx6+jrRfz4+fPy+w8fTu/fsf3uw7t3L39+//4cv7DwGQYGhpdPbt9m4BcRFlNWVJC4fuvWASszs4C379792Ldt2xZBUdEdDP5hYSqQGIjDGa965uYKCalpZQwMDAxhMTG9DAwMDLaurhIkJY7A8IgGBgYGBgd3Dz2yUpeFo6O4rasrA9T24ZRxAAMTwMpgEJwLAAAAAElFTkSuQmCC",
spider32 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACYVBMVEUAAAAcJSU2Pz85QkM9RUWEhIWMjI2MkJEcJSU2Pz85QkM9RUWWlpc9RUVXXl4cJSU2Pz85QkM8REU9RUVRWFh6ens9RUVCSkpNVFRdY2McJSU5QkM7REQ9RUVGTk5KUlJQVldcY2Rla2uTk5WampscJSVUWltZX2BrcHF1e3scJSUjLCw9RUVASEhFTU1HTk9bYWJeZGRma2xudHV1eHiZmZocJSUyOjpJUFFQVldSWlpTWVpXXl5YXl5rb3B9fX6RkZIcJSUmLy8tNTU9RUVFTU1IT1BOVldRV1hTWlp0enocJSUfKChJUFBWXV1hZ2hnbGwcJSVETExLUlJLU1NNVVVPVlZYXl9cY2RiaGlobW5rcXFyd3h0eHgcJSUpMTFDS0tQV1dRV1hSWFlWXF1bYWJma2tobW5uc3SsrK0cJSVJUFBMVFROVlZVW1xZX2BdYmNhZ2hjaGhla2tqcHBscHE4Pz9KUlJRWVlSWVlXXF1aYGFbYWFfZWZlampqbW4cJSUgKSkiKysuNjY0PD01PT07QkNES0tHTk5JUFBMUlNMU1NOU1ROVVVPVVZRVlZRV1dSWVlWXFxXXV5aX2BbYWFbYWJcYmJcYmNcY2RdYmNgZmZhZmdkaWpkampkamtlamtla2tma2tma2xnbG1obW5pbG1pb3Bqb3Brb3BtcXJudHVvcHFvcXJvc3NwcXNwdXVxc3RzeXl1eXp2eXl3ent6e3x+gYKAhISBg4SKi4yLi4yWlpeampudnZ6fn6CkpaanqKiur6+vr7C4uLm6urq6u7u8vLy9vb3Av8DR0dL2b74UAAAAgHRSTlMAEBAQEBAQECAgICAgMDBAQEBAQEBAUFBQUGBgYGBgYGBgYGBgcHBwcHCAgICAgICAgICAgICPj4+Pj4+Pj4+Pj5+fn5+fn5+fn5+vr6+vr6+/v7+/v7+/v7+/v7+/z8/Pz8/Pz8/Pz8/P39/f39/f39/f39/f7+/v7+/v7+/v78x6RlYAAAGBSURBVDjLY2AYWUCSgUGAk4GBTdlUhQebvP7yjIgCPQbWzBMnjx5wwJSX37Rwfm1isqj9/iPHTuxYlyeMJi+yunfptBkZOw/uWj9h3vatcycu8eRGlldb3Vsts3ph/cFTh7fN3bCoe2Vf8+TZoQhTvBa6REozVC7cuPvQnmULJm1e2z+308eyJieEBSLPXbKQIUqQIczk+N6eNaumtnZMaWhaHM89m8XVCqJA02Y5w0xmga6yfVsamtrN4xoXNzS0JTHkK3CXy4EVFMumcxUy2LbENTVkZfEzMDAudtJyTmNwS2XQreAFyvOlK9louDNVaXurmjkGgnTMkWDgXswtNouFISEX6Awv+RihQi5OcYY4DtVARpCCFCMGhiJ1hjwFBpagEAaWEpFoC0WQOCOjFMRRwXYMDB4BDLJ+QLYsg7GBGjtasLnEMjCIrWBgyAZ7058FI9x1SoFEnTCDsCyIhynPILYYSFgbYpUDA5bpQBluXzxpI1yYAbd2sCMYRhwAAHB9ZPztbuMUAAAAAElFTkSuQmCC",
spider64 = "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";
// Favicon
document.querySelector("link[rel=icon]").setAttribute("href", "data:image/png;base64," + spider16);
// Bake button
document.querySelector("#bake img").setAttribute("src", "data:image/png;base64," + spider32);
// About box
document.querySelector(".about-img-left").setAttribute("src", "data:image/png;base64," + spider64);
};
/**
* Replaces all instances of the word "cyber" with "spider".
* #spiderchef
*/
SeasonalWaiter.prototype.insertSpiderText = function() {
// Title
document.title = document.title.replace(/Cyber/g, "Spider");
// Body
SeasonalWaiter.treeWalk(document.body, function(node) {
// process only text nodes
if (node.nodeType === 3) {
node.nodeValue = node.nodeValue.replace(/Cyber/g, "Spider");
}
}, true);
// Bake button
SeasonalWaiter.treeWalk(document.getElementById("bake-group"), function(node) {
// process only text nodes
if (node.nodeType === 3) {
node.nodeValue = node.nodeValue.replace(/Bake/g, "Spin");
}
}, true);
// Recipe title
document.querySelector("#recipe .title").innerHTML = "Web";
};
/**
* Listen for the Konami code sequence of keys. Turn the page upside down if they are all heard in
* sequence.
@@ -102,53 +45,4 @@ SeasonalWaiter.prototype.konamiCodeListener = function(e) {
}
};
/**
* Walks through the entire DOM starting at the specified element and operates on each node.
*
* @static
* @param {element} parent - The DOM node to start from
* @param {Function} fn - The callback function to operate on each node
* @param {booleam} allNodes - Whether to operate on every node or not
*/
SeasonalWaiter.treeWalk = (function() {
// Create closure for constants
const skipTags = {
"SCRIPT": true, "IFRAME": true, "OBJECT": true,
"EMBED": true, "STYLE": true, "LINK": true, "META": true
};
return function(parent, fn, allNodes) {
let node = parent.firstChild;
while (node && node !== parent) {
if (allNodes || node.nodeType === 1) {
if (fn(node) === false) {
return false;
}
}
// If it's an element &&
// has children &&
// has a tagname && is not in the skipTags list
// then, we can enumerate children
if (node.nodeType === 1 &&
node.firstChild &&
!(node.tagName && skipTags[node.tagName])) {
node = node.firstChild;
} else if (node.nextSibling) {
node = node.nextSibling;
} else {
// No child and no nextsibling
// Find parent that has a nextSibling
while ((node = node.parentNode) !== parent) {
if (node.nextSibling) {
node = node.nextSibling;
break;
}
}
}
}
};
})();
export default SeasonalWaiter;

View File

@@ -1,18 +0,0 @@
/**
* CSS index
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import "google-code-prettify/src/prettify.css";
import "./lib/bootstrap.less";
import "bootstrap-switch/src/less/bootstrap3/build.less";
import "bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css";
import "./structure/overrides.css";
import "./structure/layout.css";
import "./structure/utils.css";
import "./themes/classic.css";

File diff suppressed because one or more lines are too long

View File

@@ -1,113 +0,0 @@
/* Bootstrap */
button,
a:focus {
outline: none;
-moz-outline-style: none;
}
.btn-default {
border-color: #ddd;
}
.btn-default:focus {
background-color: #fff;
border-color: #adadad;
}
.btn-default:hover,
.btn-default:active {
background-color: #ebebeb;
border-color: #adadad;
}
.btn,
.btn-lg,
.nav-tabs>li>a,
.form-control,
.popover,
.alert,
.modal-content,
.tooltip-inner,
.dropdown-menu {
border-radius: 0 !important;
}
input[type="search"] {
-webkit-appearance: searchfield;
box-shadow: none;
}
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: searchfield-cancel-button;
}
.modal {
overflow-y: auto;
}
.form-control {
background-color: transparent;
}
code {
border: 0;
white-space: pre-wrap;
font-family: Consolas, monospace;
}
pre {
border-radius: 0 !important;
}
blockquote {
font-size: inherit;
}
blockquote a {
cursor: pointer;
}
optgroup {
font-weight: bold;
}
.panel-body:before,
.panel-body:after {
content: "";
}
.table-nonfluid {
width: auto !important;
}
/* Bootstrap-switch */
.bootstrap-switch,
.bootstrap-switch-container,
.bootstrap-switch-handle-on,
.bootstrap-switch-handle-off,
.bootstrap-switch-label {
border-radius: 0 !important;
}
/* Sortable */
.sortable-ghost {
opacity: 0.6;
}
/* Bootstrap Colorpicker */
.colorpicker-element {
float: left;
margin-right: 15px;
}
.colorpicker-color,
.colorpicker-color div {
height: 100px;
}

View File

@@ -1,37 +0,0 @@
.word-wrap {
white-space: pre !important;
word-wrap: normal !important;
overflow-x: scroll !important;
}
.clearfix {
clear: both;
height: 0;
}
.blur {
color: transparent !important;
text-shadow: rgba(0, 0, 0, 0.95) 0 0 10px !important;
}
.no-select {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.konami {
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
-moz-transform: rotate(180deg);
}
.hl1, .hlyellow { background-color: #fff000; }
.hl2, .hlblue { background-color: #95dfff; }
.hl3, .hlred { background-color: #ffb6b6; } /* Half-Life 3 confirmed :O */
.hl4, .hlorange { background-color: #fcf8e3; }
.hl5, .hlgreen { background-color: #8de768; }

View File

@@ -1,258 +0,0 @@
#banner {
border-bottom: 1px solid #ddd;
}
.title {
border-bottom: 1px solid #ddd;
font-weight: bold;
color: #424242;
background-color: #fafafa;
}
.gutter {
background-color: #eee;
background-repeat: no-repeat;
background-position: 50%;
}
.gutter.gutter-horizontal {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAAeCAYAAAAGos/EAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAlSURBVChTYzxz5sx/BiBgAhEgwPju3TtUEZZ79+6BGcNcDQMDACWJMFs4hNOSAAAAAElFTkSuQmCC');
cursor: ew-resize;
}
.gutter.gutter-vertical {
background-image: url('data:image/png;base64,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');
cursor: ns-resize;
}
.operation {
border: 1px solid #999;
border-top-width: 0;
}
.op-list .operation { /*blue*/
color: #3a87ad;
background-color: #d9edf7;
border-color: #bce8f1;
}
#rec-list .operation { /*green*/
color: #468847;
background-color: #dff0d8;
border-color: #d6e9c6;
}
#controls {
border-top: 1px solid #ddd;
background-color: #fafafa;
}
.textarea-wrapper textarea,
.textarea-wrapper div {
font-family: Consolas, monospace;
font-size: inherit;
}
.io-info {
font-family: Consolas, monospace;
font-weight: normal;
font-size: 8pt;
}
.arg-title {
font-weight: bold;
}
.arg-input {
height: 34px;
font-size: 15px;
line-height: 1.428571429;
color: #424242;
background-color: #fff;
border: 1px solid #ddd;
font-family: Consolas, monospace;
}
select {
padding: 6px 8px;
height: 34px;
border: 1px solid #ddd;
background-color: #fff;
color: #424242;
}
.arg[disabled] {
background-color: #eee;
}
textarea.arg {
color: #424242;
font-family: Consolas, monospace;
}
.break {
color: #b94a48 !important;
background-color: #f2dede !important;
border-color: #eed3d7 !important;
}
.category-title {
background-color: #fafafa;
border-bottom: 1px solid #eee;
font-weight: bold;
}
.category-title[href='#catFavourites'] {
border-bottom-color: #ddd;
}
.category-title[aria-expanded=true] {
border-bottom-color: #ddd;
}
.category-title.collapsed {
border-bottom-color: #eee;
}
.category-title:hover {
color: #3a87ad;
}
#search {
border-bottom: 1px solid #e3e3e3;
}
.dropping-file {
border: 5px dashed #3a87ad !important;
}
.selected-op {
color: #c09853 !important;
background-color: #fcf8e3 !important;
border-color: #fbeed5 !important;
}
.option-item input[type=number] {
font-size: 14px;
line-height: 1.428571429;
color: #555;
background-color: #fff;
border: 1px solid #ccc;
}
.favourites-hover {
color: #468847;
background-color: #dff0d8;
border: 2px dashed #468847 !important;
padding: 8px 8px 9px 8px;
}
#edit-favourites-list {
border: 1px solid #bce8f1;
}
#edit-favourites-list .operation {
border-left: none;
border-right: none;
}
#edit-favourites-list .operation:last-child {
border-bottom: none;
}
.subtext {
font-style: italic;
font-size: 13px;
color: #999;
}
#save-footer {
border-bottom: 1px solid #e5e5e5;
}
.flow-control-op {
color: #396f3a !important;
background-color: #c7e4ba !important;
border-color: #b3dba2 !important;
}
.flow-control-op.break {
color: #94312f !important;
background-color: #eabfbf !important;
border-color: #e2aeb5 !important;
}
#support-modal textarea {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
#save-text,
#load-text {
font-family: Consolas, monospace;
}
button.dropdown-toggle {
background-color: #f4f4f4;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background-color: #fafafa;
}
::-webkit-scrollbar-thumb {
background-color: #ccc;
}
::-webkit-scrollbar-thumb:hover {
background-color: #bbb;
}
::-webkit-scrollbar-corner {
background-color: #fafafa;
}
.disabled {
color: #999 !important;
background-color: #dfdfdf !important;
border-color: #cdcdcd !important;
}
.grey {
color: #333;
background-color: #f5f5f5;
border-color: #ddd;
}
.dark-blue {
color: #fff;
background-color: #428bca;
border-color: #428bca;
}
.red {
color: #b94a48;
background-color: #f2dede;
border-color: #eed3d7;
}
.amber {
color: #c09853;
background-color: #fcf8e3;
border-color: #fbeed5;
}
.green {
color: #468847;
background-color: #dff0d8;
border-color: #d6e9c6;
}
.blue {
color: #3a87ad;
background-color: #d9edf7;
border-color: #bce8f1;
}

View File

@@ -20,7 +20,7 @@
-->
<!-- htmlmin:ignore -->
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="classic">
<head>
<meta charset="UTF-8">
<title>CyberChef</title>
@@ -30,15 +30,63 @@
<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">
// Load theme before the preloader is shown
document.querySelector(":root").className = JSON.parse(localStorage.getItem("options")).theme;
// Define loading messages
const loadingMsgs = [
"Proving P = NP...",
"Computing 6 x 9...",
"Mining bitcoin...",
"Dividing by 0...",
"Initialising Skynet...",
"[REDACTED]",
"Downloading more RAM...",
"Loading more loading messages...",
"Ordering 1s and 0s...",
"Navigating neural network...",
"Importing machine learning..."
];
// Shuffle array using Durstenfeld algorithm
for (let i = loadingMsgs.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
const temp = loadingMsgs[i];
loadingMsgs[i] = loadingMsgs[j];
loadingMsgs[j] = temp;
}
// Show next loading message then move it to the end of the array
function changeLoadingMsg() {
const msg = loadingMsgs.shift();
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);
</script>
</head>
<body>
<!-- Preloader overlay -->
<div id="loader-wrapper">
<div id="preloader"></div>
<div id="preloader-msg"></div>
</div>
<!-- End preloader overlay -->
<span id="edit-favourites" class="btn btn-default btn-sm"><img aria-hidden="true" src="<%- require('../static/images/favourite-16x16.png') %>" alt="Star Icon"/> Edit</span>
<div id="alert" class="alert alert-danger">
<button type="button" class="close" id="alert-close">&times;</button>
<span id="alert-content"></span>
</div>
<div id="content-wrapper">
<div id="banner" class="green">
<div id="banner">
<% if (htmlWebpackPlugin.options.inline) { %>
<span style="float: left; margin-left: 10px;">Compile time: <%= htmlWebpackPlugin.options.compileTime %></span>
<% } else { %>
@@ -57,17 +105,17 @@
<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>
<div id="wrapper">
<div id="workspace-wrapper">
<div id="operations" class="split split-horizontal no-select">
<div class="title no-select">Operations</div>
<input type="search" class="form-control" id="search" placeholder="Search..." autocomplete="off">
<ul class="op-list" id="search-results"></ul>
<div class="panel-group no-select" id="categories"></div>
<input id="search" type="search" class="form-control" placeholder="Search..." autocomplete="off">
<ul id="search-results" class="op-list"></ul>
<div id="categories" class="panel-group no-select"></div>
</div>
<div id="recipe" class="split split-horizontal no-select">
<div class="title no-select">Recipe</div>
<ul id="rec-list" class="no-select"></ul>
<ul id="rec-list" class="list-area no-select"></ul>
<div id="controls" class="no-select">
<div id="operational-controls">
@@ -165,6 +213,7 @@
<input type="checkbox" id="save-link-recipe-checkbox" checked> <label for="save-link-recipe-checkbox"> Include recipe </label>
<input type="checkbox" id="save-link-input-checkbox" checked> <label for="save-link-input-checkbox"> Include input </label>
</div>
<br>
<a id="save-link" style="word-wrap: break-word;"></a>
</div>
</div>
@@ -207,6 +256,13 @@
</div>
<div class="modal-body" id="options-body">
<p style="font-weight: bold">Please note that these options will persist between sessions.</p>
<div class="option-item">
<select option="theme" id="theme">
<option value="classic">Classic</option>
<option value="dark">Dark</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>
@@ -280,8 +336,11 @@
</div>
<div class="modal-body">
<img aria-hidden="true" class="about-img-left" src="<%- require('../static/images/cyberchef-128x128.png') %>" alt="CyberChef Logo"/>
<p class="subtext">Compile time: <%= htmlWebpackPlugin.options.compileTime %></p>
<p>&copy Crown Copyright 2016.</p>
<p class="subtext">
Version <%= htmlWebpackPlugin.options.version %><br>
Compile time: <%= htmlWebpackPlugin.options.compileTime %>
</p>
<p>&copy; Crown Copyright 2016.</p>
<p>Licenced under the Apache Licence, Version 2.0.</p>
<br>
<br>

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
// CSS
import "./css/index.js";
// Styles
import "./stylesheets/index.js";
// Libs
import "babel-polyfill";
@@ -46,6 +46,7 @@ function main() {
errorTimeout : 4000,
autoBakeThreshold : 200,
attemptHighlight : true,
theme : "classic",
};
document.removeEventListener("DOMContentLoaded", main, false);

View File

@@ -9,7 +9,7 @@
ga('create', 'UA-85682716-2', 'auto');
// Specifying location.pathname here overrides the default URL which would include arguments.
// Specifying location.pathname here overrides the default URL which could include arguments.
// This method prevents Google Analytics from logging any recipe or input data in the URL.
ga('send', 'pageview', location.pathname);

View File

@@ -0,0 +1,22 @@
/**
* Alert styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
#alert {
position: fixed;
width: 30%;
margin: 30px auto;
top: 10px;
left: 0;
right: 0;
z-index: 2000;
display: none;
}
#alert a {
text-decoration: underline;
}

View File

@@ -0,0 +1,13 @@
/**
* Button styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
button img,
span.btn img {
margin-right: 3px;
margin-bottom: 1px;
}

View File

@@ -0,0 +1,43 @@
/**
* Operation list styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
.op-list {
list-style-type: none;
margin: 0;
padding: 0;
}
.category-title {
display: block;
padding: 10px;
background-color: var(--secondary-background-colour);
border-bottom: 1px solid var(--secondary-border-colour);
font-weight: var(--title-weight);
}
.category-title[href='#catFavourites'] {
border-bottom-color: var(--primary-border-colour);
}
.category-title[aria-expanded=true] {
border-bottom-color: var(--primary-border-colour);
}
.category-title.collapsed {
border-bottom-color: var(--secondary-border-colour);
}
.category-title:hover {
color: var(--op-list-operation-font-colour);
}
.category {
margin: 0 !important;
border-radius: 0 !important;
border: none;
}

View File

@@ -0,0 +1,196 @@
/**
* Operation styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
.operation {
cursor: pointer;
padding: 10px;
list-style-type: none;
position: relative;
border-width: 1px;
border-style: solid;
border-top: none;
border-left: none;
border-right: none;
}
.arg-group {
display: table;
width: 100%;
margin-top: 10px;
}
.arg-group-text {
display: block;
}
.inline-args {
float: left;
width: auto;
margin-right: 30px;
height: 34px;
}
.inline-args input[type="checkbox"] {
margin-top: 10px;
}
.inline-args input[type="number"] {
width: 100px;
}
.arg-title {
font-weight: var(--arg-title-font-weight);
}
.arg-input {
display: table-cell;
width: 100%;
padding: 6px 12px;
vertical-align: middle;
height: var(--arg-input-height);
font-size: var(--arg-input-font-size);
line-height: var(--arg-input-line-height);
color: var(--arg-font-colour);
background-color: var(--arg-background);
border: 1px solid var(--arg-border-colour);
font-family: var(--fixed-width-font-family);
}
.short-string {
width: 150px;
}
select {
display: block;
padding: 6px 8px;
height: 34px;
border: 1px solid var(--arg-border-colour);
background-color: var(--arg-background);
color: var(--arg-font-colour);
}
.arg[disabled] {
cursor: not-allowed;
opacity: 1;
background-color: var(--arg-disabled-background);
}
textarea.arg {
width: 100%;
min-height: 50px;
height: 70px;
margin-top: 5px;
border: 1px solid var(--arg-border-colour);
resize: vertical;
color: var(--arg-font-colour);
background-color: var(--arg-background);
font-family: var(--fixed-width-font-family);
}
.arg-label {
display: table-cell;
width: 1px;
padding-right: 10px;
font-weight: normal;
vertical-align: middle;
white-space: pre;
}
.editable-option {
position: relative;
display: inline-block;
}
.editable-option-select {
min-width: 250px;
}
.editable-option-input {
position: absolute;
top: 1px;
left: 1px;
width: calc(100% - 20px);
height: calc(100% - 2px) !important;
border: none !important;
}
button.dropdown-toggle {
background-color: var(--secondary-background-colour);
}
.op-icon {
float: right;
margin-left: 10px;
margin-top: 3px;
}
.recip-icons {
position: absolute;
top: 13px;
right: 10px;
height: 16px;
}
.recip-icon {
margin-right: 10px;
vertical-align: baseline;
float: right;
}
.disable-icon {
width: 16px;
height: 16px;
margin-top: -1px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAACfElEQVQ4y6WTPWgTYRjHf8nlfVvuoDVIP4Yuki4WHKoUqggFRUTsUEGkVG2hmCq6OnTwIxYHB+eijZOKdLNDW1pKKyGigh8dBHUJElxyBgx3vEnukvdyDrUhRXDxGR+e/+/583xEwjDkfyIGwNVTzURm4tYAMA6MAoN/0tvAMrA48uL+l2bx4w0iYRjSuHKC6OnTZLqHk8CcaZq9bW1tSCkBqNVq+L5PpVIpAHdGfr5LN9bXiT7Z2nGgteb1/qFkLBJZ6OjowHEc8vk8pVIJgHg8TldXF52dnb2u6y5s7R/iuF5JSyAKkLl4eyAMwznLsrBtm1wu99Z13amk+BFJih8R13WXANrb27EsizAM5zIXbw+wC9Baj0spe5VSFAqFt4ZhXJ6ufXuK55E5cDKVSCTGenp6yGazKKWQUvZqrcebgCAIRqWUOI6DEOLR1K8POapVMgfPpoC7u2LLspYcx0FKSRAEo60OBg3DwPd9Jr5vPqWvj8zh83vEwL2J75vnfN/HMAy01oPNNQZBQBAEO1OvVsl0D/8lTuZfpYDd7gRBQKuD7XK5jGmarB679PIv8deVFJUKq8cuTZqmSblcRmu93QpYVkohhMCyrLE94n2/UlSrbJy5kRBCXBNCoJRCa73cClh0XbfgeR6WZZHNZunv719KvnmeYnWVVxdmJ2Ox2DMhxFHP83Bdt6C1XgR2LvHzQDvvb84npZQL8Xgc0zSJRqN7br7RaFCpVCiVStRqtZmhh9fTh754TQdMr82nPc+bsW27UCwWUUpRr9ep1+sopSgWi9i2XfA8b2Z6bT6ttabp4GMi0uz0aXbhn890+MFM85mO5MIdwP/Eb1pMUCdctYRzAAAAAElFTkSuQmCC') no-repeat;
}
.disable-icon-selected {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACFUlEQVR4XqWTP0tbURjGn9zY3mjBwsUhBQtS6XKxiNypIGZJ6SKYUYdaKWg7OrrE3pYO+Qit3dpFuuQO6lI7Z4nESQdjlJbkJh0MksSb3Jvk9H0gjZFu9YWH83LO7zn/3nNCSincJobAeP1sEDBFi6J50UyPy4l2RNuioz756Ts0tt1OB4jH2a52Ne2HGh9PwrJm2EcxZx/HyPRYMDgB2u02/N3d1c7w8BZMM1ptNJBPp3GwsUExB/s4RoYsPf0JOkFgdoH34YkJ/D48xC/HyTTOzl5ayWSIktwxqlVo0SjIkKWnP0Hg+4swjGitVMJFNpu5o+svptfXv6DZBDIZezoWS3Db3A0ZsvRcH8H354dGR9EoFHA3EvlorqycwvOAXM4G8Pav+f7YmEOGLD1gsIzl54+V+vBK/Yw9ZAv1LQW1FrdFSnKVfQTK5liPUfRI9I8ArqiPjLAF9vcHVybyzlpasgcZeq7voNXKNSsV3DMMXB4fp/8xLyzYuLri2DIZsvQM3sFOzXURiUR4zsQNcyrFleFVKpNyP2/IkKVnsArbF65bbkqplJSJZrl5x5qbs7G3h3artSyV+arr+lMyZOnpP2Wp6ZFos3R+vvUgCGDNzgKalkA4rECIr07662J2i0X4nrfJJ33jJT6Zmvpcr9XWCicn5WI+j7rrAmKgmLOPY2TI0sPgb8TBZOi/PpN1qnDr7/wH3jxgB/FKIXkAAAAASUVORK5CYII=') no-repeat;
}
.breakpoint {
float: right;
width: 14px;
height: 14px;
background-color: #eee;
border: 1px solid #aaa;
}
.breakpoint-selected {
background: #eee url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAXVBMVEXIUkvzUVHzTEzzn5785eXrbW24BgbzWVnze3vzVVXzY2Pyion509PzbW3zXV1UMxj0l5f1srKbRTRgOxzJDg796ur74ODfIyP5zs6LLx3pNTXYGxuxdkVZNhn////sCC1eAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAABWSURBVBjTnc+7EoAgDERRTOQVxMEZFAf//z8FjAUFDbfb060QU2FwxngimxnCea3bjegSgz+0tguAfBgIy64QGfZQdg91dgAtqUZgnfz6IacYVWvu2AvR4wNAv0nxrAAAAABJRU5ErkJggg==') no-repeat -2px -2px;
}
.break {
color: var(--breakpoint-font-colour) !important;
background-color: var(--breakpoint-bg-colour) !important;
border-color: var(--breakpoint-border-colour) !important;
}
.selected-op {
color: var(--selected-operation-font-color) !important;
background-color: var(--selected-operation-bg-colour) !important;
border-color: var(--selected-operation-border-colour) !important;
}
.flow-control-op {
color: var(--fc-operation-font-colour) !important;
background-color: var(--fc-operation-bg-colour) !important;
border-color: var(--fc-operation-border-colour) !important;
}
.flow-control-op.break {
color: var(--fc-breakpoint-operation-font-colour) !important;
background-color: var(--fc-breakpoint-operation-bg-colour) !important;
border-color: var(--fc-breakpoint-operation-border-colour) !important;
}
.disabled {
color: var(--disabled-font-colour) !important;
background-color: var(--disabled-bg-colour) !important;
border-color: var(--disabled-border-colour) !important;
}

View File

@@ -0,0 +1,30 @@
/**
* Workspace pane styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
:root {
--title-height: 43px;
}
.title {
padding: 10px;
height: var(--title-height);
border-bottom: 1px solid var(--primary-border-colour);
font-weight: var(--title-weight);
color: var(--title-colour);
background-color: var(--title-background-colour);
}
.list-area {
position: absolute;
top: var(--title-height);
bottom: 0;
width: 100%;
list-style-type: none;
margin: 0;
padding: 0;
}

View File

@@ -0,0 +1,34 @@
/**
* CyberChef styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
/* Themes */
@import "./themes/_classic.css";
@import "./themes/_dark.css";
/* Utilities */
@import "./utils/_overrides.css";
@import "./utils/_general.css";
/* Preloader styles */
@import "./preloader.css";
/* Components */
@import "./components/_alert.css";
@import "./components/_button.css";
@import "./components/_list.css";
@import "./components/_operation.css";
@import "./components/_pane.css";
/* Layout */
@import "./layout/_banner.css";
@import "./layout/_controls.css";
@import "./layout/_io.css";
@import "./layout/_modals.css";
@import "./layout/_operations.css";
@import "./layout/_recipe.css";
@import "./layout/_structure.css";

View File

@@ -0,0 +1,18 @@
/**
* Styles index
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
/* Libraries */
import "google-code-prettify/src/prettify.css";
/* Frameworks */
import "./vendors/bootstrap.less";
import "bootstrap-switch/dist/css/bootstrap3/bootstrap-switch.css";
import "bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css";
/* CyberChef styles */
import "./index.css";

View File

@@ -0,0 +1,28 @@
/**
* Banner area styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
#banner {
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;
}

View File

@@ -0,0 +1,65 @@
/**
* Controls area styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
:root {
--controls-height: 120px;
--controls-division: 65%;
}
#controls {
position: absolute;
width: 100%;
height: var(--controls-height);
bottom: 0;
padding: 10px;
border-top: 1px solid var(--primary-border-colour);
background-color: var(--secondary-background-colour);
}
#operational-controls {
width: var(--controls-division);
float: left;
text-align: center;
}
#bake-group {
display: table;
width: 100%;
}
#bake {
display: table-cell;
width: 100%;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
#auto-bake-label {
display: table-cell;
padding: 1px;
line-height: 1.35;
width: 60px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left: 1px solid var(--btn-success-bg-colour);
}
#auto-bake-label:hover {
border-left-color: var(--btn-success-hover-border-colour);
}
#auto-bake-label div {
font-size: 10px;
padding: 2px;
}
#extra-controls {
float: right;
width: calc(100% - var(--controls-division));
padding-left: 10px;
}

View File

@@ -0,0 +1,109 @@
/**
* Input/Output area styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
#input-text,
#output-text,
#output-html {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 3px;
-moz-padding-start: 3px;
-moz-padding-end: 3px;
border: none;
border-width: 0px;
resize: none;
background-color: transparent;
white-space: pre-wrap;
word-wrap: break-word;
}
#output-html {
display: none;
overflow-y: auto;
-moz-padding-start: 1px; /* Fixes bug in Firefox */
}
.textarea-wrapper {
position: absolute;
top: 43px;
bottom: 0;
width: 100%;
overflow: hidden;
}
.textarea-wrapper textarea,
.textarea-wrapper div {
font-family: var(--fixed-width-font-family);
font-size: var(--fixed-width-font-size);
color: var(--fixed-width-font-colour);
}
#input-highlighter,
#output-highlighter {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 3px;
margin: 0;
overflow: hidden;
letter-spacing: normal;
white-space: pre-wrap;
word-wrap: break-word;
color: #fff;
background-color: transparent;
border: none;
}
.io-btn-group {
float: right;
margin-top: -4px;
}
.io-info {
margin-right: 20px;
margin-top: -4px;
float: right;
height: 30px;
text-align: right;
line-height: 10px;
font-family: var(--fixed-width-font-family);
font-weight: normal;
font-size: 8pt;
}
#input-info {
line-height: 15px;
}
.dropping-file {
border: 5px dashed var(--drop-file-border-colour) !important;
}
@keyframes spinner {
from {
transform:rotate(0deg);
}
to {
transform:rotate(359deg);
}
}
.loading-icon::before {
content: "\21bb";
}
.loading-icon {
animation-name: spinner;
animation-duration: 1000ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
}

View File

@@ -0,0 +1,80 @@
/**
* Modal layout styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
.option-item .bootstrap-switch {
margin: 15px 10px;
}
.option-item button {
margin: 10px;
}
.option-item input[type=number] {
margin: 15px 10px;
width: 80px;
height: 28px;
padding: 3px 10px;
vertical-align: middle;
font-size: calc(var(--arg-input-font-size) - 1px);
line-height: var(--arg-input-line-height);
color: var(--arg-font-colour);
background-color: var(--arg-background);
border: 1px solid var(--primary-border-colour);
}
.option-item select {
margin: 10px;
display: inline-block;
}
#edit-favourites-list {
margin: 10px;
border: 1px solid var(--op-list-operation-border-colour);
}
#edit-favourites-list .operation {
border-left: none;
border-right: none;
}
#edit-favourites-list .operation:last-child {
border-bottom: none;
}
.about-img-left {
float: left;
margin: 10px 20px 20px 0;
}
.about-img-right {
float: right;
margin: 10px 0 20px 20px;
}
.save-link-options {
float: right;
}
.save-link-options input{
margin-left: 10px;
}
#save-footer {
border-top: none;
margin-top: 0;
border-bottom: 1px solid var(--primary-border-colour);
}
#support-modal textarea {
font-family: var(--primary-font-family);
}
#save-text,
#load-text {
font-family: var(--fixed-width-font-family);
}

View File

@@ -0,0 +1,32 @@
/**
* Operation area styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
.op-list .operation {
color: var(--op-list-operation-font-colour);
background-color: var(--op-list-operation-bg-colour);
border-color: var(--op-list-operation-border-colour);
}
#search {
border-radius: 0;
border: none;
border-bottom: 1px solid var(--primary-border-colour);
color: var(--primary-font-colour);
}
#edit-favourites {
float: right;
margin-top: -5px;
}
.favourites-hover {
color: var(--rec-list-operation-font-colour);
background-color: var(--rec-list-operation-bg-colour);
border: 2px dashed var(--rec-list-operation-font-colour) !important;
padding: 8px 8px 9px 8px;
}

View File

@@ -0,0 +1,18 @@
/**
* Recipe area styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
#rec-list {
bottom: var(--controls-height);
overflow: auto;
}
#rec-list .operation {
color: var(--rec-list-operation-font-colour);
background-color: var(--rec-list-operation-bg-colour);
border-color: var(--rec-list-operation-border-colour);
}

View File

@@ -0,0 +1,65 @@
/**
* Overall page structure styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
body {
overflow: hidden;
}
#content-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#workspace-wrapper {
position: absolute;
top: 30px;
bottom: 0;
width: 100%;
}
div#operations,
div#recipe {
width: 50%;
height: 100%;
}
div#input,
div#output {
width: 100%;
height: 50%;
}
.split {
box-sizing: border-box;
overflow: auto;
position: relative;
}
.split.split-horizontal, .gutter.gutter-horizontal {
height: 100%;
float: left;
}
.gutter {
background-color: var(--secondary-border-colour);
background-repeat: no-repeat;
background-position: 50%;
}
.gutter.gutter-horizontal {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAAeCAYAAAAGos/EAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB+EFBhEwBDmIiYYAAAAjSURBVBjTYzxz5sx/BgYGBiYGKGB89+4dA4oIy71790aGGgCn+DBbOcAB0wAAAABJRU5ErkJggg==');
cursor: ew-resize;
}
.gutter.gutter-vertical {
background-image: url('data:image/png;base64,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');
cursor: ns-resize;
}

View File

@@ -0,0 +1,152 @@
/**
* Preloader styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background-color: var(--secondary-border-colour);
}
#preloader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 3px solid transparent;
border-top-color: #3498db;
border-radius: 50%;
z-index: 1500;
animation: spin 2s linear infinite;
}
#preloader:before,
#preloader:after {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border: 3px solid transparent;
border-radius: 50%;
}
#preloader:before {
border-top-color: #e74c3c;
animation: spin 3s linear infinite;
}
#preloader:after {
border-top-color: #f9c922;
animation: spin 1.5s linear infinite;
}
#preloader-msg {
display: block;
position: relative;
width: 300px;
left: calc(50% - 150px);
top: calc(50% + 50px);
text-align: center;
margin-top: 50px;
opacity: 0;
}
#preloader-msg.loading {
opacity: 1;
transition: all 0.1s ease-in;
}
/* Loaded */
.loaded #preloader,
.loaded #preloader-msg {
opacity: 0;
transition: all 0.3s ease-out;
}
.loaded #loader-wrapper {
opacity: 0;
transition: all 0.5s 0.3s ease-out;
}
.loaded #rec-list li {
animation: bump 0.7s cubic-bezier(0.7, 0, 0.3, 1) both;
}
.loaded #content-wrapper {
animation-delay: 0.10s;
}
.loaded #rec-list li:first-child {
animation-delay: 0.20s;
}
.loaded #rec-list li:nth-child(2) {
animation-delay: 0.25s;
}
.loaded #rec-list li:nth-child(3) {
animation-delay: 0.30s;
}
.loaded #rec-list li:nth-child(4) {
animation-delay: 0.35s;
}
.loaded #rec-list li:nth-child(5) {
animation-delay: 0.40s;
}
.loaded #rec-list li:nth-child(6) {
animation-delay: 0.45s;
}
.loaded #rec-list li:nth-child(7) {
animation-delay: 0.50s;
}
.loaded #rec-list li:nth-child(8) {
animation-delay: 0.55s;
}
.loaded #rec-list li:nth-child(9) {
animation-delay: 0.60s;
}
.loaded #rec-list li:nth-child(10) {
animation-delay: 0.65s;
}
/* Animations */
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes bump {
from {
opacity: 0;
transform: translate3d(0, 200px, 0);
}
}

View File

@@ -0,0 +1,116 @@
/**
* Classic theme definitions
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
:root,
:root.classic {
--primary-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
--primary-font-colour: #333;
--primary-font-size: 14px;
--primary-line-height: 20px;
--fixed-width-font-family: "Consolas", monospace;
--fixed-width-font-colour: inherit;
--fixed-width-font-size: inherit;
--subtext-font-colour: #999;
--subtext-font-size: 13px;
--primary-background-colour: #fff;
--secondary-background-colour: #fafafa;
--primary-border-colour: #ddd;
--secondary-border-colour: #eee;
--title-colour: #424242;
--title-weight: bold;
--title-background-colour: #fafafa;
--banner-font-colour: #468847;
--banner-bg-colour: #dff0d8;
/* Operation colours */
--op-list-operation-font-colour: #3a87ad;
--op-list-operation-bg-colour: #d9edf7;
--op-list-operation-border-colour: #bce8f1;
--rec-list-operation-font-colour: #468847;
--rec-list-operation-bg-colour: #dff0d8;
--rec-list-operation-border-colour: #d6e9c6;
--selected-operation-font-color: #c09853;
--selected-operation-bg-colour: #fcf8e3;
--selected-operation-border-colour: #fbeed5;
--breakpoint-font-colour: #b94a48;
--breakpoint-bg-colour: #f2dede;
--breakpoint-border-colour: #eed3d7;
--disabled-font-colour: #999;
--disabled-bg-colour: #dfdfdf;
--disabled-border-colour: #cdcdcd;
--fc-operation-font-colour: #396f3a;
--fc-operation-bg-colour: #c7e4ba;
--fc-operation-border-colour: #b3dba2;
--fc-breakpoint-operation-font-colour: #94312f;
--fc-breakpoint-operation-bg-colour: #eabfbf;
--fc-breakpoint-operation-border-colour: #e2aeb5;
/* Operation arguments */
--arg-title-font-weight: bold;
--arg-input-height: 34px;
--arg-input-line-height: 20px;
--arg-input-font-size: 15px;
--arg-font-colour: #424242;
--arg-background: #fff;
--arg-border-colour: #ddd;
--arg-disabled-background: #eee;
/* Buttons */
--btn-default-font-colour: #333;
--btn-default-bg-colour: #fff;
--btn-default-border-colour: #ddd;
--btn-default-hover-font-colour: #333;
--btn-default-hover-bg-colour: #ebebeb;
--btn-default-hover-border-colour: #adadad;
--btn-success-font-colour: #fff;
--btn-success-bg-colour: #5cb85c;
--btn-success-border-colour: #4cae4c;
--btn-success-hover-font-colour: #fff;
--btn-success-hover-bg-colour: #449d44;
--btn-success-hover-border-colour: #398439;
/* Highlighter colours */
--hl1: #fff000;
--hl2: #95dfff;
--hl3: #ffb6b6;
--hl4: #fcf8e3;
--hl5: #8de768;
/* Scrollbar */
--scrollbar-track: var(--secondary-background-colour);
--scrollbar-thumb: #ccc;
--scrollbar-hover: #bbb;
/* Misc. */
--drop-file-border-colour: #3a87ad;
--popover-background: #fff;
--popover-border-colour: #ccc;
--code-background: #f9f2f4;
--code-font-colour: #c7254e;
}

View File

@@ -0,0 +1,115 @@
/**
* Dark theme definitions
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
:root.dark {
--primary-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
--primary-font-colour: #c5c5c5;
--primary-font-size: 14px;
--primary-line-height: 20px;
--fixed-width-font-family: "Monaco", "Droid Sans Mono", "Consolas", monospace;
--fixed-width-font-colour: inherit;
--fixed-width-font-size: inherit;
--subtext-font-colour: #999;
--subtext-font-size: 13px;
--primary-background-colour: #1e1e1e;
--secondary-background-colour: #252525;
--primary-border-colour: #444;
--secondary-border-colour: #3c3c3c;
--title-colour: #fff;
--title-weight: bold;
--title-background-colour: #333;
--banner-font-colour: #c5c5c5;
--banner-bg-colour: #252525;
/* Operation colours */
--op-list-operation-font-colour: #c5c5c5;
--op-list-operation-bg-colour: #333;
--op-list-operation-border-colour: #444;
--rec-list-operation-font-colour: #c5c5c5;
--rec-list-operation-bg-colour: #252525;
--rec-list-operation-border-colour: #444;
--selected-operation-font-color: #c5c5c5;
--selected-operation-bg-colour: #3f3f3f;
--selected-operation-border-colour: #444;
--breakpoint-font-colour: #ddd;
--breakpoint-bg-colour: #073655;
--breakpoint-border-colour: #444;
--disabled-font-colour: #666;
--disabled-bg-colour: #444;
--disabled-border-colour: #444;
--fc-operation-font-colour: #c5c5c5;
--fc-operation-bg-colour: #2d2d2d;
--fc-operation-border-colour: #444;
--fc-breakpoint-operation-font-colour: #ddd;
--fc-breakpoint-operation-bg-colour: #072b49;
--fc-breakpoint-operation-border-colour: #444;
/* Operation arguments */
--arg-title-font-weight: bold;
--arg-input-height: 34px;
--arg-input-line-height: 20px;
--arg-input-font-size: 15px;
--arg-font-colour: #bbb;
--arg-background: #3c3c3c;
--arg-border-colour: #3c3c3c;
--arg-disabled-background: #4f4f4f;
/* Buttons */
--btn-default-font-colour: #c5c5c5;
--btn-default-bg-colour: #2d2d2d;
--btn-default-border-colour: #3c3c3c;
--btn-default-hover-font-colour: #c5c5c5;
--btn-default-hover-bg-colour: #2d2d2d;
--btn-default-hover-border-colour: #205375;
--btn-success-font-colour: #fff;
--btn-success-bg-colour: #073655;
--btn-success-border-colour: #0e639c;
--btn-success-hover-font-colour: #fff;
--btn-success-hover-bg-colour: #0e639c;
--btn-success-hover-border-colour: #0e639c;
/* Highlighter colours */
--hl1: #264f78;
--hl2: #675351;
--hl3: #ffb6b6;
--hl4: #fcf8e3;
--hl5: #8de768;
/* Scrollbar */
--scrollbar-track: #1e1e1e;
--scrollbar-thumb: #424242;
--scrollbar-hover: #4e4e4e;
/* Misc. */
--drop-file-border-colour: #0e639c;
--popover-background: #444;
--popover-border-colour: #555;
--code-background: #0e639c;
--code-font-colour: #fff;
}

View File

@@ -0,0 +1,73 @@
/**
* General styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
body {
font-family: var(--primary-font-family);
font-size: var(--primary-font-size);
line-height: var(--primary-line-height);
color: var(--primary-font-colour);
background-color: var(--primary-background-colour);
}
.subtext {
font-style: italic;
font-size: var(--subtext-font-size);
color: var(--subtext-font-colour);
}
.word-wrap {
white-space: pre !important;
word-wrap: normal !important;
overflow-x: scroll !important;
}
.clearfix {
clear: both;
height: 0;
}
.blur {
color: transparent !important;
text-shadow: rgba(0, 0, 0, 0.95) 0 0 10px !important;
}
.no-select {
user-select: none;
}
.konami {
transform: rotate(180deg);
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background-color: var(--scrollbar-track);
}
::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb);
}
::-webkit-scrollbar-thumb:hover {
background-color: var(--scrollbar-hover);
}
::-webkit-scrollbar-corner {
background-color: var(--scrollbar-track);
}
/* Highlighters */
.hl1 { background-color: var(--hl1); }
.hl2 { background-color: var(--hl2); }
.hl3 { background-color: var(--hl3); } /* Half-Life 3 confirmed :O */
.hl4 { background-color: var(--hl4); }
.hl5 { background-color: var(--hl5); }

View File

@@ -0,0 +1,223 @@
/**
* Overrides for vendor styles
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
/* Bootstrap */
button,
a:focus {
outline: none;
}
.btn-default {
color: var(--btn-default-font-colour);
background-color: var(--btn-default-bg-colour);
border-color: var(--btn-default-border-colour);
}
.btn-default:hover,
.btn-default:active,
.btn-default:hover:active,
.open>.dropdown-toggle.btn-default {
color: var(--btn-default-hover-font-colour);
background-color: var(--btn-default-hover-bg-colour);
border-color: var(--btn-default-hover-border-colour);
}
.btn-default:focus,
.open>.dropdown-toggle.btn-default:hover,
.open>.dropdown-toggle.btn-default:focus {
color: var(--btn-default-font-colour);
background-color: var(--btn-default-bg-colour);
border-color: var(--btn-default-hover-border-colour);
}
.btn-default[disabled]:hover {
background-color: var(--primary-background-colour);
border-color: var(--primary-border-colour);
}
.btn-success {
color: var(--btn-success-font-colour);
background-color: var(--btn-success-bg-colour);
border-color: var(--btn-success-border-colour);
}
.btn-success:hover,
.btn-success:active,
.btn-success:focus,
.btn-success:hover:active {
color: var(--btn-success-hover-font-colour);
background-color: var(--btn-success-hover-bg-colour);
border-color: var(--btn-success-hover-border-colour);
}
.btn,
.btn-lg,
.nav-tabs>li>a,
.form-control,
.popover,
.alert,
.modal-content,
.tooltip-inner,
.dropdown-menu {
border-radius: 0 !important;
}
.btn.dropdown-toggle {
height: 34px;
}
input[type="search"] {
-webkit-appearance: searchfield;
box-shadow: none;
}
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: searchfield-cancel-button;
}
.modal {
overflow-y: auto;
}
.modal-content {
background-color: var(--primary-background-colour);
}
.modal-header,
.modal-footer {
border-color: var(--primary-border-colour);
}
.form-control {
background-color: transparent;
border-color: var(--primary-border-colour);
color: var(--primary-font-colour);
}
code {
border: 0;
white-space: pre-wrap;
font-family: var(--fixed-width-font-family);
background-color: var(--code-background);
color: var(--code-font-colour);
}
pre {
border-radius: 0 !important;
background-color: var(--secondary-background-colour);
border-color: var(--secondary-border-colour);
color: var(--fixed-width-font-colour);
}
blockquote {
font-size: inherit;
border-left-color: var(--secondary-border-colour);
}
blockquote a {
cursor: pointer;
}
optgroup {
font-weight: bold;
}
.panel-body:before,
.panel-body:after {
content: "";
}
.table-nonfluid {
width: auto !important;
}
.popover {
background-color: var(--popover-background);
border-color: var(--popover-border-colour);
}
.popover.right>.arrow {
border-right-color: var(--popover-border-colour);
}
.popover.right>.arrow:after {
border-right-color: var(--popover-background);
}
.nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover {
background-color: var(--primary-background-colour);
border-color: var(--primary-border-colour);
border-bottom-color: transparent;
color: var(--primary-font-colour);
}
.nav-tabs {
border-color: var(--primary-border-colour);
}
.nav>li>a:focus, .nav>li>a:hover {
background-color: var(--secondary-border-colour);
}
.nav-tabs>li>a:hover {
border-color: var(--secondary-border-colour) var(--secondary-border-colour) var(--primary-border-colour);
}
.dropdown-menu {
background-color: var(--primary-background-colour);
}
.dropdown-menu>li>a {
color: var(--primary-font-colour);
}
.dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover {
background-color: var(--secondary-background-colour);
color: var(--primary-font-colour);
}
/* Bootstrap-switch */
.bootstrap-switch,
.bootstrap-switch-container,
.bootstrap-switch-handle-on,
.bootstrap-switch-handle-off,
.bootstrap-switch-label {
border-radius: 0 !important;
}
.bootstrap-switch .bootstrap-switch-label {
background-color: transparent;
}
.bootstrap-switch {
border-color: var(--primary-border-colour);
}
/* Sortable */
.sortable-ghost {
opacity: 0.6;
}
/* Bootstrap Colorpicker */
.colorpicker-element {
float: left;
margin-right: 15px;
}
.colorpicker-color,
.colorpicker-color div {
height: 100px;
}

View File

@@ -19,7 +19,7 @@
@import "~bootstrap/less/scaffolding.less";
@import "~bootstrap/less/type.less";
@import "~bootstrap/less/code.less";
// @import "~bootstrap/less/grid.less";
@import "~bootstrap/less/grid.less";
@import "~bootstrap/less/tables.less";
@import "~bootstrap/less/forms.less";
@import "~bootstrap/less/buttons.less";
@@ -55,4 +55,4 @@
// Utility classes
@import "~bootstrap/less/utilities.less";
// @import "~bootstrap/less/responsive-utilities.less";
// @import "~bootstrap/less/responsive-utilities.less";

View File

@@ -38,7 +38,7 @@ import Chef from "../src/core/Chef.js";
TestRegister.prototype.runTests = function() {
return Promise.all(
this.tests.map(function(test, i) {
let chef = new Chef();
const chef = new Chef();
return chef.bake(
test.input,
@@ -48,7 +48,7 @@ import Chef from "../src/core/Chef.js";
false
)
.then(function(result) {
let ret = {
const ret = {
test: test,
status: null,
output: null,

View File

@@ -13,16 +13,20 @@ import "babel-polyfill";
import TestRegister from "./TestRegister.js";
import "./tests/operations/Base58.js";
import "./tests/operations/ByteRepr.js";
import "./tests/operations/CharEnc.js";
import "./tests/operations/Code.js";
import "./tests/operations/Compress.js";
import "./tests/operations/DateTime.js";
import "./tests/operations/FlowControl.js";
import "./tests/operations/Image.js";
import "./tests/operations/MorseCode.js";
import "./tests/operations/StrUtils.js";
import "./tests/operations/SeqUtils.js";
let allTestsPassing = true,
testStatusCounts = {
total: 0,
};
let allTestsPassing = true;
const testStatusCounts = {
total: 0,
};
/**
@@ -32,7 +36,7 @@ let allTestsPassing = true,
* @returns {string}
*/
function statusToIcon(status) {
let icons = {
const icons = {
erroring: "🔥",
failing: "❌",
passing: "✔️️",
@@ -48,7 +52,7 @@ function statusToIcon(status) {
*/
function handleTestResult(testResult) {
allTestsPassing = allTestsPassing && testResult.status === "passing";
let newCount = (testStatusCounts[testResult.status] || 0) + 1;
const newCount = (testStatusCounts[testResult.status] || 0) + 1;
testStatusCounts[testResult.status] = newCount;
testStatusCounts.total += 1;
@@ -74,7 +78,7 @@ function handleTestResult(testResult) {
setTimeout(function() {
console.log("Tests took longer than 10 seconds to run, returning.");
process.exit(1);
}, 1 * 1000);
}, 10 * 1000);
TestRegister.runTests()
@@ -83,8 +87,8 @@ TestRegister.runTests()
console.log("\n");
for (let testStatus in testStatusCounts) {
let count = testStatusCounts[testStatus];
for (const testStatus in testStatusCounts) {
const count = testStatusCounts[testStatus];
if (count > 0) {
console.log(testStatus.toUpperCase(), count);
}

View File

@@ -0,0 +1,90 @@
/**
* CharEnc tests.
*
* @author tlwr [toby@toby.codes]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "Encode text, Decode text: nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
"op": "Encode text",
"args": ["UTF-8 (65001)"]
},
{
"op": "Decode text",
"args": ["UTF-8 (65001)"]
},
],
},
{
name: "Encode text, Decode text: hello",
input: "hello",
expectedOutput: "hello",
recipeConfig: [
{
"op": "Encode text",
"args": ["UTF-8 (65001)"]
},
{
"op": "Decode text",
"args": ["UTF-8 (65001)"]
},
],
},
{
name: "Encode text (EBCDIC): hello",
input: "hello",
expectedOutput: "88 85 93 93 96",
recipeConfig: [
{
"op": "Encode text",
"args": ["IBM EBCDIC International (500)"]
},
{
"op": "To Hex",
"args": ["Space"]
},
],
},
{
name: "Decode text (EBCDIC): 88 85 93 93 96",
input: "88 85 93 93 96",
expectedOutput: "hello",
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "Decode text",
"args": ["IBM EBCDIC International (500)"]
},
],
},
{
name: "Generate Base64 Windows Powershell",
input: "ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==",
expectedOutput: "dir \"c:\\program files\" ",
recipeConfig: [
{
"op": "From Base64",
"args": ["A-Za-z0-9+/=", true]
},
{
"op": "Decode text",
"args": ["UTF16LE (1200)"]
},
{
"op": "Encode text",
"args": ["UTF-8 (65001)"]
},
],
},
]);

View File

@@ -0,0 +1,34 @@
/**
* DateTime tests.
*
* @author bwhitn [brian.m.whitney@outlook.com]
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "Filetime to Unix",
input: "129207366395297693",
expectedOutput: "1276263039529769300",
recipeConfig: [
{
op: "Windows Filetime to UNIX Timestamp",
args: ["Nanoseconds (ns)"],
},
],
},
{
name: "Unix to Filetime",
input: "1276263039529769300",
expectedOutput: "129207366395297693",
recipeConfig: [
{
op: "UNIX Timestamp to Windows Filetime",
args: ["Nanoseconds (ns)"],
},
],
},
]);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
/**
* SeqUtils tests.
*
* @author Chris van Marle
* @copyright Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "SeqUtils - Numeric sort photos",
input: "Photo-1.jpg\nPhoto-4.jpg\nPhoto-2.jpg\nPhoto-3.jpg\n",
expectedOutput: "Photo-1.jpg\nPhoto-2.jpg\nPhoto-3.jpg\nPhoto-4.jpg\n",
recipeConfig: [
{
"op": "Sort",
"args": ["Line feed", false, "Numeric"]
}
],
},
{
name: "SeqUtils - Numeric sort CVE IDs",
input: "CVE-2017-1234,CVE-2017-9999,CVE-2017-10000,CVE-2017-10001,CVE-2017-12345,CVE-2016-1234,CVE-2016-4321,CVE-2016-10000,CVE-2016-9999,CVE-2016-10001",
expectedOutput: "CVE-2017-12345,CVE-2017-10001,CVE-2017-10000,CVE-2017-9999,CVE-2017-1234,CVE-2016-10001,CVE-2016-10000,CVE-2016-9999,CVE-2016-4321,CVE-2016-1234",
recipeConfig: [
{
"op": "Sort",
"args": ["Comma", true, "Numeric"]
}
],
},
]);