Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1fe0b944f | ||
|
|
c1e40dd109 | ||
|
|
73823e3eb9 | ||
|
|
bf833991bf | ||
|
|
615357c977 | ||
|
|
19f23127b9 | ||
|
|
2ea6d9437f | ||
|
|
833b6d67a6 | ||
|
|
04c1adc5f0 | ||
|
|
8e8f6a0284 | ||
|
|
68bf1d123e | ||
|
|
2c03689195 | ||
|
|
45f41b1140 | ||
|
|
8fa6f3f45c | ||
|
|
78a842deb7 | ||
|
|
3657ff4f79 | ||
|
|
d4d12c3db0 | ||
|
|
1b628ac213 | ||
|
|
5fcc259efb | ||
|
|
9545205f19 | ||
|
|
4f403d4450 | ||
|
|
f2d8f930fb | ||
|
|
4a86340d50 | ||
|
|
f8e9e9ba85 | ||
|
|
934ed1af09 | ||
|
|
0fc2a219a7 | ||
|
|
aa5939c051 | ||
|
|
9c5f06101e | ||
|
|
2a7c0252a0 | ||
|
|
414726ecd4 | ||
|
|
fdc8a15595 | ||
|
|
d012fd3a65 | ||
|
|
a5ed824674 | ||
|
|
d6705c682f | ||
|
|
33b606d48f | ||
|
|
cc44be7ef9 | ||
|
|
e0eb972a54 | ||
|
|
19c54a99cd | ||
|
|
9d60ec22ee | ||
|
|
cb4eeccfd3 | ||
|
|
62e50caa99 | ||
|
|
0192566d19 | ||
|
|
8a8b70f2ab | ||
|
|
af311001cf | ||
|
|
040229418e | ||
|
|
c259963542 | ||
|
|
ca75f7fa0b | ||
|
|
4b22a409e7 | ||
|
|
55806db00f | ||
|
|
83c757ebd4 | ||
|
|
a19b02aa8c | ||
|
|
cf1ba60a10 | ||
|
|
2a4c9afdf2 | ||
|
|
ab76933158 | ||
|
|
d4d7bcab7a | ||
|
|
6698a2ac13 | ||
|
|
9161cc693d | ||
|
|
3186335f47 | ||
|
|
fadd7158ed |
@@ -22,7 +22,7 @@ deploy:
|
|||||||
repo: gchq/CyberChef
|
repo: gchq/CyberChef
|
||||||
branch: master
|
branch: master
|
||||||
- provider: releases
|
- provider: releases
|
||||||
skip_cleaup: true
|
skip_cleanup: true
|
||||||
api_key:
|
api_key:
|
||||||
secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA="
|
secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA="
|
||||||
file:
|
file:
|
||||||
|
|||||||
14
README.md
@@ -88,10 +88,10 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
|
|||||||
|
|
||||||
|
|
||||||
[1]: https://gchq.github.io/CyberChef
|
[1]: https://gchq.github.io/CyberChef
|
||||||
[2]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
|
[2]: https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
|
||||||
[3]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA
|
[3]: https://gchq.github.io/CyberChef/#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA
|
||||||
[4]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
|
[4]: https://gchq.github.io/CyberChef/#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
|
||||||
[5]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
|
[5]: https://gchq.github.io/CyberChef/#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
|
||||||
[6]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
|
[6]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
|
||||||
[7]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
||||||
[8]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22XOR%22%2C%22args%22%3A%5B%7B%22option%22%3A%22Hex%22%2C%22string%22%3A%223a%22%7D%2Cfalse%2Cfalse%5D%7D%2C%7B%22op%22%3A%22To%20Hexdump%22%2C%22args%22%3A%5B%2216%22%2Cfalse%2Cfalse%5D%7D%5D&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
[8]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||||
|
|||||||
1736
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "5.13.1",
|
"version": "5.19.3",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
@@ -82,6 +82,7 @@
|
|||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"moment": "^2.17.1",
|
"moment": "^2.17.1",
|
||||||
"moment-timezone": "^0.5.11",
|
"moment-timezone": "^0.5.11",
|
||||||
|
"otp": "^0.1.3",
|
||||||
"sladex-blowfish": "^0.8.1",
|
"sladex-blowfish": "^0.8.1",
|
||||||
"sortablejs": "^1.5.1",
|
"sortablejs": "^1.5.1",
|
||||||
"split.js": "^1.2.0",
|
"split.js": "^1.2.0",
|
||||||
|
|||||||
@@ -843,6 +843,139 @@ const Utils = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a URI fragment (#) or query (?) using a minimal amount of percent-encoding.
|
||||||
|
*
|
||||||
|
* RFC 3986 defines legal characters for the fragment and query parts of a URL to be as follows:
|
||||||
|
*
|
||||||
|
* fragment = *( pchar / "/" / "?" )
|
||||||
|
* query = *( pchar / "/" / "?" )
|
||||||
|
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||||
|
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||||
|
* pct-encoded = "%" HEXDIG HEXDIG
|
||||||
|
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||||
|
* / "*" / "+" / "," / ";" / "="
|
||||||
|
*
|
||||||
|
* Meaning that the list of characters that need not be percent-encoded are alphanumeric plus:
|
||||||
|
* -._~!$&'()*+,;=:@/?
|
||||||
|
*
|
||||||
|
* & and = are still escaped as they are used to serialise the key-value pairs in CyberChef
|
||||||
|
* fragments. + is also escaped so as to prevent it being decoded to a space.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
encodeURIFragment: function(str) {
|
||||||
|
const LEGAL_CHARS = {
|
||||||
|
"%2D": "-",
|
||||||
|
"%2E": ".",
|
||||||
|
"%5F": "_",
|
||||||
|
"%7E": "~",
|
||||||
|
"%21": "!",
|
||||||
|
"%24": "$",
|
||||||
|
//"%26": "&",
|
||||||
|
"%27": "'",
|
||||||
|
"%28": "(",
|
||||||
|
"%29": ")",
|
||||||
|
"%2A": "*",
|
||||||
|
//"%2B": "+",
|
||||||
|
"%2C": ",",
|
||||||
|
"%3B": ";",
|
||||||
|
//"%3D": "=",
|
||||||
|
"%3A": ":",
|
||||||
|
"%40": "@",
|
||||||
|
"%2F": "/",
|
||||||
|
"%3F": "?"
|
||||||
|
};
|
||||||
|
str = encodeURIComponent(str);
|
||||||
|
|
||||||
|
return str.replace(/%[0-9A-F]{2}/g, function (match) {
|
||||||
|
return LEGAL_CHARS[match] || match;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a "pretty" recipe format from a recipeConfig object.
|
||||||
|
*
|
||||||
|
* "Pretty" CyberChef recipe formats are designed to be included in the fragment (#) or query (?)
|
||||||
|
* parts of the URL. They can also be loaded into CyberChef through the 'Load' interface. In order
|
||||||
|
* to make this format as readable as possible, various special characters are used unescaped. This
|
||||||
|
* reduces the amount of percent-encoding included in the URL which is typically difficult to read,
|
||||||
|
* as well as substantially increasing the overall length. These characteristics can be quite
|
||||||
|
* offputting for users.
|
||||||
|
*
|
||||||
|
* @param {Object[]} recipeConfig
|
||||||
|
* @param {boolean} newline - whether to add a newline after each operation
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
generatePrettyRecipe: function(recipeConfig, newline) {
|
||||||
|
let prettyConfig = "",
|
||||||
|
name = "",
|
||||||
|
args = "",
|
||||||
|
disabled = "",
|
||||||
|
bp = "";
|
||||||
|
|
||||||
|
recipeConfig.forEach(op => {
|
||||||
|
name = op.op.replace(/ /g, "_");
|
||||||
|
args = JSON.stringify(op.args)
|
||||||
|
.slice(1, -1) // Remove [ and ] as they are implied
|
||||||
|
// We now need to switch double-quoted (") strings to single-quotes (') as these do not
|
||||||
|
// need to be percent-encoded.
|
||||||
|
.replace(/'/g, "\\'") // Escape single quotes
|
||||||
|
.replace(/\\"/g, '"') // Unescape double quotes
|
||||||
|
.replace(/(^|,|{|:)"/g, "$1'") // Replace opening " with '
|
||||||
|
.replace(/"(,|:|}|$)/g, "'$1"); // Replace closing " with '
|
||||||
|
|
||||||
|
disabled = op.disabled ? "/disabled": "";
|
||||||
|
bp = op.breakpoint ? "/breakpoint" : "";
|
||||||
|
prettyConfig += `${name}(${args}${disabled}${bp})`;
|
||||||
|
if (newline) prettyConfig += "\n";
|
||||||
|
});
|
||||||
|
return prettyConfig;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a recipe string to the JSON representation of the recipe.
|
||||||
|
* Accepts either stringified JSON or bespoke "pretty" recipe format.
|
||||||
|
*
|
||||||
|
* @param {string} recipe
|
||||||
|
* @returns {Object[]}
|
||||||
|
*/
|
||||||
|
parseRecipeConfig: function(recipe) {
|
||||||
|
recipe = recipe.trim();
|
||||||
|
if (recipe.length === 0) return [];
|
||||||
|
if (recipe[0] === "[") return JSON.parse(recipe);
|
||||||
|
|
||||||
|
// Parse bespoke recipe format
|
||||||
|
recipe = recipe.replace(/\n/g, "");
|
||||||
|
let m,
|
||||||
|
recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/])*)(\/[^)]+)?\)/g,
|
||||||
|
recipeConfig = [],
|
||||||
|
args;
|
||||||
|
|
||||||
|
while ((m = recipeRegex.exec(recipe))) {
|
||||||
|
// Translate strings in args back to double-quotes
|
||||||
|
args = m[2]
|
||||||
|
.replace(/"/g, '\\"') // Escape double quotes
|
||||||
|
.replace(/(^|,|{|:)'/g, '$1"') // Replace opening ' with "
|
||||||
|
.replace(/([^\\])'(,|:|}|$)/g, '$1"$2') // Replace closing ' with "
|
||||||
|
.replace(/\\'/g, "'"); // Unescape single quotes
|
||||||
|
args = "[" + args + "]";
|
||||||
|
|
||||||
|
let op = {
|
||||||
|
op: m[1].replace(/_/g, " "),
|
||||||
|
args: JSON.parse(args)
|
||||||
|
};
|
||||||
|
if (m[3] && m[3].indexOf("disabled") > 0) op.disabled = true;
|
||||||
|
if (m[3] && m[3].indexOf("breakpoint") > 0) op.breakpoint = true;
|
||||||
|
recipeConfig.push(op);
|
||||||
|
}
|
||||||
|
return recipeConfig;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expresses a number of milliseconds in a human readable format.
|
* Expresses a number of milliseconds in a human readable format.
|
||||||
*
|
*
|
||||||
@@ -1102,7 +1235,8 @@ const Utils = {
|
|||||||
"Forward slash": /\//g,
|
"Forward slash": /\//g,
|
||||||
"Backslash": /\\/g,
|
"Backslash": /\\/g,
|
||||||
"0x": /0x/g,
|
"0x": /0x/g,
|
||||||
"\\x": /\\x/g
|
"\\x": /\\x/g,
|
||||||
|
"None": /\s+/g // Included here to remove whitespace when there shouldn't be any
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ const Categories = [
|
|||||||
"AND",
|
"AND",
|
||||||
"ADD",
|
"ADD",
|
||||||
"SUB",
|
"SUB",
|
||||||
|
"Bit shift left",
|
||||||
|
"Bit shift right",
|
||||||
"Rotate left",
|
"Rotate left",
|
||||||
"Rotate right",
|
"Rotate right",
|
||||||
"ROT13",
|
"ROT13",
|
||||||
@@ -173,7 +175,6 @@ const Categories = [
|
|||||||
"Tail",
|
"Tail",
|
||||||
"Count occurrences",
|
"Count occurrences",
|
||||||
"Expand alphabet range",
|
"Expand alphabet range",
|
||||||
"Parse escaped string",
|
|
||||||
"Drop bytes",
|
"Drop bytes",
|
||||||
"Take bytes",
|
"Take bytes",
|
||||||
"Pad lines",
|
"Pad lines",
|
||||||
@@ -188,6 +189,8 @@ const Categories = [
|
|||||||
"Parse UNIX file permissions",
|
"Parse UNIX file permissions",
|
||||||
"Swap endianness",
|
"Swap endianness",
|
||||||
"Parse colour code",
|
"Parse colour code",
|
||||||
|
"Escape string",
|
||||||
|
"Unescape string",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -281,6 +284,7 @@ const Categories = [
|
|||||||
"XPath expression",
|
"XPath expression",
|
||||||
"JPath expression",
|
"JPath expression",
|
||||||
"CSS selector",
|
"CSS selector",
|
||||||
|
"Microsoft Script Decoder",
|
||||||
"Strip HTML tags",
|
"Strip HTML tags",
|
||||||
"Diff",
|
"Diff",
|
||||||
"To Snake case",
|
"To Snake case",
|
||||||
@@ -296,6 +300,8 @@ const Categories = [
|
|||||||
"Detect File Type",
|
"Detect File Type",
|
||||||
"Scan for Embedded Files",
|
"Scan for Embedded Files",
|
||||||
"Generate UUID",
|
"Generate UUID",
|
||||||
|
"Generate TOTP",
|
||||||
|
"Generate HOTP",
|
||||||
"Render Image",
|
"Render Image",
|
||||||
"Remove EXIF",
|
"Remove EXIF",
|
||||||
"Extract EXIF",
|
"Extract EXIF",
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ import IP from "../operations/IP.js";
|
|||||||
import JS from "../operations/JS.js";
|
import JS from "../operations/JS.js";
|
||||||
import MAC from "../operations/MAC.js";
|
import MAC from "../operations/MAC.js";
|
||||||
import MorseCode from "../operations/MorseCode.js";
|
import MorseCode from "../operations/MorseCode.js";
|
||||||
|
import MS from "../operations/MS.js";
|
||||||
import NetBIOS from "../operations/NetBIOS.js";
|
import NetBIOS from "../operations/NetBIOS.js";
|
||||||
import Numberwang from "../operations/Numberwang.js";
|
import Numberwang from "../operations/Numberwang.js";
|
||||||
import OS from "../operations/OS.js";
|
import OS from "../operations/OS.js";
|
||||||
|
import OTP from "../operations/OTP.js";
|
||||||
import PublicKey from "../operations/PublicKey.js";
|
import PublicKey from "../operations/PublicKey.js";
|
||||||
import Punycode from "../operations/Punycode.js";
|
import Punycode from "../operations/Punycode.js";
|
||||||
import QuotedPrintable from "../operations/QuotedPrintable.js";
|
import QuotedPrintable from "../operations/QuotedPrintable.js";
|
||||||
@@ -520,6 +522,7 @@ const OperationConfig = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
"To Charcode": {
|
"To Charcode": {
|
||||||
description: "Converts text to its unicode character code equivalent.<br><br>e.g. <code>Γειά σου</code> becomes <code>0393 03b5 03b9 03ac 20 03c3 03bf 03c5</code>",
|
description: "Converts text to its unicode character code equivalent.<br><br>e.g. <code>Γειά σου</code> becomes <code>0393 03b5 03b9 03ac 20 03c3 03bf 03c5</code>",
|
||||||
run: ByteRepr.runToCharcode,
|
run: ByteRepr.runToCharcode,
|
||||||
@@ -1593,7 +1596,7 @@ const OperationConfig = {
|
|||||||
args: []
|
args: []
|
||||||
},
|
},
|
||||||
"Rotate right": {
|
"Rotate right": {
|
||||||
description: "Rotates each byte to the right by the number of bits specified. Currently only supports 8-bit values.",
|
description: "Rotates each byte to the right by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.",
|
||||||
run: Rotate.runRotr,
|
run: Rotate.runRotr,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
highlightReverse: true,
|
highlightReverse: true,
|
||||||
@@ -1601,19 +1604,19 @@ const OperationConfig = {
|
|||||||
outputType: "byteArray",
|
outputType: "byteArray",
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "Number of bits",
|
name: "Amount",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: Rotate.ROTATE_AMOUNT
|
value: Rotate.ROTATE_AMOUNT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Rotate as a whole",
|
name: "Carry through",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: Rotate.ROTATE_WHOLE
|
value: Rotate.ROTATE_CARRY
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Rotate left": {
|
"Rotate left": {
|
||||||
description: "Rotates each byte to the left by the number of bits specified. Currently only supports 8-bit values.",
|
description: "Rotates each byte to the left by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.",
|
||||||
run: Rotate.runRotl,
|
run: Rotate.runRotl,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
highlightReverse: true,
|
highlightReverse: true,
|
||||||
@@ -1621,14 +1624,14 @@ const OperationConfig = {
|
|||||||
outputType: "byteArray",
|
outputType: "byteArray",
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "Number of bits",
|
name: "Amount",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: Rotate.ROTATE_AMOUNT
|
value: Rotate.ROTATE_AMOUNT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Rotate as a whole",
|
name: "Carry through",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: Rotate.ROTATE_WHOLE
|
value: Rotate.ROTATE_CARRY
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -2137,7 +2140,7 @@ const OperationConfig = {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Extract domains": {
|
"Extract domains": {
|
||||||
description: "Extracts domain names with common Top-Level Domains (TLDs).<br>Note that this will not include paths. Use <strong>Extract URLs</strong> to find entire URLs.",
|
description: "Extracts domain names.<br>Note that this will not include paths. Use <strong>Extract URLs</strong> to find entire URLs.",
|
||||||
run: Extract.runDomains,
|
run: Extract.runDomains,
|
||||||
inputType: "string",
|
inputType: "string",
|
||||||
outputType: "string",
|
outputType: "string",
|
||||||
@@ -3204,6 +3207,13 @@ const OperationConfig = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"Microsoft Script Decoder": {
|
||||||
|
description: "Decodes Microsoft Encoded Script files that have been encoded with Microsoft's custom encoding. These are often VBS (Visual Basic Script) files that are encoded and renamed with a '.vbe' extention or JS (JScript) files renamed with a '.jse' extention.<br><br><b>Sample</b><br><br>Encoded:<br><code>#@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&@*eEI@#@&@#@&.jm.raY 214Wv:zms/obI0xEAAA==^#~@</code><br><br>Decoded:<br><code>var my_msg = "Testing <1><2><3>!";\n\nVScript.Echo(my_msg);</code>",
|
||||||
|
run: MS.runDecodeScript,
|
||||||
|
inputType: "string",
|
||||||
|
outputType: "string",
|
||||||
|
args: []
|
||||||
|
},
|
||||||
"Syntax highlighter": {
|
"Syntax highlighter": {
|
||||||
description: "Adds syntax highlighting to a range of source code languages. Note that this will not indent the code. Use one of the 'Beautify' operations for that.",
|
description: "Adds syntax highlighting to a range of source code languages. Note that this will not indent the code. Use one of the 'Beautify' operations for that.",
|
||||||
run: Code.runSyntaxHighlight,
|
run: Code.runSyntaxHighlight,
|
||||||
@@ -3224,13 +3234,6 @@ const OperationConfig = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Parse escaped string": {
|
|
||||||
description: "Replaces escaped characters with the bytes they represent.<br><br>e.g.<code>Hello\\nWorld</code> becomes <code>Hello<br>World</code>",
|
|
||||||
run: StrUtils.runParseEscapedString,
|
|
||||||
inputType: "string",
|
|
||||||
outputType: "string",
|
|
||||||
args: []
|
|
||||||
},
|
|
||||||
"TCP/IP Checksum": {
|
"TCP/IP Checksum": {
|
||||||
description: "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes.",
|
description: "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes.",
|
||||||
run: Checksum.runTCPIP,
|
run: Checksum.runTCPIP,
|
||||||
@@ -3270,6 +3273,20 @@ const OperationConfig = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"Escape string": {
|
||||||
|
description: "Escapes special characters in a string so that they do not cause conflicts. For example, <code>Don't stop me now</code> becomes <code>Don\\'t stop me now</code>.",
|
||||||
|
run: StrUtils.runEscape,
|
||||||
|
inputType: "string",
|
||||||
|
outputType: "string",
|
||||||
|
args: []
|
||||||
|
},
|
||||||
|
"Unescape string": {
|
||||||
|
description: "Unescapes characters in a string that have been escaped. For example, <code>Don\\'t stop me now</code> becomes <code>Don't stop me now</code>.",
|
||||||
|
run: StrUtils.runUnescape,
|
||||||
|
inputType: "string",
|
||||||
|
outputType: "string",
|
||||||
|
args: []
|
||||||
|
},
|
||||||
"To Morse Code": {
|
"To Morse Code": {
|
||||||
description: "Translates alphanumeric characters into International Morse Code.<br><br>Ignores non-Morse characters.<br><br>e.g. <code>SOS</code> becomes <code>... --- ...</code>",
|
description: "Translates alphanumeric characters into International Morse Code.<br><br>Ignores non-Morse characters.<br><br>e.g. <code>SOS</code> becomes <code>... --- ...</code>",
|
||||||
run: MorseCode.runTo,
|
run: MorseCode.runTo,
|
||||||
@@ -3584,6 +3601,102 @@ const OperationConfig = {
|
|||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
|
"Bit shift left": {
|
||||||
|
description: "Shifts the bits in each byte towards the left by the specified amount.",
|
||||||
|
run: BitwiseOp.runBitShiftLeft,
|
||||||
|
inputType: "byteArray",
|
||||||
|
outputType: "byteArray",
|
||||||
|
highlight: true,
|
||||||
|
highlightReverse: true,
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "Amount",
|
||||||
|
type: "number",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Bit shift right": {
|
||||||
|
description: "Shifts the bits in each byte towards the right by the specified amount.<br><br><i>Logical shifts</i> replace the leftmost bits with zeros.<br><i>Arithmetic shifts</i> preserve the most significant bit (MSB) of the original byte keeping the sign the same (positive or negative).",
|
||||||
|
run: BitwiseOp.runBitShiftRight,
|
||||||
|
inputType: "byteArray",
|
||||||
|
outputType: "byteArray",
|
||||||
|
highlight: true,
|
||||||
|
highlightReverse: true,
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "Amount",
|
||||||
|
type: "number",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Type",
|
||||||
|
type: "option",
|
||||||
|
value: BitwiseOp.BIT_SHIFT_TYPE
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Generate TOTP": {
|
||||||
|
description: "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. T0 and T1 are in seconds.",
|
||||||
|
run: OTP.runTOTP,
|
||||||
|
inputType: "byteArray",
|
||||||
|
outputType: "string",
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "Name",
|
||||||
|
type: "string",
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Key size",
|
||||||
|
type: "number",
|
||||||
|
value: 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Code length",
|
||||||
|
type: "number",
|
||||||
|
value: 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Epoch offset (T0)",
|
||||||
|
type: "number",
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Interval (T1)",
|
||||||
|
type: "number",
|
||||||
|
value: 30
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Generate HOTP": {
|
||||||
|
description: "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated.",
|
||||||
|
run: OTP.runHOTP,
|
||||||
|
inputType: "string",
|
||||||
|
outputType: "string",
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "Name",
|
||||||
|
type: "string",
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Key size",
|
||||||
|
type: "number",
|
||||||
|
value: 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Code length",
|
||||||
|
type: "number",
|
||||||
|
value: 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Counter",
|
||||||
|
type: "number",
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OperationConfig;
|
export default OperationConfig;
|
||||||
|
|||||||
@@ -228,6 +228,46 @@ const BitwiseOp = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bit shift left operation.
|
||||||
|
*
|
||||||
|
* @param {byteArray} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {byteArray}
|
||||||
|
*/
|
||||||
|
runBitShiftLeft: function(input, args) {
|
||||||
|
const amount = args[0];
|
||||||
|
|
||||||
|
return input.map(b => {
|
||||||
|
return (b << amount) & 0xff;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
BIT_SHIFT_TYPE: ["Logical shift", "Arithmetic shift"],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bit shift right operation.
|
||||||
|
*
|
||||||
|
* @param {byteArray} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {byteArray}
|
||||||
|
*/
|
||||||
|
runBitShiftRight: function(input, args) {
|
||||||
|
const amount = args[0],
|
||||||
|
type = args[1],
|
||||||
|
mask = type === "Logical shift" ? 0 : 0x80;
|
||||||
|
|
||||||
|
return input.map(b => {
|
||||||
|
return (b >>> amount) ^ (b & mask);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XOR bitwise calculation.
|
* XOR bitwise calculation.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ const ByteRepr = {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highlight to hex
|
* Highlight from hex
|
||||||
*
|
*
|
||||||
* @param {Object[]} pos
|
* @param {Object[]} pos
|
||||||
* @param {number} pos[].start
|
* @param {number} pos[].start
|
||||||
@@ -288,10 +288,8 @@ const ByteRepr = {
|
|||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
runFromBinary: function(input, args) {
|
runFromBinary: function(input, args) {
|
||||||
if (args[0] !== "None") {
|
const delimRegex = Utils.regexRep[args[0] || "Space"];
|
||||||
const delimRegex = Utils.regexRep[args[0] || "Space"];
|
input = input.replace(delimRegex, "");
|
||||||
input = input.replace(delimRegex, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = [];
|
const output = [];
|
||||||
const byteLen = 8;
|
const byteLen = 8;
|
||||||
|
|||||||
@@ -766,8 +766,8 @@ const Cipher = {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
runSubstitute: function (input, args) {
|
runSubstitute: function (input, args) {
|
||||||
let plaintext = Utils.expandAlphRange(args[0]).join(),
|
let plaintext = Utils.expandAlphRange(args[0]).join(""),
|
||||||
ciphertext = Utils.expandAlphRange(args[1]).join(),
|
ciphertext = Utils.expandAlphRange(args[1]).join(""),
|
||||||
output = "",
|
output = "",
|
||||||
index = -1;
|
index = -1;
|
||||||
|
|
||||||
|
|||||||
@@ -170,9 +170,9 @@ const Extract = {
|
|||||||
protocol = "[A-Z]+://",
|
protocol = "[A-Z]+://",
|
||||||
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
||||||
port = ":\\d+",
|
port = ":\\d+",
|
||||||
path = "/[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]*";
|
path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
|
||||||
|
|
||||||
path += "(?:[.!,?]+[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||||
const regex = new RegExp(protocol + hostname + "(?:" + port +
|
const regex = new RegExp(protocol + hostname + "(?:" + port +
|
||||||
")?(?:" + path + ")?", "ig");
|
")?(?:" + path + ")?", "ig");
|
||||||
return Extract._search(input, regex, null, displayTotal);
|
return Extract._search(input, regex, null, displayTotal);
|
||||||
@@ -187,11 +187,8 @@ const Extract = {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
runDomains: function(input, args) {
|
runDomains: function(input, args) {
|
||||||
let displayTotal = args[0],
|
const displayTotal = args[0],
|
||||||
protocol = "https?://",
|
regex = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
||||||
hostname = "[-\\w\\.]+",
|
|
||||||
tld = "\\.(?:com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+",
|
|
||||||
regex = new RegExp("(?:" + protocol + ")?" + hostname + tld, "ig");
|
|
||||||
|
|
||||||
return Extract._search(input, regex, null, displayTotal);
|
return Extract._search(input, regex, null, displayTotal);
|
||||||
},
|
},
|
||||||
|
|||||||
213
src/core/operations/MS.js
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/**
|
||||||
|
* Microsoft operations.
|
||||||
|
*
|
||||||
|
* @author bmwhitn [brian.m.whitney@outlook.com]
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*
|
||||||
|
* @namespace
|
||||||
|
*/
|
||||||
|
const MS = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
D_DECODE: [
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"\x57\x6E\x7B",
|
||||||
|
"\x4A\x4C\x41",
|
||||||
|
"\x0B\x0B\x0B",
|
||||||
|
"\x0C\x0C\x0C",
|
||||||
|
"\x4A\x4C\x41",
|
||||||
|
"\x0E\x0E\x0E",
|
||||||
|
"\x0F\x0F\x0F",
|
||||||
|
"\x10\x10\x10",
|
||||||
|
"\x11\x11\x11",
|
||||||
|
"\x12\x12\x12",
|
||||||
|
"\x13\x13\x13",
|
||||||
|
"\x14\x14\x14",
|
||||||
|
"\x15\x15\x15",
|
||||||
|
"\x16\x16\x16",
|
||||||
|
"\x17\x17\x17",
|
||||||
|
"\x18\x18\x18",
|
||||||
|
"\x19\x19\x19",
|
||||||
|
"\x1A\x1A\x1A",
|
||||||
|
"\x1B\x1B\x1B",
|
||||||
|
"\x1C\x1C\x1C",
|
||||||
|
"\x1D\x1D\x1D",
|
||||||
|
"\x1E\x1E\x1E",
|
||||||
|
"\x1F\x1F\x1F",
|
||||||
|
"\x2E\x2D\x32",
|
||||||
|
"\x47\x75\x30",
|
||||||
|
"\x7A\x52\x21",
|
||||||
|
"\x56\x60\x29",
|
||||||
|
"\x42\x71\x5B",
|
||||||
|
"\x6A\x5E\x38",
|
||||||
|
"\x2F\x49\x33",
|
||||||
|
"\x26\x5C\x3D",
|
||||||
|
"\x49\x62\x58",
|
||||||
|
"\x41\x7D\x3A",
|
||||||
|
"\x34\x29\x35",
|
||||||
|
"\x32\x36\x65",
|
||||||
|
"\x5B\x20\x39",
|
||||||
|
"\x76\x7C\x5C",
|
||||||
|
"\x72\x7A\x56",
|
||||||
|
"\x43\x7F\x73",
|
||||||
|
"\x38\x6B\x66",
|
||||||
|
"\x39\x63\x4E",
|
||||||
|
"\x70\x33\x45",
|
||||||
|
"\x45\x2B\x6B",
|
||||||
|
"\x68\x68\x62",
|
||||||
|
"\x71\x51\x59",
|
||||||
|
"\x4F\x66\x78",
|
||||||
|
"\x09\x76\x5E",
|
||||||
|
"\x62\x31\x7D",
|
||||||
|
"\x44\x64\x4A",
|
||||||
|
"\x23\x54\x6D",
|
||||||
|
"\x75\x43\x71",
|
||||||
|
"\x4A\x4C\x41",
|
||||||
|
"\x7E\x3A\x60",
|
||||||
|
"\x4A\x4C\x41",
|
||||||
|
"\x5E\x7E\x53",
|
||||||
|
"\x40\x4C\x40",
|
||||||
|
"\x77\x45\x42",
|
||||||
|
"\x4A\x2C\x27",
|
||||||
|
"\x61\x2A\x48",
|
||||||
|
"\x5D\x74\x72",
|
||||||
|
"\x22\x27\x75",
|
||||||
|
"\x4B\x37\x31",
|
||||||
|
"\x6F\x44\x37",
|
||||||
|
"\x4E\x79\x4D",
|
||||||
|
"\x3B\x59\x52",
|
||||||
|
"\x4C\x2F\x22",
|
||||||
|
"\x50\x6F\x54",
|
||||||
|
"\x67\x26\x6A",
|
||||||
|
"\x2A\x72\x47",
|
||||||
|
"\x7D\x6A\x64",
|
||||||
|
"\x74\x39\x2D",
|
||||||
|
"\x54\x7B\x20",
|
||||||
|
"\x2B\x3F\x7F",
|
||||||
|
"\x2D\x38\x2E",
|
||||||
|
"\x2C\x77\x4C",
|
||||||
|
"\x30\x67\x5D",
|
||||||
|
"\x6E\x53\x7E",
|
||||||
|
"\x6B\x47\x6C",
|
||||||
|
"\x66\x34\x6F",
|
||||||
|
"\x35\x78\x79",
|
||||||
|
"\x25\x5D\x74",
|
||||||
|
"\x21\x30\x43",
|
||||||
|
"\x64\x23\x26",
|
||||||
|
"\x4D\x5A\x76",
|
||||||
|
"\x52\x5B\x25",
|
||||||
|
"\x63\x6C\x24",
|
||||||
|
"\x3F\x48\x2B",
|
||||||
|
"\x7B\x55\x28",
|
||||||
|
"\x78\x70\x23",
|
||||||
|
"\x29\x69\x41",
|
||||||
|
"\x28\x2E\x34",
|
||||||
|
"\x73\x4C\x09",
|
||||||
|
"\x59\x21\x2A",
|
||||||
|
"\x33\x24\x44",
|
||||||
|
"\x7F\x4E\x3F",
|
||||||
|
"\x6D\x50\x77",
|
||||||
|
"\x55\x09\x3B",
|
||||||
|
"\x53\x56\x55",
|
||||||
|
"\x7C\x73\x69",
|
||||||
|
"\x3A\x35\x61",
|
||||||
|
"\x5F\x61\x63",
|
||||||
|
"\x65\x4B\x50",
|
||||||
|
"\x46\x58\x67",
|
||||||
|
"\x58\x3B\x51",
|
||||||
|
"\x31\x57\x49",
|
||||||
|
"\x69\x22\x4F",
|
||||||
|
"\x6C\x6D\x46",
|
||||||
|
"\x5A\x4D\x68",
|
||||||
|
"\x48\x25\x7C",
|
||||||
|
"\x27\x28\x36",
|
||||||
|
"\x5C\x46\x70",
|
||||||
|
"\x3D\x4A\x6E",
|
||||||
|
"\x24\x32\x7A",
|
||||||
|
"\x79\x41\x2F",
|
||||||
|
"\x37\x3D\x5F",
|
||||||
|
"\x60\x5F\x4B",
|
||||||
|
"\x51\x4F\x5A",
|
||||||
|
"\x20\x42\x2C",
|
||||||
|
"\x36\x65\x57"
|
||||||
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
D_COMBINATION: [
|
||||||
|
0, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 2, 0, 0, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1,
|
||||||
|
0, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 2, 1
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes Microsoft Encoded Script files that can be read and executed by cscript.exe/wscript.exe.
|
||||||
|
* This is a conversion of a Python script that was originally created by Didier Stevens
|
||||||
|
* (https://DidierStevens.com).
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} data
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_decode: function (data) {
|
||||||
|
let result = [];
|
||||||
|
let index = -1;
|
||||||
|
data = data.replace(/@&/g, String.fromCharCode(10))
|
||||||
|
.replace(/@#/g, String.fromCharCode(13))
|
||||||
|
.replace(/@\*/g, ">")
|
||||||
|
.replace(/@!/g, "<")
|
||||||
|
.replace(/@\$/g, "@");
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let byte = data.charCodeAt(i);
|
||||||
|
let char = data.charAt(i);
|
||||||
|
if (byte < 128) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((byte === 9 || byte > 31 && byte < 128) &&
|
||||||
|
byte !== 60 &&
|
||||||
|
byte !== 62 &&
|
||||||
|
byte !== 64) {
|
||||||
|
char = MS.D_DECODE[byte].charAt(MS.D_COMBINATION[index % 64]);
|
||||||
|
}
|
||||||
|
result.push(char);
|
||||||
|
}
|
||||||
|
return result.join("");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Microsoft Script Decoder operation.
|
||||||
|
*
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
runDecodeScript: function (input, args) {
|
||||||
|
let matcher = /#@~\^.{6}==(.+).{6}==\^#~@/;
|
||||||
|
let encodedData = matcher.exec(input);
|
||||||
|
if (encodedData){
|
||||||
|
return MS._decode(encodedData[1]);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MS;
|
||||||
55
src/core/operations/OTP.js
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
import otp from "otp";
|
||||||
|
import Base64 from "./Base64.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One-Time Password operations.
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*
|
||||||
|
* @namespace
|
||||||
|
*/
|
||||||
|
const OTP = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate TOTP operation.
|
||||||
|
*
|
||||||
|
* @param {byteArray} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
runTOTP: function(input, args) {
|
||||||
|
const otpObj = otp({
|
||||||
|
name: args[0],
|
||||||
|
keySize: args[1],
|
||||||
|
codeLength: args[2],
|
||||||
|
secret: Base64.runTo32(input, []),
|
||||||
|
epoch: args[3],
|
||||||
|
timeSlice: args[4]
|
||||||
|
});
|
||||||
|
return `URI: ${otpObj.totpURL}\n\nPassword: ${otpObj.totp()}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate HOTP operation.
|
||||||
|
*
|
||||||
|
* @param {byteArray} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
runHOTP: function(input, args) {
|
||||||
|
const otpObj = otp({
|
||||||
|
name: args[0],
|
||||||
|
keySize: args[1],
|
||||||
|
codeLength: args[2],
|
||||||
|
secret: Base64.runTo32(input, []),
|
||||||
|
});
|
||||||
|
const counter = args[3];
|
||||||
|
return `URI: ${otpObj.hotpURL}\n\nPassword: ${otpObj.hotp(counter)}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OTP;
|
||||||
@@ -20,7 +20,7 @@ const Rotate = {
|
|||||||
* @constant
|
* @constant
|
||||||
* @default
|
* @default
|
||||||
*/
|
*/
|
||||||
ROTATE_WHOLE: false,
|
ROTATE_CARRY: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs rotation operations across the input data.
|
* Runs rotation operations across the input data.
|
||||||
@@ -53,7 +53,7 @@ const Rotate = {
|
|||||||
*/
|
*/
|
||||||
runRotr: function(input, args) {
|
runRotr: function(input, args) {
|
||||||
if (args[1]) {
|
if (args[1]) {
|
||||||
return Rotate._rotrWhole(input, args[0]);
|
return Rotate._rotrCarry(input, args[0]);
|
||||||
} else {
|
} else {
|
||||||
return Rotate._rot(input, args[0], Rotate._rotr);
|
return Rotate._rot(input, args[0], Rotate._rotr);
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ const Rotate = {
|
|||||||
*/
|
*/
|
||||||
runRotl: function(input, args) {
|
runRotl: function(input, args) {
|
||||||
if (args[1]) {
|
if (args[1]) {
|
||||||
return Rotate._rotlWhole(input, args[0]);
|
return Rotate._rotlCarry(input, args[0]);
|
||||||
} else {
|
} else {
|
||||||
return Rotate._rot(input, args[0], Rotate._rotl);
|
return Rotate._rot(input, args[0], Rotate._rotl);
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ const Rotate = {
|
|||||||
* @param {number} amount
|
* @param {number} amount
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
_rotrWhole: function(data, amount) {
|
_rotrCarry: function(data, amount) {
|
||||||
let carryBits = 0,
|
let carryBits = 0,
|
||||||
newByte,
|
newByte,
|
||||||
result = [];
|
result = [];
|
||||||
@@ -223,7 +223,7 @@ const Rotate = {
|
|||||||
* @param {number} amount
|
* @param {number} amount
|
||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
_rotlWhole: function(data, amount) {
|
_rotlCarry: function(data, amount) {
|
||||||
let carryBits = 0,
|
let carryBits = 0,
|
||||||
newByte,
|
newByte,
|
||||||
result = [];
|
result = [];
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ const StrUtils = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "URL",
|
name: "URL",
|
||||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Domain",
|
name: "Domain",
|
||||||
value: "(?:(https?):\\/\\/)?([-\\w.]+)\\.(com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+"
|
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Windows file path",
|
name: "Windows file path",
|
||||||
@@ -450,14 +450,84 @@ const StrUtils = {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse escaped string operation.
|
* @constant
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
ESCAPE_REPLACEMENTS: [
|
||||||
|
{"escaped": "\\\\", "unescaped": "\\"}, // Must be first
|
||||||
|
{"escaped": "\\'", "unescaped": "'"},
|
||||||
|
{"escaped": "\\\"", "unescaped": "\""},
|
||||||
|
{"escaped": "\\n", "unescaped": "\n"},
|
||||||
|
{"escaped": "\\r", "unescaped": "\r"},
|
||||||
|
{"escaped": "\\t", "unescaped": "\t"},
|
||||||
|
{"escaped": "\\b", "unescaped": "\b"},
|
||||||
|
{"escaped": "\\f", "unescaped": "\f"},
|
||||||
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape string operation.
|
||||||
|
*
|
||||||
|
* @author Vel0x [dalemy@microsoft.com]
|
||||||
*
|
*
|
||||||
* @param {string} input
|
* @param {string} input
|
||||||
* @param {Object[]} args
|
* @param {Object[]} args
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* StrUtils.runUnescape("Don't do that", [])
|
||||||
|
* > "Don\'t do that"
|
||||||
|
* StrUtils.runUnescape(`Hello
|
||||||
|
* World`, [])
|
||||||
|
* > "Hello\nWorld"
|
||||||
*/
|
*/
|
||||||
runParseEscapedString: function(input, args) {
|
runEscape: function(input, args) {
|
||||||
return Utils.parseEscapedChars(input);
|
return StrUtils._replaceByKeys(input, "unescaped", "escaped");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescape string operation.
|
||||||
|
*
|
||||||
|
* @author Vel0x [dalemy@microsoft.com]
|
||||||
|
*
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* StrUtils.runUnescape("Don\'t do that", [])
|
||||||
|
* > "Don't do that"
|
||||||
|
* StrUtils.runUnescape("Hello\nWorld", [])
|
||||||
|
* > `Hello
|
||||||
|
* World`
|
||||||
|
*/
|
||||||
|
runUnescape: function(input, args) {
|
||||||
|
return StrUtils._replaceByKeys(input, "escaped", "unescaped");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces all matching tokens in ESCAPE_REPLACEMENTS with the correction. The
|
||||||
|
* ordering is determined by the patternKey and the replacementKey.
|
||||||
|
*
|
||||||
|
* @author Vel0x [dalemy@microsoft.com]
|
||||||
|
* @author Matt C [matt@artemisbot.uk]
|
||||||
|
*
|
||||||
|
* @param {string} input
|
||||||
|
* @param {string} pattern_key
|
||||||
|
* @param {string} replacement_key
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_replaceByKeys: function(input, patternKey, replacementKey) {
|
||||||
|
let output = input;
|
||||||
|
|
||||||
|
// Catch the \\x encoded characters
|
||||||
|
if (patternKey === "escaped") output = Utils.parseEscapedChars(input);
|
||||||
|
|
||||||
|
StrUtils.ESCAPE_REPLACEMENTS.forEach(replacement => {
|
||||||
|
output = output.split(replacement[patternKey]).join(replacement[replacementKey]);
|
||||||
|
});
|
||||||
|
return output;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ App.prototype.loadURIParams = function() {
|
|||||||
// Read in recipe from URI params
|
// Read in recipe from URI params
|
||||||
if (this.uriParams.recipe) {
|
if (this.uriParams.recipe) {
|
||||||
try {
|
try {
|
||||||
const recipeConfig = JSON.parse(this.uriParams.recipe);
|
const recipeConfig = Utils.parseRecipeConfig(this.uriParams.recipe);
|
||||||
this.setRecipeConfig(recipeConfig);
|
this.setRecipeConfig(recipeConfig);
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
} else if (this.uriParams.op) {
|
} else if (this.uriParams.op) {
|
||||||
@@ -482,6 +482,7 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
|
|||||||
// Populate arguments
|
// Populate arguments
|
||||||
const args = item.querySelectorAll(".arg");
|
const args = item.querySelectorAll(".arg");
|
||||||
for (let j = 0; j < args.length; j++) {
|
for (let j = 0; j < args.length; j++) {
|
||||||
|
if (recipeConfig[i].args[j] === undefined) continue;
|
||||||
if (args[j].getAttribute("type") === "checkbox") {
|
if (args[j].getAttribute("type") === "checkbox") {
|
||||||
// checkbox
|
// checkbox
|
||||||
args[j].checked = recipeConfig[i].args[j];
|
args[j].checked = recipeConfig[i].args[j];
|
||||||
@@ -676,7 +677,14 @@ App.prototype.stateChange = function(e) {
|
|||||||
if (recipeConfig.length === 1) {
|
if (recipeConfig.length === 1) {
|
||||||
title = `${recipeConfig[0].op} - ${title}`;
|
title = `${recipeConfig[0].op} - ${title}`;
|
||||||
} else if (recipeConfig.length > 1) {
|
} else if (recipeConfig.length > 1) {
|
||||||
title = `${recipeConfig.length} operations - ${title}`;
|
// See how long the full recipe is
|
||||||
|
const ops = recipeConfig.map(op => op.op).join(", ");
|
||||||
|
if (ops.length < 45) {
|
||||||
|
title = `${ops} - ${title}`;
|
||||||
|
} else {
|
||||||
|
// If it's too long, just use the first one and say how many more there are
|
||||||
|
title = `${recipeConfig[0].op}, ${recipeConfig.length - 1} more - ${title}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
document.title = title;
|
document.title = title;
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
|||||||
const link = baseURL || window.location.protocol + "//" +
|
const link = baseURL || window.location.protocol + "//" +
|
||||||
window.location.host +
|
window.location.host +
|
||||||
window.location.pathname;
|
window.location.pathname;
|
||||||
const recipeStr = JSON.stringify(recipeConfig);
|
const recipeStr = Utils.generatePrettyRecipe(recipeConfig);
|
||||||
const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
|
const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
|
||||||
|
|
||||||
includeRecipe = includeRecipe && (recipeConfig.length > 0);
|
includeRecipe = includeRecipe && (recipeConfig.length > 0);
|
||||||
@@ -184,7 +184,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
|||||||
|
|
||||||
const hash = params
|
const hash = params
|
||||||
.filter(v => v)
|
.filter(v => v)
|
||||||
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
|
.map(([key, value]) => `${key}=${Utils.encodeURIFragment(value)}`)
|
||||||
.join("&");
|
.join("&");
|
||||||
|
|
||||||
if (hash) {
|
if (hash) {
|
||||||
@@ -198,9 +198,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
|||||||
/**
|
/**
|
||||||
* Handler for changes made to the save dialog text area. Re-initialises the save link.
|
* Handler for changes made to the save dialog text area. Re-initialises the save link.
|
||||||
*/
|
*/
|
||||||
ControlsWaiter.prototype.saveTextChange = function() {
|
ControlsWaiter.prototype.saveTextChange = function(e) {
|
||||||
try {
|
try {
|
||||||
const recipeConfig = JSON.parse(document.getElementById("save-text").value);
|
const recipeConfig = Utils.parseRecipeConfig(e.target.value);
|
||||||
this.initialiseSaveLink(recipeConfig);
|
this.initialiseSaveLink(recipeConfig);
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
};
|
};
|
||||||
@@ -211,9 +211,16 @@ ControlsWaiter.prototype.saveTextChange = function() {
|
|||||||
*/
|
*/
|
||||||
ControlsWaiter.prototype.saveClick = function() {
|
ControlsWaiter.prototype.saveClick = function() {
|
||||||
const recipeConfig = this.app.getRecipeConfig();
|
const recipeConfig = this.app.getRecipeConfig();
|
||||||
const recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
|
const recipeStr = JSON.stringify(recipeConfig);
|
||||||
|
|
||||||
document.getElementById("save-text").value = recipeStr;
|
document.getElementById("save-text-chef").value = Utils.generatePrettyRecipe(recipeConfig, true);
|
||||||
|
document.getElementById("save-text-clean").value = JSON.stringify(recipeConfig, null, 2)
|
||||||
|
.replace(/{\n\s+"/g, "{ \"")
|
||||||
|
.replace(/\[\n\s{3,}/g, "[")
|
||||||
|
.replace(/\n\s{3,}]/g, "]")
|
||||||
|
.replace(/\s*\n\s*}/g, " }")
|
||||||
|
.replace(/\n\s{6,}/g, " ");
|
||||||
|
document.getElementById("save-text-compact").value = recipeStr;
|
||||||
|
|
||||||
this.initialiseSaveLink(recipeConfig);
|
this.initialiseSaveLink(recipeConfig);
|
||||||
$("#save-modal").modal();
|
$("#save-modal").modal();
|
||||||
@@ -250,7 +257,7 @@ ControlsWaiter.prototype.loadClick = function() {
|
|||||||
*/
|
*/
|
||||||
ControlsWaiter.prototype.saveButtonClick = function() {
|
ControlsWaiter.prototype.saveButtonClick = function() {
|
||||||
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
|
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
|
||||||
const recipeStr = document.getElementById("save-text").value;
|
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
|
||||||
|
|
||||||
if (!recipeName) {
|
if (!recipeName) {
|
||||||
this.app.alert("Please enter a recipe name", "danger", 2000);
|
this.app.alert("Please enter a recipe name", "danger", 2000);
|
||||||
@@ -339,7 +346,7 @@ ControlsWaiter.prototype.loadNameChange = function(e) {
|
|||||||
*/
|
*/
|
||||||
ControlsWaiter.prototype.loadButtonClick = function() {
|
ControlsWaiter.prototype.loadButtonClick = function() {
|
||||||
try {
|
try {
|
||||||
const recipeConfig = JSON.parse(document.getElementById("load-text").value);
|
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
|
||||||
this.app.setRecipeConfig(recipeConfig);
|
this.app.setRecipeConfig(recipeConfig);
|
||||||
|
|
||||||
$("#rec-list [data-toggle=popover]").popover();
|
$("#rec-list [data-toggle=popover]").popover();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ Manager.prototype.initialiseEventListeners = function() {
|
|||||||
document.getElementById("load-name").addEventListener("change", this.controls.loadNameChange.bind(this.controls));
|
document.getElementById("load-name").addEventListener("change", this.controls.loadNameChange.bind(this.controls));
|
||||||
document.getElementById("load-button").addEventListener("click", this.controls.loadButtonClick.bind(this.controls));
|
document.getElementById("load-button").addEventListener("click", this.controls.loadButtonClick.bind(this.controls));
|
||||||
document.getElementById("support").addEventListener("click", this.controls.supportButtonClick.bind(this.controls));
|
document.getElementById("support").addEventListener("click", this.controls.supportButtonClick.bind(this.controls));
|
||||||
this.addMultiEventListener("#save-text", "keyup paste", this.controls.saveTextChange, this.controls);
|
this.addMultiEventListeners("#save-texts textarea", "keyup paste", this.controls.saveTextChange, this.controls);
|
||||||
|
|
||||||
// Operations
|
// Operations
|
||||||
this.addMultiEventListener("#search", "keyup paste search", this.ops.searchOperations, this.ops);
|
this.addMultiEventListener("#search", "keyup paste search", this.ops.searchOperations, this.ops);
|
||||||
@@ -118,6 +118,7 @@ Manager.prototype.initialiseEventListeners = function() {
|
|||||||
// Recipe
|
// Recipe
|
||||||
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe);
|
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe);
|
||||||
this.addDynamicListener(".arg", "change", this.recipe.ingChange, this.recipe);
|
this.addDynamicListener(".arg", "change", this.recipe.ingChange, this.recipe);
|
||||||
|
this.addDynamicListener(".arg", "input", this.recipe.ingChange, this.recipe);
|
||||||
this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe);
|
this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe);
|
||||||
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
|
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
|
||||||
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);
|
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);
|
||||||
|
|||||||
@@ -295,6 +295,9 @@ RecipeWaiter.prototype.getConfig = function() {
|
|||||||
option: ingList[j].previousSibling.children[0].textContent.slice(0, -1),
|
option: ingList[j].previousSibling.children[0].textContent.slice(0, -1),
|
||||||
string: ingList[j].value
|
string: ingList[j].value
|
||||||
};
|
};
|
||||||
|
} else if (ingList[j].getAttribute("type") === "number") {
|
||||||
|
// number
|
||||||
|
ingredients[j] = parseFloat(ingList[j].value, 10);
|
||||||
} else {
|
} else {
|
||||||
// all others
|
// all others
|
||||||
ingredients[j] = ingList[j].value;
|
ingredients[j] = ingList[j].value;
|
||||||
|
|||||||
@@ -215,7 +215,22 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="save-text">Save your recipe to local storage or copy the following string to load later</label>
|
<label for="save-text">Save your recipe to local storage or copy the following string to load later</label>
|
||||||
<textarea class="form-control" id="save-text" rows="5"></textarea>
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
|
<li role="presentation" class="active"><a href="#chef-format" role="tab" data-toggle="tab">Chef format</a></li>
|
||||||
|
<li role="presentation"><a href="#clean-json" role="tab" data-toggle="tab">Clean JSON</a></li>
|
||||||
|
<li role="presentation"><a href="#compact-json" role="tab" data-toggle="tab">Compact JSON</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="save-texts">
|
||||||
|
<div role="tabpanel" class="tab-pane active" id="chef-format">
|
||||||
|
<textarea class="form-control" id="save-text-chef" rows="5"></textarea>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="clean-json">
|
||||||
|
<textarea class="form-control" id="save-text-clean" rows="5"></textarea>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="compact-json">
|
||||||
|
<textarea class="form-control" id="save-text-compact" rows="5"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="save-name">Recipe name</label>
|
<label for="save-name">Recipe name</label>
|
||||||
@@ -280,6 +295,7 @@
|
|||||||
<select option="theme" id="theme">
|
<select option="theme" id="theme">
|
||||||
<option value="classic">Classic</option>
|
<option value="classic">Classic</option>
|
||||||
<option value="dark">Dark</option>
|
<option value="dark">Dark</option>
|
||||||
|
<option value="geocities">GeoCities</option>
|
||||||
</select>
|
</select>
|
||||||
<label for="theme"> Theme (only supported in modern browsers)</label>
|
<label for="theme"> Theme (only supported in modern browsers)</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -390,12 +406,12 @@
|
|||||||
<div class="collapse" id="faq-examples">
|
<div class="collapse" id="faq-examples">
|
||||||
<p>There are around 200 operations in CyberChef allowing you to carry out simple and complex tasks easily. Here are some examples:</p>
|
<p>There are around 200 operations in CyberChef allowing you to carry out simple and complex tasks easily. Here are some examples:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
|
<li><a href="#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
|
||||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
|
<li><a href="#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
|
||||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
|
<li><a href="#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
|
||||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
|
<li><a href="#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
|
||||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
|
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
|
||||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
|
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@@ -415,7 +431,7 @@
|
|||||||
<div class="collapse" id="faq-fork">
|
<div class="collapse" id="faq-fork">
|
||||||
<p>Maybe you have 10 timestamps that you want to parse or 16 encoded strings that all have the same key.</p>
|
<p>Maybe you have 10 timestamps that you want to parse or 16 encoded strings that all have the same key.</p>
|
||||||
<p>The 'Fork' operation (found in the 'Flow control' category) splits up the input line by line and runs all subsequent operations on each line separately. Each output is then displayed on a separate line. These delimiters can be changed, so if your inputs are separated by commas, you can change the split delimiter to a comma instead.</p>
|
<p>The 'Fork' operation (found in the 'Flow control' category) splits up the input line by line and runs all subsequent operations on each line separately. Each output is then displayed on a separate line. These delimiters can be changed, so if your inputs are separated by commas, you can change the split delimiter to a comma instead.</p>
|
||||||
<p><a href='#recipe=%5B%7B"op"%3A"Fork"%2C"args"%3A%5B"%5C%5Cn"%2C"%5C%5Cn"%5D%7D%2C%7B"op"%3A"From%20UNIX%20Timestamp"%2C"args"%3A%5B"Seconds%20(s)"%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA%3D%3D'>Click here</a> for an example.</p>
|
<p><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Click here</a> for an example.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div role="tabpanel" class="tab-pane" id="report-bug">
|
<div role="tabpanel" class="tab-pane" id="report-bug">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 773 B After Width: | Height: | Size: 672 B |
|
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 654 B |
|
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 762 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 419 B After Width: | Height: | Size: 245 B |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 746 B After Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 590 B After Width: | Height: | Size: 467 B |
|
Before Width: | Height: | Size: 905 B After Width: | Height: | Size: 764 B |
|
Before Width: | Height: | Size: 680 B After Width: | Height: | Size: 584 B |
|
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 351 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 843 B After Width: | Height: | Size: 764 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 320 B |
|
Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 346 B |
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 175 B |
|
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 446 B |
|
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 660 B |
|
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 564 B |
|
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 382 B |
|
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 179 B |
|
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 463 B |
|
Before Width: | Height: | Size: 695 B After Width: | Height: | Size: 680 B |
|
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 542 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 798 B |
|
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 345 B |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 513 B |
|
Before Width: | Height: | Size: 575 B After Width: | Height: | Size: 534 B |
|
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 662 B |
|
Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 627 B |
|
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 445 B |
@@ -9,6 +9,7 @@
|
|||||||
/* Themes */
|
/* Themes */
|
||||||
@import "./themes/_classic.css";
|
@import "./themes/_classic.css";
|
||||||
@import "./themes/_dark.css";
|
@import "./themes/_dark.css";
|
||||||
|
@import "./themes/_geocities.css";
|
||||||
|
|
||||||
/* Utilities */
|
/* Utilities */
|
||||||
@import "./utils/_overrides.css";
|
@import "./utils/_overrides.css";
|
||||||
|
|||||||
@@ -78,7 +78,13 @@
|
|||||||
font-family: var(--primary-font-family);
|
font-family: var(--primary-font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
#save-text,
|
#save-texts textarea,
|
||||||
#load-text {
|
#load-text {
|
||||||
font-family: var(--fixed-width-font-family);
|
font-family: var(--fixed-width-font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#save-texts textarea {
|
||||||
|
border-top: none;
|
||||||
|
box-shadow: none;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|||||||
115
src/web/stylesheets/themes/_geocities.css
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* GeoCities theme definitions
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root.geocities {
|
||||||
|
--primary-font-family: "Comic Sans", "Comic Sans MS", "Chalkboard", "ChalkboardSE-Regular", "Marker Felt", "Purisa", "URW Chancery L", cursive, sans-serif;
|
||||||
|
--primary-font-colour: black;
|
||||||
|
--primary-font-size: 14px;
|
||||||
|
--primary-line-height: 20px;
|
||||||
|
|
||||||
|
--fixed-width-font-family: "Courier New", Courier, monospace;
|
||||||
|
--fixed-width-font-colour: yellow;
|
||||||
|
--fixed-width-font-size: inherit;
|
||||||
|
|
||||||
|
--subtext-font-colour: darkgrey;
|
||||||
|
--subtext-font-size: 13px;
|
||||||
|
|
||||||
|
--primary-background-colour: #00f;
|
||||||
|
--secondary-background-colour: #f00;
|
||||||
|
|
||||||
|
--primary-border-colour: pink;
|
||||||
|
--secondary-border-colour: springgreen;
|
||||||
|
|
||||||
|
--title-colour: red;
|
||||||
|
--title-weight: bold;
|
||||||
|
--title-background-colour: yellow;
|
||||||
|
|
||||||
|
--banner-font-colour: white;
|
||||||
|
--banner-bg-colour: maroon;
|
||||||
|
|
||||||
|
|
||||||
|
/* Operation colours */
|
||||||
|
--op-list-operation-font-colour: blue;
|
||||||
|
--op-list-operation-bg-colour: yellow;
|
||||||
|
--op-list-operation-border-colour: green;
|
||||||
|
|
||||||
|
--rec-list-operation-font-colour: white;
|
||||||
|
--rec-list-operation-bg-colour: purple;
|
||||||
|
--rec-list-operation-border-colour: green;
|
||||||
|
|
||||||
|
--selected-operation-font-color: white;
|
||||||
|
--selected-operation-bg-colour: pink;
|
||||||
|
--selected-operation-border-colour: blue;
|
||||||
|
|
||||||
|
--breakpoint-font-colour: white;
|
||||||
|
--breakpoint-bg-colour: red;
|
||||||
|
--breakpoint-border-colour: blue;
|
||||||
|
|
||||||
|
--disabled-font-colour: grey;
|
||||||
|
--disabled-bg-colour: black;
|
||||||
|
--disabled-border-colour: grey;
|
||||||
|
|
||||||
|
--fc-operation-font-colour: sienna;
|
||||||
|
--fc-operation-bg-colour: pink;
|
||||||
|
--fc-operation-border-colour: yellow;
|
||||||
|
|
||||||
|
--fc-breakpoint-operation-font-colour: darkgrey;
|
||||||
|
--fc-breakpoint-operation-bg-colour: deeppink;
|
||||||
|
--fc-breakpoint-operation-border-colour: yellowgreen;
|
||||||
|
|
||||||
|
|
||||||
|
/* Operation arguments */
|
||||||
|
--arg-title-font-weight: bold;
|
||||||
|
--arg-input-height: 34px;
|
||||||
|
--arg-input-line-height: 20px;
|
||||||
|
--arg-input-font-size: 15px;
|
||||||
|
--arg-font-colour: white;
|
||||||
|
--arg-background: black;
|
||||||
|
--arg-border-colour: lime;
|
||||||
|
--arg-disabled-background: grey;
|
||||||
|
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
--btn-default-font-colour: black;
|
||||||
|
--btn-default-bg-colour: white;
|
||||||
|
--btn-default-border-colour: grey;
|
||||||
|
|
||||||
|
--btn-default-hover-font-colour: black;
|
||||||
|
--btn-default-hover-bg-colour: white;
|
||||||
|
--btn-default-hover-border-colour: grey;
|
||||||
|
|
||||||
|
--btn-success-font-colour: white;
|
||||||
|
--btn-success-bg-colour: lawngreen;
|
||||||
|
--btn-success-border-colour: grey;
|
||||||
|
|
||||||
|
--btn-success-hover-font-colour: white;
|
||||||
|
--btn-success-hover-bg-colour: lime;
|
||||||
|
--btn-success-hover-border-colour: grey;
|
||||||
|
|
||||||
|
|
||||||
|
/* Highlighter colours */
|
||||||
|
--hl1: #fff000;
|
||||||
|
--hl2: #95dfff;
|
||||||
|
--hl3: #ffb6b6;
|
||||||
|
--hl4: #fcf8e3;
|
||||||
|
--hl5: #8de768;
|
||||||
|
|
||||||
|
|
||||||
|
/* Scrollbar */
|
||||||
|
--scrollbar-track: lightsteelblue;
|
||||||
|
--scrollbar-thumb: lightslategrey;
|
||||||
|
--scrollbar-hover: grey;
|
||||||
|
|
||||||
|
|
||||||
|
/* Misc. */
|
||||||
|
--drop-file-border-colour: purple;
|
||||||
|
--popover-background: turquoise;
|
||||||
|
--popover-border-colour: violet;
|
||||||
|
--code-background: black;
|
||||||
|
--code-font-colour: limegreen;
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import "babel-polyfill";
|
|||||||
import TestRegister from "./TestRegister.js";
|
import TestRegister from "./TestRegister.js";
|
||||||
import "./tests/operations/Base58.js";
|
import "./tests/operations/Base58.js";
|
||||||
import "./tests/operations/BCD.js";
|
import "./tests/operations/BCD.js";
|
||||||
|
import "./tests/operations/BitwiseOp.js";
|
||||||
import "./tests/operations/ByteRepr.js";
|
import "./tests/operations/ByteRepr.js";
|
||||||
import "./tests/operations/CharEnc.js";
|
import "./tests/operations/CharEnc.js";
|
||||||
import "./tests/operations/Cipher.js";
|
import "./tests/operations/Cipher.js";
|
||||||
@@ -22,9 +23,11 @@ import "./tests/operations/DateTime.js";
|
|||||||
import "./tests/operations/FlowControl.js";
|
import "./tests/operations/FlowControl.js";
|
||||||
import "./tests/operations/Image.js";
|
import "./tests/operations/Image.js";
|
||||||
import "./tests/operations/MorseCode.js";
|
import "./tests/operations/MorseCode.js";
|
||||||
|
import "./tests/operations/MS.js";
|
||||||
import "./tests/operations/StrUtils.js";
|
import "./tests/operations/StrUtils.js";
|
||||||
import "./tests/operations/SeqUtils.js";
|
import "./tests/operations/SeqUtils.js";
|
||||||
|
|
||||||
|
|
||||||
let allTestsPassing = true;
|
let allTestsPassing = true;
|
||||||
const testStatusCounts = {
|
const testStatusCounts = {
|
||||||
total: 0,
|
total: 0,
|
||||||
|
|||||||
50
test/tests/operations/BitwiseOp.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* BitwiseOp tests
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../TestRegister.js";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Bit shift left",
|
||||||
|
input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100",
|
||||||
|
expectedOutput: "10101010 01010100 11111110 00000000 11100000 00011110 01100110 10011000",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "From Binary",
|
||||||
|
"args": ["Space"] },
|
||||||
|
{ "op": "Bit shift left",
|
||||||
|
"args": [1] },
|
||||||
|
{ "op": "To Binary",
|
||||||
|
"args": ["Space"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bit shift right: Logical shift",
|
||||||
|
input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100",
|
||||||
|
expectedOutput: "00101010 01010101 01111111 00000000 01111000 00000111 00011001 01100110",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "From Binary",
|
||||||
|
"args": ["Space"] },
|
||||||
|
{ "op": "Bit shift right",
|
||||||
|
"args": [1, "Logical shift"] },
|
||||||
|
{ "op": "To Binary",
|
||||||
|
"args": ["Space"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bit shift right: Arithmetic shift",
|
||||||
|
input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100",
|
||||||
|
expectedOutput: "00101010 11010101 11111111 00000000 11111000 00000111 00011001 11100110",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "From Binary",
|
||||||
|
"args": ["Space"] },
|
||||||
|
{ "op": "Bit shift right",
|
||||||
|
"args": [1, "Arithmetic shift"] },
|
||||||
|
{ "op": "To Binary",
|
||||||
|
"args": ["Space"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
||||||
22
test/tests/operations/MS.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* MS tests.
|
||||||
|
*
|
||||||
|
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../TestRegister.js";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Microsoft Script Decoder",
|
||||||
|
input: "#@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&@*eEI@#@&@#@&\x7fjm.raY 214Wv:zms/obI0xEAAA==^#~@",
|
||||||
|
expectedOutput: "var my_msg = \"Testing <1><2><3>!\";\r\n\r\nWScript.Echo(my_msg);",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Microsoft Script Decoder",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
@@ -232,4 +232,48 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Escape String: quotes",
|
||||||
|
input: "Hello \"World\"! Escape 'these' quotes.",
|
||||||
|
expectedOutput: "Hello \\\"World\\\"! Escape \\'these\\' quotes.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Escape string",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Escape String: special characters",
|
||||||
|
input: "Fizz & buzz\n\ttabbed newline\rcarriage returned line\nbackspace character: \"\" form feed character: \"\"",
|
||||||
|
expectedOutput: "Fizz & buzz\\n\\ttabbed newline\\rcarriage returned line\\nbackspace character: \\\"\\b\\\" form feed character: \\\"\\f\\\"",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Escape string",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unescape String: quotes",
|
||||||
|
input: "Hello \\\"World\\\"! Escape \\'these\\' quotes.",
|
||||||
|
expectedOutput: "Hello \"World\"! Escape 'these' quotes.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Unescape string",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unescape String: special characters",
|
||||||
|
input: "Fizz \x26 buzz\\n\\ttabbed newline\\rcarriage returned line\\nbackspace character: \\\"\\b\\\" form feed character: \\\"\\f\\\"",
|
||||||
|
expectedOutput: "Fizz & buzz\n\ttabbed newline\rcarriage returned line\nbackspace character: \"\" form feed character: \"\"",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Unescape string",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||