mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
608 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
078849041f | ||
|
|
1c711f5e03 | ||
|
|
614af0602a | ||
|
|
e55cfe0bc1 | ||
|
|
2b703b2b9b | ||
|
|
170feaaff2 | ||
|
|
870c2b6d8b | ||
|
|
eee8b7db56 | ||
|
|
3c669a075e | ||
|
|
f528930ad2 | ||
|
|
231322eddf | ||
|
|
8e6763c165 | ||
|
|
f091918575 | ||
|
|
bb077c87b3 | ||
|
|
fe8f8bc712 | ||
|
|
abe87830cd | ||
|
|
7490651a06 | ||
|
|
6220128a74 | ||
|
|
ec205f4f7d | ||
|
|
512487328d | ||
|
|
6fbb2f26d1 | ||
|
|
c91bfeaa81 | ||
|
|
aa2b3b2843 | ||
|
|
90d8be48d4 | ||
|
|
aa6890432c | ||
|
|
192d0ed8a6 | ||
|
|
fff188eb30 | ||
|
|
71067939e3 | ||
|
|
b07c014b48 | ||
|
|
f2c073798b | ||
|
|
4cc38db895 | ||
|
|
2762319dbb | ||
|
|
8e5d43dfa8 | ||
|
|
82ad8cc444 | ||
|
|
1d6bf39548 | ||
|
|
ec02b7deda | ||
|
|
fa938f832f | ||
|
|
6f59d9217c | ||
|
|
7176e5ca6e | ||
|
|
429829471f | ||
|
|
4760e539b7 | ||
|
|
f53e7ad617 | ||
|
|
28c83fa921 | ||
|
|
4588cd151c | ||
|
|
2d9f87abef | ||
|
|
491e6f5f5f | ||
|
|
ab7c05284d | ||
|
|
0586fa0e01 | ||
|
|
53eba2337c | ||
|
|
283d3e1e7b | ||
|
|
7992a540ae | ||
|
|
3f3e7a78eb | ||
|
|
8d3d39acd3 | ||
|
|
7b20aba2ff | ||
|
|
bbfb732d8f | ||
|
|
566adbcda5 | ||
|
|
1bff490fa4 | ||
|
|
d38375a08c | ||
|
|
56551712d6 | ||
|
|
c241d2f90b | ||
|
|
0ba28dc891 | ||
|
|
ac9af6d2ba | ||
|
|
90d9e087f7 | ||
|
|
50b24d9a56 | ||
|
|
10f42e9a7f | ||
|
|
987bd303a0 | ||
|
|
a3f58fb831 | ||
|
|
f52f5a0edb | ||
|
|
b58942f69a | ||
|
|
68e52d1645 | ||
|
|
9fc7e6cd98 | ||
|
|
87f346d88c | ||
|
|
e423ff2639 | ||
|
|
fa6905ef00 | ||
|
|
8684bc0158 | ||
|
|
a96eb450de | ||
|
|
d079420d46 | ||
|
|
124ff83206 | ||
|
|
2c9e67ad1d | ||
|
|
75a554e215 | ||
|
|
849d41ee56 | ||
|
|
e18ec5f2b2 | ||
|
|
50e4daeaf2 | ||
|
|
f7f07f2cb5 | ||
|
|
e2161ec934 | ||
|
|
1e4d2ba90d | ||
|
|
caf794b01d | ||
|
|
e81122739b | ||
|
|
a0aa363203 | ||
|
|
bad0816115 | ||
|
|
53a3f3d452 | ||
|
|
ff94172b3c | ||
|
|
af71ca6a25 | ||
|
|
0e7989111f | ||
|
|
8ee3742216 | ||
|
|
194eb184f3 | ||
|
|
98f59ace3a | ||
|
|
c1fb6d9776 | ||
|
|
fc7d2c2f52 | ||
|
|
0fea84ed7a | ||
|
|
5e7f8e3976 | ||
|
|
fe4c5f5899 | ||
|
|
d47b7b9242 | ||
|
|
09b6661e35 | ||
|
|
57b1667b69 | ||
|
|
5e9380b550 | ||
|
|
fc8a0480fb | ||
|
|
317327d097 | ||
|
|
ecd0ac2521 | ||
|
|
f9eaf67db2 | ||
|
|
99e0c8d5e3 | ||
|
|
7a951d86d8 | ||
|
|
d9dfaec84c | ||
|
|
80719ae368 | ||
|
|
9407809356 | ||
|
|
f7e958e7a1 | ||
|
|
5d75f8636a | ||
|
|
22aaeb3ff5 | ||
|
|
8c29ce95e2 | ||
|
|
049fc66785 | ||
|
|
029c55fd53 | ||
|
|
7b433b9bd6 | ||
|
|
5ec210990b | ||
|
|
a7a0cacddb | ||
|
|
e61ced93d6 | ||
|
|
df122da1d2 | ||
|
|
31d90939fe | ||
|
|
67b0fdf73e | ||
|
|
12fc8c22dd | ||
|
|
4e00ac9300 | ||
|
|
4ca2a30249 | ||
|
|
08a31523b2 | ||
|
|
4b29a61065 | ||
|
|
06c83cb44c | ||
|
|
75a5fc0ddc | ||
|
|
946d165aa0 | ||
|
|
224d79be05 | ||
|
|
435ed587a5 | ||
|
|
81082ea001 | ||
|
|
1d3229a729 | ||
|
|
a9e60d3450 | ||
|
|
f9ddee7d80 | ||
|
|
ef0d3b73b0 | ||
|
|
5368040e83 | ||
|
|
b9b4147c2f | ||
|
|
caae0ec5ca | ||
|
|
2b47631f4d | ||
|
|
298e8e8491 | ||
|
|
6ad3728314 | ||
|
|
772f9a806e | ||
|
|
ae8d1f2178 | ||
|
|
9bc6c46dc3 | ||
|
|
b48e940f2d | ||
|
|
e500cfae75 | ||
|
|
f01c0adee2 | ||
|
|
021cae1a95 | ||
|
|
f66cd8f983 | ||
|
|
fe8049199a | ||
|
|
cfb6dd9471 | ||
|
|
7abda44fd6 | ||
|
|
47ce240e70 | ||
|
|
c23d7fd79c | ||
|
|
555fed2d51 | ||
|
|
7a2f68e14a | ||
|
|
8fd08cb2bf | ||
|
|
7a2b75c861 | ||
|
|
00074f914f | ||
|
|
ea352e05f0 | ||
|
|
305956cbe3 | ||
|
|
5399d27875 | ||
|
|
29047c2481 | ||
|
|
50a32e90d9 | ||
|
|
f596fe8404 | ||
|
|
4be7f89fd8 | ||
|
|
8b30fdf7f1 | ||
|
|
2cd4256ece | ||
|
|
c6a65c4686 | ||
|
|
1553b5f54b | ||
|
|
2ddd2e0a60 | ||
|
|
d924ede9cf | ||
|
|
638e03856b | ||
|
|
8afd77b32d | ||
|
|
599fefb39b | ||
|
|
ec7294d734 | ||
|
|
c0d03db9e8 | ||
|
|
0365f96678 | ||
|
|
40d8b42478 | ||
|
|
e5a32ac57d | ||
|
|
390d5927a4 | ||
|
|
b61a1b4edb | ||
|
|
1d78578fc2 | ||
|
|
0e3751407b | ||
|
|
7feafbf0e7 | ||
|
|
cfd9b16f8b | ||
|
|
1bbc73ec50 | ||
|
|
dc9ba583d5 | ||
|
|
6b5ff83927 | ||
|
|
a5ffa406a8 | ||
|
|
6234afc119 | ||
|
|
ef2ead262b | ||
|
|
cd5265fad4 | ||
|
|
0c4ef1cc94 | ||
|
|
4fee6cd5d8 | ||
|
|
da63420d67 | ||
|
|
72c79c684b | ||
|
|
a997ec0695 | ||
|
|
e3be2a9531 | ||
|
|
bd1790b692 | ||
|
|
90763dee6a | ||
|
|
16879a9190 | ||
|
|
2afd23fcf7 | ||
|
|
39fd0f9b34 | ||
|
|
ee57a92daa | ||
|
|
ab7cc878c3 | ||
|
|
877ab57f0a | ||
|
|
e2ac297102 | ||
|
|
b86dceb3c6 | ||
|
|
35c9dca955 | ||
|
|
d54d7011d9 | ||
|
|
392652ed8e | ||
|
|
7557e1e9e5 | ||
|
|
d924da2f25 | ||
|
|
be4d1eabaa | ||
|
|
db98e56e72 | ||
|
|
e2a35ea844 | ||
|
|
7966b2bde6 | ||
|
|
9391b947c6 | ||
|
|
e61e3bcf9b | ||
|
|
89ca2cc631 | ||
|
|
e2cae035f2 | ||
|
|
d79a0e737a | ||
|
|
c60ec7c170 | ||
|
|
e42b19d324 | ||
|
|
3be370aefa | ||
|
|
b13917fbdc | ||
|
|
9028761821 | ||
|
|
f6b52b7c82 | ||
|
|
13f07abb8a | ||
|
|
8c960f0661 | ||
|
|
77203a4363 | ||
|
|
d3246b7c8b | ||
|
|
c93edec55b | ||
|
|
83d258c396 | ||
|
|
81acb5bdab | ||
|
|
0b79019e0f | ||
|
|
be07298741 | ||
|
|
2d779fdcd0 | ||
|
|
35382faf28 | ||
|
|
dba0b104ab | ||
|
|
174cabdc74 | ||
|
|
3c52a9faab | ||
|
|
73561993a7 | ||
|
|
6e875393d9 | ||
|
|
bbd85a491b | ||
|
|
a736be7ca8 | ||
|
|
f1fe0b944f | ||
|
|
c1e40dd109 | ||
|
|
73823e3eb9 | ||
|
|
bf833991bf | ||
|
|
615357c977 | ||
|
|
19f23127b9 | ||
|
|
2ea6d9437f | ||
|
|
833b6d67a6 | ||
|
|
04c1adc5f0 | ||
|
|
8e8f6a0284 | ||
|
|
68bf1d123e | ||
|
|
2c03689195 | ||
|
|
45f41b1140 | ||
|
|
8fa6f3f45c | ||
|
|
78a842deb7 | ||
|
|
3657ff4f79 | ||
|
|
d4d12c3db0 | ||
|
|
1b628ac213 | ||
|
|
5fcc259efb | ||
|
|
9545205f19 | ||
|
|
cb6708c02e | ||
|
|
4f403d4450 | ||
|
|
f2d8f930fb | ||
|
|
4a86340d50 | ||
|
|
f8e9e9ba85 | ||
|
|
934ed1af09 | ||
|
|
0fc2a219a7 | ||
|
|
aa5939c051 | ||
|
|
9c5f06101e | ||
|
|
2a7c0252a0 | ||
|
|
414726ecd4 | ||
|
|
fdc8a15595 | ||
|
|
d012fd3a65 | ||
|
|
a5ed824674 | ||
|
|
d6705c682f | ||
|
|
d68523a54e | ||
|
|
6af82680f1 | ||
|
|
a4aee761c2 | ||
|
|
33b606d48f | ||
|
|
cc44be7ef9 | ||
|
|
e0eb972a54 | ||
|
|
19c54a99cd | ||
|
|
9d60ec22ee | ||
|
|
cb4eeccfd3 | ||
|
|
62e50caa99 | ||
|
|
0192566d19 | ||
|
|
8a8b70f2ab | ||
|
|
af311001cf | ||
|
|
040229418e | ||
|
|
c259963542 | ||
|
|
ca75f7fa0b | ||
|
|
4b22a409e7 | ||
|
|
55806db00f | ||
|
|
83c757ebd4 | ||
|
|
a19b02aa8c | ||
|
|
cf1ba60a10 | ||
|
|
2a4c9afdf2 | ||
|
|
ab76933158 | ||
|
|
d4d7bcab7a | ||
|
|
a61cf6a68a | ||
|
|
146a307b59 | ||
|
|
875946b4e8 | ||
|
|
81f2a460ed | ||
|
|
6698a2ac13 | ||
|
|
9161cc693d | ||
|
|
be689e293d | ||
|
|
53c22d5e29 | ||
|
|
5c0c80829e | ||
|
|
55aedfe901 | ||
|
|
4b87d66131 | ||
|
|
fc9497f067 | ||
|
|
3186335f47 | ||
|
|
31bfd8664a | ||
|
|
ab1c9e27dc | ||
|
|
c07cc913c8 | ||
|
|
b8fb5493c5 | ||
|
|
e8e5eb9c53 | ||
|
|
a15034b03e | ||
|
|
1435acdc28 | ||
|
|
37f164f11c | ||
|
|
7a2f071269 | ||
|
|
9f19afc943 | ||
|
|
6742bef289 | ||
|
|
9ee0964d0e | ||
|
|
33ecbfa95b | ||
|
|
e977a1006c | ||
|
|
559c13a003 | ||
|
|
8f00345430 | ||
|
|
f1ebab0c2d | ||
|
|
98884d851a | ||
|
|
78d0369e71 | ||
|
|
7a56af8ffa | ||
|
|
ed2bfbd27c | ||
|
|
e0905255ba | ||
|
|
de80db73f2 | ||
|
|
90ed62add2 | ||
|
|
d46e279933 | ||
|
|
77e074efc2 | ||
|
|
bd000d2d2c | ||
|
|
5f1c88104d | ||
|
|
a61df0832f | ||
|
|
58361e58f8 | ||
|
|
96b4361b31 | ||
|
|
c773edceb9 | ||
|
|
bcaef8ba54 | ||
|
|
c7d0b0ccc5 | ||
|
|
38792a0f02 | ||
|
|
cda557e1b9 | ||
|
|
8d09f7c7eb | ||
|
|
4845a56435 | ||
|
|
f164dcdd70 | ||
|
|
cc3aad17e1 | ||
|
|
6c8da6b070 | ||
|
|
09df753ca9 | ||
|
|
72ec9df1b1 | ||
|
|
086d5272ac | ||
|
|
2555de7712 | ||
|
|
645e540c66 | ||
|
|
d16e1a4451 | ||
|
|
7c5dd2bd78 | ||
|
|
2f0121f0e4 | ||
|
|
7e310a8de7 | ||
|
|
c460c2bf6b | ||
|
|
760ab688b2 | ||
|
|
ff78c72d54 | ||
|
|
2400de337b | ||
|
|
85d41085de | ||
|
|
48d45d026e | ||
|
|
183c57643b | ||
|
|
e7cea889ab | ||
|
|
61c799447b | ||
|
|
ad25daf206 | ||
|
|
4143bba89f | ||
|
|
8eb7d65b74 | ||
|
|
51798553e1 | ||
|
|
323928ff86 | ||
|
|
fe3aeabd0a | ||
|
|
ec7a55dba6 | ||
|
|
b4fe708d70 | ||
|
|
c3469bd545 | ||
|
|
92018b761d | ||
|
|
bb45ff0515 | ||
|
|
df1405e998 | ||
|
|
62ec018bb2 | ||
|
|
14b7c4bf23 | ||
|
|
5c774a3ce2 | ||
|
|
246480daef | ||
|
|
91c6f682e7 | ||
|
|
a417a6469c | ||
|
|
2821bdd52b | ||
|
|
d37300be39 | ||
|
|
15b83072bb | ||
|
|
6d2e2259db | ||
|
|
5b70614212 | ||
|
|
4363da534d | ||
|
|
685f7a4f00 | ||
|
|
6e26f25418 | ||
|
|
d8051ce9a2 | ||
|
|
00e7d8a390 | ||
|
|
213ec028b8 | ||
|
|
61951e76ac | ||
|
|
47cf763b3f | ||
|
|
04aac03d6e | ||
|
|
3faef2c9c9 | ||
|
|
eda17d1671 | ||
|
|
fbd6ead6b7 | ||
|
|
bf2950abdd | ||
|
|
3eacc325a3 | ||
|
|
15decd9cd9 | ||
|
|
c0142adba9 | ||
|
|
ec01333c83 | ||
|
|
8110384ea2 | ||
|
|
0c2c0d7b8b | ||
|
|
ae38bb0927 | ||
|
|
003e076b00 | ||
|
|
2c2a0eb7d9 | ||
|
|
e7f5b17184 | ||
|
|
69e12b1067 | ||
|
|
fef446687a | ||
|
|
3affce8f98 | ||
|
|
0b91468edc | ||
|
|
127364e8a4 | ||
|
|
a144f65dcf | ||
|
|
96ec3a869b | ||
|
|
52426bc1a4 | ||
|
|
cbab995c6d | ||
|
|
d27fa43120 | ||
|
|
45a9da5b30 | ||
|
|
aed22aebb2 | ||
|
|
369d213da5 | ||
|
|
e92775eec2 | ||
|
|
2c0f48f4e5 | ||
|
|
a5f1c430a3 | ||
|
|
e4a91b5397 | ||
|
|
cbcd45cd70 | ||
|
|
0968912954 | ||
|
|
3bfe22c0f7 | ||
|
|
6cf64d794f | ||
|
|
6741ba0783 | ||
|
|
f1e7bc3363 | ||
|
|
2dbe2d044e | ||
|
|
ea3630e018 | ||
|
|
c6391d958d | ||
|
|
71aa4033a4 | ||
|
|
57dcd961d5 | ||
|
|
83878d6b05 | ||
|
|
9055fc72d2 | ||
|
|
fb4ab56b47 | ||
|
|
51e195ed17 | ||
|
|
9947c574d2 | ||
|
|
693abdacf6 | ||
|
|
dd3b42fb53 | ||
|
|
8e72d7d0d6 | ||
|
|
a6317212d9 | ||
|
|
347adf688a | ||
|
|
3ee67927a5 | ||
|
|
7ecd36efcf | ||
|
|
714ce8a8a3 | ||
|
|
7b18a2f46f | ||
|
|
19103a64e5 | ||
|
|
a13f1d27e2 | ||
|
|
9a6e4b1e85 | ||
|
|
67b78fc230 | ||
|
|
5e79187176 | ||
|
|
491a82cd67 | ||
|
|
87c2ec678f | ||
|
|
70135ab3ea | ||
|
|
ad18d84f14 | ||
|
|
77e47e3fa4 | ||
|
|
04432385b3 | ||
|
|
cbdc24d869 | ||
|
|
2b3e471f96 | ||
|
|
488d54493a | ||
|
|
a418f63a44 | ||
|
|
0e285151f3 | ||
|
|
e4ad7768d5 | ||
|
|
f800fab1a3 | ||
|
|
dc61aeeeb8 | ||
|
|
4b1d0fd011 | ||
|
|
2b7ba594fc | ||
|
|
d87b14af13 | ||
|
|
83623d23cf | ||
|
|
07fba53b73 | ||
|
|
823b276ef5 | ||
|
|
0e72d78731 | ||
|
|
768609e357 | ||
|
|
526a157421 | ||
|
|
62154309fb | ||
|
|
ad74e6c475 | ||
|
|
82d28242cc | ||
|
|
60fddf837d | ||
|
|
ee25df0c28 | ||
|
|
478af40359 | ||
|
|
6bf06a9629 | ||
|
|
3c15bd9e29 | ||
|
|
71796e3dbf | ||
|
|
280f1ee2df | ||
|
|
0dc72d8301 | ||
|
|
c43b67ea90 | ||
|
|
244421b69e | ||
|
|
1adedff61a | ||
|
|
6abd10f9e2 | ||
|
|
a85096ea11 | ||
|
|
f67157f0ad | ||
|
|
5efe9bd91d | ||
|
|
dc7a7267c9 | ||
|
|
17188b1e38 | ||
|
|
e9c3bebfff | ||
|
|
03fc22d3da | ||
|
|
5d52c49c31 | ||
|
|
d53da4cfb5 | ||
|
|
76204f5f47 | ||
|
|
b68adbd9a8 | ||
|
|
951b168f3a | ||
|
|
53d89af459 | ||
|
|
4f844ea837 | ||
|
|
59a36e77bd | ||
|
|
61d8d4473c | ||
|
|
508a371175 | ||
|
|
b010fd88e8 | ||
|
|
66a93b81c6 | ||
|
|
274e1139fa | ||
|
|
6122e33f4f | ||
|
|
b365ce3195 | ||
|
|
0a3233d289 | ||
|
|
15aea9e9ea | ||
|
|
5b03a84be8 | ||
|
|
80cdf0c014 | ||
|
|
d41d56e670 | ||
|
|
7e4e1f1a0d | ||
|
|
463b06f508 | ||
|
|
d3377d56b4 | ||
|
|
c7611fbc05 | ||
|
|
67ee218f69 | ||
|
|
d1d394eec7 | ||
|
|
98bc68c2bf | ||
|
|
116c0680a2 | ||
|
|
1b8a25ec88 | ||
|
|
d5def01a9d | ||
|
|
ee07b72415 | ||
|
|
f7547db272 | ||
|
|
5d271687ec | ||
|
|
d05543db30 | ||
|
|
b33f73ac9a | ||
|
|
31e5d785fe | ||
|
|
8096fd20a7 | ||
|
|
addd45ae8e | ||
|
|
d6895537ac | ||
|
|
4ac40fee5e | ||
|
|
05b8d0b45c | ||
|
|
446f539803 | ||
|
|
6ef2e46aa3 | ||
|
|
e4c5c4a901 | ||
|
|
be231f3a91 | ||
|
|
39f36c9184 | ||
|
|
2e4076bb75 | ||
|
|
d71ac2e894 | ||
|
|
7e7da26f29 | ||
|
|
4375a151dd | ||
|
|
0f02fb5d05 | ||
|
|
05edc1f9c4 | ||
|
|
50784f2600 | ||
|
|
2c0f0d9a20 | ||
|
|
21c0fed833 | ||
|
|
d081ff745d | ||
|
|
e3f41fea9c | ||
|
|
dea214bd2e | ||
|
|
a13e2468db | ||
|
|
3fb660d816 | ||
|
|
9f60dc3dd6 | ||
|
|
02f855ff09 | ||
|
|
c39622ed1e | ||
|
|
07bb095e73 | ||
|
|
e409029bb3 | ||
|
|
a4d93f23d6 | ||
|
|
6201176852 | ||
|
|
7d958cc20e | ||
|
|
e0e5670d0e | ||
|
|
68e855e3d2 | ||
|
|
bf91352fce | ||
|
|
a840504b3d | ||
|
|
e120422b05 | ||
|
|
c60e99288f | ||
|
|
d9006d6e37 | ||
|
|
9121b83bd1 | ||
|
|
fad3db1556 | ||
|
|
9d4862b5c8 | ||
|
|
2a07999db6 | ||
|
|
44d2e100bd | ||
|
|
8d9c114acd | ||
|
|
bce0950498 | ||
|
|
dcac64fb9a | ||
|
|
fadd7158ed |
6
.babelrc
6
.babelrc
@@ -4,9 +4,11 @@
|
||||
"targets": {
|
||||
"chrome": 40,
|
||||
"firefox": 35,
|
||||
"edge": 14
|
||||
"edge": 14,
|
||||
"node": "6.5",
|
||||
},
|
||||
"modules": false
|
||||
"modules": false,
|
||||
"useBuiltIns": true
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
||||
2
.eslintignore
Normal file
2
.eslintignore
Normal file
@@ -0,0 +1,2 @@
|
||||
src/core/lib/**
|
||||
src/core/config/MetaConfig.js
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"ecmaVersion": 8,
|
||||
"ecmaFeatures": {
|
||||
"impliedStrict": true
|
||||
},
|
||||
@@ -28,18 +28,13 @@
|
||||
// modify rules from base configurations
|
||||
"no-unused-vars": ["error", {
|
||||
"args": "none",
|
||||
"vars": "local",
|
||||
// Allow vars that start with a capital letter to be unused.
|
||||
// This is mainly for exported module names which are useful to indicate
|
||||
// the name of the module and may be used to refer to itself in future.
|
||||
"varsIgnorePattern": "^[A-Z]"
|
||||
"vars": "all"
|
||||
}],
|
||||
"no-empty": ["error", {
|
||||
"allowEmptyCatch": true
|
||||
}],
|
||||
|
||||
// disable rules from base configurations
|
||||
"no-console": "off",
|
||||
"no-control-regex": "off",
|
||||
|
||||
// stylistic conventions
|
||||
@@ -52,6 +47,9 @@
|
||||
"no-trailing-spaces": "warn",
|
||||
"eol-last": "error",
|
||||
"func-call-spacing": "error",
|
||||
"key-spacing": ["warn", {
|
||||
"mode": "minimum"
|
||||
}],
|
||||
"indent": ["error", 4, {
|
||||
"ArrayExpression": "first",
|
||||
"SwitchCase": 1
|
||||
@@ -84,14 +82,20 @@
|
||||
}],
|
||||
"no-whitespace-before-property": "error",
|
||||
"operator-linebreak": ["error", "after"],
|
||||
"space-in-parens": "error"
|
||||
"space-in-parens": "error",
|
||||
"no-var": "error"
|
||||
},
|
||||
"globals": {
|
||||
"$": false,
|
||||
"jQuery": false,
|
||||
"moment": false,
|
||||
"log": false,
|
||||
|
||||
"COMPILE_TIME": false,
|
||||
"COMPILE_MSG": false
|
||||
"COMPILE_MSG": false,
|
||||
"PKG_VERSION": false,
|
||||
"ENVIRONMENT_IS_WORKER": false,
|
||||
"ENVIRONMENT_IS_NODE": false,
|
||||
"ENVIRONMENT_IS_WEB": false
|
||||
}
|
||||
}
|
||||
13
.github/ISSUE_TEMPLATE.md
vendored
13
.github/ISSUE_TEMPLATE.md
vendored
@@ -5,21 +5,10 @@
|
||||
<!-- Misc: -->
|
||||
|
||||
### Summary
|
||||
<!-- If you're describing a bug, tell us what's wrong -->
|
||||
<!-- If you're suggesting a change/improvement, tell us what it is and how it should work -->
|
||||
|
||||
|
||||
### Example
|
||||
<!-- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!-- Include a link that triggers the bug if possible -->
|
||||
<!-- If you are requesting a new operation, include example input and output -->
|
||||
|
||||
### Possible solutions
|
||||
<!-- Not obligatory, but suggest a fix/reason for the bug, or ideas for how to -->
|
||||
<!-- implement the addition or change, including links to relevant resources -->
|
||||
|
||||
### Environment
|
||||
<!-- Include any relevant details about the environment you experienced the bug in -->
|
||||
<!-- This information is displayed in the About/Support pane -->
|
||||
* CyberChef compile time:
|
||||
* User-Agent:
|
||||
* [Link to reproduce]()
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,7 +1,9 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
travis.log
|
||||
build
|
||||
docs/*
|
||||
!docs/*.conf.json
|
||||
!docs/*.ico
|
||||
.vscode
|
||||
src/core/config/MetaConfig.js
|
||||
8
.npmignore
Executable file
8
.npmignore
Executable file
@@ -0,0 +1,8 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
travis.log
|
||||
build/*
|
||||
!build/node
|
||||
docs
|
||||
.vscode
|
||||
.github
|
||||
22
.travis.yml
22
.travis.yml
@@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- node
|
||||
- "8.4"
|
||||
install: npm install
|
||||
before_script:
|
||||
- npm install -g grunt
|
||||
@@ -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,9 +19,10 @@ deploy:
|
||||
local_dir: build/prod/
|
||||
target_branch: gh-pages
|
||||
on:
|
||||
repo: gchq/CyberChef
|
||||
branch: master
|
||||
- provider: releases
|
||||
skip_cleaup: true
|
||||
skip_cleanup: true
|
||||
api_key:
|
||||
secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA="
|
||||
file:
|
||||
@@ -30,3 +31,18 @@ deploy:
|
||||
on:
|
||||
repo: gchq/CyberChef
|
||||
tags: true
|
||||
- provider: npm
|
||||
skip_cleanup: true
|
||||
email: "n1474335@gmail.com"
|
||||
api_key:
|
||||
secure: "Z3FK6bm4RfQEIRXZ1lBNzQkVIoHpivThr9U+XBHmsBgIfdrK/XUnzs/slugo+NIz8nPiGmMx4gxyJonBCLHDGb1ysky2aEWTl26c0teaF4DeQEjWC1ZaGzv8MV1/GkUamnr1qouXjyUhyEAp33rd8ccN9Rq3QNYB/qLDcA9/FCme7JCW6sCd4zWO0LGEYMJEMc2FzAUkqhqsI05hegGhSDgKXRn5PmLARek4yHD+Hx7pstaTeQIy0WoGJjdzoB3iJIMmo/hWZGzZafktUOh223c5qzx4zMpDRNmMngBUw6R94nKd4KvplYRgB87Y3L/aiVU4CF+axwLmK8RPaC1wbJnlHf06zxHPdiFmsY/zKPpNel+nOnxzRrF5l2KMU4TU6gug3s9Jnzp9T5UMfhp0jW3YkxHGeuOPOeE1i0lTUWUGWrPHLQquAhLfkr2zxaU4ETk/y85hq9W4LAy0ENEDVXX2jP7FnI4Z1fdpmljpmVNJR+outPg6t+Coqgvil7v7XpMtDm8lKQanVYuxwmkb/ncOWFRWuM2j5zIEg3CHnFDcJ9bYrfKRg0b0tb/2BWD14pQnV76goVwzJQYVzdPc8TKIYJw2BZ1Nh9c0iruQVebe/6l1FX9fDCkz8VMmltni61/LxZrf8y0NT1YaU1raeNY2dH5UWvEa9p72FPMI6Eg="
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/83c143a6822e218d5b34
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: never
|
||||
|
||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at oss@gchq.gov.uk. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
354
Gruntfile.js
354
Gruntfile.js
@@ -1,7 +1,18 @@
|
||||
var webpack = require("webpack"),
|
||||
ExtractTextPlugin = require("extract-text-webpack-plugin"),
|
||||
HtmlWebpackPlugin = require("html-webpack-plugin"),
|
||||
Inliner = require("web-resource-inliner");
|
||||
"use strict";
|
||||
|
||||
const webpack = require("webpack");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const NodeExternals = require("webpack-node-externals");
|
||||
const Inliner = require("web-resource-inliner");
|
||||
const fs = require("fs");
|
||||
|
||||
/**
|
||||
* Grunt configuration for building the app in various formats.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
module.exports = function (grunt) {
|
||||
grunt.file.defaultEncoding = "utf8";
|
||||
@@ -10,15 +21,15 @@ module.exports = function (grunt) {
|
||||
// Tasks
|
||||
grunt.registerTask("dev",
|
||||
"A persistent task which creates a development build whenever source files are modified.",
|
||||
["clean:dev", "webpack:webDev"]);
|
||||
["clean:dev", "concurrent:dev"]);
|
||||
|
||||
grunt.registerTask("node",
|
||||
"Compiles CyberChef into a single NodeJS module.",
|
||||
["clean:node", "webpack:node", "chmod:build"]);
|
||||
["clean:node", "webpack:metaConf", "webpack:node", "chmod:build"]);
|
||||
|
||||
grunt.registerTask("test",
|
||||
"A task which runs all the tests in test/tests.",
|
||||
["clean:test", "webpack:tests", "execute:test"]);
|
||||
["clean:test", "webpack:metaConf", "webpack:tests", "execute:test"]);
|
||||
|
||||
grunt.registerTask("docs",
|
||||
"Compiles documentation in the /docs directory.",
|
||||
@@ -26,7 +37,7 @@ module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask("prod",
|
||||
"Creates a production-ready build. Use the --msg flag to add a compile message.",
|
||||
["eslint", "clean:prod", "webpack:webProd", "inline", "chmod"]);
|
||||
["eslint", "clean:prod", "webpack:metaConf", "webpack:web", "inline", "chmod"]);
|
||||
|
||||
grunt.registerTask("default",
|
||||
"Lints the code base",
|
||||
@@ -34,8 +45,10 @@ module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask("inline",
|
||||
"Compiles a production build of CyberChef into a single, portable web page.",
|
||||
runInliner);
|
||||
["webpack:webInline", "runInliner", "clean:inlineScripts"]);
|
||||
|
||||
|
||||
grunt.registerTask("runInliner", runInliner);
|
||||
grunt.registerTask("doc", "docs");
|
||||
grunt.registerTask("tests", "test");
|
||||
grunt.registerTask("lint", "eslint");
|
||||
@@ -51,36 +64,34 @@ module.exports = function (grunt) {
|
||||
grunt.loadNpmTasks("grunt-exec");
|
||||
grunt.loadNpmTasks("grunt-execute");
|
||||
grunt.loadNpmTasks("grunt-accessibility");
|
||||
grunt.loadNpmTasks("grunt-concurrent");
|
||||
|
||||
|
||||
// Project configuration
|
||||
var compileTime = grunt.template.today("dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||
banner = "/**\n" +
|
||||
"* CyberChef - The Cyber Swiss Army Knife\n" +
|
||||
"*\n" +
|
||||
"* @copyright Crown Copyright 2016\n" +
|
||||
"* @license Apache-2.0\n" +
|
||||
"*\n" +
|
||||
"* Copyright 2016 Crown Copyright\n" +
|
||||
"*\n" +
|
||||
'* Licensed under the Apache License, Version 2.0 (the "License");\n' +
|
||||
"* you may not use this file except in compliance with the License.\n" +
|
||||
"* You may obtain a copy of the License at\n" +
|
||||
"*\n" +
|
||||
"* http://www.apache.org/licenses/LICENSE-2.0\n" +
|
||||
"*\n" +
|
||||
"* Unless required by applicable law or agreed to in writing, software\n" +
|
||||
'* distributed under the License is distributed on an "AS IS" BASIS,\n' +
|
||||
"* 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";
|
||||
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||
pkg = grunt.file.readJSON("package.json"),
|
||||
webpackConfig = require("./webpack.config.js"),
|
||||
BUILD_CONSTANTS = {
|
||||
COMPILE_TIME: JSON.stringify(compileTime),
|
||||
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
|
||||
PKG_VERSION: JSON.stringify(pkg.version),
|
||||
ENVIRONMENT_IS_WORKER: function() {
|
||||
return typeof importScripts === "function";
|
||||
},
|
||||
ENVIRONMENT_IS_NODE: function() {
|
||||
return typeof process === "object" && typeof require === "function";
|
||||
},
|
||||
ENVIRONMENT_IS_WEB: function() {
|
||||
return typeof window === "object";
|
||||
}
|
||||
},
|
||||
moduleEntryPoints = listEntryModules();
|
||||
|
||||
/**
|
||||
* Compiles a production build of CyberChef into a single, portable web page.
|
||||
*/
|
||||
function runInliner() {
|
||||
var inlinerError = false;
|
||||
const done = this.async();
|
||||
Inliner.html({
|
||||
relativeTo: "build/prod/",
|
||||
fileContent: grunt.file.read("build/prod/cyberchef.htm"),
|
||||
@@ -91,30 +102,48 @@ module.exports = function (grunt) {
|
||||
strict: true
|
||||
}, function(error, result) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
inlinerError = true;
|
||||
return false;
|
||||
if (error instanceof Error) {
|
||||
done(error);
|
||||
} else {
|
||||
done(new Error(error));
|
||||
}
|
||||
} else {
|
||||
grunt.file.write("build/prod/cyberchef.htm", result);
|
||||
done(true);
|
||||
}
|
||||
grunt.file.write("build/prod/cyberchef.htm", result);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an entry list for all the modules.
|
||||
*/
|
||||
function listEntryModules() {
|
||||
const path = "./src/core/config/modules/";
|
||||
let entryModules = {};
|
||||
|
||||
fs.readdirSync(path).forEach(file => {
|
||||
if (file !== "Default.js" && file !== "OpModules.js")
|
||||
entryModules[file.split(".js")[0]] = path + file;
|
||||
});
|
||||
|
||||
return !inlinerError;
|
||||
return entryModules;
|
||||
}
|
||||
|
||||
grunt.initConfig({
|
||||
clean: {
|
||||
dev: ["build/dev/*"],
|
||||
prod: ["build/prod/*"],
|
||||
test: ["build/test/*"],
|
||||
node: ["build/node/*"],
|
||||
docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico"],
|
||||
dev: ["build/dev/*", "src/core/config/MetaConfig.js"],
|
||||
prod: ["build/prod/*", "src/core/config/MetaConfig.js"],
|
||||
test: ["build/test/*", "src/core/config/MetaConfig.js"],
|
||||
node: ["build/node/*", "src/core/config/MetaConfig.js"],
|
||||
docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico", "!docs/*.png"],
|
||||
inlineScripts: ["build/prod/scripts.js"],
|
||||
},
|
||||
eslint: {
|
||||
options: {
|
||||
configFile: "src/.eslintrc.json"
|
||||
configFile: "./.eslintrc.json"
|
||||
},
|
||||
configs: ["Gruntfile.js"],
|
||||
core: ["src/core/**/*.js", "!src/core/lib/**/*"],
|
||||
core: ["src/core/**/*.js", "!src/core/lib/**/*", "!src/core/config/MetaConfig.js"],
|
||||
web: ["src/web/**/*.js"],
|
||||
node: ["src/node/**/*.js"],
|
||||
tests: ["test/**/*.js"],
|
||||
@@ -131,116 +160,76 @@ module.exports = function (grunt) {
|
||||
src: [
|
||||
"src/**/*.js",
|
||||
"!src/core/lib/**/*",
|
||||
"!src/core/config/MetaConfig.js"
|
||||
],
|
||||
}
|
||||
},
|
||||
concurrent: {
|
||||
options: {
|
||||
logConcurrentOutput: true
|
||||
},
|
||||
dev: ["webpack:metaConfDev", "webpack-dev-server:start"]
|
||||
},
|
||||
accessibility: {
|
||||
options: {
|
||||
accessibilityLevel: "WCAG2A"
|
||||
accessibilityLevel: "WCAG2A",
|
||||
verbose: false,
|
||||
ignore: [
|
||||
"WCAG2A.Principle1.Guideline1_3.1_3_1.H42.2"
|
||||
]
|
||||
},
|
||||
test: {
|
||||
src: ["build/**/*.html"]
|
||||
}
|
||||
},
|
||||
webpack: {
|
||||
options: {
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
moment: "moment-timezone"
|
||||
}),
|
||||
new webpack.BannerPlugin({
|
||||
banner: banner,
|
||||
raw: true,
|
||||
entryOnly: true
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
COMPILE_TIME: JSON.stringify(compileTime),
|
||||
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || "")
|
||||
}),
|
||||
new ExtractTextPlugin("styles.css"),
|
||||
options: webpackConfig,
|
||||
metaConf: {
|
||||
target: "node",
|
||||
entry: [
|
||||
"babel-polyfill",
|
||||
"./src/core/config/OperationConfig.js"
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
jquery: "jquery/src/jquery"
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader?compact=false"
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: "css-loader?minimize"
|
||||
})
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: [
|
||||
{ loader: "css-loader?minimize" },
|
||||
{ loader: "less-loader" }
|
||||
]
|
||||
})
|
||||
},
|
||||
{
|
||||
test: /\.(ico|eot|ttf|woff|woff2)$/,
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
limit: 10000
|
||||
}
|
||||
},
|
||||
{ // First party images are saved as files to be cached
|
||||
test: /\.(png|jpg|gif|svg)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "file-loader",
|
||||
options: {
|
||||
name: "images/[name].[ext]"
|
||||
}
|
||||
},
|
||||
{ // Third party images are inlined
|
||||
test: /\.(png|jpg|gif|svg)$/,
|
||||
exclude: /web\/static/,
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
limit: 10000
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
stats: {
|
||||
children: false
|
||||
}
|
||||
},
|
||||
webDev: {
|
||||
target: "web",
|
||||
entry: "./src/web/index.js",
|
||||
output: {
|
||||
filename: "scripts.js",
|
||||
path: __dirname + "/build/dev"
|
||||
filename: "MetaConfig.js",
|
||||
path: __dirname + "/src/core/config/",
|
||||
library: "MetaConfig",
|
||||
libraryTarget: "commonjs2",
|
||||
libraryExport: "default"
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
compileTime: compileTime
|
||||
})
|
||||
externals: [NodeExternals()],
|
||||
},
|
||||
metaConfDev: {
|
||||
target: "node",
|
||||
entry: [
|
||||
"babel-polyfill",
|
||||
"./src/core/config/OperationConfig.js"
|
||||
],
|
||||
output: {
|
||||
filename: "MetaConfig.js",
|
||||
path: __dirname + "/src/core/config/",
|
||||
library: "MetaConfig",
|
||||
libraryTarget: "commonjs2",
|
||||
libraryExport: "default"
|
||||
},
|
||||
externals: [NodeExternals()],
|
||||
watch: true
|
||||
},
|
||||
webProd: {
|
||||
web: {
|
||||
target: "web",
|
||||
entry: "./src/web/index.js",
|
||||
entry: Object.assign({
|
||||
main: "./src/web/index.js"
|
||||
}, moduleEntryPoints),
|
||||
output: {
|
||||
filename: "scripts.js",
|
||||
path: __dirname + "/build/prod"
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"./config/modules/OpModules.js": "./config/modules/Default.js"
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
"screw_ie8": true,
|
||||
@@ -250,10 +239,12 @@ module.exports = function (grunt) {
|
||||
},
|
||||
comments: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({ // Main version
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
chunks: ["main"],
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
@@ -261,10 +252,31 @@ module.exports = function (grunt) {
|
||||
minifyCSS: true
|
||||
}
|
||||
}),
|
||||
new HtmlWebpackPlugin({ // Inline version
|
||||
]
|
||||
},
|
||||
webInline: {
|
||||
target: "web",
|
||||
entry: "./src/web/index.js",
|
||||
output: {
|
||||
filename: "scripts.js",
|
||||
path: __dirname + "/build/prod"
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
"screw_ie8": true,
|
||||
"dead_code": true,
|
||||
"unused": true,
|
||||
"warnings": false
|
||||
},
|
||||
comments: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "cyberchef.htm",
|
||||
template: "./src/web/html/index.html",
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
inline: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
@@ -278,19 +290,66 @@ module.exports = function (grunt) {
|
||||
tests: {
|
||||
target: "node",
|
||||
entry: "./test/index.js",
|
||||
externals: [NodeExternals()],
|
||||
output: {
|
||||
filename: "index.js",
|
||||
path: __dirname + "/build/test"
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS)
|
||||
]
|
||||
},
|
||||
node: {
|
||||
target: "node",
|
||||
entry: "./src/node/index.js",
|
||||
externals: [NodeExternals()],
|
||||
output: {
|
||||
filename: "CyberChef.js",
|
||||
path: __dirname + "/build/node",
|
||||
library: "CyberChef",
|
||||
libraryTarget: "commonjs2"
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS)
|
||||
]
|
||||
}
|
||||
},
|
||||
"webpack-dev-server": {
|
||||
options: {
|
||||
webpack: webpackConfig,
|
||||
host: "0.0.0.0",
|
||||
disableHostCheck: true,
|
||||
overlay: true,
|
||||
inline: false,
|
||||
clientLogLevel: "error",
|
||||
stats: {
|
||||
children: false,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
warningsFilter: /source-map/,
|
||||
}
|
||||
},
|
||||
start: {
|
||||
webpack: {
|
||||
target: "web",
|
||||
entry: Object.assign({
|
||||
main: "./src/web/index.js"
|
||||
}, moduleEntryPoints),
|
||||
resolve: {
|
||||
alias: {
|
||||
"./config/modules/OpModules.js": "./config/modules/Default.js"
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
chunks: ["main"],
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -299,13 +358,27 @@ module.exports = function (grunt) {
|
||||
options: {
|
||||
process: function (content, srcpath) {
|
||||
// Add Google Analytics code to index.html
|
||||
content = content.replace("</body></html>",
|
||||
grunt.file.read("src/web/static/ga.html") + "</body></html>");
|
||||
return grunt.template.process(content);
|
||||
}
|
||||
if (srcpath.indexOf("index.html") >= 0) {
|
||||
content = content.replace("</body></html>",
|
||||
grunt.file.read("src/web/static/ga.html") + "</body></html>");
|
||||
return grunt.template.process(content, srcpath);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
},
|
||||
noProcess: ["**", "!**/*.html"]
|
||||
},
|
||||
src: "build/prod/index.html",
|
||||
dest: "build/prod/index.html"
|
||||
files: [
|
||||
{
|
||||
src: "build/prod/index.html",
|
||||
dest: "build/prod/index.html"
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
src: "docs/**",
|
||||
dest: "build/prod/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
chmod: {
|
||||
@@ -338,5 +411,4 @@ module.exports = function (grunt) {
|
||||
test: "build/test/index.js"
|
||||
},
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
67
README.md
67
README.md
@@ -1,10 +1,18 @@
|
||||
# CyberChef
|
||||
|
||||
[](https://travis-ci.org/gchq/CyberChef)
|
||||
[](https://david-dm.org/gchq/CyberChef)
|
||||
[](https://www.npmjs.com/package/cyberchef)
|
||||

|
||||
[](https://github.com/gchq/CyberChef/blob/master/LICENSE)
|
||||
[](https://gitter.im/gchq/CyberChef?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
|
||||
#### *The Cyber Swiss Army Knife*
|
||||
|
||||
CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include creating hexdumps, simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, data compression and decompression, calculating hashes and checksums, IPv6 and X.509 parsing, and much more.
|
||||
CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, creating binary and hexdumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
|
||||
|
||||
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years. Every effort has been made to structure the code in a readable and extendable format, however it should be noted that the analyst is not a professional developer and the code has not been peer-reviewed for compliance with a formal specification.
|
||||
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years. Every effort has been made to structure the code in a readable and extendable format, however it should be noted that the analyst is not a professional developer.
|
||||
|
||||
## Live demo
|
||||
|
||||
@@ -19,10 +27,10 @@ Cryptographic operations in CyberChef should not be relied upon to provide secur
|
||||
|
||||
There are four main areas in CyberChef:
|
||||
|
||||
1. The **input** box in the top right, where you can paste, type or drag the data you want to operate on.
|
||||
2. The **output** box in the bottom right, where the outcome of the specified processing will be displayed.
|
||||
1. The **input** box in the top right, where you can paste, type or drag the text or file you want to operate on.
|
||||
2. The **output** box in the bottom right, where the outcome of your processing will be displayed.
|
||||
3. The **operations** list on the far left, where you can find all the operations that CyberChef is capable of in categorised lists, or by searching.
|
||||
4. The **recipe** area in the middle, where you drag the operations that you want to use and specify arguments and options.
|
||||
4. The **recipe** area in the middle, where you can drag the operations that you want to use and specify arguments and options.
|
||||
|
||||
You can use as many operations as you like in simple or complex ways. Some examples are as follows:
|
||||
|
||||
@@ -30,44 +38,50 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||
- [Convert a date and time to a different time zone][3]
|
||||
- [Parse a Teredo IPv6 address][4]
|
||||
- [Convert data from a hexdump, then decompress][5]
|
||||
- [Display multiple timestamps as full dates][6]
|
||||
- [Carry out different operations on data of different types][7]
|
||||
- [Decrypt and disassemble shellcode][6]
|
||||
- [Display multiple timestamps as full dates][7]
|
||||
- [Carry out different operations on data of different types][8]
|
||||
- [Use parts of the input as arguments to operations][9]
|
||||
- [Perform AES decryption, extracting the IV from the beginning of the cipher stream][10]
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- Drag and drop
|
||||
- Operations can be dragged in and out of the recipe list, or reorganised.
|
||||
- Files can be dragged over the input box to load them directly.
|
||||
- Files can be dragged over the input box to load them directly into the browser.
|
||||
- Auto Bake
|
||||
- Whenever you modify the input or the recipe, CyberChef will automatically “bake” for you and produce the output immediately.
|
||||
- Whenever you modify the input or the recipe, CyberChef will automatically "bake" for you and produce the output immediately.
|
||||
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
|
||||
- If any bake takes longer than 200 milliseconds, auto bake will be switched off automatically to prevent further performance issues.
|
||||
- Breakpoints
|
||||
- You can set breakpoints on any operation in your recipe to pause execution before running it.
|
||||
- You can also step through the recipe one operation at a time to see what the data looks like at each stage.
|
||||
- Save and load recipes
|
||||
- If you come up with an awesome recipe that you know you’ll want to use again, just click save and add it to your local storage. It'll be waiting for you next time you visit CyberChef.
|
||||
- You can also copy a URL which includes your recipe and input which can be shared with others.
|
||||
- If you come up with an awesome recipe that you know you’ll want to use again, just click "Save recipe" and add it to your local storage. It'll be waiting for you next time you visit CyberChef.
|
||||
- You can also copy the URL, which includes your recipe and input, to easily share it with others.
|
||||
- Search
|
||||
- If you know the name of the operation you want or a word associated with it, start typing it into the search field and any matching operations will immediately be shown.
|
||||
- Highlighting
|
||||
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][8]).
|
||||
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][11]).
|
||||
- Save to file and load from file
|
||||
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field (note that files larger than about 500kb may cause your browser to hang or even crash due to the way that browsers handle large amounts of textual data).
|
||||
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 500MB are supported (depending on your browser), however some operations may take a very long time to run over this much data.
|
||||
- CyberChef is entirely client-side
|
||||
- It should be noted that none of your input or recipe configuration is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer.
|
||||
- Due to this feature, CyberChef can be compiled into a single HTML file. You can download this file and drop it into a virtual machine, share it with other people, or use it independently on your desktop.
|
||||
- It should be noted that none of your recipe configuration or input (either text or files) is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer.
|
||||
- Due to this feature, CyberChef can be compiled into a single HTML file. You can download this file and drop it into a virtual machine, share it with other people, or use it independently on your local machine.
|
||||
|
||||
|
||||
## Browser support
|
||||
|
||||
CyberChef is built to support Google Chrome 40+, Mozilla Firefox 35+ and Microsoft Edge 14+.
|
||||
CyberChef is built to support
|
||||
|
||||
- Google Chrome 40+
|
||||
- Mozilla Firefox 35+
|
||||
- Microsoft Edge 14+
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
An installation walkthrough, how-to guides for adding new operations, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
|
||||
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
|
||||
|
||||
- Sign the [GCHQ Contributor Licence Agreement](https://github.com/gchq/Gaffer/wiki/GCHQ-OSS-Contributor-License-Agreement-V1.0)
|
||||
- Push your changes to your fork.
|
||||
@@ -80,10 +94,13 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
|
||||
|
||||
|
||||
[1]: https://gchq.github.io/CyberChef
|
||||
[2]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
|
||||
[3]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA
|
||||
[4]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
|
||||
[5]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
|
||||
[6]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
|
||||
[7]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
||||
[8]: https://gchq.github.io/CyberChef/?recipe=%5B%7B%22op%22%3A%22XOR%22%2C%22args%22%3A%5B%7B%22option%22%3A%22Hex%22%2C%22string%22%3A%223a%22%7D%2Cfalse%2Cfalse%5D%7D%2C%7B%22op%22%3A%22To%20Hexdump%22%2C%22args%22%3A%5B%2216%22%2Cfalse%2Cfalse%5D%7D%5D&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||
[2]: https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
|
||||
[3]: https://gchq.github.io/CyberChef/#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA
|
||||
[4]: https://gchq.github.io/CyberChef/#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
|
||||
[5]: https://gchq.github.io/CyberChef/#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
|
||||
[6]: https://gchq.github.io/CyberChef/#recipe=RC4(%7B'option':'UTF8','string':'secret'%7D,'Hex','Hex')Disassemble_x86('64','Full%20x86%20architecture',16,0,true,true)&input=MjFkZGQyNTQwMTYwZWU2NWZlMDc3NzEwM2YyYTM5ZmJlNWJjYjZhYTBhYWJkNDE0ZjkwYzZjYWY1MzEyNzU0YWY3NzRiNzZiM2JiY2QxOTNjYjNkZGZkYmM1YTI2NTMzYTY4NmI1OWI4ZmVkNGQzODBkNDc0NDIwMWFlYzIwNDA1MDcxMzhlMmZlMmIzOTUwNDQ2ZGIzMWQyYmM2MjliZTRkM2YyZWIwMDQzYzI5M2Q3YTVkMjk2MmMwMGZlNmRhMzAwNzJkOGM1YTZiNGZlN2Q4NTlhMDQwZWVhZjI5OTczMzYzMDJmNWEwZWMxOQ
|
||||
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
|
||||
[8]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
||||
[9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ
|
||||
[10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D)&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg
|
||||
[11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||
|
||||
BIN
docs/favicon.ico
BIN
docs/favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -2,11 +2,14 @@
|
||||
"tags": {
|
||||
"allowUnknownTags": true
|
||||
},
|
||||
"plugins": ["plugins/markdown"],
|
||||
"plugins": [
|
||||
"plugins/markdown",
|
||||
"node_modules/jsdoc-babel"
|
||||
],
|
||||
"templates": {
|
||||
"systemName": "CyberChef",
|
||||
"footer": "",
|
||||
"copyright": "© Crown Copyright 2016",
|
||||
"copyright": "© Crown Copyright 2017",
|
||||
"navType": "inline",
|
||||
"theme": "cerulean",
|
||||
"linenums": true,
|
||||
@@ -16,7 +19,7 @@
|
||||
"outputSourcePath": true,
|
||||
"dateFormat": "ddd MMM Do YYYY",
|
||||
"sort": false,
|
||||
"logoFile": "../build/prod/images/cyberchef-32x32.png",
|
||||
"logoFile": "cyberchef-32x32.png",
|
||||
"cleverLinks": false,
|
||||
"monospaceLinks": false,
|
||||
"protocol": "html://",
|
||||
|
||||
11885
package-lock.json
generated
Normal file
11885
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
107
package.json
107
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "5.1.1",
|
||||
"description": "CyberChef is a simple, intuitive web app for analysing and decoding data within a web browser.",
|
||||
"version": "7.6.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",
|
||||
"copyright": "Crown copyright 2016",
|
||||
@@ -19,66 +19,95 @@
|
||||
"hex",
|
||||
"encoding",
|
||||
"format",
|
||||
"cybersecurity"
|
||||
"cybersecurity",
|
||||
"data manipulation",
|
||||
"data analysis"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/gchq/CyberChef/"
|
||||
},
|
||||
"main": "build/node/CyberChef.js",
|
||||
"bugs": "https://github.com/gchq/CyberChef/issues",
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.24.0",
|
||||
"babel-loader": "^6.4.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-env": "^1.2.2",
|
||||
"css-loader": "^0.27.3",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"css-loader": "^0.28.9",
|
||||
"exports-loader": "^0.6.4",
|
||||
"extract-text-webpack-plugin": "^2.1.0",
|
||||
"file-loader": "^0.10.1",
|
||||
"grunt": ">=0.4.5",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.6",
|
||||
"grunt": ">=1.0.1",
|
||||
"grunt-accessibility": "~5.0.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-contrib-clean": "~1.0.0",
|
||||
"grunt-concurrent": "^2.3.1",
|
||||
"grunt-contrib-clean": "~1.1.0",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-eslint": "^19.0.0",
|
||||
"grunt-exec": "~1.0.1",
|
||||
"grunt-eslint": "^20.1.0",
|
||||
"grunt-exec": "~3.0.0",
|
||||
"grunt-execute": "^0.2.2",
|
||||
"grunt-jsdoc": "^2.1.0",
|
||||
"grunt-webpack": "^2.0.1",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"grunt-jsdoc": "^2.2.1",
|
||||
"grunt-webpack": "^3.0.2",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"imports-loader": "^0.7.1",
|
||||
"ink-docstrap": "^1.1.4",
|
||||
"less": "^2.7.2",
|
||||
"less-loader": "^4.0.2",
|
||||
"style-loader": "^0.15.0",
|
||||
"url-loader": "^0.5.8",
|
||||
"web-resource-inliner": "^4.1.0",
|
||||
"webpack": "^2.2.1"
|
||||
"ink-docstrap": "^1.3.2",
|
||||
"jsdoc-babel": "^0.3.0",
|
||||
"less": "^2.7.3",
|
||||
"less-loader": "^4.0.5",
|
||||
"postcss-css-variables": "^0.8.0",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.10",
|
||||
"style-loader": "^0.19.1",
|
||||
"url-loader": "^0.6.2",
|
||||
"val-loader": "^1.1.0",
|
||||
"web-resource-inliner": "^4.2.1",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-dev-server": "^2.11.1",
|
||||
"webpack-node-externals": "^1.6.0",
|
||||
"worker-loader": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bignumber.js": "^6.0.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"bootstrap-colorpicker": "^2.5.1",
|
||||
"bootstrap-colorpicker": "^2.5.2",
|
||||
"bootstrap-switch": "^3.3.4",
|
||||
"crypto-api": "^0.6.2",
|
||||
"crypto-api": "^0.7.5",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"diff": "^3.2.0",
|
||||
"escodegen": "^1.8.1",
|
||||
"diff": "^3.4.0",
|
||||
"escodegen": "^1.9.0",
|
||||
"esmangle": "^1.0.1",
|
||||
"esprima": "^3.1.3",
|
||||
"google-code-prettify": "^1.0.5",
|
||||
"jquery": "^3.1.1",
|
||||
"esprima": "^4.0.0",
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^1.3.3",
|
||||
"highlight.js": "^9.12.0",
|
||||
"jquery": "^3.3.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.7.0",
|
||||
"jsbn": "^1.1.0",
|
||||
"jsrsasign": "^7.1.0",
|
||||
"moment": "^2.17.1",
|
||||
"moment-timezone": "^0.5.11",
|
||||
"jsonpath": "^1.0.0",
|
||||
"jsrsasign": "8.0.4",
|
||||
"lodash": "^4.17.4",
|
||||
"loglevel": "^1.6.1",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"moment": "^2.20.1",
|
||||
"moment-timezone": "^0.5.14",
|
||||
"node-forge": "^0.7.1",
|
||||
"node-md6": "^0.1.0",
|
||||
"nwmatcher": "^1.4.3",
|
||||
"otp": "^0.1.3",
|
||||
"sladex-blowfish": "^0.8.1",
|
||||
"sortablejs": "^1.5.1",
|
||||
"split.js": "^1.2.0",
|
||||
"vkbeautify": "^0.99.1",
|
||||
"sortablejs": "^1.7.0",
|
||||
"split.js": "^1.3.5",
|
||||
"utf8": "^3.0.0",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.1.27",
|
||||
"xpath": "0.0.24",
|
||||
"zlibjs": "^0.2.0"
|
||||
"xpath": "0.0.27",
|
||||
"xregexp": "^4.0.0",
|
||||
"zlibjs": "^0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "grunt dev",
|
||||
"build": "grunt prod",
|
||||
"test": "grunt test",
|
||||
"docs": "grunt docs"
|
||||
|
||||
15
postcss.config.js
Normal file
15
postcss.config.js
Normal 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
|
||||
}),
|
||||
]
|
||||
};
|
||||
@@ -11,7 +11,7 @@ import Recipe from "./Recipe.js";
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
var Chef = function() {
|
||||
const Chef = function() {
|
||||
this.dish = new Dish();
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ var Chef = function() {
|
||||
/**
|
||||
* Runs the recipe over the input.
|
||||
*
|
||||
* @param {string} inputText - The input data as a string
|
||||
* @param {string|ArrayBuffer} input - The input data as a string or ArrayBuffer
|
||||
* @param {Object[]} recipeConfig - The recipe configuration object
|
||||
* @param {Object} options - The options object storing various user choices
|
||||
* @param {boolean} options.attempHighlight - Whether or not to attempt highlighting
|
||||
@@ -30,22 +30,18 @@ var Chef = function() {
|
||||
* @returns {string} response.result - The output of the recipe
|
||||
* @returns {string} response.type - The data type of the result
|
||||
* @returns {number} response.progress - The position that we have got to in the recipe
|
||||
* @returns {number} response.options - The app options object (which may have been changed)
|
||||
* @returns {number} response.duration - The number of ms it took to execute the recipe
|
||||
* @returns {number} response.error - The error object thrown by a failed operation (false if no error)
|
||||
*/
|
||||
Chef.prototype.bake = function(inputText, recipeConfig, options, progress, step) {
|
||||
var startTime = new Date().getTime(),
|
||||
Chef.prototype.bake = async function(input, recipeConfig, options, progress, step) {
|
||||
log.debug("Chef baking");
|
||||
const startTime = new Date().getTime(),
|
||||
recipe = new Recipe(recipeConfig),
|
||||
containsFc = recipe.containsFlowControl(),
|
||||
error = false;
|
||||
notUTF8 = options && options.hasOwnProperty("treatAsUtf8") && !options.treatAsUtf8;
|
||||
let error = false;
|
||||
|
||||
// Reset attemptHighlight flag
|
||||
if (options.hasOwnProperty("attemptHighlight")) {
|
||||
options.attemptHighlight = true;
|
||||
}
|
||||
|
||||
if (containsFc) options.attemptHighlight = false;
|
||||
if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
||||
|
||||
// Clean up progress
|
||||
if (progress >= recipeConfig.length) {
|
||||
@@ -68,25 +64,32 @@ Chef.prototype.bake = function(inputText, recipeConfig, options, progress, step)
|
||||
|
||||
// If starting from scratch, load data
|
||||
if (progress === 0) {
|
||||
this.dish.set(inputText, Dish.STRING);
|
||||
const type = input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING;
|
||||
this.dish.set(input, type);
|
||||
}
|
||||
|
||||
try {
|
||||
progress = recipe.execute(this.dish, progress);
|
||||
progress = await recipe.execute(this.dish, progress);
|
||||
} catch (err) {
|
||||
// Return the error in the result so that everything else gets correctly updated
|
||||
// rather than throwing it here and losing state info.
|
||||
error = err;
|
||||
log.error(err);
|
||||
error = {
|
||||
displayStr: err.displayStr,
|
||||
};
|
||||
progress = err.progress;
|
||||
}
|
||||
|
||||
// Depending on the size of the output, we may send it back as a string or an ArrayBuffer.
|
||||
// This can prevent unnecessary casting as an ArrayBuffer can be easily downloaded as a file.
|
||||
// The threshold is specified in KiB.
|
||||
const threshold = (options.ioDisplayThreshold || 1024) * 1024;
|
||||
const returnType = this.dish.size() > threshold ? Dish.ARRAY_BUFFER : Dish.STRING;
|
||||
|
||||
return {
|
||||
result: this.dish.type === Dish.HTML ?
|
||||
this.dish.get(Dish.HTML) :
|
||||
this.dish.get(Dish.STRING),
|
||||
this.dish.get(Dish.HTML, notUTF8) :
|
||||
this.dish.get(returnType, notUTF8),
|
||||
type: Dish.enumLookup(this.dish.type),
|
||||
progress: progress,
|
||||
options: options,
|
||||
duration: new Date().getTime() - startTime,
|
||||
error: error
|
||||
};
|
||||
@@ -111,7 +114,9 @@ Chef.prototype.bake = function(inputText, recipeConfig, options, progress, step)
|
||||
* @returns {number} The time it took to run the silent bake in milliseconds.
|
||||
*/
|
||||
Chef.prototype.silentBake = function(recipeConfig) {
|
||||
var startTime = new Date().getTime(),
|
||||
log.debug("Running silent bake");
|
||||
|
||||
let startTime = new Date().getTime(),
|
||||
recipe = new Recipe(recipeConfig),
|
||||
dish = new Dish("", Dish.STRING);
|
||||
|
||||
@@ -123,4 +128,38 @@ Chef.prototype.silentBake = function(recipeConfig) {
|
||||
return new Date().getTime() - startTime;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates highlight offsets if possible.
|
||||
*
|
||||
* @param {Object[]} recipeConfig
|
||||
* @param {string} direction
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
* @returns {Object}
|
||||
*/
|
||||
Chef.prototype.calculateHighlights = function(recipeConfig, direction, pos) {
|
||||
const recipe = new Recipe(recipeConfig);
|
||||
const highlights = recipe.generateHighlightList();
|
||||
|
||||
if (!highlights) return false;
|
||||
|
||||
for (let i = 0; i < highlights.length; i++) {
|
||||
// Remove multiple highlights before processing again
|
||||
pos = [pos[0]];
|
||||
|
||||
const func = direction === "forward" ? highlights[i].f : highlights[i].b;
|
||||
|
||||
if (typeof func == "function") {
|
||||
pos = func(pos, highlights[i].args);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pos: pos,
|
||||
direction: direction
|
||||
};
|
||||
};
|
||||
|
||||
export default Chef;
|
||||
|
||||
211
src/core/ChefWorker.js
Normal file
211
src/core/ChefWorker.js
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Web Worker to handle communications between the front-end and the core.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import "babel-polyfill";
|
||||
import Chef from "./Chef.js";
|
||||
import OperationConfig from "./config/MetaConfig.js";
|
||||
import OpModules from "./config/modules/Default.js";
|
||||
|
||||
// Add ">" to the start of all log messages in the Chef Worker
|
||||
import loglevelMessagePrefix from "loglevel-message-prefix";
|
||||
|
||||
loglevelMessagePrefix(log, {
|
||||
prefixes: [],
|
||||
staticPrefixes: [">"],
|
||||
prefixFormat: "%p"
|
||||
});
|
||||
|
||||
|
||||
// Set up Chef instance
|
||||
self.chef = new Chef();
|
||||
|
||||
self.OpModules = OpModules;
|
||||
self.OperationConfig = OperationConfig;
|
||||
|
||||
// Tell the app that the worker has loaded and is ready to operate
|
||||
self.postMessage({
|
||||
action: "workerLoaded",
|
||||
data: {}
|
||||
});
|
||||
|
||||
/**
|
||||
* Respond to message from parent thread.
|
||||
*
|
||||
* Messages should have the following format:
|
||||
* {
|
||||
* action: "bake" | "silentBake",
|
||||
* data: {
|
||||
* input: {string},
|
||||
* recipeConfig: {[Object]},
|
||||
* options: {Object},
|
||||
* progress: {number},
|
||||
* step: {boolean}
|
||||
* } | undefined
|
||||
* }
|
||||
*/
|
||||
self.addEventListener("message", function(e) {
|
||||
// Handle message
|
||||
const r = e.data;
|
||||
log.debug("ChefWorker receiving command '" + r.action + "'");
|
||||
|
||||
switch (r.action) {
|
||||
case "bake":
|
||||
bake(r.data);
|
||||
break;
|
||||
case "silentBake":
|
||||
silentBake(r.data);
|
||||
break;
|
||||
case "docURL":
|
||||
// Used to set the URL of the current document so that scripts can be
|
||||
// imported into an inline worker.
|
||||
self.docURL = r.data;
|
||||
break;
|
||||
case "highlight":
|
||||
calculateHighlights(
|
||||
r.data.recipeConfig,
|
||||
r.data.direction,
|
||||
r.data.pos
|
||||
);
|
||||
break;
|
||||
case "setLogLevel":
|
||||
log.setLevel(r.data, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Baking handler
|
||||
*
|
||||
* @param {Object} data
|
||||
*/
|
||||
async function bake(data) {
|
||||
// Ensure the relevant modules are loaded
|
||||
loadRequiredModules(data.recipeConfig);
|
||||
|
||||
try {
|
||||
const response = await self.chef.bake(
|
||||
data.input, // The user's input
|
||||
data.recipeConfig, // The configuration of the recipe
|
||||
data.options, // Options set by the user
|
||||
data.progress, // The current position in the recipe
|
||||
data.step // Whether or not to take one step or execute the whole recipe
|
||||
);
|
||||
|
||||
self.postMessage({
|
||||
action: "bakeComplete",
|
||||
data: response
|
||||
});
|
||||
} catch (err) {
|
||||
self.postMessage({
|
||||
action: "bakeError",
|
||||
data: err
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Silent baking handler
|
||||
*/
|
||||
function silentBake(data) {
|
||||
const duration = self.chef.silentBake(data.recipeConfig);
|
||||
|
||||
self.postMessage({
|
||||
action: "silentBakeComplete",
|
||||
data: duration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that all required modules are loaded and loads them if not.
|
||||
*
|
||||
* @param {Object} recipeConfig
|
||||
*/
|
||||
function loadRequiredModules(recipeConfig) {
|
||||
recipeConfig.forEach(op => {
|
||||
let module = self.OperationConfig[op.op].module;
|
||||
|
||||
if (!OpModules.hasOwnProperty(module)) {
|
||||
log.info("Loading module " + module);
|
||||
self.sendStatusMessage("Loading module " + module);
|
||||
self.importScripts(self.docURL + "/" + module + ".js");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates highlight offsets if possible.
|
||||
*
|
||||
* @param {Object[]} recipeConfig
|
||||
* @param {string} direction
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
function calculateHighlights(recipeConfig, direction, pos) {
|
||||
pos = self.chef.calculateHighlights(recipeConfig, direction, pos);
|
||||
|
||||
self.postMessage({
|
||||
action: "highlightsCalculated",
|
||||
data: pos
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send status update to the app.
|
||||
*
|
||||
* @param {string} msg
|
||||
*/
|
||||
self.sendStatusMessage = function(msg) {
|
||||
self.postMessage({
|
||||
action: "statusMessage",
|
||||
data: msg
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send an option value update to the app.
|
||||
*
|
||||
* @param {string} option
|
||||
* @param {*} value
|
||||
*/
|
||||
self.setOption = function(option, value) {
|
||||
self.postMessage({
|
||||
action: "optionUpdate",
|
||||
data: {
|
||||
option: option,
|
||||
value: value
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send register values back to the app.
|
||||
*
|
||||
* @param {number} opIndex
|
||||
* @param {number} numPrevRegisters
|
||||
* @param {string[]} registers
|
||||
*/
|
||||
self.setRegisters = function(opIndex, numPrevRegisters, registers) {
|
||||
self.postMessage({
|
||||
action: "setRegisters",
|
||||
data: {
|
||||
opIndex: opIndex,
|
||||
numPrevRegisters: numPrevRegisters,
|
||||
registers: registers
|
||||
}
|
||||
});
|
||||
};
|
||||
137
src/core/Dish.js
137
src/core/Dish.js
@@ -1,20 +1,21 @@
|
||||
import Utils from "./Utils.js";
|
||||
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* The data being operated on by each operation.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @class
|
||||
* @param {byteArray|string|number} value - The value of the input data.
|
||||
* @param {byteArray|string|number|ArrayBuffer|BigNumber} value - The value of the input data.
|
||||
* @param {number} type - The data type of value, see Dish enums.
|
||||
*/
|
||||
var Dish = function(value, type) {
|
||||
this.value = value || typeof value == "string" ? value : null;
|
||||
this.type = type || Dish.BYTE_ARRAY;
|
||||
const Dish = function(value, type) {
|
||||
this.value = value || typeof value === "string" ? value : null;
|
||||
this.type = type || Dish.BYTE_ARRAY;
|
||||
};
|
||||
|
||||
|
||||
@@ -42,6 +43,18 @@ Dish.NUMBER = 2;
|
||||
* @enum
|
||||
*/
|
||||
Dish.HTML = 3;
|
||||
/**
|
||||
* Dish data type enum for ArrayBuffers.
|
||||
* @readonly
|
||||
* @enum
|
||||
*/
|
||||
Dish.ARRAY_BUFFER = 4;
|
||||
/**
|
||||
* Dish data type enum for BigNumbers.
|
||||
* @readonly
|
||||
* @enum
|
||||
*/
|
||||
Dish.BIG_NUMBER = 5;
|
||||
|
||||
|
||||
/**
|
||||
@@ -52,19 +65,22 @@ Dish.HTML = 3;
|
||||
* @returns {number} The data type enum value.
|
||||
*/
|
||||
Dish.typeEnum = function(typeStr) {
|
||||
switch (typeStr) {
|
||||
case "byteArray":
|
||||
case "Byte array":
|
||||
switch (typeStr.toLowerCase()) {
|
||||
case "bytearray":
|
||||
case "byte array":
|
||||
return Dish.BYTE_ARRAY;
|
||||
case "string":
|
||||
case "String":
|
||||
return Dish.STRING;
|
||||
case "number":
|
||||
case "Number":
|
||||
return Dish.NUMBER;
|
||||
case "html":
|
||||
case "HTML":
|
||||
return Dish.HTML;
|
||||
case "arraybuffer":
|
||||
case "array buffer":
|
||||
return Dish.ARRAY_BUFFER;
|
||||
case "bignumber":
|
||||
case "big number":
|
||||
return Dish.BIG_NUMBER;
|
||||
default:
|
||||
throw "Invalid data type string. No matching enum.";
|
||||
}
|
||||
@@ -75,8 +91,8 @@ Dish.typeEnum = function(typeStr) {
|
||||
* Returns the data type string for the given type enum.
|
||||
*
|
||||
* @static
|
||||
* @param {string} typeEnum - The enum value of the data type.
|
||||
* @returns {number} The data type as a string.
|
||||
* @param {number} typeEnum - The enum value of the data type.
|
||||
* @returns {string} The data type as a string.
|
||||
*/
|
||||
Dish.enumLookup = function(typeEnum) {
|
||||
switch (typeEnum) {
|
||||
@@ -88,6 +104,10 @@ Dish.enumLookup = function(typeEnum) {
|
||||
return "number";
|
||||
case Dish.HTML:
|
||||
return "html";
|
||||
case Dish.ARRAY_BUFFER:
|
||||
return "ArrayBuffer";
|
||||
case Dish.BIG_NUMBER:
|
||||
return "BigNumber";
|
||||
default:
|
||||
throw "Invalid data type enum. No matching type.";
|
||||
}
|
||||
@@ -97,15 +117,16 @@ Dish.enumLookup = function(typeEnum) {
|
||||
/**
|
||||
* Sets the data value and type and then validates them.
|
||||
*
|
||||
* @param {byteArray|string|number} value - The value of the input data.
|
||||
* @param {byteArray|string|number|ArrayBuffer|BigNumber} value - The value of the input data.
|
||||
* @param {number} type - The data type of value, see Dish enums.
|
||||
*/
|
||||
Dish.prototype.set = function(value, type) {
|
||||
log.debug("Dish type: " + Dish.enumLookup(type));
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
this.type = type;
|
||||
|
||||
if (!this.valid()) {
|
||||
var sample = Utils.truncate(JSON.stringify(this.value), 13);
|
||||
const sample = Utils.truncate(JSON.stringify(this.value), 13);
|
||||
throw "Data is not a valid " + Dish.enumLookup(type) + ": " + sample;
|
||||
}
|
||||
};
|
||||
@@ -115,11 +136,12 @@ Dish.prototype.set = function(value, type) {
|
||||
* Returns the value of the data in the type format specified.
|
||||
*
|
||||
* @param {number} type - The data type of value, see Dish enums.
|
||||
* @returns {byteArray|string|number} The value of the output data.
|
||||
* @param {boolean} [notUTF8] - Do not treat strings as UTF8.
|
||||
* @returns {byteArray|string|number|ArrayBuffer|BigNumber} The value of the output data.
|
||||
*/
|
||||
Dish.prototype.get = function(type) {
|
||||
Dish.prototype.get = function(type, notUTF8) {
|
||||
if (this.type !== type) {
|
||||
this.translate(type);
|
||||
this.translate(type, notUTF8);
|
||||
}
|
||||
return this.value;
|
||||
};
|
||||
@@ -129,37 +151,59 @@ Dish.prototype.get = function(type) {
|
||||
* Translates the data to the given type format.
|
||||
*
|
||||
* @param {number} toType - The data type of value, see Dish enums.
|
||||
* @param {boolean} [notUTF8] - Do not treat strings as UTF8.
|
||||
*/
|
||||
Dish.prototype.translate = function(toType) {
|
||||
Dish.prototype.translate = function(toType, notUTF8) {
|
||||
log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`);
|
||||
const byteArrayToStr = notUTF8 ? Utils.byteArrayToChars : Utils.byteArrayToUtf8;
|
||||
|
||||
// Convert data to intermediate byteArray type
|
||||
switch (this.type) {
|
||||
case Dish.STRING:
|
||||
this.value = this.value ? Utils.strToByteArray(this.value) : [];
|
||||
this.type = Dish.BYTE_ARRAY;
|
||||
break;
|
||||
case Dish.NUMBER:
|
||||
this.value = typeof this.value == "number" ? Utils.strToByteArray(this.value.toString()) : [];
|
||||
this.type = Dish.BYTE_ARRAY;
|
||||
break;
|
||||
case Dish.HTML:
|
||||
this.value = this.value ? Utils.strToByteArray(Utils.unescapeHtml(Utils.stripHtmlTags(this.value, true))) : [];
|
||||
this.type = Dish.BYTE_ARRAY;
|
||||
break;
|
||||
case Dish.ARRAY_BUFFER:
|
||||
// Array.from() would be nicer here, but it's slightly slower
|
||||
this.value = Array.prototype.slice.call(new Uint8Array(this.value));
|
||||
break;
|
||||
case Dish.BIG_NUMBER:
|
||||
this.value = this.value instanceof BigNumber ? Utils.strToByteArray(this.value.toFixed()) : [];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.type = Dish.BYTE_ARRAY;
|
||||
|
||||
// Convert from byteArray to toType
|
||||
switch (toType) {
|
||||
case Dish.STRING:
|
||||
case Dish.HTML:
|
||||
this.value = this.value ? Utils.byteArrayToUtf8(this.value) : "";
|
||||
this.value = this.value ? byteArrayToStr(this.value) : "";
|
||||
this.type = Dish.STRING;
|
||||
break;
|
||||
case Dish.NUMBER:
|
||||
this.value = this.value ? parseFloat(Utils.byteArrayToUtf8(this.value)) : 0;
|
||||
this.value = this.value ? parseFloat(byteArrayToStr(this.value)) : 0;
|
||||
this.type = Dish.NUMBER;
|
||||
break;
|
||||
case Dish.ARRAY_BUFFER:
|
||||
this.value = new Uint8Array(this.value).buffer;
|
||||
this.type = Dish.ARRAY_BUFFER;
|
||||
break;
|
||||
case Dish.BIG_NUMBER:
|
||||
try {
|
||||
this.value = new BigNumber(byteArrayToStr(this.value));
|
||||
} catch (err) {
|
||||
this.value = new BigNumber(NaN);
|
||||
}
|
||||
this.type = Dish.BIG_NUMBER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -180,8 +224,8 @@ Dish.prototype.valid = function() {
|
||||
}
|
||||
|
||||
// Check that every value is a number between 0 - 255
|
||||
for (var i = 0; i < this.value.length; i++) {
|
||||
if (typeof this.value[i] != "number" ||
|
||||
for (let i = 0; i < this.value.length; i++) {
|
||||
if (typeof this.value[i] !== "number" ||
|
||||
this.value[i] < 0 ||
|
||||
this.value[i] > 255) {
|
||||
return false;
|
||||
@@ -190,18 +234,41 @@ Dish.prototype.valid = function() {
|
||||
return true;
|
||||
case Dish.STRING:
|
||||
case Dish.HTML:
|
||||
if (typeof this.value == "string") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return typeof this.value === "string";
|
||||
case Dish.NUMBER:
|
||||
if (typeof this.value == "number") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return typeof this.value === "number";
|
||||
case Dish.ARRAY_BUFFER:
|
||||
return this.value instanceof ArrayBuffer;
|
||||
case Dish.BIG_NUMBER:
|
||||
return this.value instanceof BigNumber;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines how much space the Dish takes up.
|
||||
* Numbers in JavaScript are 64-bit floating point, however for the purposes of the Dish,
|
||||
* we measure how many bytes are taken up when the number is written as a string.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
Dish.prototype.size = function() {
|
||||
switch (this.type) {
|
||||
case Dish.BYTE_ARRAY:
|
||||
case Dish.STRING:
|
||||
case Dish.HTML:
|
||||
return this.value.length;
|
||||
case Dish.NUMBER:
|
||||
case Dish.BIG_NUMBER:
|
||||
return this.value.toString().length;
|
||||
case Dish.ARRAY_BUFFER:
|
||||
return this.value.byteLength;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default Dish;
|
||||
|
||||
@@ -13,22 +13,6 @@ import Dish from "./Dish.js";
|
||||
*/
|
||||
const FlowControl = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FORK_DELIM: "\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MERGE_DELIM: "\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FORK_IGNORE_ERRORS: false,
|
||||
|
||||
/**
|
||||
* Fork operation.
|
||||
*
|
||||
@@ -38,8 +22,8 @@ const FlowControl = {
|
||||
* @param {Operation[]} state.opList - The list of operations in the recipe.
|
||||
* @returns {Object} The updated state of the recipe.
|
||||
*/
|
||||
runFork: function(state) {
|
||||
var opList = state.opList,
|
||||
runFork: async function(state) {
|
||||
let opList = state.opList,
|
||||
inputType = opList[state.progress].inputType,
|
||||
outputType = opList[state.progress].outputType,
|
||||
input = state.dish.get(inputType),
|
||||
@@ -48,14 +32,15 @@ const FlowControl = {
|
||||
mergeDelim = ings[1],
|
||||
ignoreErrors = ings[2],
|
||||
subOpList = [],
|
||||
inputs = [];
|
||||
inputs = [],
|
||||
i;
|
||||
|
||||
if (input)
|
||||
inputs = input.split(splitDelim);
|
||||
|
||||
// Create subOpList for each tranche to operate on
|
||||
// (all remaining operations unless we encounter a Merge)
|
||||
for (var i = state.progress + 1; i < opList.length; i++) {
|
||||
for (i = state.progress + 1; i < opList.length; i++) {
|
||||
if (opList[i].name === "Merge" && !opList[i].isDisabled()) {
|
||||
break;
|
||||
} else {
|
||||
@@ -63,17 +48,29 @@ const FlowControl = {
|
||||
}
|
||||
}
|
||||
|
||||
var recipe = new Recipe(),
|
||||
let recipe = new Recipe(),
|
||||
output = "",
|
||||
progress = 0;
|
||||
|
||||
state.forkOffset += state.progress + 1;
|
||||
|
||||
recipe.addOperations(subOpList);
|
||||
|
||||
// Take a deep(ish) copy of the ingredient values
|
||||
const ingValues = subOpList.map(op => JSON.parse(JSON.stringify(op.getIngValues())));
|
||||
|
||||
// Run recipe over each tranche
|
||||
for (i = 0; i < inputs.length; i++) {
|
||||
var dish = new Dish(inputs[i], inputType);
|
||||
log.debug(`Entering tranche ${i + 1} of ${inputs.length}`);
|
||||
|
||||
// Baseline ing values for each tranche so that registers are reset
|
||||
subOpList.forEach((op, i) => {
|
||||
op.setIngValues(JSON.parse(JSON.stringify(ingValues[i])));
|
||||
});
|
||||
|
||||
const dish = new Dish(inputs[i], inputType);
|
||||
try {
|
||||
progress = recipe.execute(dish, 0);
|
||||
progress = await recipe.execute(dish, 0, state);
|
||||
} catch (err) {
|
||||
if (!ignoreErrors) {
|
||||
throw err;
|
||||
@@ -106,15 +103,72 @@ const FlowControl = {
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
* Register operation.
|
||||
*
|
||||
* @param {Object} state - The current state of the recipe.
|
||||
* @param {number} state.progress - The current position in the recipe.
|
||||
* @param {Dish} state.dish - The Dish being operated on.
|
||||
* @param {Operation[]} state.opList - The list of operations in the recipe.
|
||||
* @returns {Object} The updated state of the recipe.
|
||||
*/
|
||||
JUMP_NUM: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MAX_JUMPS: 10,
|
||||
runRegister: function(state) {
|
||||
const ings = state.opList[state.progress].getIngValues(),
|
||||
extractorStr = ings[0],
|
||||
i = ings[1],
|
||||
m = ings[2];
|
||||
|
||||
let modifiers = "";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
const extractor = new RegExp(extractorStr, modifiers),
|
||||
input = state.dish.get(Dish.STRING),
|
||||
registers = input.match(extractor);
|
||||
|
||||
if (!registers) return state;
|
||||
|
||||
if (ENVIRONMENT_IS_WORKER()) {
|
||||
self.setRegisters(state.forkOffset + state.progress, state.numRegisters, registers.slice(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces references to registers (e.g. $R0) with the contents of those registers.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
function replaceRegister(str) {
|
||||
// Replace references to registers ($Rn) with contents of registers
|
||||
return str.replace(/(\\*)\$R(\d{1,2})/g, (match, slashes, regNum) => {
|
||||
const index = parseInt(regNum, 10) + 1;
|
||||
if (index <= state.numRegisters || index >= state.numRegisters + registers.length)
|
||||
return match;
|
||||
if (slashes.length % 2 !== 0) return match.slice(1); // Remove escape
|
||||
return slashes + registers[index - state.numRegisters];
|
||||
});
|
||||
}
|
||||
|
||||
// Step through all subsequent ops and replace registers in args with extracted content
|
||||
for (let i = state.progress + 1; i < state.opList.length; i++) {
|
||||
if (state.opList[i].isDisabled()) continue;
|
||||
|
||||
let args = state.opList[i].getIngValues();
|
||||
args = args.map(arg => {
|
||||
if (typeof arg !== "string" && typeof arg !== "object") return arg;
|
||||
|
||||
if (typeof arg === "object" && arg.hasOwnProperty("string")) {
|
||||
arg.string = replaceRegister(arg.string);
|
||||
return arg;
|
||||
}
|
||||
return replaceRegister(arg);
|
||||
});
|
||||
state.opList[i].setIngValues(args);
|
||||
}
|
||||
|
||||
state.numRegisters += registers.length - 1;
|
||||
return state;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Jump operation.
|
||||
@@ -127,20 +181,19 @@ const FlowControl = {
|
||||
* @returns {Object} The updated state of the recipe.
|
||||
*/
|
||||
runJump: function(state) {
|
||||
var ings = state.opList[state.progress].getIngValues(),
|
||||
jumpNum = ings[0],
|
||||
maxJumps = ings[1];
|
||||
const ings = state.opList[state.progress].getIngValues(),
|
||||
label = ings[0],
|
||||
maxJumps = ings[1],
|
||||
jmpIndex = FlowControl._getLabelIndex(label, state);
|
||||
|
||||
if (jumpNum < 0) {
|
||||
jumpNum--;
|
||||
}
|
||||
|
||||
if (state.numJumps >= maxJumps) {
|
||||
if (state.numJumps >= maxJumps || jmpIndex === -1) {
|
||||
log.debug("Maximum jumps reached or label cannot be found");
|
||||
return state;
|
||||
}
|
||||
|
||||
state.progress += jumpNum;
|
||||
state.progress = jmpIndex;
|
||||
state.numJumps++;
|
||||
log.debug(`Jumping to label '${label}' at position ${jmpIndex} (jumps = ${state.numJumps})`);
|
||||
return state;
|
||||
},
|
||||
|
||||
@@ -156,23 +209,26 @@ const FlowControl = {
|
||||
* @returns {Object} The updated state of the recipe.
|
||||
*/
|
||||
runCondJump: function(state) {
|
||||
var ings = state.opList[state.progress].getIngValues(),
|
||||
const ings = state.opList[state.progress].getIngValues(),
|
||||
dish = state.dish,
|
||||
regexStr = ings[0],
|
||||
jumpNum = ings[1],
|
||||
maxJumps = ings[2];
|
||||
invert = ings[1],
|
||||
label = ings[2],
|
||||
maxJumps = ings[3],
|
||||
jmpIndex = FlowControl._getLabelIndex(label, state);
|
||||
|
||||
if (jumpNum < 0) {
|
||||
jumpNum--;
|
||||
}
|
||||
|
||||
if (state.numJumps >= maxJumps) {
|
||||
if (state.numJumps >= maxJumps || jmpIndex === -1) {
|
||||
log.debug("Maximum jumps reached or label cannot be found");
|
||||
return state;
|
||||
}
|
||||
|
||||
if (regexStr !== "" && dish.get(Dish.STRING).search(regexStr) > -1) {
|
||||
state.progress += jumpNum;
|
||||
state.numJumps++;
|
||||
if (regexStr !== "") {
|
||||
let strMatch = dish.get(Dish.STRING).search(regexStr) > -1;
|
||||
if (!invert && strMatch || invert && !strMatch) {
|
||||
state.progress = jmpIndex;
|
||||
state.numJumps++;
|
||||
log.debug(`Jumping to label '${label}' at position ${jmpIndex} (jumps = ${state.numJumps})`);
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -193,6 +249,41 @@ const FlowControl = {
|
||||
return state;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Comment operation.
|
||||
*
|
||||
* @param {Object} state - The current state of the recipe.
|
||||
* @param {number} state.progress - The current position in the recipe.
|
||||
* @param {Dish} state.dish - The Dish being operated on.
|
||||
* @param {Operation[]} state.opList - The list of operations in the recipe.
|
||||
* @returns {Object} The updated state of the recipe.
|
||||
*/
|
||||
runComment: function(state) {
|
||||
return state;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of a label.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} state
|
||||
* @param {string} name
|
||||
* @returns {number}
|
||||
*/
|
||||
_getLabelIndex: function(name, state) {
|
||||
for (let o = 0; o < state.opList.length; o++) {
|
||||
let operation = state.opList[o];
|
||||
if (operation.name === "Label"){
|
||||
let ings = operation.getIngValues();
|
||||
if (name === ings[0]) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
};
|
||||
|
||||
export default FlowControl;
|
||||
|
||||
@@ -11,7 +11,7 @@ import Utils from "./Utils.js";
|
||||
* @class
|
||||
* @param {Object} ingredientConfig
|
||||
*/
|
||||
var Ingredient = function(ingredientConfig) {
|
||||
const Ingredient = function(ingredientConfig) {
|
||||
this.name = "";
|
||||
this.type = "";
|
||||
this.value = null;
|
||||
@@ -63,6 +63,8 @@ Ingredient.prototype.setValue = function(value) {
|
||||
* @param {string} type - The name of the data type.
|
||||
*/
|
||||
Ingredient.prepare = function(data, type) {
|
||||
let number;
|
||||
|
||||
switch (type) {
|
||||
case "binaryString":
|
||||
case "binaryShortString":
|
||||
@@ -71,14 +73,14 @@ Ingredient.prepare = function(data, type) {
|
||||
case "byteArray":
|
||||
if (typeof data == "string") {
|
||||
data = data.replace(/\s+/g, "");
|
||||
return Utils.hexToByteArray(data);
|
||||
return Utils.fromHex(data);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
case "number":
|
||||
var number = parseFloat(data);
|
||||
number = parseFloat(data);
|
||||
if (isNaN(number)) {
|
||||
var sample = Utils.truncate(data.toString(), 10);
|
||||
const sample = Utils.truncate(data.toString(), 10);
|
||||
throw "Invalid ingredient value. Not a number: " + sample;
|
||||
}
|
||||
return number;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import Dish from "./Dish.js";
|
||||
import Ingredient from "./Ingredient.js";
|
||||
import OperationConfig from "./config/MetaConfig.js";
|
||||
import OpModules from "./config/modules/OpModules.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -11,10 +13,10 @@ import Ingredient from "./Ingredient.js";
|
||||
*
|
||||
* @class
|
||||
* @param {string} operationName
|
||||
* @param {Object} operationConfig
|
||||
*/
|
||||
var Operation = function(operationName, operationConfig) {
|
||||
const Operation = function(operationName) {
|
||||
this.name = operationName;
|
||||
this.module = "";
|
||||
this.description = "";
|
||||
this.inputType = -1;
|
||||
this.outputType = -1;
|
||||
@@ -25,8 +27,8 @@ var Operation = function(operationName, operationConfig) {
|
||||
this.disabled = false;
|
||||
this.ingList = [];
|
||||
|
||||
if (operationConfig) {
|
||||
this._parseConfig(operationConfig);
|
||||
if (OperationConfig.hasOwnProperty(this.name)) {
|
||||
this._parseConfig(OperationConfig[this.name]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,19 +40,28 @@ var Operation = function(operationName, operationConfig) {
|
||||
* @param {Object} operationConfig
|
||||
*/
|
||||
Operation.prototype._parseConfig = function(operationConfig) {
|
||||
this.module = operationConfig.module;
|
||||
this.description = operationConfig.description;
|
||||
this.inputType = Dish.typeEnum(operationConfig.inputType);
|
||||
this.outputType = Dish.typeEnum(operationConfig.outputType);
|
||||
this.run = operationConfig.run;
|
||||
this.highlight = operationConfig.highlight;
|
||||
this.highlightReverse = operationConfig.highlightReverse;
|
||||
this.flowControl = operationConfig.flowControl;
|
||||
this.run = OpModules[this.module][this.name];
|
||||
|
||||
for (var a = 0; a < operationConfig.args.length; a++) {
|
||||
var ingredientConfig = operationConfig.args[a];
|
||||
var ingredient = new Ingredient(ingredientConfig);
|
||||
for (let a = 0; a < operationConfig.args.length; a++) {
|
||||
const ingredientConfig = operationConfig.args[a];
|
||||
const ingredient = new Ingredient(ingredientConfig);
|
||||
this.addIngredient(ingredient);
|
||||
}
|
||||
|
||||
if (this.highlight === "func") {
|
||||
this.highlight = OpModules[this.module][`${this.name}-highlight`];
|
||||
}
|
||||
|
||||
if (this.highlightReverse === "func") {
|
||||
this.highlightReverse = OpModules[this.module][`${this.name}-highlightReverse`];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -60,13 +71,13 @@ Operation.prototype._parseConfig = function(operationConfig) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
Operation.prototype.getConfig = function() {
|
||||
var ingredientConfig = [];
|
||||
const ingredientConfig = [];
|
||||
|
||||
for (var o = 0; o < this.ingList.length; o++) {
|
||||
for (let o = 0; o < this.ingList.length; o++) {
|
||||
ingredientConfig.push(this.ingList[o].getConfig());
|
||||
}
|
||||
|
||||
var operationConfig = {
|
||||
const operationConfig = {
|
||||
"op": this.name,
|
||||
"args": ingredientConfig
|
||||
};
|
||||
@@ -91,7 +102,7 @@ Operation.prototype.addIngredient = function(ingredient) {
|
||||
* @param {Object[]} ingValues
|
||||
*/
|
||||
Operation.prototype.setIngValues = function(ingValues) {
|
||||
for (var i = 0; i < ingValues.length; i++) {
|
||||
for (let i = 0; i < ingValues.length; i++) {
|
||||
this.ingList[i].setValue(ingValues[i]);
|
||||
}
|
||||
};
|
||||
@@ -103,8 +114,8 @@ Operation.prototype.setIngValues = function(ingValues) {
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
Operation.prototype.getIngValues = function() {
|
||||
var ingValues = [];
|
||||
for (var i = 0; i < this.ingList.length; i++) {
|
||||
const ingValues = [];
|
||||
for (let i = 0; i < this.ingList.length; i++) {
|
||||
ingValues.push(this.ingList[i].value);
|
||||
}
|
||||
return ingValues;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Operation from "./Operation.js";
|
||||
import OperationConfig from "./config/OperationConfig.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -12,7 +11,7 @@ import OperationConfig from "./config/OperationConfig.js";
|
||||
* @class
|
||||
* @param {Object} recipeConfig
|
||||
*/
|
||||
var Recipe = function(recipeConfig) {
|
||||
const Recipe = function(recipeConfig) {
|
||||
this.opList = [];
|
||||
|
||||
if (recipeConfig) {
|
||||
@@ -28,10 +27,9 @@ var Recipe = function(recipeConfig) {
|
||||
* @param {Object} recipeConfig
|
||||
*/
|
||||
Recipe.prototype._parseConfig = function(recipeConfig) {
|
||||
for (var c = 0; c < recipeConfig.length; c++) {
|
||||
var operationName = recipeConfig[c].op;
|
||||
var operationConfig = OperationConfig[operationName];
|
||||
var operation = new Operation(operationName, operationConfig);
|
||||
for (let c = 0; c < recipeConfig.length; c++) {
|
||||
const operationName = recipeConfig[c].op;
|
||||
const operation = new Operation(operationName);
|
||||
operation.setIngValues(recipeConfig[c].args);
|
||||
operation.setBreakpoint(recipeConfig[c].breakpoint);
|
||||
operation.setDisabled(recipeConfig[c].disabled);
|
||||
@@ -46,9 +44,9 @@ Recipe.prototype._parseConfig = function(recipeConfig) {
|
||||
* @returns {*}
|
||||
*/
|
||||
Recipe.prototype.getConfig = function() {
|
||||
var recipeConfig = [];
|
||||
const recipeConfig = [];
|
||||
|
||||
for (var o = 0; o < this.opList.length; o++) {
|
||||
for (let o = 0; o < this.opList.length; o++) {
|
||||
recipeConfig.push(this.opList[o].getConfig());
|
||||
}
|
||||
|
||||
@@ -98,7 +96,7 @@ Recipe.prototype.setBreakpoint = function(position, value) {
|
||||
* @param {number} pos
|
||||
*/
|
||||
Recipe.prototype.removeBreaksUpTo = function(pos) {
|
||||
for (var i = 0; i < pos; i++) {
|
||||
for (let i = 0; i < pos; i++) {
|
||||
this.opList[i].setBreakpoint(false);
|
||||
}
|
||||
};
|
||||
@@ -110,7 +108,7 @@ Recipe.prototype.removeBreaksUpTo = function(pos) {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Recipe.prototype.containsFlowControl = function() {
|
||||
for (var i = 0; i < this.opList.length; i++) {
|
||||
for (let i = 0; i < this.opList.length; i++) {
|
||||
if (this.opList[i].isFlowControl()) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -125,7 +123,7 @@ Recipe.prototype.containsFlowControl = function() {
|
||||
* @returns (number}
|
||||
*/
|
||||
Recipe.prototype.lastOpIndex = function(startIndex) {
|
||||
var i = startIndex + 1 || 0,
|
||||
let i = startIndex + 1 || 0,
|
||||
op;
|
||||
|
||||
for (; i < this.opList.length; i++) {
|
||||
@@ -143,42 +141,53 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
|
||||
*
|
||||
* @param {Dish} dish
|
||||
* @param {number} [startFrom=0] - The index of the Operation to start executing from
|
||||
* @param {number} [forkState={}] - If this is a forked recipe, the state of the recipe up to this point
|
||||
* @returns {number} - The final progress through the recipe
|
||||
*/
|
||||
Recipe.prototype.execute = function(dish, startFrom) {
|
||||
startFrom = startFrom || 0;
|
||||
var op, input, output, numJumps = 0;
|
||||
Recipe.prototype.execute = async function(dish, startFrom = 0, forkState = {}) {
|
||||
let op, input, output,
|
||||
numJumps = 0,
|
||||
numRegisters = forkState.numRegisters || 0;
|
||||
|
||||
for (var i = startFrom; i < this.opList.length; i++) {
|
||||
log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`);
|
||||
|
||||
for (let i = startFrom; i < this.opList.length; i++) {
|
||||
op = this.opList[i];
|
||||
log.debug(`[${i}] ${op.name} ${JSON.stringify(op.getIngValues())}`);
|
||||
if (op.isDisabled()) {
|
||||
log.debug("Operation is disabled, skipping");
|
||||
continue;
|
||||
}
|
||||
if (op.isBreakpoint()) {
|
||||
log.debug("Pausing at breakpoint");
|
||||
return i;
|
||||
}
|
||||
|
||||
try {
|
||||
input = dish.get(op.inputType);
|
||||
log.debug("Executing operation");
|
||||
|
||||
if (op.isFlowControl()) {
|
||||
// Package up the current state
|
||||
var state = {
|
||||
"progress" : i,
|
||||
"dish" : dish,
|
||||
"opList" : this.opList,
|
||||
"numJumps" : numJumps
|
||||
let state = {
|
||||
"progress": i,
|
||||
"dish": dish,
|
||||
"opList": this.opList,
|
||||
"numJumps": numJumps,
|
||||
"numRegisters": numRegisters,
|
||||
"forkOffset": forkState.forkOffset || 0
|
||||
};
|
||||
|
||||
state = op.run(state);
|
||||
state = await op.run(state);
|
||||
i = state.progress;
|
||||
numJumps = state.numJumps;
|
||||
numRegisters = state.numRegisters;
|
||||
} else {
|
||||
output = op.run(input, op.getIngValues());
|
||||
output = await op.run(input, op.getIngValues());
|
||||
dish.set(output, op.outputType);
|
||||
}
|
||||
} catch (err) {
|
||||
var e = typeof err == "string" ? { message: err } : err;
|
||||
const e = typeof err == "string" ? { message: err } : err;
|
||||
|
||||
e.progress = i;
|
||||
if (e.fileName) {
|
||||
@@ -193,6 +202,7 @@ Recipe.prototype.execute = function(dish, startFrom) {
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("Recipe complete");
|
||||
return this.opList.length;
|
||||
};
|
||||
|
||||
@@ -213,8 +223,42 @@ Recipe.prototype.toString = function() {
|
||||
* @param {string} recipeStr
|
||||
*/
|
||||
Recipe.prototype.fromString = function(recipeStr) {
|
||||
var recipeConfig = JSON.parse(recipeStr);
|
||||
const recipeConfig = JSON.parse(recipeStr);
|
||||
this._parseConfig(recipeConfig);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
|
||||
* entire recipe supports highlighting.
|
||||
*
|
||||
* @returns {Object[]} highlights
|
||||
* @returns {function} highlights[].f
|
||||
* @returns {function} highlights[].b
|
||||
* @returns {Object[]} highlights[].args
|
||||
*/
|
||||
Recipe.prototype.generateHighlightList = function() {
|
||||
const highlights = [];
|
||||
|
||||
for (let i = 0; i < this.opList.length; i++) {
|
||||
let op = this.opList[i];
|
||||
if (op.isDisabled()) continue;
|
||||
|
||||
// If any breakpoints are set, do not attempt to highlight
|
||||
if (op.isBreakpoint()) return false;
|
||||
|
||||
// If any of the operations do not support highlighting, fail immediately.
|
||||
if (op.highlight === false || op.highlight === undefined) return false;
|
||||
|
||||
highlights.push({
|
||||
f: op.highlight,
|
||||
b: op.highlightReverse,
|
||||
args: op.getIngValues()
|
||||
});
|
||||
}
|
||||
|
||||
return highlights;
|
||||
};
|
||||
|
||||
|
||||
export default Recipe;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,8 @@ const Categories = [
|
||||
"From Base58",
|
||||
"To Base",
|
||||
"From Base",
|
||||
"To BCD",
|
||||
"From BCD",
|
||||
"To HTML Entity",
|
||||
"From HTML Entity",
|
||||
"URL Encode",
|
||||
@@ -61,7 +63,8 @@ const Categories = [
|
||||
"Hex to PEM",
|
||||
"Parse ASN.1 hex string",
|
||||
"Change IP format",
|
||||
"Text encoding",
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Swap endianness",
|
||||
]
|
||||
},
|
||||
@@ -76,8 +79,8 @@ const Categories = [
|
||||
"DES Decrypt",
|
||||
"Triple DES Encrypt",
|
||||
"Triple DES Decrypt",
|
||||
"Rabbit Encrypt",
|
||||
"Rabbit Decrypt",
|
||||
"RC2 Encrypt",
|
||||
"RC2 Decrypt",
|
||||
"RC4",
|
||||
"RC4 Drop",
|
||||
"ROT13",
|
||||
@@ -88,12 +91,15 @@ const Categories = [
|
||||
"Vigenère Decode",
|
||||
"To Morse Code",
|
||||
"From Morse Code",
|
||||
"Bifid Cipher Encode",
|
||||
"Bifid Cipher Decode",
|
||||
"Affine Cipher Encode",
|
||||
"Affine Cipher Decode",
|
||||
"Atbash Cipher",
|
||||
"Substitute",
|
||||
"Derive PBKDF2 key",
|
||||
"Derive EVP key",
|
||||
"Pseudo-Random Number Generator",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -108,7 +114,7 @@ const Categories = [
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Logical operations",
|
||||
name: "Arithmetic / Logic",
|
||||
ops: [
|
||||
"XOR",
|
||||
"XOR Brute Force",
|
||||
@@ -117,6 +123,15 @@ const Categories = [
|
||||
"AND",
|
||||
"ADD",
|
||||
"SUB",
|
||||
"Sum",
|
||||
"Subtract",
|
||||
"Multiply",
|
||||
"Divide",
|
||||
"Mean",
|
||||
"Median",
|
||||
"Standard Deviation",
|
||||
"Bit shift left",
|
||||
"Bit shift right",
|
||||
"Rotate left",
|
||||
"Rotate right",
|
||||
"ROT13",
|
||||
@@ -125,6 +140,7 @@ const Categories = [
|
||||
{
|
||||
name: "Networking",
|
||||
ops: [
|
||||
"HTTP request",
|
||||
"Strip HTTP headers",
|
||||
"Parse User Agent",
|
||||
"Parse IP range",
|
||||
@@ -143,7 +159,8 @@ const Categories = [
|
||||
{
|
||||
name: "Language",
|
||||
ops: [
|
||||
"Text encoding",
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Unescape Unicode Characters",
|
||||
]
|
||||
},
|
||||
@@ -162,15 +179,17 @@ const Categories = [
|
||||
"Unique",
|
||||
"Split",
|
||||
"Filter",
|
||||
"Head",
|
||||
"Tail",
|
||||
"Count occurrences",
|
||||
"Expand alphabet range",
|
||||
"Parse escaped string",
|
||||
"Drop bytes",
|
||||
"Take bytes",
|
||||
"Pad lines",
|
||||
"Find / Replace",
|
||||
"Regular expression",
|
||||
"Offset checker",
|
||||
"Hamming Distance",
|
||||
"Convert distance",
|
||||
"Convert area",
|
||||
"Convert mass",
|
||||
@@ -179,6 +198,10 @@ const Categories = [
|
||||
"Parse UNIX file permissions",
|
||||
"Swap endianness",
|
||||
"Parse colour code",
|
||||
"Escape string",
|
||||
"Unescape string",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Sleep",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -188,7 +211,10 @@ const Categories = [
|
||||
"Translate DateTime Format",
|
||||
"From UNIX Timestamp",
|
||||
"To UNIX Timestamp",
|
||||
"Windows Filetime to UNIX Timestamp",
|
||||
"UNIX Timestamp to Windows Filetime",
|
||||
"Extract dates",
|
||||
"Sleep",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -204,7 +230,9 @@ const Categories = [
|
||||
"Extract dates",
|
||||
"Regular expression",
|
||||
"XPath expression",
|
||||
"JPath expression",
|
||||
"CSS selector",
|
||||
"Extract EXIF",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -231,20 +259,24 @@ const Categories = [
|
||||
"MD2",
|
||||
"MD4",
|
||||
"MD5",
|
||||
"MD6",
|
||||
"SHA0",
|
||||
"SHA1",
|
||||
"SHA224",
|
||||
"SHA256",
|
||||
"SHA384",
|
||||
"SHA512",
|
||||
"SHA2",
|
||||
"SHA3",
|
||||
"RIPEMD-160",
|
||||
"Keccak",
|
||||
"Shake",
|
||||
"RIPEMD",
|
||||
"HAS-160",
|
||||
"Whirlpool",
|
||||
"Snefru",
|
||||
"HMAC",
|
||||
"Fletcher-8 Checksum",
|
||||
"Fletcher-16 Checksum",
|
||||
"Fletcher-32 Checksum",
|
||||
"Fletcher-64 Checksum",
|
||||
"Adler-32 Checksum",
|
||||
"CRC-16 Checksum",
|
||||
"CRC-32 Checksum",
|
||||
"TCP/IP Checksum",
|
||||
]
|
||||
@@ -266,9 +298,15 @@ const Categories = [
|
||||
"CSS Beautify",
|
||||
"CSS Minify",
|
||||
"XPath expression",
|
||||
"JPath expression",
|
||||
"CSS selector",
|
||||
"PHP Deserialize",
|
||||
"Microsoft Script Decoder",
|
||||
"Strip HTML tags",
|
||||
"Diff",
|
||||
"To Snake case",
|
||||
"To Camel case",
|
||||
"To Kebab case",
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -276,9 +314,17 @@ const Categories = [
|
||||
ops: [
|
||||
"Entropy",
|
||||
"Frequency distribution",
|
||||
"Chi Square",
|
||||
"Detect File Type",
|
||||
"Scan for Embedded Files",
|
||||
"Disassemble x86",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Generate UUID",
|
||||
"Generate TOTP",
|
||||
"Generate HOTP",
|
||||
"Render Image",
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
"Numberwang",
|
||||
]
|
||||
},
|
||||
@@ -287,9 +333,12 @@ const Categories = [
|
||||
ops: [
|
||||
"Fork",
|
||||
"Merge",
|
||||
"Register",
|
||||
"Label",
|
||||
"Jump",
|
||||
"Conditional Jump",
|
||||
"Return",
|
||||
"Comment"
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
21
src/core/config/modules/CharEnc.js
Normal file
21
src/core/config/modules/CharEnc.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import CharEnc from "../../operations/CharEnc.js";
|
||||
|
||||
|
||||
/**
|
||||
* CharEnc module.
|
||||
*
|
||||
* Libraries:
|
||||
* - cptable
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.CharEnc = {
|
||||
"Encode text": CharEnc.runEncode,
|
||||
"Decode text": CharEnc.runDecode,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
44
src/core/config/modules/Ciphers.js
Normal file
44
src/core/config/modules/Ciphers.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import Cipher from "../../operations/Cipher.js";
|
||||
|
||||
|
||||
/**
|
||||
* Ciphers module.
|
||||
*
|
||||
* Libraries:
|
||||
* - CryptoJS
|
||||
* - Blowfish
|
||||
* - Forge
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Ciphers = {
|
||||
"AES Encrypt": Cipher.runAesEnc,
|
||||
"AES Decrypt": Cipher.runAesDec,
|
||||
"Blowfish Encrypt": Cipher.runBlowfishEnc,
|
||||
"Blowfish Decrypt": Cipher.runBlowfishDec,
|
||||
"DES Encrypt": Cipher.runDesEnc,
|
||||
"DES Decrypt": Cipher.runDesDec,
|
||||
"Triple DES Encrypt": Cipher.runTripleDesEnc,
|
||||
"Triple DES Decrypt": Cipher.runTripleDesDec,
|
||||
"Derive PBKDF2 key": Cipher.runPbkdf2,
|
||||
"Derive EVP key": Cipher.runEvpkdf,
|
||||
"RC4": Cipher.runRc4,
|
||||
"RC4 Drop": Cipher.runRc4drop,
|
||||
"RC2 Encrypt": Cipher.runRc2Enc,
|
||||
"RC2 Decrypt": Cipher.runRc2Dec,
|
||||
"Vigenère Encode": Cipher.runVigenereEnc,
|
||||
"Vigenère Decode": Cipher.runVigenereDec,
|
||||
"Bifid Cipher Encode": Cipher.runBifidEnc,
|
||||
"Bifid Cipher Decode": Cipher.runBifidDec,
|
||||
"Affine Cipher Encode": Cipher.runAffineEnc,
|
||||
"Affine Cipher Decode": Cipher.runAffineDec,
|
||||
"Atbash Cipher": Cipher.runAtbash,
|
||||
"Substitute": Cipher.runSubstitute,
|
||||
"Pseudo-Random Number Generator": Cipher.runPRNG,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
44
src/core/config/modules/Code.js
Normal file
44
src/core/config/modules/Code.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import JS from "../../operations/JS.js";
|
||||
import Code from "../../operations/Code.js";
|
||||
|
||||
|
||||
/**
|
||||
* Code module.
|
||||
*
|
||||
* Libraries:
|
||||
* - lodash
|
||||
* - vkbeautify
|
||||
* - xmldom
|
||||
* - xpath
|
||||
* - jpath
|
||||
* - highlight.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Code = {
|
||||
"JavaScript Parser": JS.runParse,
|
||||
"JavaScript Beautify": JS.runBeautify,
|
||||
"JavaScript Minify": JS.runMinify,
|
||||
"Syntax highlighter": Code.runSyntaxHighlight,
|
||||
"Generic Code Beautify": Code.runGenericBeautify,
|
||||
"JSON Beautify": Code.runJsonBeautify,
|
||||
"JSON Minify": Code.runJsonMinify,
|
||||
"XML Beautify": Code.runXmlBeautify,
|
||||
"XML Minify": Code.runXmlMinify,
|
||||
"SQL Beautify": Code.runSqlBeautify,
|
||||
"SQL Minify": Code.runSqlMinify,
|
||||
"CSS Beautify": Code.runCssBeautify,
|
||||
"CSS Minify": Code.runCssMinify,
|
||||
"XPath expression": Code.runXpath,
|
||||
"CSS selector": Code.runCSSQuery,
|
||||
"To Snake case": Code.runToSnakeCase,
|
||||
"To Camel case": Code.runToCamelCase,
|
||||
"To Kebab case": Code.runToKebabCase,
|
||||
"JPath expression": Code.runJpath,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
32
src/core/config/modules/Compression.js
Normal file
32
src/core/config/modules/Compression.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import Compress from "../../operations/Compress.js";
|
||||
|
||||
|
||||
/**
|
||||
* Compression module.
|
||||
*
|
||||
* Libraries:
|
||||
* - zlib.js
|
||||
* - bzip2.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Compression = {
|
||||
"Raw Deflate": Compress.runRawDeflate,
|
||||
"Raw Inflate": Compress.runRawInflate,
|
||||
"Zlib Deflate": Compress.runZlibDeflate,
|
||||
"Zlib Inflate": Compress.runZlibInflate,
|
||||
"Gzip": Compress.runGzip,
|
||||
"Gunzip": Compress.runGunzip,
|
||||
"Zip": Compress.runPkzip,
|
||||
"Unzip": Compress.runPkunzip,
|
||||
"Bzip2 Decompress": Compress.runBzip2Decompress,
|
||||
"Tar": Compress.runTar,
|
||||
"Untar": Compress.runUntar,
|
||||
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
194
src/core/config/modules/Default.js
Normal file
194
src/core/config/modules/Default.js
Normal file
@@ -0,0 +1,194 @@
|
||||
import FlowControl from "../../FlowControl.js";
|
||||
import Arithmetic from "../../operations/Arithmetic.js";
|
||||
import Base from "../../operations/Base.js";
|
||||
import Base58 from "../../operations/Base58.js";
|
||||
import Base64 from "../../operations/Base64.js";
|
||||
import BCD from "../../operations/BCD.js";
|
||||
import BitwiseOp from "../../operations/BitwiseOp.js";
|
||||
import ByteRepr from "../../operations/ByteRepr.js";
|
||||
import Convert from "../../operations/Convert.js";
|
||||
import DateTime from "../../operations/DateTime.js";
|
||||
import Endian from "../../operations/Endian.js";
|
||||
import Entropy from "../../operations/Entropy.js";
|
||||
import Filetime from "../../operations/Filetime.js";
|
||||
import FileType from "../../operations/FileType.js";
|
||||
import Hexdump from "../../operations/Hexdump.js";
|
||||
import HTML from "../../operations/HTML.js";
|
||||
import MAC from "../../operations/MAC.js";
|
||||
import MorseCode from "../../operations/MorseCode.js";
|
||||
import MS from "../../operations/MS.js";
|
||||
import NetBIOS from "../../operations/NetBIOS.js";
|
||||
import Numberwang from "../../operations/Numberwang.js";
|
||||
import OS from "../../operations/OS.js";
|
||||
import OTP from "../../operations/OTP.js";
|
||||
import PHP from "../../operations/PHP.js";
|
||||
import QuotedPrintable from "../../operations/QuotedPrintable.js";
|
||||
import Rotate from "../../operations/Rotate.js";
|
||||
import SeqUtils from "../../operations/SeqUtils.js";
|
||||
import StrUtils from "../../operations/StrUtils.js";
|
||||
import Tidy from "../../operations/Tidy.js";
|
||||
import Unicode from "../../operations/Unicode.js";
|
||||
import UUID from "../../operations/UUID.js";
|
||||
|
||||
/**
|
||||
* Default module.
|
||||
*
|
||||
* The Default module is for operations that are expected to be very commonly used or
|
||||
* do not require any libraries. This module is loaded into the app at compile time.
|
||||
*
|
||||
* Libraries:
|
||||
* - Utils.js
|
||||
* - otp
|
||||
* - crypto
|
||||
* - bignumber.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Default = {
|
||||
"To Hexdump": Hexdump.runTo,
|
||||
"From Hexdump": Hexdump.runFrom,
|
||||
"To Hex": ByteRepr.runToHex,
|
||||
"From Hex": ByteRepr.runFromHex,
|
||||
"To Octal": ByteRepr.runToOct,
|
||||
"From Octal": ByteRepr.runFromOct,
|
||||
"To Charcode": ByteRepr.runToCharcode,
|
||||
"From Charcode": ByteRepr.runFromCharcode,
|
||||
"To Decimal": ByteRepr.runToDecimal,
|
||||
"From Decimal": ByteRepr.runFromDecimal,
|
||||
"To Binary": ByteRepr.runToBinary,
|
||||
"From Binary": ByteRepr.runFromBinary,
|
||||
"To Hex Content": ByteRepr.runToHexContent,
|
||||
"From Hex Content": ByteRepr.runFromHexContent,
|
||||
"To Base64": Base64.runTo,
|
||||
"From Base64": Base64.runFrom,
|
||||
"Show Base64 offsets": Base64.runOffsets,
|
||||
"To Base32": Base64.runTo32,
|
||||
"From Base32": Base64.runFrom32,
|
||||
"To Base58": Base58.runTo,
|
||||
"From Base58": Base58.runFrom,
|
||||
"To Base": Base.runTo,
|
||||
"From Base": Base.runFrom,
|
||||
"To BCD": BCD.runToBCD,
|
||||
"From BCD": BCD.runFromBCD,
|
||||
"To HTML Entity": HTML.runToEntity,
|
||||
"From HTML Entity": HTML.runFromEntity,
|
||||
"Strip HTML tags": HTML.runStripTags,
|
||||
"Parse colour code": HTML.runParseColourCode,
|
||||
"Unescape Unicode Characters": Unicode.runUnescape,
|
||||
"To Quoted Printable": QuotedPrintable.runTo,
|
||||
"From Quoted Printable": QuotedPrintable.runFrom,
|
||||
"Swap endianness": Endian.runSwapEndianness,
|
||||
"ROT13": Rotate.runRot13,
|
||||
"ROT47": Rotate.runRot47,
|
||||
"Rotate left": Rotate.runRotl,
|
||||
"Rotate right": Rotate.runRotr,
|
||||
"Bit shift left": BitwiseOp.runBitShiftLeft,
|
||||
"Bit shift right": BitwiseOp.runBitShiftRight,
|
||||
"XOR": BitwiseOp.runXor,
|
||||
"XOR Brute Force": BitwiseOp.runXorBrute,
|
||||
"OR": BitwiseOp.runXor,
|
||||
"NOT": BitwiseOp.runNot,
|
||||
"AND": BitwiseOp.runAnd,
|
||||
"ADD": BitwiseOp.runAdd,
|
||||
"SUB": BitwiseOp.runSub,
|
||||
"To Morse Code": MorseCode.runTo,
|
||||
"From Morse Code": MorseCode.runFrom,
|
||||
"Format MAC addresses": MAC.runFormat,
|
||||
"Encode NetBIOS Name": NetBIOS.runEncodeName,
|
||||
"Decode NetBIOS Name": NetBIOS.runDecodeName,
|
||||
"Offset checker": StrUtils.runOffsetChecker,
|
||||
"To Upper case": StrUtils.runUpper,
|
||||
"To Lower case": StrUtils.runLower,
|
||||
"Split": StrUtils.runSplit,
|
||||
"Filter": StrUtils.runFilter,
|
||||
"Escape string": StrUtils.runEscape,
|
||||
"Unescape string": StrUtils.runUnescape,
|
||||
"Head": StrUtils.runHead,
|
||||
"Tail": StrUtils.runTail,
|
||||
"Hamming Distance": StrUtils.runHamming,
|
||||
"Remove whitespace": Tidy.runRemoveWhitespace,
|
||||
"Remove null bytes": Tidy.runRemoveNulls,
|
||||
"Drop bytes": Tidy.runDropBytes,
|
||||
"Take bytes": Tidy.runTakeBytes,
|
||||
"Pad lines": Tidy.runPad,
|
||||
"Reverse": SeqUtils.runReverse,
|
||||
"Sort": SeqUtils.runSort,
|
||||
"Unique": SeqUtils.runUnique,
|
||||
"Count occurrences": SeqUtils.runCount,
|
||||
"Add line numbers": SeqUtils.runAddLineNumbers,
|
||||
"Remove line numbers": SeqUtils.runRemoveLineNumbers,
|
||||
"Expand alphabet range": SeqUtils.runExpandAlphRange,
|
||||
"Convert distance": Convert.runDistance,
|
||||
"Convert area": Convert.runArea,
|
||||
"Convert mass": Convert.runMass,
|
||||
"Convert speed": Convert.runSpeed,
|
||||
"Convert data units": Convert.runDataSize,
|
||||
"Parse UNIX file permissions": OS.runParseUnixPerms,
|
||||
"Parse DateTime": DateTime.runParse,
|
||||
"Translate DateTime Format": DateTime.runTranslateFormat,
|
||||
"From UNIX Timestamp": DateTime.runFromUnixTimestamp,
|
||||
"To UNIX Timestamp": DateTime.runToUnixTimestamp,
|
||||
"Sleep": DateTime.runSleep,
|
||||
"Microsoft Script Decoder": MS.runDecodeScript,
|
||||
"Entropy": Entropy.runEntropy,
|
||||
"Frequency distribution": Entropy.runFreqDistrib,
|
||||
"Chi Square": Entropy.runChiSq,
|
||||
"Detect File Type": FileType.runDetect,
|
||||
"Scan for Embedded Files": FileType.runScanForEmbeddedFiles,
|
||||
"Generate UUID": UUID.runGenerateV4,
|
||||
"Numberwang": Numberwang.run,
|
||||
"Generate TOTP": OTP.runTOTP,
|
||||
"Generate HOTP": OTP.runHOTP,
|
||||
"Fork": FlowControl.runFork,
|
||||
"Merge": FlowControl.runMerge,
|
||||
"Register": FlowControl.runRegister,
|
||||
"Label": FlowControl.runComment,
|
||||
"Jump": FlowControl.runJump,
|
||||
"Conditional Jump": FlowControl.runCondJump,
|
||||
"Return": FlowControl.runReturn,
|
||||
"Comment": FlowControl.runComment,
|
||||
"PHP Deserialize": PHP.runDeserialize,
|
||||
"Sum": Arithmetic.runSum,
|
||||
"Subtract": Arithmetic.runSub,
|
||||
"Multiply": Arithmetic.runMulti,
|
||||
"Divide": Arithmetic.runDiv,
|
||||
"Mean": Arithmetic.runMean,
|
||||
"Median": Arithmetic.runMedian,
|
||||
"Standard Deviation": Arithmetic.runStdDev,
|
||||
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
|
||||
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
|
||||
|
||||
|
||||
/*
|
||||
Highlighting functions.
|
||||
|
||||
This is a temporary solution as highlighting should be entirely
|
||||
overhauled at some point.
|
||||
*/
|
||||
"From Base64-highlight": Base64.highlightFrom,
|
||||
"From Base64-highlightReverse": Base64.highlightTo,
|
||||
"To Base64-highlight": Base64.highlightTo,
|
||||
"To Base64-highlightReverse": Base64.highlightFrom,
|
||||
"From Hex-highlight": ByteRepr.highlightFrom,
|
||||
"From Hex-highlightReverse": ByteRepr.highlightTo,
|
||||
"To Hex-highlight": ByteRepr.highlightTo,
|
||||
"To Hex-highlightReverse": ByteRepr.highlightFrom,
|
||||
"From Charcode-highlight": ByteRepr.highlightFrom,
|
||||
"From Charcode-highlightReverse": ByteRepr.highlightTo,
|
||||
"To Charcode-highlight": ByteRepr.highlightTo,
|
||||
"To Charcode-highlightReverse": ByteRepr.highlightFrom,
|
||||
"From Binary-highlight": ByteRepr.highlightFromBinary,
|
||||
"From Binary-highlightReverse": ByteRepr.highlightToBinary,
|
||||
"To Binary-highlight": ByteRepr.highlightToBinary,
|
||||
"To Binary-highlightReverse": ByteRepr.highlightFromBinary,
|
||||
"From Hexdump-highlight": Hexdump.highlightFrom,
|
||||
"From Hexdump-highlightReverse": Hexdump.highlightTo,
|
||||
"To Hexdump-highlight": Hexdump.highlightTo,
|
||||
"To Hexdump-highlightReverse": Hexdump.highlightFrom,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
20
src/core/config/modules/Diff.js
Normal file
20
src/core/config/modules/Diff.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import Diff from "../../operations/Diff.js";
|
||||
|
||||
|
||||
/**
|
||||
* Diff module.
|
||||
*
|
||||
* Libraries:
|
||||
* - JsDIff
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Diff = {
|
||||
"Diff": Diff.runDiff,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
21
src/core/config/modules/Encodings.js
Normal file
21
src/core/config/modules/Encodings.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import Punycode from "../../operations/Punycode.js";
|
||||
|
||||
|
||||
/**
|
||||
* Encodings module.
|
||||
*
|
||||
* Libraries:
|
||||
* - punycode
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Encodings = {
|
||||
"To Punycode": Punycode.runToAscii,
|
||||
"From Punycode": Punycode.runToUnicode,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
22
src/core/config/modules/HTTP.js
Normal file
22
src/core/config/modules/HTTP.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import HTTP from "../../operations/HTTP.js";
|
||||
|
||||
|
||||
/**
|
||||
* HTTP module.
|
||||
*
|
||||
* Libraries:
|
||||
* - UAS_parser
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.HTTP = {
|
||||
"HTTP request": HTTP.runHTTPRequest,
|
||||
"Strip HTTP headers": HTTP.runStripHeaders,
|
||||
"Parse User Agent": HTTP.runParseUserAgent,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
48
src/core/config/modules/Hashing.js
Normal file
48
src/core/config/modules/Hashing.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import Checksum from "../../operations/Checksum.js";
|
||||
import Hash from "../../operations/Hash.js";
|
||||
|
||||
|
||||
/**
|
||||
* Hashing module.
|
||||
*
|
||||
* Libraries:
|
||||
* - CryptoApi
|
||||
* - node-md6
|
||||
* - js-sha3
|
||||
* - ./Checksum.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Hashing = {
|
||||
"Analyse hash": Hash.runAnalyse,
|
||||
"Generate all hashes": Hash.runAll,
|
||||
"MD2": Hash.runMD2,
|
||||
"MD4": Hash.runMD4,
|
||||
"MD5": Hash.runMD5,
|
||||
"MD6": Hash.runMD6,
|
||||
"SHA0": Hash.runSHA0,
|
||||
"SHA1": Hash.runSHA1,
|
||||
"SHA2": Hash.runSHA2,
|
||||
"SHA3": Hash.runSHA3,
|
||||
"Keccak": Hash.runKeccak,
|
||||
"Shake": Hash.runShake,
|
||||
"RIPEMD": Hash.runRIPEMD,
|
||||
"HAS-160": Hash.runHAS,
|
||||
"Whirlpool": Hash.runWhirlpool,
|
||||
"Snefru": Hash.runSnefru,
|
||||
"HMAC": Hash.runHMAC,
|
||||
"Fletcher-8 Checksum": Checksum.runFletcher8,
|
||||
"Fletcher-16 Checksum": Checksum.runFletcher16,
|
||||
"Fletcher-32 Checksum": Checksum.runFletcher32,
|
||||
"Fletcher-64 Checksum": Checksum.runFletcher64,
|
||||
"Adler-32 Checksum": Checksum.runAdler32,
|
||||
"CRC-16 Checksum": Checksum.runCRC16,
|
||||
"CRC-32 Checksum": Checksum.runCRC32,
|
||||
"TCP/IP Checksum": Checksum.runTCPIP,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
25
src/core/config/modules/Image.js
Normal file
25
src/core/config/modules/Image.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import Image from "../../operations/Image.js";
|
||||
|
||||
|
||||
/**
|
||||
* Image module.
|
||||
*
|
||||
* Libraries:
|
||||
* - exif-parser
|
||||
* - remove-exif
|
||||
* - ./FileType.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Image = {
|
||||
"Extract EXIF": Image.runExtractEXIF,
|
||||
"Remove EXIF": Image.runRemoveEXIF,
|
||||
"Render Image": Image.runRenderImage,
|
||||
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
25
src/core/config/modules/JSBN.js
Normal file
25
src/core/config/modules/JSBN.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import IP from "../../operations/IP.js";
|
||||
|
||||
|
||||
/**
|
||||
* JSBN module.
|
||||
*
|
||||
* Libraries:
|
||||
* - jsbn
|
||||
* - ./Checksum.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.JSBN = {
|
||||
"Parse IP range": IP.runParseIpRange,
|
||||
"Parse IPv6 address": IP.runParseIPv6,
|
||||
"Parse IPv4 header": IP.runParseIPv4Header,
|
||||
"Change IP format": IP.runChangeIpFormat,
|
||||
"Group IP addresses": IP.runGroupIps,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
43
src/core/config/modules/OpModules.js
Normal file
43
src/core/config/modules/OpModules.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Imports all modules for builds which do not load modules separately.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import OpModules from "./Default.js";
|
||||
import CharEncModule from "./CharEnc.js";
|
||||
import CipherModule from "./Ciphers.js";
|
||||
import CodeModule from "./Code.js";
|
||||
import CompressionModule from "./Compression.js";
|
||||
import DiffModule from "./Diff.js";
|
||||
import EncodingModule from "./Encodings.js";
|
||||
import HashingModule from "./Hashing.js";
|
||||
import HTTPModule from "./HTTP.js";
|
||||
import ImageModule from "./Image.js";
|
||||
import JSBNModule from "./JSBN.js";
|
||||
import PublicKeyModule from "./PublicKey.js";
|
||||
import RegexModule from "./Regex.js";
|
||||
import ShellcodeModule from "./Shellcode.js";
|
||||
import URLModule from "./URL.js";
|
||||
|
||||
Object.assign(
|
||||
OpModules,
|
||||
CharEncModule,
|
||||
CipherModule,
|
||||
CodeModule,
|
||||
CompressionModule,
|
||||
DiffModule,
|
||||
EncodingModule,
|
||||
HashingModule,
|
||||
HTTPModule,
|
||||
ImageModule,
|
||||
JSBNModule,
|
||||
PublicKeyModule,
|
||||
RegexModule,
|
||||
ShellcodeModule,
|
||||
URLModule
|
||||
);
|
||||
|
||||
export default OpModules;
|
||||
25
src/core/config/modules/PublicKey.js
Normal file
25
src/core/config/modules/PublicKey.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import PublicKey from "../../operations/PublicKey.js";
|
||||
|
||||
|
||||
/**
|
||||
* PublicKey module.
|
||||
*
|
||||
* Libraries:
|
||||
* - jsrsasign
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.PublicKey = {
|
||||
"Parse X.509 certificate": PublicKey.runParseX509,
|
||||
"Parse ASN.1 hex string": PublicKey.runParseAsn1HexString,
|
||||
"PEM to Hex": PublicKey.runPemToHex,
|
||||
"Hex to PEM": PublicKey.runHexToPem,
|
||||
"Hex to Object Identifier": PublicKey.runHexToObjectIdentifier,
|
||||
"Object Identifier to Hex": PublicKey.runObjectIdentifierToHex,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
30
src/core/config/modules/Regex.js
Normal file
30
src/core/config/modules/Regex.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import Extract from "../../operations/Extract.js";
|
||||
import Regex from "../../operations/Regex.js";
|
||||
|
||||
|
||||
/**
|
||||
* Regex module.
|
||||
*
|
||||
* Libraries:
|
||||
* - XRegExp
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Regex = {
|
||||
"Regular expression": Regex.runRegex,
|
||||
"Find / Replace": Regex.runFindReplace,
|
||||
"Strings": Extract.runStrings,
|
||||
"Extract IP addresses": Extract.runIp,
|
||||
"Extract email addresses": Extract.runEmail,
|
||||
"Extract MAC addresses": Extract.runMac,
|
||||
"Extract URLs": Extract.runUrls,
|
||||
"Extract domains": Extract.runDomains,
|
||||
"Extract file paths": Extract.runFilePaths,
|
||||
"Extract dates": Extract.runDates,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
20
src/core/config/modules/Shellcode.js
Normal file
20
src/core/config/modules/Shellcode.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import Shellcode from "../../operations/Shellcode.js";
|
||||
|
||||
|
||||
/**
|
||||
* Shellcode module.
|
||||
*
|
||||
* Libraries:
|
||||
* - DisassembleX86-64.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Shellcode = {
|
||||
"Disassemble x86": Shellcode.runDisassemble,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
23
src/core/config/modules/URL.js
Normal file
23
src/core/config/modules/URL.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import URL_ from "../../operations/URL.js";
|
||||
|
||||
|
||||
/**
|
||||
* URL module.
|
||||
*
|
||||
* Libraries:
|
||||
* - Utils.js
|
||||
* - url
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.URL = {
|
||||
"URL Encode": URL_.runTo,
|
||||
"URL Decode": URL_.runFrom,
|
||||
"Parse URI": URL_.runParse,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
5722
src/core/lib/DisassembleX86-64.js
Normal file
5722
src/core/lib/DisassembleX86-64.js
Normal file
File diff suppressed because it is too large
Load Diff
1982
src/core/lib/js-codepage/cptable.js
Normal file
1982
src/core/lib/js-codepage/cptable.js
Normal file
File diff suppressed because it is too large
Load Diff
515
src/core/lib/js-codepage/cputils.js
Normal file
515
src/core/lib/js-codepage/cputils.js
Normal 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
153
src/core/lib/remove-exif.js
Normal 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;
|
||||
253
src/core/operations/Arithmetic.js
Normal file
253
src/core/operations/Arithmetic.js
Normal file
@@ -0,0 +1,253 @@
|
||||
import Utils from "../Utils.js";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
|
||||
/**
|
||||
* Math operations on numbers.
|
||||
*
|
||||
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Arithmetic = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIM_OPTIONS: ["Line feed", "Space", "Comma", "Semi-colon", "Colon", "CRLF"],
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and calculates the sum of numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runSum: function(input, args) {
|
||||
const val = Arithmetic._sum(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and subtracts all the numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runSub: function(input, args) {
|
||||
let val = Arithmetic._sub(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and multiplies the numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMulti: function(input, args) {
|
||||
let val = Arithmetic._multi(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and divides the numbers.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runDiv: function(input, args) {
|
||||
let val = Arithmetic._div(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and computes the mean (average).
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMean: function(input, args) {
|
||||
let val = Arithmetic._mean(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string based on a delimiter and finds the median.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMedian: function(input, args) {
|
||||
let val = Arithmetic._median(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* splits a string based on a delimiter and computes the standard deviation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runStdDev: function(input, args) {
|
||||
let val = Arithmetic._stdDev(Arithmetic._createNumArray(input, args[0]));
|
||||
return val instanceof BigNumber ? val : new BigNumber(NaN);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts a string array to a number array.
|
||||
*
|
||||
* @private
|
||||
* @param {string[]} input
|
||||
* @param {string} delim
|
||||
* @returns {BigNumber[]}
|
||||
*/
|
||||
_createNumArray: function(input, delim) {
|
||||
delim = Utils.charRep[delim || "Space"];
|
||||
let splitNumbers = input.split(delim),
|
||||
numbers = [],
|
||||
num;
|
||||
|
||||
for (let i = 0; i < splitNumbers.length; i++) {
|
||||
try {
|
||||
num = BigNumber(splitNumbers[i].trim());
|
||||
if (!num.isNaN()) {
|
||||
numbers.push(num);
|
||||
}
|
||||
} catch (err) {
|
||||
// This line is not a valid number
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_sum: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.plus(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Subtracts an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_sub: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.minus(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Multiplies an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_multi: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.times(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Divides an array of numbers and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_div: function(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.div(curr));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Computes mean of a number array and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_mean: function(data) {
|
||||
if (data.length > 0) {
|
||||
return Arithmetic._sum(data).div(data.length);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Computes median of a number array and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_median: function (data) {
|
||||
if ((data.length % 2) === 0 && data.length > 0) {
|
||||
let first, second;
|
||||
data.sort(function(a, b){
|
||||
return a.minus(b);
|
||||
});
|
||||
first = data[Math.floor(data.length / 2)];
|
||||
second = data[Math.floor(data.length / 2) - 1];
|
||||
return Arithmetic._mean([first, second]);
|
||||
} else {
|
||||
return data[Math.floor(data.length / 2)];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Computes standard deviation of a number array and returns the value.
|
||||
*
|
||||
* @private
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
_stdDev: function (data) {
|
||||
if (data.length > 0) {
|
||||
let avg = Arithmetic._mean(data);
|
||||
let devSum = new BigNumber(0);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
devSum = devSum.plus(data[i].minus(avg).pow(2));
|
||||
}
|
||||
return devSum.div(data.length).sqrt();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default Arithmetic;
|
||||
215
src/core/operations/BCD.js
Executable file
215
src/core/operations/BCD.js
Executable file
@@ -0,0 +1,215 @@
|
||||
import Utils from "../Utils.js";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
|
||||
/**
|
||||
* Binary-Coded Decimal operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const BCD = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENCODING_SCHEME: [
|
||||
"8 4 2 1",
|
||||
"7 4 2 1",
|
||||
"4 2 2 1",
|
||||
"2 4 2 1",
|
||||
"8 4 -2 -1",
|
||||
"Excess-3",
|
||||
"IBM 8 4 2 1",
|
||||
],
|
||||
|
||||
/**
|
||||
* Lookup table for the binary value of each digit representation.
|
||||
*
|
||||
* I wrote a very nice algorithm to generate 8 4 2 1 encoding programatically,
|
||||
* but unfortunately it's much easier (if less elegant) to use lookup tables
|
||||
* when supporting multiple encoding schemes.
|
||||
*
|
||||
* "Practicality beats purity" - PEP 20
|
||||
*
|
||||
* In some schemes it is possible to represent the same value in multiple ways.
|
||||
* For instance, in 4 2 2 1 encoding, 0100 and 0010 both represent 2. Support
|
||||
* has not yet been added for this.
|
||||
*
|
||||
* @constant
|
||||
*/
|
||||
ENCODING_LOOKUP: {
|
||||
"8 4 2 1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
"7 4 2 1": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10],
|
||||
"4 2 2 1": [0, 1, 4, 5, 8, 9, 12, 13, 14, 15],
|
||||
"2 4 2 1": [0, 1, 2, 3, 4, 11, 12, 13, 14, 15],
|
||||
"8 4 -2 -1": [0, 7, 6, 5, 4, 11, 10, 9, 8, 15],
|
||||
"Excess-3": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||
"IBM 8 4 2 1": [10, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
},
|
||||
|
||||
/**
|
||||
* @default
|
||||
* @constant
|
||||
*/
|
||||
FORMAT: ["Nibbles", "Bytes", "Raw"],
|
||||
|
||||
|
||||
/**
|
||||
* To BCD operation.
|
||||
*
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToBCD: function(input, args) {
|
||||
if (input.isNaN())
|
||||
return "Invalid input";
|
||||
if (!input.integerValue(BigNumber.ROUND_DOWN).isEqualTo(input))
|
||||
return "Fractional values are not supported by BCD";
|
||||
|
||||
const encoding = BCD.ENCODING_LOOKUP[args[0]],
|
||||
packed = args[1],
|
||||
signed = args[2],
|
||||
outputFormat = args[3];
|
||||
|
||||
// Split input number up into separate digits
|
||||
const digits = input.toFixed().split("");
|
||||
|
||||
if (digits[0] === "-" || digits[0] === "+") {
|
||||
digits.shift();
|
||||
}
|
||||
|
||||
let nibbles = [];
|
||||
|
||||
digits.forEach(d => {
|
||||
const n = parseInt(d, 10);
|
||||
nibbles.push(encoding[n]);
|
||||
});
|
||||
|
||||
if (signed) {
|
||||
if (packed && digits.length % 2 === 0) {
|
||||
// If there are an even number of digits, we add a leading 0 so
|
||||
// that the sign nibble doesn't sit in its own byte, leading to
|
||||
// ambiguity around whether the number ends with a 0 or not.
|
||||
nibbles.unshift(encoding[0]);
|
||||
}
|
||||
|
||||
nibbles.push(input > 0 ? 12 : 13);
|
||||
// 12 ("C") for + (credit)
|
||||
// 13 ("D") for - (debit)
|
||||
}
|
||||
|
||||
let bytes = [];
|
||||
|
||||
if (packed) {
|
||||
let encoded = 0,
|
||||
little = false;
|
||||
|
||||
nibbles.forEach(n => {
|
||||
encoded ^= little ? n : (n << 4);
|
||||
if (little) {
|
||||
bytes.push(encoded);
|
||||
encoded = 0;
|
||||
}
|
||||
little = !little;
|
||||
});
|
||||
|
||||
if (little) bytes.push(encoded);
|
||||
} else {
|
||||
bytes = nibbles;
|
||||
|
||||
// Add null high nibbles
|
||||
nibbles = nibbles.map(n => {
|
||||
return [0, n];
|
||||
}).reduce((a, b) => {
|
||||
return a.concat(b);
|
||||
});
|
||||
}
|
||||
|
||||
// Output
|
||||
switch (outputFormat) {
|
||||
case "Nibbles":
|
||||
return nibbles.map(n => {
|
||||
return n.toString(2).padStart(4, "0");
|
||||
}).join(" ");
|
||||
case "Bytes":
|
||||
return bytes.map(b => {
|
||||
return b.toString(2).padStart(8, "0");
|
||||
}).join(" ");
|
||||
case "Raw":
|
||||
default:
|
||||
return Utils.byteArrayToChars(bytes);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From BCD operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runFromBCD: function(input, args) {
|
||||
const encoding = BCD.ENCODING_LOOKUP[args[0]],
|
||||
packed = args[1],
|
||||
signed = args[2],
|
||||
inputFormat = args[3];
|
||||
|
||||
let nibbles = [],
|
||||
output = "",
|
||||
byteArray;
|
||||
|
||||
// Normalise the input
|
||||
switch (inputFormat) {
|
||||
case "Nibbles":
|
||||
case "Bytes":
|
||||
input = input.replace(/\s/g, "");
|
||||
for (let i = 0; i < input.length; i += 4) {
|
||||
nibbles.push(parseInt(input.substr(i, 4), 2));
|
||||
}
|
||||
break;
|
||||
case "Raw":
|
||||
default:
|
||||
byteArray = Utils.strToByteArray(input);
|
||||
byteArray.forEach(b => {
|
||||
nibbles.push(b >>> 4);
|
||||
nibbles.push(b & 15);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if (!packed) {
|
||||
// Discard each high nibble
|
||||
for (let i = 0; i < nibbles.length; i++) {
|
||||
nibbles.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (signed) {
|
||||
const sign = nibbles.pop();
|
||||
if (sign === 13 ||
|
||||
sign === 11) {
|
||||
// Negative
|
||||
output += "-";
|
||||
}
|
||||
}
|
||||
|
||||
nibbles.forEach(n => {
|
||||
if (isNaN(n)) throw "Invalid input";
|
||||
let val = encoding.indexOf(n);
|
||||
if (val < 0) throw `Value ${Utils.bin(n, 4)} not in encoding scheme`;
|
||||
output += val.toString();
|
||||
});
|
||||
|
||||
return new BigNumber(output);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default BCD;
|
||||
@@ -1,3 +1,5 @@
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* Numerical base operations.
|
||||
*
|
||||
@@ -18,7 +20,7 @@ const Base = {
|
||||
/**
|
||||
* To Base operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
@@ -26,7 +28,7 @@ const Base = {
|
||||
if (!input) {
|
||||
throw ("Error: Input must be a number");
|
||||
}
|
||||
var radix = args[0] || Base.DEFAULT_RADIX;
|
||||
const radix = args[0] || Base.DEFAULT_RADIX;
|
||||
if (radix < 2 || radix > 36) {
|
||||
throw "Error: Radix argument must be between 2 and 36";
|
||||
}
|
||||
@@ -39,23 +41,23 @@ const Base = {
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var radix = args[0] || Base.DEFAULT_RADIX;
|
||||
const radix = args[0] || Base.DEFAULT_RADIX;
|
||||
if (radix < 2 || radix > 36) {
|
||||
throw "Error: Radix argument must be between 2 and 36";
|
||||
}
|
||||
|
||||
var number = input.replace(/\s/g, "").split("."),
|
||||
result = parseInt(number[0], radix) || 0;
|
||||
let number = input.replace(/\s/g, "").split("."),
|
||||
result = new BigNumber(number[0], radix) || 0;
|
||||
|
||||
if (number.length === 1) return result;
|
||||
|
||||
// Fractional part
|
||||
for (var i = 0; i < number[1].length; i++) {
|
||||
var digit = parseInt(number[1][i], radix);
|
||||
result += digit / Math.pow(radix, i+1);
|
||||
for (let i = 0; i < number[1].length; i++) {
|
||||
const digit = new BigNumber(number[1][i], radix);
|
||||
result += digit.div(Math.pow(radix, i+1));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -40,7 +40,7 @@ const Base58 = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var alphabet = args[0] || Base58.ALPHABET_OPTIONS[0].value,
|
||||
let alphabet = args[0] || Base58.ALPHABET_OPTIONS[0].value,
|
||||
result = [0];
|
||||
|
||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||
@@ -53,11 +53,11 @@ const Base58 = {
|
||||
if (input.length === 0) return "";
|
||||
|
||||
input.forEach(function(b) {
|
||||
var carry = (result[0] << 8) + b;
|
||||
let carry = (result[0] << 8) + b;
|
||||
result[0] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
|
||||
for (var i = 1; i < result.length; i++) {
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
carry += result[i] << 8;
|
||||
result[i] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
@@ -89,7 +89,7 @@ const Base58 = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var alphabet = args[0] || Base58.ALPHABET_OPTIONS[0].value,
|
||||
let alphabet = args[0] || Base58.ALPHABET_OPTIONS[0].value,
|
||||
removeNonAlphaChars = args[1] === undefined ? true : args[1],
|
||||
result = [0];
|
||||
|
||||
@@ -103,7 +103,7 @@ const Base58 = {
|
||||
if (input.length === 0) return [];
|
||||
|
||||
[].forEach.call(input, function(c, charIndex) {
|
||||
var index = alphabet.indexOf(c);
|
||||
const index = alphabet.indexOf(c);
|
||||
|
||||
if (index === -1) {
|
||||
if (removeNonAlphaChars) {
|
||||
@@ -113,11 +113,11 @@ const Base58 = {
|
||||
}
|
||||
}
|
||||
|
||||
var carry = result[0] * 58 + index;
|
||||
let carry = result[0] * 58 + index;
|
||||
result[0] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
|
||||
for (var i = 1; i < result.length; i++) {
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
carry += result[i] * 58;
|
||||
result[i] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
|
||||
@@ -40,13 +40,13 @@ const Base64 = {
|
||||
/**
|
||||
* To Base64 operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET;
|
||||
return Utils.toBase64(input, alphabet);
|
||||
const alphabet = args[0] || Base64.ALPHABET;
|
||||
return Utils.toBase64(new Uint8Array(input), alphabet);
|
||||
},
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ const Base64 = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET,
|
||||
let alphabet = args[0] || Base64.ALPHABET,
|
||||
removeNonAlphChars = args[1];
|
||||
|
||||
return Utils.fromBase64(input, alphabet, "byteArray", removeNonAlphChars);
|
||||
@@ -87,7 +87,7 @@ const Base64 = {
|
||||
runTo32: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
var alphabet = args[0] ?
|
||||
let alphabet = args[0] ?
|
||||
Utils.expandAlphRange(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
||||
output = "",
|
||||
chr1, chr2, chr3, chr4, chr5,
|
||||
@@ -139,17 +139,17 @@ const Base64 = {
|
||||
runFrom32: function(input, args) {
|
||||
if (!input) return [];
|
||||
|
||||
var alphabet = args[0] ?
|
||||
let alphabet = args[0] ?
|
||||
Utils.expandAlphRange(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
||||
removeNonAlphChars = args[0];
|
||||
|
||||
var output = [],
|
||||
let output = [],
|
||||
chr1, chr2, chr3, chr4, chr5,
|
||||
enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8,
|
||||
i = 0;
|
||||
|
||||
if (removeNonAlphChars) {
|
||||
var re = new RegExp("[^" + alphabet.replace(/[\]\\\-^]/g, "\\$&") + "]", "g");
|
||||
const re = new RegExp("[^" + alphabet.replace(/[\]\\\-^]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ const Base64 = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runOffsets: function(input, args) {
|
||||
var alphabet = args[0] || Base64.ALPHABET,
|
||||
let alphabet = args[0] || Base64.ALPHABET,
|
||||
showVariable = args[1],
|
||||
offset0 = Utils.toBase64(input, alphabet),
|
||||
offset1 = Utils.toBase64([0].concat(input), alphabet),
|
||||
@@ -221,15 +221,15 @@ const Base64 = {
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 2) + "</span>";
|
||||
"<span class='hl5'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset0.substr(offset0.length - 2) + "</span>";
|
||||
} else if (len0 % 4 === 3) {
|
||||
staticSection = offset0.slice(0, -2);
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset0.substr(offset0.length - 1) + "</span>";
|
||||
"<span class='hl5'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset0.substr(offset0.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset0;
|
||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
@@ -243,23 +243,23 @@ const Base64 = {
|
||||
|
||||
|
||||
// Highlight offset 1
|
||||
padding = "<span class='hlred'>" + offset1.substr(0, 1) + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(1, 1) + "</span>";
|
||||
padding = "<span class='hl3'>" + offset1.substr(0, 1) + "</span>" +
|
||||
"<span class='hl5'>" + offset1.substr(1, 1) + "</span>";
|
||||
offset1 = offset1.substr(2);
|
||||
if (len1 % 4 === 2) {
|
||||
staticSection = offset1.slice(0, -3);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 2) + "</span>";
|
||||
"<span class='hl5'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset1.substr(offset1.length - 2) + "</span>";
|
||||
} else if (len1 % 4 === 3) {
|
||||
staticSection = offset1.slice(0, -2);
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset1.substr(offset1.length - 1) + "</span>";
|
||||
"<span class='hl5'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset1.substr(offset1.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset1;
|
||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
@@ -272,23 +272,23 @@ const Base64 = {
|
||||
}
|
||||
|
||||
// Highlight offset 2
|
||||
padding = "<span class='hlred'>" + offset2.substr(0, 2) + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(2, 1) + "</span>";
|
||||
padding = "<span class='hl3'>" + offset2.substr(0, 2) + "</span>" +
|
||||
"<span class='hl5'>" + offset2.substr(2, 1) + "</span>";
|
||||
offset2 = offset2.substr(3);
|
||||
if (len2 % 4 === 2) {
|
||||
staticSection = offset2.slice(0, -3);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 2) + "</span>";
|
||||
"<span class='hl5'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset2.substr(offset2.length - 2) + "</span>";
|
||||
} else if (len2 % 4 === 3) {
|
||||
staticSection = offset2.slice(0, -2);
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
Utils.escapeHtml(Utils.fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||
staticSection + "</span>" +
|
||||
"<span class='hlgreen'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
||||
"<span class='hlred'>" + offset2.substr(offset2.length - 1) + "</span>";
|
||||
"<span class='hl5'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
||||
"<span class='hl3'>" + offset2.substr(offset2.length - 1) + "</span>";
|
||||
} else {
|
||||
staticSection = offset2;
|
||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||
@@ -300,8 +300,8 @@ const Base64 = {
|
||||
offset2 = staticSection;
|
||||
}
|
||||
|
||||
return (showVariable ? "Characters highlighted in <span class='hlgreen'>green</span> could change if the input is surrounded by more data." +
|
||||
"\nCharacters highlighted in <span class='hlred'>red</span> are for padding purposes only." +
|
||||
return (showVariable ? "Characters highlighted in <span class='hl5'>green</span> could change if the input is surrounded by more data." +
|
||||
"\nCharacters highlighted in <span class='hl3'>red</span> are for padding purposes only." +
|
||||
"\nUnhighlighted characters are <span data-toggle='tooltip' data-placement='top' title='Tooltip on left'>static</span>." +
|
||||
"\nHover over the static sections to see what they decode to on their own.\n" +
|
||||
"\nOffset 0: " + offset0 +
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,17 +25,19 @@ const BitwiseOp = {
|
||||
*/
|
||||
_bitOp: function (input, key, func, nullPreserving, scheme) {
|
||||
if (!key || !key.length) key = [0];
|
||||
var result = [],
|
||||
let result = [],
|
||||
x = null,
|
||||
k = null,
|
||||
o = null;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
k = key[i % key.length];
|
||||
o = input[i];
|
||||
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
|
||||
result.push(x);
|
||||
if (scheme !== "Standard" && !(nullPreserving && (o === 0 || o === k))) {
|
||||
if (scheme &&
|
||||
scheme !== "Standard" &&
|
||||
!(nullPreserving && (o === 0 || o === k))) {
|
||||
switch (scheme) {
|
||||
case "Input differential":
|
||||
key[i % key.length] = x;
|
||||
@@ -66,7 +67,7 @@ const BitwiseOp = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
KEY_FORMAT: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
|
||||
KEY_FORMAT: ["Hex", "Base64", "UTF8", "Latin1"],
|
||||
|
||||
/**
|
||||
* XOR operation.
|
||||
@@ -76,12 +77,10 @@ const BitwiseOp = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runXor: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || ""),
|
||||
const key = Utils.convertToByteArray(args[0].string || "", args[0].option),
|
||||
scheme = args[1],
|
||||
nullPreserving = args[2];
|
||||
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._xor, nullPreserving, scheme);
|
||||
},
|
||||
|
||||
@@ -90,7 +89,7 @@ const BitwiseOp = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
XOR_BRUTE_KEY_LENGTH: ["1", "2"],
|
||||
XOR_BRUTE_KEY_LENGTH: 1,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -120,39 +119,62 @@ const BitwiseOp = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runXorBrute: function (input, args) {
|
||||
var keyLength = parseInt(args[0], 10),
|
||||
const keyLength = args[0],
|
||||
sampleLength = args[1],
|
||||
sampleOffset = args[2],
|
||||
nullPreserving = args[3],
|
||||
differential = args[4],
|
||||
crib = args[5],
|
||||
printKey = args[6],
|
||||
outputHex = args[7],
|
||||
regex;
|
||||
scheme = args[3],
|
||||
nullPreserving = args[4],
|
||||
printKey = args[5],
|
||||
outputHex = args[6],
|
||||
crib = args[7].toLowerCase();
|
||||
|
||||
var output = "",
|
||||
let output = [],
|
||||
result,
|
||||
resultUtf8;
|
||||
resultUtf8,
|
||||
record = "";
|
||||
|
||||
input = input.slice(sampleOffset, sampleOffset + sampleLength);
|
||||
|
||||
if (crib !== "") {
|
||||
regex = new RegExp(crib, "im");
|
||||
}
|
||||
if (ENVIRONMENT_IS_WORKER())
|
||||
self.sendStatusMessage("Calculating " + Math.pow(256, keyLength) + " values...");
|
||||
|
||||
/**
|
||||
* Converts an integer to an array of bytes expressing that number.
|
||||
*
|
||||
* @param {number} int
|
||||
* @param {number} len - Length of the resulting array
|
||||
* @returns {array}
|
||||
*/
|
||||
const intToByteArray = (int, len) => {
|
||||
let res = Array(len).fill(0);
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
res[i] = int & 0xff;
|
||||
int = int >>> 8;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
for (var key = 1, l = Math.pow(256, keyLength); key < l; key++) {
|
||||
result = BitwiseOp._bitOp(input, Utils.hexToByteArray(key.toString(16)), BitwiseOp._xor, nullPreserving, differential);
|
||||
for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) {
|
||||
if (key % 10000 === 0 && ENVIRONMENT_IS_WORKER()) {
|
||||
self.sendStatusMessage("Calculating " + l + " values... " + Math.floor(key / l * 100) + "%");
|
||||
}
|
||||
|
||||
result = BitwiseOp._bitOp(input, intToByteArray(key, keyLength), BitwiseOp._xor, nullPreserving, scheme);
|
||||
resultUtf8 = Utils.byteArrayToUtf8(result);
|
||||
if (crib !== "" && resultUtf8.search(regex) === -1) continue;
|
||||
if (printKey) output += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
|
||||
if (outputHex)
|
||||
output += Utils.byteArrayToHex(result) + "\n";
|
||||
else
|
||||
output += Utils.printable(resultUtf8, false) + "\n";
|
||||
if (printKey) output += "\n";
|
||||
record = "";
|
||||
|
||||
if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue;
|
||||
if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
|
||||
if (outputHex) {
|
||||
record += Utils.toHex(result);
|
||||
} else {
|
||||
record += Utils.printable(resultUtf8, false);
|
||||
}
|
||||
|
||||
output.push(record);
|
||||
}
|
||||
return output;
|
||||
|
||||
return output.join("\n");
|
||||
},
|
||||
|
||||
|
||||
@@ -176,8 +198,7 @@ const BitwiseOp = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runAnd: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._and);
|
||||
},
|
||||
@@ -191,8 +212,7 @@ const BitwiseOp = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runOr: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._or);
|
||||
},
|
||||
@@ -206,8 +226,7 @@ const BitwiseOp = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runAdd: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._add);
|
||||
},
|
||||
@@ -221,13 +240,52 @@ const BitwiseOp = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runSub: function (input, args) {
|
||||
var key = Utils.format[args[0].option].parse(args[0].string || "");
|
||||
key = Utils.wordArrayToByteArray(key);
|
||||
const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
|
||||
|
||||
return BitwiseOp._bitOp(input, key, BitwiseOp._sub);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -301,7 +359,7 @@ const BitwiseOp = {
|
||||
* @returns {number}
|
||||
*/
|
||||
_sub: function (operand, key) {
|
||||
var result = operand - key;
|
||||
const result = operand - key;
|
||||
return (result < 0) ? 256 + result : result;
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* globals app */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
@@ -32,13 +31,13 @@ const ByteRepr = {
|
||||
/**
|
||||
* To Hex operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToHex: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
return Utils.toHex(input, delim, 2);
|
||||
const delim = Utils.charRep[args[0] || "Space"];
|
||||
return Utils.toHex(new Uint8Array(input), delim, 2);
|
||||
},
|
||||
|
||||
|
||||
@@ -50,7 +49,7 @@ const ByteRepr = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromHex: function(input, args) {
|
||||
var delim = args[0] || "Space";
|
||||
const delim = args[0] || "Space";
|
||||
return Utils.fromHex(input, delim, 2);
|
||||
},
|
||||
|
||||
@@ -58,13 +57,13 @@ const ByteRepr = {
|
||||
/**
|
||||
* To Octal operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runToOct: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
const delim = Utils.charRep[args[0] || "Space"];
|
||||
return input.map(val => val.toString(8)).join(delim);
|
||||
},
|
||||
|
||||
@@ -72,13 +71,13 @@ const ByteRepr = {
|
||||
/**
|
||||
* From Octal operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromOct: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
const delim = Utils.charRep[args[0] || "Space"];
|
||||
if (input.length === 0) return [];
|
||||
return input.split(delim).map(val => parseInt(val, 8));
|
||||
},
|
||||
@@ -98,7 +97,7 @@ const ByteRepr = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToCharcode: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
let delim = Utils.charRep[args[0] || "Space"],
|
||||
base = args[1],
|
||||
output = "",
|
||||
padding = 2,
|
||||
@@ -108,8 +107,9 @@ const ByteRepr = {
|
||||
throw "Error: Base argument must be between 2 and 36";
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
ordinal = Utils.ord(input[i]);
|
||||
const charcode = Utils.strToCharcode(input);
|
||||
for (let i = 0; i < charcode.length; i++) {
|
||||
ordinal = charcode[i];
|
||||
|
||||
if (base === 16) {
|
||||
if (ordinal < 256) padding = 2;
|
||||
@@ -118,11 +118,11 @@ const ByteRepr = {
|
||||
else if (ordinal < 4294967296) padding = 8;
|
||||
else padding = 2;
|
||||
|
||||
if (padding > 2 && app) app.options.attemptHighlight = false;
|
||||
if (padding > 2 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
||||
|
||||
output += Utils.hex(ordinal, padding) + delim;
|
||||
} else {
|
||||
if (app) app.options.attemptHighlight = false;
|
||||
if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
||||
output += ordinal.toString(base) + delim;
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ const ByteRepr = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromCharcode: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
let delim = Utils.charRep[args[0] || "Space"],
|
||||
base = args[1],
|
||||
bites = input.split(delim),
|
||||
i = 0;
|
||||
@@ -148,9 +148,7 @@ const ByteRepr = {
|
||||
throw "Error: Base argument must be between 2 and 36";
|
||||
}
|
||||
|
||||
if (base !== 16 && app) {
|
||||
app.options.attemptHighlight = false;
|
||||
}
|
||||
if (base !== 16 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
||||
|
||||
// Split into groups of 2 if the whole string is concatenated and
|
||||
// too long to be a single character
|
||||
@@ -161,7 +159,7 @@ const ByteRepr = {
|
||||
}
|
||||
}
|
||||
|
||||
var latin1 = "";
|
||||
let latin1 = "";
|
||||
for (i = 0; i < bites.length; i++) {
|
||||
latin1 += Utils.chr(parseInt(bites[i], base));
|
||||
}
|
||||
@@ -179,7 +177,7 @@ const ByteRepr = {
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightTo: function(pos, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
let delim = Utils.charRep[args[0] || "Space"],
|
||||
len = delim === "\r\n" ? 1 : delim.length;
|
||||
|
||||
pos[0].start = pos[0].start * (2 + len);
|
||||
@@ -188,14 +186,14 @@ const ByteRepr = {
|
||||
// 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
|
||||
if (delim === "0x" || delim === "\\x") {
|
||||
pos[0].start += 2;
|
||||
pos[0].end += 2;
|
||||
pos[0].end += 2;
|
||||
}
|
||||
return pos;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Highlight to hex
|
||||
* Highlight from hex
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
@@ -204,7 +202,7 @@ const ByteRepr = {
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFrom: function(pos, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
let delim = Utils.charRep[args[0] || "Space"],
|
||||
len = delim === "\r\n" ? 1 : delim.length,
|
||||
width = len + 2;
|
||||
|
||||
@@ -230,7 +228,7 @@ const ByteRepr = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToDecimal: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]];
|
||||
const delim = Utils.charRep[args[0]];
|
||||
return input.join(delim);
|
||||
},
|
||||
|
||||
@@ -243,12 +241,12 @@ const ByteRepr = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromDecimal: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]];
|
||||
var byteStr = input.split(delim), output = [];
|
||||
const delim = Utils.charRep[args[0]];
|
||||
let byteStr = input.split(delim), output = [];
|
||||
if (byteStr[byteStr.length-1] === "")
|
||||
byteStr = byteStr.slice(0, byteStr.length-1);
|
||||
|
||||
for (var i = 0; i < byteStr.length; i++) {
|
||||
for (let i = 0; i < byteStr.length; i++) {
|
||||
output[i] = parseInt(byteStr[i], 10);
|
||||
}
|
||||
return output;
|
||||
@@ -263,12 +261,12 @@ const ByteRepr = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToBinary: function(input, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"],
|
||||
let delim = Utils.charRep[args[0] || "Space"],
|
||||
output = "",
|
||||
padding = 8;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
output += Utils.pad(input[i].toString(2), padding) + delim;
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
output += input[i].toString(2).padStart(padding, "0") + delim;
|
||||
}
|
||||
|
||||
if (delim.length) {
|
||||
@@ -287,14 +285,12 @@ const ByteRepr = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromBinary: function(input, args) {
|
||||
if (args[0] !== "None") {
|
||||
var delimRegex = Utils.regexRep[args[0] || "Space"];
|
||||
input = input.replace(delimRegex, "");
|
||||
}
|
||||
const delimRegex = Utils.regexRep[args[0] || "Space"];
|
||||
input = input.replace(delimRegex, "");
|
||||
|
||||
var output = [];
|
||||
var byteLen = 8;
|
||||
for (var i = 0; i < input.length; i += byteLen) {
|
||||
const output = [];
|
||||
const byteLen = 8;
|
||||
for (let i = 0; i < input.length; i += byteLen) {
|
||||
output.push(parseInt(input.substr(i, byteLen), 2));
|
||||
}
|
||||
return output;
|
||||
@@ -311,7 +307,7 @@ const ByteRepr = {
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightToBinary: function(pos, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
const delim = Utils.charRep[args[0] || "Space"];
|
||||
pos[0].start = pos[0].start * (8 + delim.length);
|
||||
pos[0].end = pos[0].end * (8 + delim.length) - delim.length;
|
||||
return pos;
|
||||
@@ -328,7 +324,7 @@ const ByteRepr = {
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFromBinary: function(pos, args) {
|
||||
var delim = Utils.charRep[args[0] || "Space"];
|
||||
const delim = Utils.charRep[args[0] || "Space"];
|
||||
pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length));
|
||||
pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length));
|
||||
return pos;
|
||||
@@ -354,19 +350,19 @@ const ByteRepr = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToHexContent: function(input, args) {
|
||||
var convert = args[0];
|
||||
var spaces = args[1];
|
||||
const convert = args[0];
|
||||
const spaces = args[1];
|
||||
if (convert === "All chars") {
|
||||
var result = "|" + Utils.toHex(input) + "|";
|
||||
let result = "|" + Utils.toHex(input) + "|";
|
||||
if (!spaces) result = result.replace(/ /g, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
var output = "",
|
||||
let output = "",
|
||||
inHex = false,
|
||||
convertSpaces = convert === "Only special chars including spaces",
|
||||
b;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
b = input[i];
|
||||
if ((b === 32 && convertSpaces) || (b < 48 && b !== 32) || (b > 57 && b < 65) || (b > 90 && b < 97) || b > 122) {
|
||||
if (!inHex) {
|
||||
@@ -395,17 +391,17 @@ const ByteRepr = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFromHexContent: function(input, args) {
|
||||
var regex = /\|([a-f\d ]{2,})\|/gi;
|
||||
var output = [], m, i = 0;
|
||||
const regex = /\|([a-f\d ]{2,})\|/gi;
|
||||
let output = [], m, i = 0;
|
||||
while ((m = regex.exec(input))) {
|
||||
// Add up to match
|
||||
for (; i < m.index;)
|
||||
output.push(Utils.ord(input[i++]));
|
||||
|
||||
// Add match
|
||||
var bytes = Utils.fromHex(m[1]);
|
||||
const bytes = Utils.fromHex(m[1]);
|
||||
if (bytes) {
|
||||
for (var a = 0; a < bytes.length;)
|
||||
for (let a = 0; a < bytes.length;)
|
||||
output.push(bytes[a++]);
|
||||
} else {
|
||||
// Not valid hex, print as normal
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
import cptable from "../lib/js-codepage/cptable.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -17,34 +16,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) {
|
||||
var 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;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as CRC from "js-crc";
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
@@ -20,10 +21,10 @@ const Checksum = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher8: function(input, args) {
|
||||
var a = 0,
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xf;
|
||||
b = (b + a) % 0xf;
|
||||
}
|
||||
@@ -40,10 +41,10 @@ const Checksum = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher16: function(input, args) {
|
||||
var a = 0,
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xff;
|
||||
b = (b + a) % 0xff;
|
||||
}
|
||||
@@ -60,10 +61,10 @@ const Checksum = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher32: function(input, args) {
|
||||
var a = 0,
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xffff;
|
||||
b = (b + a) % 0xffff;
|
||||
}
|
||||
@@ -80,10 +81,10 @@ const Checksum = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFletcher64: function(input, args) {
|
||||
var a = 0,
|
||||
let a = 0,
|
||||
b = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a = (a + input[i]) % 0xffffffff;
|
||||
b = (b + a) % 0xffffffff;
|
||||
}
|
||||
@@ -100,11 +101,11 @@ const Checksum = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runAdler32: function(input, args) {
|
||||
var MOD_ADLER = 65521,
|
||||
let MOD_ADLER = 65521,
|
||||
a = 1,
|
||||
b = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
a += input[i];
|
||||
b += a;
|
||||
}
|
||||
@@ -119,19 +120,24 @@ const Checksum = {
|
||||
/**
|
||||
* CRC-32 Checksum operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCRC32: function(input, args) {
|
||||
var crcTable = global.crcTable || (global.crcTable = Checksum._genCRCTable()),
|
||||
crc = 0 ^ (-1);
|
||||
return CRC.crc32(input);
|
||||
},
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
crc = (crc >>> 8) ^ crcTable[(crc ^ input[i]) & 0xff];
|
||||
}
|
||||
|
||||
return Utils.hex((crc ^ (-1)) >>> 0);
|
||||
/**
|
||||
* CRC-16 Checksum operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runCRC16: function(input, args) {
|
||||
return CRC.crc16(input);
|
||||
},
|
||||
|
||||
|
||||
@@ -153,9 +159,9 @@ const Checksum = {
|
||||
* 0x00,0x00,0xac,0x11,0x00,0x03,0xac,0x11,0x00,0x04])
|
||||
*/
|
||||
runTCPIP: function(input, args) {
|
||||
var csum = 0;
|
||||
let csum = 0;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
if (i % 2 === 0) {
|
||||
csum += (input[i] << 8);
|
||||
} else {
|
||||
@@ -168,28 +174,6 @@ const Checksum = {
|
||||
return Utils.hex(0xffff - csum);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generates a CRC table for use with CRC checksums.
|
||||
*
|
||||
* @private
|
||||
* @returns {array}
|
||||
*/
|
||||
_genCRCTable: function() {
|
||||
var c,
|
||||
crcTable = [];
|
||||
|
||||
for (var n = 0; n < 256; n++) {
|
||||
c = n;
|
||||
for (var k = 0; k < 8; k++) {
|
||||
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
|
||||
}
|
||||
crcTable[n] = c;
|
||||
}
|
||||
|
||||
return crcTable;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Checksum;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
||||
import Utils from "../Utils.js";
|
||||
import {camelCase, kebabCase, snakeCase} from "lodash";
|
||||
import vkbeautify from "vkbeautify";
|
||||
import {DOMParser as dom} from "xmldom";
|
||||
import {DOMParser} from "xmldom";
|
||||
import xpath from "xpath";
|
||||
import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js";
|
||||
import jpath from "jsonpath";
|
||||
import nwmatcher from "nwmatcher";
|
||||
import hljs from "highlight.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -20,12 +22,7 @@ const Code = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LANGUAGES: ["default-code", "default-markup", "bash", "bsh", "c", "cc", "coffee", "cpp", "cs", "csh", "cv", "cxx", "cyc", "htm", "html", "in.tag", "java", "javascript", "js", "json", "m", "mxml", "perl", "pl", "pm", "py", "python", "rb", "rc", "rs", "ruby", "rust", "sh", "uq.val", "xhtml", "xml", "xsl"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
LINE_NUMS: false,
|
||||
LANGUAGES: ["auto detect"].concat(hljs.listLanguages()),
|
||||
|
||||
/**
|
||||
* Syntax highlighter operation.
|
||||
@@ -35,9 +32,13 @@ const Code = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runSyntaxHighlight: function(input, args) {
|
||||
var language = args[0],
|
||||
lineNums = args[1];
|
||||
return "<code class='prettyprint'>" + prettyPrintOne(Utils.escapeHtml(input), language, lineNums) + "</code>";
|
||||
const language = args[0];
|
||||
|
||||
if (language === "auto detect") {
|
||||
return hljs.highlightAuto(input).value;
|
||||
}
|
||||
|
||||
return hljs.highlight(language, input, true).value;
|
||||
},
|
||||
|
||||
|
||||
@@ -55,7 +56,7 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runXmlBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
const indentStr = args[0];
|
||||
return vkbeautify.xml(input, indentStr);
|
||||
},
|
||||
|
||||
@@ -68,7 +69,7 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runJsonBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
const indentStr = args[0];
|
||||
if (!input) return "";
|
||||
return vkbeautify.json(input, indentStr);
|
||||
},
|
||||
@@ -82,7 +83,7 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runCssBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
const indentStr = args[0];
|
||||
return vkbeautify.css(input, indentStr);
|
||||
},
|
||||
|
||||
@@ -95,7 +96,7 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSqlBeautify: function(input, args) {
|
||||
var indentStr = args[0];
|
||||
const indentStr = args[0];
|
||||
return vkbeautify.sql(input, indentStr);
|
||||
},
|
||||
|
||||
@@ -114,7 +115,7 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runXmlMinify: function(input, args) {
|
||||
var preserveComments = args[0];
|
||||
const preserveComments = args[0];
|
||||
return vkbeautify.xmlmin(input, preserveComments);
|
||||
},
|
||||
|
||||
@@ -140,7 +141,7 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runCssMinify: function(input, args) {
|
||||
var preserveComments = args[0];
|
||||
const preserveComments = args[0];
|
||||
return vkbeautify.cssmin(input, preserveComments);
|
||||
},
|
||||
|
||||
@@ -181,73 +182,69 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runGenericBeautify: function(input, args) {
|
||||
var code = input,
|
||||
let code = input,
|
||||
t = 0,
|
||||
preservedTokens = [],
|
||||
m;
|
||||
|
||||
// Remove strings
|
||||
var sstrings = /'([^'\\]|\\.)*'/g;
|
||||
const sstrings = /'([^'\\]|\\.)*'/g;
|
||||
while ((m = sstrings.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
sstrings.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var dstrings = /"([^"\\]|\\.)*"/g;
|
||||
const dstrings = /"([^"\\]|\\.)*"/g;
|
||||
while ((m = dstrings.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
dstrings.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Remove comments
|
||||
var scomments = /\/\/[^\n\r]*/g;
|
||||
const scomments = /\/\/[^\n\r]*/g;
|
||||
while ((m = scomments.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
scomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var mcomments = /\/\*[\s\S]*?\*\//gm;
|
||||
const mcomments = /\/\*[\s\S]*?\*\//gm;
|
||||
while ((m = mcomments.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
mcomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
var hcomments = /(^|\n)#[^\n\r#]+/g;
|
||||
const hcomments = /(^|\n)#[^\n\r#]+/g;
|
||||
while ((m = hcomments.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
hcomments.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Remove regexes
|
||||
var regexes = /\/.*?[^\\]\/[gim]{0,3}/gi;
|
||||
const regexes = /\/.*?[^\\]\/[gim]{0,3}/gi;
|
||||
while ((m = regexes.exec(code))) {
|
||||
code = preserveToken(code, m, t++);
|
||||
regexes.lastIndex = m.index;
|
||||
}
|
||||
|
||||
// Create newlines after ;
|
||||
code = code.replace(/;/g, ";\n");
|
||||
|
||||
// Create newlines after { and around }
|
||||
code = code.replace(/{/g, "{\n");
|
||||
code = code.replace(/}/g, "\n}\n");
|
||||
|
||||
// Remove carriage returns
|
||||
code = code.replace(/\r/g, "");
|
||||
|
||||
// Remove all indentation
|
||||
code = code.replace(/^\s+/g, "");
|
||||
code = code.replace(/\n\s+/g, "\n");
|
||||
|
||||
// Remove trailing spaces
|
||||
code = code.replace(/\s*$/g, "");
|
||||
|
||||
// Remove newlines before {
|
||||
code = code.replace(/\n{/g, "{");
|
||||
code = code
|
||||
// Create newlines after ;
|
||||
.replace(/;/g, ";\n")
|
||||
// Create newlines after { and around }
|
||||
.replace(/{/g, "{\n")
|
||||
.replace(/}/g, "\n}\n")
|
||||
// Remove carriage returns
|
||||
.replace(/\r/g, "")
|
||||
// Remove all indentation
|
||||
.replace(/^\s+/g, "")
|
||||
.replace(/\n\s+/g, "\n")
|
||||
// Remove trailing spaces
|
||||
.replace(/\s*$/g, "")
|
||||
.replace(/\n{/g, "{");
|
||||
|
||||
// Indent
|
||||
var i = 0,
|
||||
level = 0;
|
||||
let i = 0,
|
||||
level = 0,
|
||||
indent;
|
||||
while (i < code.length) {
|
||||
switch (code[i]) {
|
||||
case "{":
|
||||
@@ -257,7 +254,7 @@ const Code = {
|
||||
if (i+1 >= code.length) break;
|
||||
|
||||
if (code[i+1] === "}") level--;
|
||||
var indent = (level >= 0) ? Array(level*4+1).join(" ") : "";
|
||||
indent = (level >= 0) ? Array(level*4+1).join(" ") : "";
|
||||
|
||||
code = code.substring(0, i+1) + indent + code.substring(i+1);
|
||||
if (level > 0) i += level*4;
|
||||
@@ -266,35 +263,33 @@ const Code = {
|
||||
i++;
|
||||
}
|
||||
|
||||
// Add strategic spaces
|
||||
code = code.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ");
|
||||
code = code.replace(/\s*<([=]?)\s*/g, " <$1 ");
|
||||
code = code.replace(/\s*>([=]?)\s*/g, " >$1 ");
|
||||
code = code.replace(/([^+])\+([^+=])/g, "$1 + $2");
|
||||
code = code.replace(/([^-])-([^-=])/g, "$1 - $2");
|
||||
code = code.replace(/([^*])\*([^*=])/g, "$1 * $2");
|
||||
code = code.replace(/([^/])\/([^/=])/g, "$1 / $2");
|
||||
code = code.replace(/\s*,\s*/g, ", ");
|
||||
code = code.replace(/\s*{/g, " {");
|
||||
code = code.replace(/}\n/g, "}\n\n");
|
||||
|
||||
// Just... don't look at this
|
||||
code = code.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3");
|
||||
code = code.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3");
|
||||
code = code.replace(/else\s*\n([^{])/gim, "else\n $1");
|
||||
code = code.replace(/else\s+([^{])/gim, "else $1");
|
||||
|
||||
// Remove strategic spaces
|
||||
code = code.replace(/\s+;/g, ";");
|
||||
code = code.replace(/\{\s+\}/g, "{}");
|
||||
code = code.replace(/\[\s+\]/g, "[]");
|
||||
code = code.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
|
||||
|
||||
code = code
|
||||
// Add strategic spaces
|
||||
.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ")
|
||||
.replace(/\s*<([=]?)\s*/g, " <$1 ")
|
||||
.replace(/\s*>([=]?)\s*/g, " >$1 ")
|
||||
.replace(/([^+])\+([^+=])/g, "$1 + $2")
|
||||
.replace(/([^-])-([^-=])/g, "$1 - $2")
|
||||
.replace(/([^*])\*([^*=])/g, "$1 * $2")
|
||||
.replace(/([^/])\/([^/=])/g, "$1 / $2")
|
||||
.replace(/\s*,\s*/g, ", ")
|
||||
.replace(/\s*{/g, " {")
|
||||
.replace(/}\n/g, "}\n\n")
|
||||
// Hacky horribleness
|
||||
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3")
|
||||
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3")
|
||||
.replace(/else\s*\n([^{])/gim, "else\n $1")
|
||||
.replace(/else\s+([^{])/gim, "else $1")
|
||||
// Remove strategic spaces
|
||||
.replace(/\s+;/g, ";")
|
||||
.replace(/\{\s+\}/g, "{}")
|
||||
.replace(/\[\s+\]/g, "[]")
|
||||
.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
|
||||
|
||||
// Replace preserved tokens
|
||||
var ptokens = /###preservedToken(\d+)###/g;
|
||||
const ptokens = /###preservedToken(\d+)###/g;
|
||||
while ((m = ptokens.exec(code))) {
|
||||
var ti = parseInt(m[1], 10);
|
||||
const ti = parseInt(m[1], 10);
|
||||
code = code.substring(0, m.index) + preservedTokens[ti] + code.substring(m.index + m[0].length);
|
||||
ptokens.lastIndex = m.index;
|
||||
}
|
||||
@@ -333,25 +328,25 @@ const Code = {
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runXpath:function(input, args) {
|
||||
var query = args[0],
|
||||
runXpath: function(input, args) {
|
||||
let query = args[0],
|
||||
delimiter = args[1];
|
||||
|
||||
var doc;
|
||||
let doc;
|
||||
try {
|
||||
doc = new dom().parseFromString(input);
|
||||
doc = new DOMParser().parseFromString(input, "application/xml");
|
||||
} catch (err) {
|
||||
return "Invalid input XML.";
|
||||
}
|
||||
|
||||
var nodes;
|
||||
let nodes;
|
||||
try {
|
||||
nodes = xpath.select(query, doc);
|
||||
} catch (err) {
|
||||
return "Invalid XPath. Details:\n" + err.message;
|
||||
}
|
||||
|
||||
var nodeToString = function(node) {
|
||||
const nodeToString = function(node) {
|
||||
return node.toString();
|
||||
};
|
||||
|
||||
@@ -359,6 +354,48 @@ const Code = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
JPATH_INITIAL: "",
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
JPATH_DELIMITER: "\\n",
|
||||
|
||||
/**
|
||||
* JPath expression operation.
|
||||
*
|
||||
* @author Matt C (matt@artemisbot.uk)
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runJpath: function(input, args) {
|
||||
let query = args[0],
|
||||
delimiter = args[1],
|
||||
results,
|
||||
obj;
|
||||
|
||||
try {
|
||||
obj = JSON.parse(input);
|
||||
} catch (err) {
|
||||
return "Invalid input JSON: " + err.message;
|
||||
}
|
||||
|
||||
try {
|
||||
results = jpath.query(obj, query);
|
||||
} catch (err) {
|
||||
return "Invalid JPath expression: " + err.message;
|
||||
}
|
||||
|
||||
return results.map(result => JSON.stringify(result)).join(delimiter);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -381,10 +418,10 @@ const Code = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runCSSQuery: function(input, args) {
|
||||
var query = args[0],
|
||||
let query = args[0],
|
||||
delimiter = args[1],
|
||||
parser = new DOMParser(),
|
||||
html,
|
||||
dom,
|
||||
result;
|
||||
|
||||
if (!query.length || !input.length) {
|
||||
@@ -392,36 +429,114 @@ const Code = {
|
||||
}
|
||||
|
||||
try {
|
||||
html = parser.parseFromString(input, "text/html");
|
||||
dom = parser.parseFromString(input);
|
||||
} catch (err) {
|
||||
return "Invalid input HTML.";
|
||||
}
|
||||
|
||||
try {
|
||||
result = html.querySelectorAll(query);
|
||||
const matcher = nwmatcher({document: dom});
|
||||
result = matcher.select(query, dom);
|
||||
} catch (err) {
|
||||
return "Invalid CSS Selector. Details:\n" + err.message;
|
||||
}
|
||||
|
||||
var nodeToString = function(node) {
|
||||
const nodeToString = function(node) {
|
||||
return node.toString();
|
||||
/* xmldom does not return the outerHTML value.
|
||||
switch (node.nodeType) {
|
||||
case Node.ELEMENT_NODE: return node.outerHTML;
|
||||
case Node.ATTRIBUTE_NODE: return node.value;
|
||||
case Node.COMMENT_NODE: return node.data;
|
||||
case Node.TEXT_NODE: return node.wholeText;
|
||||
case Node.DOCUMENT_NODE: return node.outerHTML;
|
||||
case node.ELEMENT_NODE: return node.outerHTML;
|
||||
case node.ATTRIBUTE_NODE: return node.value;
|
||||
case node.TEXT_NODE: return node.wholeText;
|
||||
case node.COMMENT_NODE: return node.data;
|
||||
case node.DOCUMENT_NODE: return node.outerHTML;
|
||||
default: throw new Error("Unknown Node Type: " + node.nodeType);
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
return Array.apply(null, Array(result.length))
|
||||
.map(function(_, i) {
|
||||
return result[i];
|
||||
})
|
||||
return result
|
||||
.map(nodeToString)
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
/**
|
||||
* This tries to rename variable names in a code snippet according to a function.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {function} replacer - this function will be fed the token which should be renamed.
|
||||
* @returns {string}
|
||||
*/
|
||||
_replaceVariableNames(input, replacer) {
|
||||
const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig;
|
||||
|
||||
return input.replace(tokenRegex, (...args) => {
|
||||
let match = args[0],
|
||||
quotes = args[1];
|
||||
|
||||
if (!quotes) {
|
||||
return match;
|
||||
} else {
|
||||
return replacer(match);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts to snake_case.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
*/
|
||||
runToSnakeCase(input, args) {
|
||||
const smart = args[0];
|
||||
|
||||
if (smart) {
|
||||
return Code._replaceVariableNames(input, snakeCase);
|
||||
} else {
|
||||
return snakeCase(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts to camelCase.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
*/
|
||||
runToCamelCase(input, args) {
|
||||
const smart = args[0];
|
||||
|
||||
if (smart) {
|
||||
return Code._replaceVariableNames(input, camelCase);
|
||||
} else {
|
||||
return camelCase(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts to kebab-case.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
*/
|
||||
runToKebabCase(input, args) {
|
||||
const smart = args[0];
|
||||
|
||||
if (smart) {
|
||||
return Code._replaceVariableNames(input, kebabCase);
|
||||
} else {
|
||||
return kebabCase(input);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default Code;
|
||||
|
||||
@@ -6,15 +6,15 @@ import zip from "zlibjs/bin/zip.min";
|
||||
import unzip from "zlibjs/bin/unzip.min";
|
||||
import bzip2 from "exports-loader?bzip2!../lib/bzip2.js";
|
||||
|
||||
var Zlib = {
|
||||
const Zlib = {
|
||||
RawDeflate: rawdeflate.Zlib.RawDeflate,
|
||||
RawInflate: rawinflate.Zlib.RawInflate,
|
||||
Deflate: zlibAndGzip.Zlib.Deflate,
|
||||
Inflate: zlibAndGzip.Zlib.Inflate,
|
||||
Gzip: zlibAndGzip.Zlib.Gzip,
|
||||
Gunzip: zlibAndGzip.Zlib.Gunzip,
|
||||
Zip: zip.Zlib.Zip,
|
||||
Unzip: unzip.Zlib.Unzip,
|
||||
Deflate: zlibAndGzip.Zlib.Deflate,
|
||||
Inflate: zlibAndGzip.Zlib.Inflate,
|
||||
Gzip: zlibAndGzip.Zlib.Gzip,
|
||||
Gunzip: zlibAndGzip.Zlib.Gunzip,
|
||||
Zip: zip.Zlib.Zip,
|
||||
Unzip: unzip.Zlib.Unzip,
|
||||
};
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ const Compress = {
|
||||
* @default
|
||||
*/
|
||||
RAW_COMPRESSION_TYPE_LOOKUP: {
|
||||
"Fixed Huffman Coding" : Zlib.RawDeflate.CompressionType.FIXED,
|
||||
"Dynamic Huffman Coding" : Zlib.RawDeflate.CompressionType.DYNAMIC,
|
||||
"None (Store)" : Zlib.RawDeflate.CompressionType.NONE,
|
||||
"Fixed Huffman Coding": Zlib.RawDeflate.CompressionType.FIXED,
|
||||
"Dynamic Huffman Coding": Zlib.RawDeflate.CompressionType.DYNAMIC,
|
||||
"None (Store)": Zlib.RawDeflate.CompressionType.NONE,
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -67,7 +67,7 @@ const Compress = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRawDeflate: function(input, args) {
|
||||
var deflate = new Zlib.RawDeflate(input, {
|
||||
const deflate = new Zlib.RawDeflate(input, {
|
||||
compressionType: Compress.RAW_COMPRESSION_TYPE_LOOKUP[args[0]]
|
||||
});
|
||||
return Array.prototype.slice.call(deflate.compress());
|
||||
@@ -99,8 +99,8 @@ const Compress = {
|
||||
* @default
|
||||
*/
|
||||
RAW_BUFFER_TYPE_LOOKUP: {
|
||||
"Adaptive" : Zlib.RawInflate.BufferType.ADAPTIVE,
|
||||
"Block" : Zlib.RawInflate.BufferType.BLOCK,
|
||||
"Adaptive": Zlib.RawInflate.BufferType.ADAPTIVE,
|
||||
"Block": Zlib.RawInflate.BufferType.BLOCK,
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -113,7 +113,7 @@ const Compress = {
|
||||
runRawInflate: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.strToByteArray(Utils.byteArrayToUtf8(input));
|
||||
var inflate = new Zlib.RawInflate(input, {
|
||||
let inflate = new Zlib.RawInflate(input, {
|
||||
index: args[0],
|
||||
bufferSize: args[1],
|
||||
bufferType: Compress.RAW_BUFFER_TYPE_LOOKUP[args[2]],
|
||||
@@ -129,8 +129,8 @@ const Compress = {
|
||||
if (result.length > 158 && result[0] === 93 && result[5] === 93) {
|
||||
// If the first two square brackets are there, check that the others
|
||||
// are also there. If they are, throw an error. If not, continue.
|
||||
var valid = false;
|
||||
for (var i = 0; i < 155; i += 5) {
|
||||
let valid = false;
|
||||
for (let i = 0; i < 155; i += 5) {
|
||||
if (result[i] !== 93) {
|
||||
valid = true;
|
||||
}
|
||||
@@ -150,9 +150,9 @@ const Compress = {
|
||||
* @default
|
||||
*/
|
||||
ZLIB_COMPRESSION_TYPE_LOOKUP: {
|
||||
"Fixed Huffman Coding" : Zlib.Deflate.CompressionType.FIXED,
|
||||
"Dynamic Huffman Coding" : Zlib.Deflate.CompressionType.DYNAMIC,
|
||||
"None (Store)" : Zlib.Deflate.CompressionType.NONE,
|
||||
"Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED,
|
||||
"Dynamic Huffman Coding": Zlib.Deflate.CompressionType.DYNAMIC,
|
||||
"None (Store)": Zlib.Deflate.CompressionType.NONE,
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -163,7 +163,7 @@ const Compress = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runZlibDeflate: function(input, args) {
|
||||
var deflate = new Zlib.Deflate(input, {
|
||||
const deflate = new Zlib.Deflate(input, {
|
||||
compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]]
|
||||
});
|
||||
return Array.prototype.slice.call(deflate.compress());
|
||||
@@ -175,8 +175,8 @@ const Compress = {
|
||||
* @default
|
||||
*/
|
||||
ZLIB_BUFFER_TYPE_LOOKUP: {
|
||||
"Adaptive" : Zlib.Inflate.BufferType.ADAPTIVE,
|
||||
"Block" : Zlib.Inflate.BufferType.BLOCK,
|
||||
"Adaptive": Zlib.Inflate.BufferType.ADAPTIVE,
|
||||
"Block": Zlib.Inflate.BufferType.BLOCK,
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -189,7 +189,7 @@ const Compress = {
|
||||
runZlibInflate: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.strToByteArray(Utils.byteArrayToUtf8(input));
|
||||
var inflate = new Zlib.Inflate(input, {
|
||||
const inflate = new Zlib.Inflate(input, {
|
||||
index: args[0],
|
||||
bufferSize: args[1],
|
||||
bufferType: Compress.ZLIB_BUFFER_TYPE_LOOKUP[args[2]],
|
||||
@@ -214,7 +214,7 @@ const Compress = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runGzip: function(input, args) {
|
||||
var filename = args[1],
|
||||
let filename = args[1],
|
||||
comment = args[2],
|
||||
options = {
|
||||
deflateOptions: {
|
||||
@@ -234,7 +234,7 @@ const Compress = {
|
||||
options.comment = comment;
|
||||
}
|
||||
|
||||
var gzip = new Zlib.Gzip(input, options);
|
||||
const gzip = new Zlib.Gzip(input, options);
|
||||
return Array.prototype.slice.call(gzip.compress());
|
||||
},
|
||||
|
||||
@@ -249,7 +249,7 @@ const Compress = {
|
||||
runGunzip: function(input, args) {
|
||||
// Deal with character encoding issues
|
||||
input = Utils.strToByteArray(Utils.byteArrayToUtf8(input));
|
||||
var gunzip = new Zlib.Gunzip(input);
|
||||
const gunzip = new Zlib.Gunzip(input);
|
||||
return Array.prototype.slice.call(gunzip.decompress());
|
||||
},
|
||||
|
||||
@@ -264,17 +264,17 @@ const Compress = {
|
||||
* @default
|
||||
*/
|
||||
ZIP_COMPRESSION_METHOD_LOOKUP: {
|
||||
"Deflate" : Zlib.Zip.CompressionMethod.DEFLATE,
|
||||
"None (Store)" : Zlib.Zip.CompressionMethod.STORE
|
||||
"Deflate": Zlib.Zip.CompressionMethod.DEFLATE,
|
||||
"None (Store)": Zlib.Zip.CompressionMethod.STORE
|
||||
},
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ZIP_OS_LOOKUP: {
|
||||
"MSDOS" : Zlib.Zip.OperatingSystem.MSDOS,
|
||||
"Unix" : Zlib.Zip.OperatingSystem.UNIX,
|
||||
"Macintosh" : Zlib.Zip.OperatingSystem.MACINTOSH
|
||||
"MSDOS": Zlib.Zip.OperatingSystem.MSDOS,
|
||||
"Unix": Zlib.Zip.OperatingSystem.UNIX,
|
||||
"Macintosh": Zlib.Zip.OperatingSystem.MACINTOSH
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -285,7 +285,7 @@ const Compress = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runPkzip: function(input, args) {
|
||||
var password = Utils.strToByteArray(args[2]),
|
||||
let password = Utils.strToByteArray(args[2]),
|
||||
options = {
|
||||
filename: Utils.strToByteArray(args[0]),
|
||||
comment: Utils.strToByteArray(args[1]),
|
||||
@@ -318,7 +318,7 @@ const Compress = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runPkunzip: function(input, args) {
|
||||
var options = {
|
||||
let options = {
|
||||
password: Utils.strToByteArray(args[0]),
|
||||
verify: args[1]
|
||||
},
|
||||
@@ -327,15 +327,15 @@ const Compress = {
|
||||
files = [];
|
||||
|
||||
filenames.forEach(function(fileName) {
|
||||
var bytes = unzip.decompress(fileName);
|
||||
var contents = Utils.byteArrayToUtf8(bytes);
|
||||
const bytes = unzip.decompress(fileName);
|
||||
const contents = Utils.byteArrayToUtf8(bytes);
|
||||
|
||||
var file = {
|
||||
const file = {
|
||||
fileName: fileName,
|
||||
size: contents.length,
|
||||
};
|
||||
|
||||
var isDir = contents.length === 0 && fileName.endsWith("/");
|
||||
const isDir = contents.length === 0 && fileName.endsWith("/");
|
||||
if (!isDir) {
|
||||
file.bytes = bytes;
|
||||
file.contents = contents;
|
||||
@@ -356,7 +356,7 @@ const Compress = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runBzip2Decompress: function(input, args) {
|
||||
var compressed = new Uint8Array(input),
|
||||
let compressed = new Uint8Array(input),
|
||||
bzip2Reader,
|
||||
plain = "";
|
||||
|
||||
@@ -383,19 +383,19 @@ const Compress = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runTar: function(input, args) {
|
||||
var Tarball = function() {
|
||||
const Tarball = function() {
|
||||
this.bytes = new Array(512);
|
||||
this.position = 0;
|
||||
};
|
||||
|
||||
Tarball.prototype.addEmptyBlock = function() {
|
||||
var filler = new Array(512);
|
||||
const filler = new Array(512);
|
||||
filler.fill(0);
|
||||
this.bytes = this.bytes.concat(filler);
|
||||
};
|
||||
|
||||
Tarball.prototype.writeBytes = function(bytes) {
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
if (this.position + bytes.length > this.bytes.length) {
|
||||
this.addEmptyBlock();
|
||||
@@ -412,17 +412,17 @@ const Compress = {
|
||||
};
|
||||
|
||||
Tarball.prototype.writeEndBlocks = function() {
|
||||
var numEmptyBlocks = 2;
|
||||
for (var i = 0; i < numEmptyBlocks; i++) {
|
||||
const numEmptyBlocks = 2;
|
||||
for (let i = 0; i < numEmptyBlocks; i++) {
|
||||
this.addEmptyBlock();
|
||||
}
|
||||
};
|
||||
|
||||
var fileSize = Utils.padLeft(input.length.toString(8), 11, "0");
|
||||
var currentUnixTimestamp = Math.floor(Date.now() / 1000);
|
||||
var lastModTime = Utils.padLeft(currentUnixTimestamp.toString(8), 11, "0");
|
||||
const fileSize = input.length.toString(8).padStart(11, "0");
|
||||
const currentUnixTimestamp = Math.floor(Date.now() / 1000);
|
||||
const lastModTime = currentUnixTimestamp.toString(8).padStart(11, "0");
|
||||
|
||||
var file = {
|
||||
const file = {
|
||||
fileName: Utils.padBytesRight(args[0], 100),
|
||||
fileMode: Utils.padBytesRight("0000664", 8),
|
||||
ownerUID: Utils.padBytesRight("0", 8),
|
||||
@@ -441,9 +441,9 @@ const Compress = {
|
||||
fileNamePrefix: Utils.padBytesRight("", 155),
|
||||
};
|
||||
|
||||
var checksum = 0;
|
||||
for (var key in file) {
|
||||
var bytes = file[key];
|
||||
let checksum = 0;
|
||||
for (const key in file) {
|
||||
const bytes = file[key];
|
||||
Array.prototype.forEach.call(bytes, function(b) {
|
||||
if (typeof b.charCodeAt !== "undefined") {
|
||||
checksum += b.charCodeAt();
|
||||
@@ -452,10 +452,10 @@ const Compress = {
|
||||
}
|
||||
});
|
||||
}
|
||||
checksum = Utils.padBytesRight(Utils.padLeft(checksum.toString(8), 7, "0"), 8);
|
||||
checksum = Utils.padBytesRight(checksum.toString(8).padStart(7, "0"), 8);
|
||||
file.checksum = checksum;
|
||||
|
||||
var tarball = new Tarball();
|
||||
const tarball = new Tarball();
|
||||
tarball.writeBytes(file.fileName);
|
||||
tarball.writeBytes(file.fileMode);
|
||||
tarball.writeBytes(file.ownerUID);
|
||||
@@ -490,22 +490,22 @@ const Compress = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runUntar: function(input, args) {
|
||||
var Stream = function(input) {
|
||||
const Stream = function(input) {
|
||||
this.bytes = input;
|
||||
this.position = 0;
|
||||
};
|
||||
|
||||
Stream.prototype.getBytes = function(bytesToGet) {
|
||||
var newPosition = this.position + bytesToGet;
|
||||
var bytes = this.bytes.slice(this.position, newPosition);
|
||||
const newPosition = this.position + bytesToGet;
|
||||
const bytes = this.bytes.slice(this.position, newPosition);
|
||||
this.position = newPosition;
|
||||
return bytes;
|
||||
};
|
||||
|
||||
Stream.prototype.readString = function(numBytes) {
|
||||
var result = "";
|
||||
for (var i = this.position; i < this.position + numBytes; i++) {
|
||||
var currentByte = this.bytes[i];
|
||||
let result = "";
|
||||
for (let i = this.position; i < this.position + numBytes; i++) {
|
||||
const currentByte = this.bytes[i];
|
||||
if (currentByte === 0) break;
|
||||
result += String.fromCharCode(currentByte);
|
||||
}
|
||||
@@ -514,7 +514,7 @@ const Compress = {
|
||||
};
|
||||
|
||||
Stream.prototype.readInt = function(numBytes, base) {
|
||||
var string = this.readString(numBytes);
|
||||
const string = this.readString(numBytes);
|
||||
return parseInt(string, base);
|
||||
};
|
||||
|
||||
@@ -522,13 +522,13 @@ const Compress = {
|
||||
return this.position < this.bytes.length;
|
||||
};
|
||||
|
||||
var stream = new Stream(input),
|
||||
let stream = new Stream(input),
|
||||
files = [];
|
||||
|
||||
while (stream.hasMore()) {
|
||||
var dataPosition = stream.position + 512;
|
||||
const dataPosition = stream.position + 512;
|
||||
|
||||
var file = {
|
||||
const file = {
|
||||
fileName: stream.readString(100),
|
||||
fileMode: stream.readString(8),
|
||||
ownerUID: stream.readString(8),
|
||||
@@ -555,7 +555,7 @@ const Compress = {
|
||||
if (file.type === "0") {
|
||||
// File
|
||||
files.push(file);
|
||||
var endPosition = stream.position + file.size;
|
||||
let endPosition = stream.position + file.size;
|
||||
if (file.size % 512 !== 0) {
|
||||
endPosition += 512 - (file.size % 512);
|
||||
}
|
||||
|
||||
@@ -25,52 +25,51 @@ const Convert = {
|
||||
* @default
|
||||
*/
|
||||
DISTANCE_FACTOR: { // Multiples of a metre
|
||||
"Nanometres (nm)" : 1e-9,
|
||||
"Micrometres (µm)" : 1e-6,
|
||||
"Millimetres (mm)" : 1e-3,
|
||||
"Centimetres (cm)" : 1e-2,
|
||||
"Metres (m)" : 1,
|
||||
"Kilometers (km)" : 1e3,
|
||||
"Nanometres (nm)": 1e-9,
|
||||
"Micrometres (µm)": 1e-6,
|
||||
"Millimetres (mm)": 1e-3,
|
||||
"Centimetres (cm)": 1e-2,
|
||||
"Metres (m)": 1,
|
||||
"Kilometers (km)": 1e3,
|
||||
|
||||
"Thou (th)" : 0.0000254,
|
||||
"Inches (in)" : 0.0254,
|
||||
"Feet (ft)" : 0.3048,
|
||||
"Yards (yd)" : 0.9144,
|
||||
"Chains (ch)" : 20.1168,
|
||||
"Furlongs (fur)" : 201.168,
|
||||
"Miles (mi)" : 1609.344,
|
||||
"Leagues (lea)" : 4828.032,
|
||||
"Thou (th)": 0.0000254,
|
||||
"Inches (in)": 0.0254,
|
||||
"Feet (ft)": 0.3048,
|
||||
"Yards (yd)": 0.9144,
|
||||
"Chains (ch)": 20.1168,
|
||||
"Furlongs (fur)": 201.168,
|
||||
"Miles (mi)": 1609.344,
|
||||
"Leagues (lea)": 4828.032,
|
||||
|
||||
"Fathoms (ftm)" : 1.853184,
|
||||
"Cables" : 185.3184,
|
||||
"Nautical miles" : 1853.184,
|
||||
"Fathoms (ftm)": 1.853184,
|
||||
"Cables": 185.3184,
|
||||
"Nautical miles": 1853.184,
|
||||
|
||||
"Cars (4m)" : 4,
|
||||
"Buses (8.4m)" : 8.4,
|
||||
"Cars (4m)": 4,
|
||||
"Buses (8.4m)": 8.4,
|
||||
"American football fields (91m)": 91,
|
||||
"Football pitches (105m)": 105,
|
||||
|
||||
"Earth-to-Moons" : 380000000,
|
||||
"Earth's equators" : 40075016.686,
|
||||
"Earth-to-Moons": 380000000,
|
||||
"Earth's equators": 40075016.686,
|
||||
"Astronomical units (au)": 149597870700,
|
||||
"Light-years (ly)" : 9460730472580800,
|
||||
"Parsecs (pc)" : 3.0856776e16
|
||||
"Light-years (ly)": 9460730472580800,
|
||||
"Parsecs (pc)": 3.0856776e16
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert distance operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runDistance: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.DISTANCE_FACTOR[inputUnits];
|
||||
return input / Convert.DISTANCE_FACTOR[outputUnits];
|
||||
// TODO Remove rounding errors (e.g. 1.000000000001)
|
||||
input = input.times(Convert.DISTANCE_FACTOR[inputUnits]);
|
||||
return input.div(Convert.DISTANCE_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
@@ -90,67 +89,67 @@ const Convert = {
|
||||
* @default
|
||||
*/
|
||||
DATA_FACTOR: { // Multiples of a bit
|
||||
"Bits (b)" : 1,
|
||||
"Nibbles" : 4,
|
||||
"Octets" : 8,
|
||||
"Bytes (B)" : 8,
|
||||
"Bits (b)": 1,
|
||||
"Nibbles": 4,
|
||||
"Octets": 8,
|
||||
"Bytes (B)": 8,
|
||||
|
||||
// Binary bits (2^n)
|
||||
"Kibibits (Kib)" : 1024,
|
||||
"Mebibits (Mib)" : 1048576,
|
||||
"Gibibits (Gib)" : 1073741824,
|
||||
"Tebibits (Tib)" : 1099511627776,
|
||||
"Pebibits (Pib)" : 1125899906842624,
|
||||
"Exbibits (Eib)" : 1152921504606846976,
|
||||
"Zebibits (Zib)" : 1180591620717411303424,
|
||||
"Yobibits (Yib)" : 1208925819614629174706176,
|
||||
"Kibibits (Kib)": 1024,
|
||||
"Mebibits (Mib)": 1048576,
|
||||
"Gibibits (Gib)": 1073741824,
|
||||
"Tebibits (Tib)": 1099511627776,
|
||||
"Pebibits (Pib)": 1125899906842624,
|
||||
"Exbibits (Eib)": 1152921504606846976,
|
||||
"Zebibits (Zib)": 1180591620717411303424,
|
||||
"Yobibits (Yib)": 1208925819614629174706176,
|
||||
|
||||
// Decimal bits (10^n)
|
||||
"Decabits" : 10,
|
||||
"Hectobits" : 100,
|
||||
"Kilobits (Kb)" : 1e3,
|
||||
"Megabits (Mb)" : 1e6,
|
||||
"Gigabits (Gb)" : 1e9,
|
||||
"Terabits (Tb)" : 1e12,
|
||||
"Petabits (Pb)" : 1e15,
|
||||
"Exabits (Eb)" : 1e18,
|
||||
"Zettabits (Zb)" : 1e21,
|
||||
"Yottabits (Yb)" : 1e24,
|
||||
"Decabits": 10,
|
||||
"Hectobits": 100,
|
||||
"Kilobits (Kb)": 1e3,
|
||||
"Megabits (Mb)": 1e6,
|
||||
"Gigabits (Gb)": 1e9,
|
||||
"Terabits (Tb)": 1e12,
|
||||
"Petabits (Pb)": 1e15,
|
||||
"Exabits (Eb)": 1e18,
|
||||
"Zettabits (Zb)": 1e21,
|
||||
"Yottabits (Yb)": 1e24,
|
||||
|
||||
// Binary bytes (8 x 2^n)
|
||||
"Kibibytes (KiB)" : 8192,
|
||||
"Mebibytes (MiB)" : 8388608,
|
||||
"Gibibytes (GiB)" : 8589934592,
|
||||
"Tebibytes (TiB)" : 8796093022208,
|
||||
"Pebibytes (PiB)" : 9007199254740992,
|
||||
"Exbibytes (EiB)" : 9223372036854775808,
|
||||
"Zebibytes (ZiB)" : 9444732965739290427392,
|
||||
"Yobibytes (YiB)" : 9671406556917033397649408,
|
||||
"Kibibytes (KiB)": 8192,
|
||||
"Mebibytes (MiB)": 8388608,
|
||||
"Gibibytes (GiB)": 8589934592,
|
||||
"Tebibytes (TiB)": 8796093022208,
|
||||
"Pebibytes (PiB)": 9007199254740992,
|
||||
"Exbibytes (EiB)": 9223372036854775808,
|
||||
"Zebibytes (ZiB)": 9444732965739290427392,
|
||||
"Yobibytes (YiB)": 9671406556917033397649408,
|
||||
|
||||
// Decimal bytes (8 x 10^n)
|
||||
"Kilobytes (KB)" : 8e3,
|
||||
"Megabytes (MB)" : 8e6,
|
||||
"Gigabytes (GB)" : 8e9,
|
||||
"Terabytes (TB)" : 8e12,
|
||||
"Petabytes (PB)" : 8e15,
|
||||
"Exabytes (EB)" : 8e18,
|
||||
"Zettabytes (ZB)" : 8e21,
|
||||
"Yottabytes (YB)" : 8e24,
|
||||
"Kilobytes (KB)": 8e3,
|
||||
"Megabytes (MB)": 8e6,
|
||||
"Gigabytes (GB)": 8e9,
|
||||
"Terabytes (TB)": 8e12,
|
||||
"Petabytes (PB)": 8e15,
|
||||
"Exabytes (EB)": 8e18,
|
||||
"Zettabytes (ZB)": 8e21,
|
||||
"Yottabytes (YB)": 8e24,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert data units operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runDataSize: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.DATA_FACTOR[inputUnits];
|
||||
return input / Convert.DATA_FACTOR[outputUnits];
|
||||
input = input.times(Convert.DATA_FACTOR[inputUnits]);
|
||||
return input.div(Convert.DATA_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
@@ -171,66 +170,66 @@ const Convert = {
|
||||
*/
|
||||
AREA_FACTOR: { // Multiples of a square metre
|
||||
// Metric
|
||||
"Square metre (sq m)" : 1,
|
||||
"Square kilometre (sq km)" : 1e6,
|
||||
"Square metre (sq m)": 1,
|
||||
"Square kilometre (sq km)": 1e6,
|
||||
|
||||
"Centiare (ca)" : 1,
|
||||
"Deciare (da)" : 10,
|
||||
"Are (a)" : 100,
|
||||
"Decare (daa)" : 1e3,
|
||||
"Hectare (ha)" : 1e4,
|
||||
"Centiare (ca)": 1,
|
||||
"Deciare (da)": 10,
|
||||
"Are (a)": 100,
|
||||
"Decare (daa)": 1e3,
|
||||
"Hectare (ha)": 1e4,
|
||||
|
||||
// Imperial
|
||||
"Square inch (sq in)" : 0.00064516,
|
||||
"Square foot (sq ft)" : 0.09290304,
|
||||
"Square yard (sq yd)" : 0.83612736,
|
||||
"Square mile (sq mi)" : 2589988.110336,
|
||||
"Perch (sq per)" : 42.21,
|
||||
"Rood (ro)" : 1011,
|
||||
"International acre (ac)" : 4046.8564224,
|
||||
"Square inch (sq in)": 0.00064516,
|
||||
"Square foot (sq ft)": 0.09290304,
|
||||
"Square yard (sq yd)": 0.83612736,
|
||||
"Square mile (sq mi)": 2589988.110336,
|
||||
"Perch (sq per)": 42.21,
|
||||
"Rood (ro)": 1011,
|
||||
"International acre (ac)": 4046.8564224,
|
||||
|
||||
// US customary units
|
||||
"US survey acre (ac)" : 4046.87261,
|
||||
"US survey square mile (sq mi)" : 2589998.470305239,
|
||||
"US survey township" : 93239944.9309886,
|
||||
"US survey acre (ac)": 4046.87261,
|
||||
"US survey square mile (sq mi)": 2589998.470305239,
|
||||
"US survey township": 93239944.9309886,
|
||||
|
||||
// Nuclear physics
|
||||
"Yoctobarn (yb)" : 1e-52,
|
||||
"Zeptobarn (zb)" : 1e-49,
|
||||
"Attobarn (ab)" : 1e-46,
|
||||
"Femtobarn (fb)" : 1e-43,
|
||||
"Picobarn (pb)" : 1e-40,
|
||||
"Nanobarn (nb)" : 1e-37,
|
||||
"Microbarn (μb)" : 1e-34,
|
||||
"Millibarn (mb)" : 1e-31,
|
||||
"Barn (b)" : 1e-28,
|
||||
"Kilobarn (kb)" : 1e-25,
|
||||
"Megabarn (Mb)" : 1e-22,
|
||||
"Yoctobarn (yb)": 1e-52,
|
||||
"Zeptobarn (zb)": 1e-49,
|
||||
"Attobarn (ab)": 1e-46,
|
||||
"Femtobarn (fb)": 1e-43,
|
||||
"Picobarn (pb)": 1e-40,
|
||||
"Nanobarn (nb)": 1e-37,
|
||||
"Microbarn (μb)": 1e-34,
|
||||
"Millibarn (mb)": 1e-31,
|
||||
"Barn (b)": 1e-28,
|
||||
"Kilobarn (kb)": 1e-25,
|
||||
"Megabarn (Mb)": 1e-22,
|
||||
|
||||
"Planck area" : 2.6e-70,
|
||||
"Shed" : 1e-52,
|
||||
"Outhouse" : 1e-34,
|
||||
"Planck area": 2.6e-70,
|
||||
"Shed": 1e-52,
|
||||
"Outhouse": 1e-34,
|
||||
|
||||
// Comparisons
|
||||
"Washington D.C." : 176119191.502848,
|
||||
"Isle of Wight" : 380000000,
|
||||
"Wales" : 20779000000,
|
||||
"Texas" : 696241000000,
|
||||
"Washington D.C.": 176119191.502848,
|
||||
"Isle of Wight": 380000000,
|
||||
"Wales": 20779000000,
|
||||
"Texas": 696241000000,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert area operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runArea: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.AREA_FACTOR[inputUnits];
|
||||
return input / Convert.AREA_FACTOR[outputUnits];
|
||||
input = input.times(Convert.AREA_FACTOR[inputUnits]);
|
||||
return input.div(Convert.AREA_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
@@ -252,96 +251,96 @@ const Convert = {
|
||||
*/
|
||||
MASS_FACTOR: { // Multiples of a gram
|
||||
// Metric
|
||||
"Yoctogram (yg)" : 1e-24,
|
||||
"Zeptogram (zg)" : 1e-21,
|
||||
"Attogram (ag)" : 1e-18,
|
||||
"Femtogram (fg)" : 1e-15,
|
||||
"Picogram (pg)" : 1e-12,
|
||||
"Nanogram (ng)" : 1e-9,
|
||||
"Microgram (μg)" : 1e-6,
|
||||
"Milligram (mg)" : 1e-3,
|
||||
"Centigram (cg)" : 1e-2,
|
||||
"Decigram (dg)" : 1e-1,
|
||||
"Gram (g)" : 1,
|
||||
"Decagram (dag)" : 10,
|
||||
"Hectogram (hg)" : 100,
|
||||
"Kilogram (kg)" : 1000,
|
||||
"Megagram (Mg)" : 1e6,
|
||||
"Tonne (t)" : 1e6,
|
||||
"Gigagram (Gg)" : 1e9,
|
||||
"Teragram (Tg)" : 1e12,
|
||||
"Petagram (Pg)" : 1e15,
|
||||
"Exagram (Eg)" : 1e18,
|
||||
"Zettagram (Zg)" : 1e21,
|
||||
"Yottagram (Yg)" : 1e24,
|
||||
"Yoctogram (yg)": 1e-24,
|
||||
"Zeptogram (zg)": 1e-21,
|
||||
"Attogram (ag)": 1e-18,
|
||||
"Femtogram (fg)": 1e-15,
|
||||
"Picogram (pg)": 1e-12,
|
||||
"Nanogram (ng)": 1e-9,
|
||||
"Microgram (μg)": 1e-6,
|
||||
"Milligram (mg)": 1e-3,
|
||||
"Centigram (cg)": 1e-2,
|
||||
"Decigram (dg)": 1e-1,
|
||||
"Gram (g)": 1,
|
||||
"Decagram (dag)": 10,
|
||||
"Hectogram (hg)": 100,
|
||||
"Kilogram (kg)": 1000,
|
||||
"Megagram (Mg)": 1e6,
|
||||
"Tonne (t)": 1e6,
|
||||
"Gigagram (Gg)": 1e9,
|
||||
"Teragram (Tg)": 1e12,
|
||||
"Petagram (Pg)": 1e15,
|
||||
"Exagram (Eg)": 1e18,
|
||||
"Zettagram (Zg)": 1e21,
|
||||
"Yottagram (Yg)": 1e24,
|
||||
|
||||
// Imperial Avoirdupois
|
||||
"Grain (gr)" : 64.79891e-3,
|
||||
"Dram (dr)" : 1.7718451953125,
|
||||
"Ounce (oz)" : 28.349523125,
|
||||
"Pound (lb)" : 453.59237,
|
||||
"Nail" : 3175.14659,
|
||||
"Stone (st)" : 6.35029318e3,
|
||||
"Quarter (gr)" : 12700.58636,
|
||||
"Tod" : 12700.58636,
|
||||
"US hundredweight (cwt)" : 45.359237e3,
|
||||
"Imperial hundredweight (cwt)" : 50.80234544e3,
|
||||
"US ton (t)" : 907.18474e3,
|
||||
"Imperial ton (t)" : 1016.0469088e3,
|
||||
"Grain (gr)": 64.79891e-3,
|
||||
"Dram (dr)": 1.7718451953125,
|
||||
"Ounce (oz)": 28.349523125,
|
||||
"Pound (lb)": 453.59237,
|
||||
"Nail": 3175.14659,
|
||||
"Stone (st)": 6.35029318e3,
|
||||
"Quarter (gr)": 12700.58636,
|
||||
"Tod": 12700.58636,
|
||||
"US hundredweight (cwt)": 45.359237e3,
|
||||
"Imperial hundredweight (cwt)": 50.80234544e3,
|
||||
"US ton (t)": 907.18474e3,
|
||||
"Imperial ton (t)": 1016.0469088e3,
|
||||
|
||||
// Imperial Troy
|
||||
"Pennyweight (dwt)" : 1.55517384,
|
||||
"Troy dram (dr t)" : 3.8879346,
|
||||
"Troy ounce (oz t)" : 31.1034768,
|
||||
"Troy pound (lb t)" : 373.2417216,
|
||||
"Mark" : 248.8278144,
|
||||
"Pennyweight (dwt)": 1.55517384,
|
||||
"Troy dram (dr t)": 3.8879346,
|
||||
"Troy ounce (oz t)": 31.1034768,
|
||||
"Troy pound (lb t)": 373.2417216,
|
||||
"Mark": 248.8278144,
|
||||
|
||||
// Archaic
|
||||
"Wey" : 76.5e3,
|
||||
"Wool wey" : 101.7e3,
|
||||
"Suffolk wey" : 161.5e3,
|
||||
"Wool sack" : 153000,
|
||||
"Coal sack" : 50.80234544e3,
|
||||
"Load" : 918000,
|
||||
"Last" : 1836000,
|
||||
"Flax or feather last" : 770e3,
|
||||
"Gunpowder last" : 1090e3,
|
||||
"Picul" : 60.478982e3,
|
||||
"Rice last" : 1200e3,
|
||||
"Wey": 76.5e3,
|
||||
"Wool wey": 101.7e3,
|
||||
"Suffolk wey": 161.5e3,
|
||||
"Wool sack": 153000,
|
||||
"Coal sack": 50.80234544e3,
|
||||
"Load": 918000,
|
||||
"Last": 1836000,
|
||||
"Flax or feather last": 770e3,
|
||||
"Gunpowder last": 1090e3,
|
||||
"Picul": 60.478982e3,
|
||||
"Rice last": 1200e3,
|
||||
|
||||
// Comparisons
|
||||
"Big Ben (14 tonnes)" : 14e6,
|
||||
"Blue whale (180 tonnes)" : 180e6,
|
||||
"International Space Station (417 tonnes)" : 417e6,
|
||||
"Space Shuttle (2,041 tonnes)" : 2041e6,
|
||||
"RMS Titanic (52,000 tonnes)" : 52000e6,
|
||||
"Great Pyramid of Giza (6,000,000 tonnes)" : 6e12,
|
||||
"Earth's oceans (1.4 yottagrams)" : 1.4e24,
|
||||
"Big Ben (14 tonnes)": 14e6,
|
||||
"Blue whale (180 tonnes)": 180e6,
|
||||
"International Space Station (417 tonnes)": 417e6,
|
||||
"Space Shuttle (2,041 tonnes)": 2041e6,
|
||||
"RMS Titanic (52,000 tonnes)": 52000e6,
|
||||
"Great Pyramid of Giza (6,000,000 tonnes)": 6e12,
|
||||
"Earth's oceans (1.4 yottagrams)": 1.4e24,
|
||||
|
||||
// Astronomical
|
||||
"A teaspoon of neutron star (5,500 million tonnes)" : 5.5e15,
|
||||
"Lunar mass (ML)" : 7.342e25,
|
||||
"Earth mass (M⊕)" : 5.97219e27,
|
||||
"Jupiter mass (MJ)" : 1.8981411476999997e30,
|
||||
"Solar mass (M☉)" : 1.98855e33,
|
||||
"Sagittarius A* (7.5 x 10^36 kgs-ish)" : 7.5e39,
|
||||
"Milky Way galaxy (1.2 x 10^42 kgs)" : 1.2e45,
|
||||
"The observable universe (1.45 x 10^53 kgs)" : 1.45e56,
|
||||
"A teaspoon of neutron star (5,500 million tonnes)": 5.5e15,
|
||||
"Lunar mass (ML)": 7.342e25,
|
||||
"Earth mass (M⊕)": 5.97219e27,
|
||||
"Jupiter mass (MJ)": 1.8981411476999997e30,
|
||||
"Solar mass (M☉)": 1.98855e33,
|
||||
"Sagittarius A* (7.5 x 10^36 kgs-ish)": 7.5e39,
|
||||
"Milky Way galaxy (1.2 x 10^42 kgs)": 1.2e45,
|
||||
"The observable universe (1.45 x 10^53 kgs)": 1.45e56,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert mass operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runMass: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.MASS_FACTOR[inputUnits];
|
||||
return input / Convert.MASS_FACTOR[outputUnits];
|
||||
input = input.times(Convert.MASS_FACTOR[inputUnits]);
|
||||
return input.div(Convert.MASS_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
|
||||
@@ -361,52 +360,52 @@ const Convert = {
|
||||
*/
|
||||
SPEED_FACTOR: { // Multiples of m/s
|
||||
// Metric
|
||||
"Metres per second (m/s)" : 1,
|
||||
"Kilometres per hour (km/h)" : 0.2778,
|
||||
"Metres per second (m/s)": 1,
|
||||
"Kilometres per hour (km/h)": 0.2778,
|
||||
|
||||
// Imperial
|
||||
"Miles per hour (mph)" : 0.44704,
|
||||
"Knots (kn)" : 0.5144,
|
||||
"Miles per hour (mph)": 0.44704,
|
||||
"Knots (kn)": 0.5144,
|
||||
|
||||
// Comparisons
|
||||
"Human hair growth rate" : 4.8e-9,
|
||||
"Bamboo growth rate" : 1.4e-5,
|
||||
"World's fastest snail" : 0.00275,
|
||||
"Usain Bolt's top speed" : 12.42,
|
||||
"Jet airliner cruising speed" : 250,
|
||||
"Concorde" : 603,
|
||||
"SR-71 Blackbird" : 981,
|
||||
"Space Shuttle" : 1400,
|
||||
"International Space Station" : 7700,
|
||||
"Human hair growth rate": 4.8e-9,
|
||||
"Bamboo growth rate": 1.4e-5,
|
||||
"World's fastest snail": 0.00275,
|
||||
"Usain Bolt's top speed": 12.42,
|
||||
"Jet airliner cruising speed": 250,
|
||||
"Concorde": 603,
|
||||
"SR-71 Blackbird": 981,
|
||||
"Space Shuttle": 1400,
|
||||
"International Space Station": 7700,
|
||||
|
||||
// Scientific
|
||||
"Sound in standard atmosphere" : 340.3,
|
||||
"Sound in water" : 1500,
|
||||
"Lunar escape velocity" : 2375,
|
||||
"Earth escape velocity" : 11200,
|
||||
"Earth's solar orbit" : 29800,
|
||||
"Solar system's Milky Way orbit" : 200000,
|
||||
"Milky Way relative to the cosmic microwave background" : 552000,
|
||||
"Solar escape velocity" : 617700,
|
||||
"Neutron star escape velocity (0.3c)" : 100000000,
|
||||
"Light in a diamond (0.4136c)" : 124000000,
|
||||
"Signal in an optical fibre (0.667c)" : 200000000,
|
||||
"Light (c)" : 299792458,
|
||||
"Sound in standard atmosphere": 340.3,
|
||||
"Sound in water": 1500,
|
||||
"Lunar escape velocity": 2375,
|
||||
"Earth escape velocity": 11200,
|
||||
"Earth's solar orbit": 29800,
|
||||
"Solar system's Milky Way orbit": 200000,
|
||||
"Milky Way relative to the cosmic microwave background": 552000,
|
||||
"Solar escape velocity": 617700,
|
||||
"Neutron star escape velocity (0.3c)": 100000000,
|
||||
"Light in a diamond (0.4136c)": 124000000,
|
||||
"Signal in an optical fibre (0.667c)": 200000000,
|
||||
"Light (c)": 299792458,
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert speed operation.
|
||||
*
|
||||
* @param {number} input
|
||||
* @param {BigNumber} input
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
runSpeed: function (input, args) {
|
||||
var inputUnits = args[0],
|
||||
let inputUnits = args[0],
|
||||
outputUnits = args[1];
|
||||
|
||||
input = input * Convert.SPEED_FACTOR[inputUnits];
|
||||
return input / Convert.SPEED_FACTOR[outputUnits];
|
||||
input = input.times(Convert.SPEED_FACTOR[inputUnits]);
|
||||
return input.div(Convert.SPEED_FACTOR[outputUnits]);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ const DateTime = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFromUnixTimestamp: function(input, args) {
|
||||
var units = args[0],
|
||||
let units = args[0],
|
||||
d;
|
||||
|
||||
input = parseFloat(input);
|
||||
@@ -46,6 +46,12 @@ const DateTime = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
TREAT_AS_UTC: true,
|
||||
|
||||
/**
|
||||
* To UNIX Timestamp operation.
|
||||
*
|
||||
@@ -54,8 +60,9 @@ const DateTime = {
|
||||
* @returns {number}
|
||||
*/
|
||||
runToUnixTimestamp: function(input, args) {
|
||||
var units = args[0],
|
||||
d = moment(input);
|
||||
let units = args[0],
|
||||
treatAsUTC = args[1],
|
||||
d = treatAsUTC ? moment.utc(input) : moment(input);
|
||||
|
||||
if (units === "Seconds (s)") {
|
||||
return d.unix();
|
||||
@@ -129,7 +136,7 @@ const DateTime = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runTranslateFormat: function(input, args) {
|
||||
var inputFormat = args[1],
|
||||
let inputFormat = args[1],
|
||||
inputTimezone = args[2],
|
||||
outputFormat = args[3],
|
||||
outputTimezone = args[4],
|
||||
@@ -154,7 +161,7 @@ const DateTime = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runParse: function(input, args) {
|
||||
var inputFormat = args[1],
|
||||
let inputFormat = args[1],
|
||||
inputTimezone = args[2],
|
||||
date,
|
||||
output = "";
|
||||
@@ -182,271 +189,287 @@ const DateTime = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sleep operation.
|
||||
*
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runSleep: async function(input, args) {
|
||||
const ms = args[0];
|
||||
await new Promise(r => setTimeout(r, ms));
|
||||
return input;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
*/
|
||||
FORMAT_EXAMPLES: "Format string tokens:\n\n\
|
||||
<table class='table table-striped table-hover table-condensed table-bordered' style='font-family: sans-serif'>\
|
||||
<thead>\
|
||||
<tr>\
|
||||
<th>Category</th>\
|
||||
<th>Token</th>\
|
||||
<th>Output</th>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<td><b>Month</b></td>\
|
||||
<td>M</td>\
|
||||
<td>1 2 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Mo</td>\
|
||||
<td>1st 2nd ... 11th 12th</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>MM</td>\
|
||||
<td>01 02 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>MMM</td>\
|
||||
<td>Jan Feb ... Nov Dec</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>MMMM</td>\
|
||||
<td>January February ... November December</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Quarter</b></td>\
|
||||
<td>Q</td>\
|
||||
<td>1 2 3 4</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Month</b></td>\
|
||||
<td>D</td>\
|
||||
<td>1 2 ... 30 31</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Do</td>\
|
||||
<td>1st 2nd ... 30th 31st</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>DD</td>\
|
||||
<td>01 02 ... 30 31</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Year</b></td>\
|
||||
<td>DDD</td>\
|
||||
<td>1 2 ... 364 365</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>DDDo</td>\
|
||||
<td>1st 2nd ... 364th 365th</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>DDDD</td>\
|
||||
<td>001 002 ... 364 365</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Week</b></td>\
|
||||
<td>d</td>\
|
||||
<td>0 1 ... 5 6</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>do</td>\
|
||||
<td>0th 1st ... 5th 6th</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>dd</td>\
|
||||
<td>Su Mo ... Fr Sa</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ddd</td>\
|
||||
<td>Sun Mon ... Fri Sat</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>dddd</td>\
|
||||
<td>Sunday Monday ... Friday Saturday</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Week (Locale)</b></td>\
|
||||
<td>e</td>\
|
||||
<td>0 1 ... 5 6</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Week (ISO)</b></td>\
|
||||
<td>E</td>\
|
||||
<td>1 2 ... 6 7</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week of Year</b></td>\
|
||||
<td>w</td>\
|
||||
<td>1 2 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>wo</td>\
|
||||
<td>1st 2nd ... 52nd 53rd</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ww</td>\
|
||||
<td>01 02 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week of Year (ISO)</b></td>\
|
||||
<td>W</td>\
|
||||
<td>1 2 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Wo</td>\
|
||||
<td>1st 2nd ... 52nd 53rd</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>WW</td>\
|
||||
<td>01 02 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Year</b></td>\
|
||||
<td>YY</td>\
|
||||
<td>70 71 ... 29 30</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>YYYY</td>\
|
||||
<td>1970 1971 ... 2029 2030</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week Year</b></td>\
|
||||
<td>gg</td>\
|
||||
<td>70 71 ... 29 30</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>gggg</td>\
|
||||
<td>1970 1971 ... 2029 2030</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week Year (ISO)</b></td>\
|
||||
<td>GG</td>\
|
||||
<td>70 71 ... 29 30</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>GGGG</td>\
|
||||
<td>1970 1971 ... 2029 2030</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>AM/PM</b></td>\
|
||||
<td>A</td>\
|
||||
<td>AM PM</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>a</td>\
|
||||
<td>am pm</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Hour</b></td>\
|
||||
<td>H</td>\
|
||||
<td>0 1 ... 22 23</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>HH</td>\
|
||||
<td>00 01 ... 22 23</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>h</td>\
|
||||
<td>1 2 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>hh</td>\
|
||||
<td>01 02 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Minute</b></td>\
|
||||
<td>m</td>\
|
||||
<td>0 1 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>mm</td>\
|
||||
<td>00 01 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Second</b></td>\
|
||||
<td>s</td>\
|
||||
<td>0 1 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ss</td>\
|
||||
<td>00 01 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Fractional Second</b></td>\
|
||||
<td>S</td>\
|
||||
<td>0 1 ... 8 9</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>SS</td>\
|
||||
<td>00 01 ... 98 99</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>SSS</td>\
|
||||
<td>000 001 ... 998 999</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>SSSS ... SSSSSSSSS</td>\
|
||||
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Timezone</b></td>\
|
||||
<td>z or zz</td>\
|
||||
<td>EST CST ... MST PST</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Z</td>\
|
||||
<td>-07:00 -06:00 ... +06:00 +07:00</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ZZ</td>\
|
||||
<td>-0700 -0600 ... +0600 +0700</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Unix Timestamp</b></td>\
|
||||
<td>X</td>\
|
||||
<td>1360013296</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Unix Millisecond Timestamp</b></td>\
|
||||
<td>x</td>\
|
||||
<td>1360013296123</td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
</table>",
|
||||
FORMAT_EXAMPLES: `Format string tokens:
|
||||
|
||||
|
||||
<table class="table table-striped table-hover table-condensed table-bordered" style="font-family: sans-serif">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th>Token</th>
|
||||
<th>Output</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>Month</b></td>
|
||||
<td>M</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Mo</td>
|
||||
<td>1st 2nd ... 11th 12th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MM</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMM</td>
|
||||
<td>Jan Feb ... Nov Dec</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMMM</td>
|
||||
<td>January February ... November December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Quarter</b></td>
|
||||
<td>Q</td>
|
||||
<td>1 2 3 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Month</b></td>
|
||||
<td>D</td>
|
||||
<td>1 2 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Do</td>
|
||||
<td>1st 2nd ... 30th 31st</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DD</td>
|
||||
<td>01 02 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Year</b></td>
|
||||
<td>DDD</td>
|
||||
<td>1 2 ... 364 365</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DDDo</td>
|
||||
<td>1st 2nd ... 364th 365th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DDDD</td>
|
||||
<td>001 002 ... 364 365</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week</b></td>
|
||||
<td>d</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>do</td>
|
||||
<td>0th 1st ... 5th 6th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dd</td>
|
||||
<td>Su Mo ... Fr Sa</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ddd</td>
|
||||
<td>Sun Mon ... Fri Sat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dddd</td>
|
||||
<td>Sunday Monday ... Friday Saturday</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week (Locale)</b></td>
|
||||
<td>e</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week (ISO)</b></td>
|
||||
<td>E</td>
|
||||
<td>1 2 ... 6 7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week of Year</b></td>
|
||||
<td>w</td>
|
||||
<td>1 2 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>wo</td>
|
||||
<td>1st 2nd ... 52nd 53rd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ww</td>
|
||||
<td>01 02 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week of Year (ISO)</b></td>
|
||||
<td>W</td>
|
||||
<td>1 2 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Wo</td>
|
||||
<td>1st 2nd ... 52nd 53rd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>WW</td>
|
||||
<td>01 02 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Year</b></td>
|
||||
<td>YY</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>YYYY</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week Year</b></td>
|
||||
<td>gg</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>gggg</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week Year (ISO)</b></td>
|
||||
<td>GG</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>GGGG</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>AM/PM</b></td>
|
||||
<td>A</td>
|
||||
<td>AM PM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>a</td>
|
||||
<td>am pm</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hour</b></td>
|
||||
<td>H</td>
|
||||
<td>0 1 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>HH</td>
|
||||
<td>00 01 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>h</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>hh</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Minute</b></td>
|
||||
<td>m</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>mm</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Second</b></td>
|
||||
<td>s</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ss</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Fractional Second</b></td>
|
||||
<td>S</td>
|
||||
<td>0 1 ... 8 9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SS</td>
|
||||
<td>00 01 ... 98 99</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSS</td>
|
||||
<td>000 001 ... 998 999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSSS ... SSSSSSSSS</td>
|
||||
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Timezone</b></td>
|
||||
<td>z or zz</td>
|
||||
<td>EST CST ... MST PST</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Z</td>
|
||||
<td>-07:00 -06:00 ... +06:00 +07:00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ZZ</td>
|
||||
<td>-0700 -0600 ... +0600 +0700</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Unix Timestamp</b></td>
|
||||
<td>X</td>
|
||||
<td>1360013296</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Unix Millisecond Timestamp</b></td>
|
||||
<td>x</td>
|
||||
<td>1360013296123</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>`,
|
||||
|
||||
};
|
||||
|
||||
|
||||
94
src/core/operations/Diff.js
Normal file
94
src/core/operations/Diff.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import Utils from "../Utils.js";
|
||||
import * as JsDiff from "diff";
|
||||
|
||||
|
||||
/**
|
||||
* Diff operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Diff = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DIFF_SAMPLE_DELIMITER: "\\n\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
|
||||
|
||||
/**
|
||||
* Diff operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runDiff: function(input, args) {
|
||||
let sampleDelim = args[0],
|
||||
diffBy = args[1],
|
||||
showAdded = args[2],
|
||||
showRemoved = args[3],
|
||||
ignoreWhitespace = args[4],
|
||||
samples = input.split(sampleDelim),
|
||||
output = "",
|
||||
diff;
|
||||
|
||||
if (!samples || samples.length !== 2) {
|
||||
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
|
||||
}
|
||||
|
||||
switch (diffBy) {
|
||||
case "Character":
|
||||
diff = JsDiff.diffChars(samples[0], samples[1]);
|
||||
break;
|
||||
case "Word":
|
||||
if (ignoreWhitespace) {
|
||||
diff = JsDiff.diffWords(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Line":
|
||||
if (ignoreWhitespace) {
|
||||
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffLines(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Sentence":
|
||||
diff = JsDiff.diffSentences(samples[0], samples[1]);
|
||||
break;
|
||||
case "CSS":
|
||||
diff = JsDiff.diffCss(samples[0], samples[1]);
|
||||
break;
|
||||
case "JSON":
|
||||
diff = JsDiff.diffJson(samples[0], samples[1]);
|
||||
break;
|
||||
default:
|
||||
return "Invalid 'Diff by' option.";
|
||||
}
|
||||
|
||||
for (let i = 0; i < diff.length; i++) {
|
||||
if (diff[i].added) {
|
||||
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else if (diff[i].removed) {
|
||||
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else {
|
||||
output += Utils.escapeHtml(diff[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Diff;
|
||||
@@ -36,7 +36,7 @@ const Endian = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSwapEndianness: function(input, args) {
|
||||
var dataFormat = args[0],
|
||||
let dataFormat = args[0],
|
||||
wordLength = args[1],
|
||||
padIncompleteWords = args[2],
|
||||
data = [],
|
||||
@@ -63,7 +63,7 @@ const Endian = {
|
||||
|
||||
// Split up into words
|
||||
for (i = 0; i < data.length; i += wordLength) {
|
||||
var word = data.slice(i, i + wordLength);
|
||||
const word = data.slice(i, i + wordLength);
|
||||
|
||||
// Pad word if too short
|
||||
if (padIncompleteWords && word.length < wordLength){
|
||||
|
||||
@@ -26,7 +26,7 @@ const Entropy = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runEntropy: function(input, args) {
|
||||
var chunkSize = args[0],
|
||||
let chunkSize = args[0],
|
||||
output = "",
|
||||
entropy = Entropy._calcEntropy(input);
|
||||
|
||||
@@ -58,9 +58,9 @@ const Entropy = {
|
||||
]);\
|
||||
</script>";
|
||||
|
||||
var chunkEntropy = 0;
|
||||
let chunkEntropy = 0;
|
||||
if (chunkSize !== 0) {
|
||||
for (var i = 0; i < input.length; i += chunkSize) {
|
||||
for (let i = 0; i < input.length; i += chunkSize) {
|
||||
chunkEntropy = Entropy._calcEntropy(input.slice(i, i+chunkSize));
|
||||
output += "Bytes " + i + " to " + (i+chunkSize) + ": " + chunkEntropy + "\n";
|
||||
}
|
||||
@@ -81,37 +81,34 @@ const Entropy = {
|
||||
/**
|
||||
* Frequency distribution operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runFreqDistrib: function (input, args) {
|
||||
if (!input.length) return "No data";
|
||||
const data = new Uint8Array(input);
|
||||
if (!data.length) return "No data";
|
||||
|
||||
var distrib = new Array(256),
|
||||
let distrib = new Array(256).fill(0),
|
||||
percentages = new Array(256),
|
||||
len = input.length,
|
||||
showZeroes = args[0];
|
||||
|
||||
// Initialise distrib to 0
|
||||
for (var i = 0; i < 256; i++) {
|
||||
distrib[i] = 0;
|
||||
}
|
||||
len = data.length,
|
||||
showZeroes = args[0],
|
||||
i;
|
||||
|
||||
// Count bytes
|
||||
for (i = 0; i < len; i++) {
|
||||
distrib[input[i]]++;
|
||||
distrib[data[i]]++;
|
||||
}
|
||||
|
||||
// Calculate percentages
|
||||
var repr = 0;
|
||||
let repr = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (distrib[i] > 0) repr++;
|
||||
percentages[i] = distrib[i] / len * 100;
|
||||
}
|
||||
|
||||
// Print
|
||||
var output = "<canvas id='chart-area'></canvas><br>" +
|
||||
let output = "<canvas id='chart-area'></canvas><br>" +
|
||||
"Total data length: " + len +
|
||||
"\nNumber of bytes represented: " + repr +
|
||||
"\nNumber of bytes not represented: " + (256-repr) +
|
||||
@@ -130,7 +127,7 @@ const Entropy = {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (distrib[i] || showZeroes) {
|
||||
output += " " + Utils.hex(i, 2) + " (" +
|
||||
Utils.padRight(percentages[i].toFixed(2).replace(".00", "") + "%)", 8) +
|
||||
(percentages[i].toFixed(2).replace(".00", "") + "%)").padEnd(8, " ") +
|
||||
Array(Math.ceil(percentages[i])+1).join("|") + "\n";
|
||||
}
|
||||
}
|
||||
@@ -139,6 +136,32 @@ const Entropy = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Chi Square operation.
|
||||
*
|
||||
* @param {ArrayBuffer} data
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runChiSq: function(input, args) {
|
||||
const data = new Uint8Array(input);
|
||||
let distArray = new Array(256).fill(0),
|
||||
total = 0;
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
distArray[data[i]]++;
|
||||
}
|
||||
|
||||
for (let i = 0; i < distArray.length; i++) {
|
||||
if (distArray[i] > 0) {
|
||||
total += Math.pow(distArray[i] - data.length / 256, 2) / (data.length / 256);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Shannon entropy for a given chunk of data.
|
||||
*
|
||||
@@ -147,15 +170,16 @@ const Entropy = {
|
||||
* @returns {number}
|
||||
*/
|
||||
_calcEntropy: function(data) {
|
||||
var prob = [],
|
||||
let prob = [],
|
||||
uniques = data.unique(),
|
||||
str = Utils.byteArrayToChars(data);
|
||||
str = Utils.byteArrayToChars(data),
|
||||
i;
|
||||
|
||||
for (var i = 0; i < uniques.length; i++) {
|
||||
for (i = 0; i < uniques.length; i++) {
|
||||
prob.push(str.count(Utils.chr(uniques[i])) / data.length);
|
||||
}
|
||||
|
||||
var entropy = 0,
|
||||
let entropy = 0,
|
||||
p;
|
||||
|
||||
for (i = 0; i < prob.length; i++) {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import XRegExp from "xregexp";
|
||||
|
||||
|
||||
/**
|
||||
* Identifier extraction operations.
|
||||
*
|
||||
@@ -21,11 +24,16 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_search: function(input, searchRegex, removeRegex, includeTotal) {
|
||||
var output = "",
|
||||
let output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = searchRegex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (match.index === searchRegex.lastIndex) {
|
||||
searchRegex.lastIndex++;
|
||||
}
|
||||
|
||||
if (removeRegex && removeRegex.test(match[0]))
|
||||
continue;
|
||||
total++;
|
||||
@@ -43,7 +51,20 @@ const Extract = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MIN_STRING_LEN: 3,
|
||||
MIN_STRING_LEN: 4,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
STRING_MATCH_TYPE: [
|
||||
"[ASCII]", "Alphanumeric + punctuation (A)", "All printable chars (A)", "Null-terminated strings (A)",
|
||||
"[Unicode]", "Alphanumeric + punctuation (U)", "All printable chars (U)", "Null-terminated strings (U)"
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ENCODING_LIST: ["Single byte", "16-bit littleendian", "16-bit bigendian", "All"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -58,10 +79,59 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runStrings: function(input, args) {
|
||||
var minLen = args[0] || Extract.MIN_STRING_LEN,
|
||||
displayTotal = args[1],
|
||||
strings = "[A-Z\\d/\\-:.,_$%'\"()<>= !\\[\\]{}@]",
|
||||
regex = new RegExp(strings + "{" + minLen + ",}", "ig");
|
||||
const encoding = args[0],
|
||||
minLen = args[1],
|
||||
matchType = args[2],
|
||||
displayTotal = args[3],
|
||||
alphanumeric = "A-Z\\d",
|
||||
punctuation = "/\\-:.,_$%'\"()<>= !\\[\\]{}@",
|
||||
printable = "\x20-\x7e",
|
||||
uniAlphanumeric = "\\pL\\pN",
|
||||
uniPunctuation = "\\pP\\pZ",
|
||||
uniPrintable = "\\pL\\pM\\pZ\\pS\\pN\\pP";
|
||||
|
||||
let strings = "";
|
||||
|
||||
switch (matchType) {
|
||||
case "Alphanumeric + punctuation (A)":
|
||||
strings = `[${alphanumeric + punctuation}]`;
|
||||
break;
|
||||
case "All printable chars (A)":
|
||||
case "Null-terminated strings (A)":
|
||||
strings = `[${printable}]`;
|
||||
break;
|
||||
case "Alphanumeric + punctuation (U)":
|
||||
strings = `[${uniAlphanumeric + uniPunctuation}]`;
|
||||
break;
|
||||
case "All printable chars (U)":
|
||||
case "Null-terminated strings (U)":
|
||||
strings = `[${uniPrintable}]`;
|
||||
break;
|
||||
}
|
||||
|
||||
// UTF-16 support is hacked in by allowing null bytes on either side of the matched chars
|
||||
switch (encoding) {
|
||||
case "All":
|
||||
strings = `(\x00?${strings}\x00?)`;
|
||||
break;
|
||||
case "16-bit littleendian":
|
||||
strings = `(${strings}\x00)`;
|
||||
break;
|
||||
case "16-bit bigendian":
|
||||
strings = `(\x00${strings})`;
|
||||
break;
|
||||
case "Single byte":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
strings = `${strings}{${minLen},}`;
|
||||
|
||||
if (matchType.includes("Null-terminated")) {
|
||||
strings += "\x00";
|
||||
}
|
||||
|
||||
const regex = new XRegExp(strings, "ig");
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
@@ -91,7 +161,7 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runIp: function(input, args) {
|
||||
var includeIpv4 = args[0],
|
||||
let includeIpv4 = args[0],
|
||||
includeIpv6 = args[1],
|
||||
removeLocal = args[2],
|
||||
displayTotal = args[3],
|
||||
@@ -108,10 +178,10 @@ const Extract = {
|
||||
}
|
||||
|
||||
if (ips) {
|
||||
var regex = new RegExp(ips, "ig");
|
||||
const regex = new RegExp(ips, "ig");
|
||||
|
||||
if (removeLocal) {
|
||||
var ten = "10\\..+",
|
||||
let ten = "10\\..+",
|
||||
oneninetwo = "192\\.168\\..+",
|
||||
oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
|
||||
onetwoseven = "127\\..+",
|
||||
@@ -136,7 +206,7 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runEmail: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
let displayTotal = args[0],
|
||||
regex = /\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}/ig;
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
@@ -151,7 +221,7 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMac: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
let displayTotal = args[0],
|
||||
regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig;
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
@@ -166,14 +236,14 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runUrls: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
let displayTotal = args[0],
|
||||
protocol = "[A-Z]+://",
|
||||
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
||||
port = ":\\d+",
|
||||
path = "/[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]*";
|
||||
path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
|
||||
|
||||
path += "(?:[.!,?]+[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||
var regex = new RegExp(protocol + hostname + "(?:" + port +
|
||||
path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||
const regex = new RegExp(protocol + hostname + "(?:" + port +
|
||||
")?(?:" + path + ")?", "ig");
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
@@ -187,11 +257,8 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runDomains: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
protocol = "https?://",
|
||||
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");
|
||||
const displayTotal = args[0],
|
||||
regex = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
||||
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
@@ -216,11 +283,11 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFilePaths: function(input, args) {
|
||||
var includeWinPath = args[0],
|
||||
let includeWinPath = args[0],
|
||||
includeUnixPath = args[1],
|
||||
displayTotal = args[2],
|
||||
winDrive = "[A-Z]:\\\\",
|
||||
winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)]{0,61}",
|
||||
winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)~]{0,61}",
|
||||
winExt = "[A-Z\\d]{1,6}",
|
||||
winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName +
|
||||
"(?:\\." + winExt + ")?",
|
||||
@@ -236,7 +303,7 @@ const Extract = {
|
||||
}
|
||||
|
||||
if (filePaths) {
|
||||
var regex = new RegExp(filePaths, "ig");
|
||||
const regex = new RegExp(filePaths, "ig");
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
} else {
|
||||
return "";
|
||||
@@ -252,7 +319,7 @@ const Extract = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runDates: function(input, args) {
|
||||
var displayTotal = args[0],
|
||||
let displayTotal = args[0],
|
||||
date1 = "(?:19|20)\\d\\d[- /.](?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])", // yyyy-mm-dd
|
||||
date2 = "(?:0[1-9]|[12][0-9]|3[01])[- /.](?:0[1-9]|1[012])[- /.](?:19|20)\\d\\d", // dd/mm/yyyy
|
||||
date3 = "(?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])[- /.](?:19|20)\\d\\d", // mm/dd/yyyy
|
||||
@@ -261,39 +328,6 @@ const Extract = {
|
||||
return Extract._search(input, regex, null, displayTotal);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Extract all identifiers operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runAllIdents: function(input, args) {
|
||||
var output = "";
|
||||
output += "IP addresses\n";
|
||||
output += Extract.runIp(input, [true, true, false]);
|
||||
|
||||
output += "\nEmail addresses\n";
|
||||
output += Extract.runEmail(input, []);
|
||||
|
||||
output += "\nMAC addresses\n";
|
||||
output += Extract.runMac(input, []);
|
||||
|
||||
output += "\nURLs\n";
|
||||
output += Extract.runUrls(input, []);
|
||||
|
||||
output += "\nDomain names\n";
|
||||
output += Extract.runDomains(input, []);
|
||||
|
||||
output += "\nFile paths\n";
|
||||
output += Extract.runFilePaths(input, [true, true]);
|
||||
|
||||
output += "\nDates\n";
|
||||
output += Extract.runDates(input, []);
|
||||
return output;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Extract;
|
||||
|
||||
@@ -15,17 +15,18 @@ const FileType = {
|
||||
/**
|
||||
* Detect File Type operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDetect: function(input, args) {
|
||||
var type = FileType._magicType(input);
|
||||
const data = new Uint8Array(input),
|
||||
type = FileType.magicType(data);
|
||||
|
||||
if (!type) {
|
||||
return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
|
||||
} else {
|
||||
var output = "File extension: " + type.ext + "\n" +
|
||||
let output = "File extension: " + type.ext + "\n" +
|
||||
"MIME type: " + type.mime;
|
||||
|
||||
if (type.desc && type.desc.length) {
|
||||
@@ -46,20 +47,21 @@ const FileType = {
|
||||
/**
|
||||
* Scan for Embedded Files operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runScanForEmbeddedFiles: function(input, args) {
|
||||
var output = "Scanning data for 'magic bytes' which may indicate embedded files. The following results may be false positives and should not be treat as reliable. Any suffiently long file is likely to contain these magic bytes coincidentally.\n",
|
||||
let output = "Scanning data for 'magic bytes' which may indicate embedded files. The following results may be false positives and should not be treat as reliable. Any suffiently long file is likely to contain these magic bytes coincidentally.\n",
|
||||
type,
|
||||
ignoreCommon = args[0],
|
||||
commonExts = ["ico", "ttf", ""],
|
||||
numFound = 0,
|
||||
numCommonFound = 0;
|
||||
const ignoreCommon = args[0],
|
||||
commonExts = ["ico", "ttf", ""],
|
||||
data = new Uint8Array(input);
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
type = FileType._magicType(input.slice(i));
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
type = FileType.magicType(data.slice(i));
|
||||
if (type) {
|
||||
if (ignoreCommon && commonExts.indexOf(type.ext) > -1) {
|
||||
numCommonFound++;
|
||||
@@ -96,14 +98,13 @@ const FileType = {
|
||||
* Given a buffer, detects magic byte sequences at specific positions and returns the
|
||||
* extension and mime type.
|
||||
*
|
||||
* @private
|
||||
* @param {byteArray} buf
|
||||
* @param {Uint8Array} 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;
|
||||
}
|
||||
|
||||
103
src/core/operations/Filetime.js
Normal file
103
src/core/operations/Filetime.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* Windows Filetime operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Filetime = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FILETIME_FORMATS: ["Decimal", "Hex"],
|
||||
|
||||
/**
|
||||
* 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],
|
||||
format = args[1];
|
||||
|
||||
if (!input) return "";
|
||||
|
||||
if (format === "Hex") {
|
||||
input = new BigNumber(input, 16);
|
||||
} else {
|
||||
input = new BigNumber(input);
|
||||
}
|
||||
|
||||
input = input.minus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.dividedBy(new BigNumber("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
input = input.dividedBy(new BigNumber("10000"));
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
input = input.dividedBy(new BigNumber("10"));
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
input = input.multipliedBy(new BigNumber("100"));
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
return input.toFixed();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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],
|
||||
format = args[1];
|
||||
|
||||
if (!input) return "";
|
||||
|
||||
input = new BigNumber(input);
|
||||
|
||||
if (units === "Seconds (s)"){
|
||||
input = input.multipliedBy(new BigNumber("10000000"));
|
||||
} else if (units === "Milliseconds (ms)") {
|
||||
input = input.multipliedBy(new BigNumber("10000"));
|
||||
} else if (units === "Microseconds (μs)") {
|
||||
input = input.multiplyiedBy(new BigNumber("10"));
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
input = input.dividedBy(new BigNumber("100"));
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
}
|
||||
|
||||
input = input.plus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (format === "Hex"){
|
||||
return input.toString(16);
|
||||
} else {
|
||||
return input.toFixed();
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Filetime;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
*
|
||||
@@ -20,7 +31,7 @@ const HTTP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runStripHeaders: function(input, args) {
|
||||
var headerEnd = input.indexOf("\r\n\r\n");
|
||||
let headerEnd = input.indexOf("\r\n\r\n");
|
||||
headerEnd = (headerEnd < 0) ? input.indexOf("\n\n") + 2 : headerEnd + 4;
|
||||
|
||||
return (headerEnd < 2) ? input : input.slice(headerEnd, input.length);
|
||||
@@ -35,7 +46,7 @@ const HTTP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseUserAgent: function(input, args) {
|
||||
var ua = UAParser.parse(input);
|
||||
const ua = UAParser.parse(input);
|
||||
|
||||
return "Type: " + ua.type + "\n" +
|
||||
"Family: " + ua.uaFamily + "\n" +
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
import CryptoApi from "crypto-api";
|
||||
import MD6 from "node-md6";
|
||||
import * as SHA3 from "js-sha3";
|
||||
import Checksum from "./Checksum.js";
|
||||
|
||||
|
||||
@@ -15,6 +16,22 @@ import Checksum from "./Checksum.js";
|
||||
*/
|
||||
const Hash = {
|
||||
|
||||
/**
|
||||
* Generic hash function.
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} input
|
||||
* @returns {string}
|
||||
*/
|
||||
runHash: function(name, input) {
|
||||
const hasher = CryptoApi.hasher(name);
|
||||
hasher.state.message = input;
|
||||
hasher.state.length += input.length;
|
||||
hasher.process();
|
||||
return hasher.finalize().stringify("hex");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD2 operation.
|
||||
*
|
||||
@@ -23,7 +40,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD2: function (input, args) {
|
||||
return Utils.toHexFast(CryptoApi.hash("md2", input, {}));
|
||||
return Hash.runHash("md2", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -35,7 +52,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD4: function (input, args) {
|
||||
return Utils.toHexFast(CryptoApi.hash("md4", input, {}));
|
||||
return Hash.runHash("md4", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -47,8 +64,39 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD5: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray
|
||||
return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex);
|
||||
return Hash.runHash("md5", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MD6_SIZE: 256,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MD6_LEVELS: 64,
|
||||
|
||||
/**
|
||||
* MD6 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD6: function (input, args) {
|
||||
const size = args[0],
|
||||
levels = args[1],
|
||||
key = args[2];
|
||||
|
||||
if (size < 0 || size > 512)
|
||||
return "Size must be between 0 and 512";
|
||||
if (levels < 0)
|
||||
return "Levels must be greater than 0";
|
||||
|
||||
return MD6.getHashOfText(input, size, key, levels);
|
||||
},
|
||||
|
||||
|
||||
@@ -60,7 +108,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA0: function (input, args) {
|
||||
return Utils.toHexFast(CryptoApi.hash("sha0", input, {}));
|
||||
return Hash.runHash("sha0", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -72,60 +120,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA1: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA1(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA224 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA224: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA224(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA256 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA256: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA256(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA384 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA384: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA384(input).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* SHA512 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA512: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.SHA512(input).toString(CryptoJS.enc.Hex);
|
||||
return Hash.runHash("sha1", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -133,7 +128,26 @@ const Hash = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHA3_LENGTH: ["512", "384", "256", "224"],
|
||||
SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
|
||||
|
||||
/**
|
||||
* SHA2 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA2: function (input, args) {
|
||||
const size = args[0];
|
||||
return Hash.runHash("sha" + size, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHA3_SIZE: ["512", "384", "256", "224"],
|
||||
|
||||
/**
|
||||
* SHA3 operation.
|
||||
@@ -143,25 +157,27 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA3: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
var sha3Length = args[0],
|
||||
options = {
|
||||
outputLength: parseInt(sha3Length, 10)
|
||||
};
|
||||
return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
const size = parseInt(args[0], 10);
|
||||
let algo;
|
||||
|
||||
switch (size) {
|
||||
case 224:
|
||||
algo = SHA3.sha3_224;
|
||||
break;
|
||||
case 384:
|
||||
algo = SHA3.sha3_384;
|
||||
break;
|
||||
case 256:
|
||||
algo = SHA3.sha3_256;
|
||||
break;
|
||||
case 512:
|
||||
algo = SHA3.sha3_512;
|
||||
break;
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
|
||||
/**
|
||||
* RIPEMD-160 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRIPEMD160: function (input, args) {
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
return CryptoJS.RIPEMD160(input).toString(CryptoJS.enc.Hex);
|
||||
return algo(input);
|
||||
},
|
||||
|
||||
|
||||
@@ -169,7 +185,181 @@ const Hash = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HMAC_FUNCTIONS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD-160"],
|
||||
KECCAK_SIZE: ["512", "384", "256", "224"],
|
||||
|
||||
/**
|
||||
* Keccak operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runKeccak: function (input, args) {
|
||||
const size = parseInt(args[0], 10);
|
||||
let algo;
|
||||
|
||||
switch (size) {
|
||||
case 224:
|
||||
algo = SHA3.keccak224;
|
||||
break;
|
||||
case 384:
|
||||
algo = SHA3.keccak384;
|
||||
break;
|
||||
case 256:
|
||||
algo = SHA3.keccak256;
|
||||
break;
|
||||
case 512:
|
||||
algo = SHA3.keccak512;
|
||||
break;
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
|
||||
return algo(input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHAKE_CAPACITY: ["256", "128"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SHAKE_SIZE: 512,
|
||||
|
||||
/**
|
||||
* Shake operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runShake: function (input, args) {
|
||||
const capacity = parseInt(args[0], 10),
|
||||
size = args[1];
|
||||
let algo;
|
||||
|
||||
if (size < 0)
|
||||
return "Size must be greater than 0";
|
||||
|
||||
switch (capacity) {
|
||||
case 128:
|
||||
algo = SHA3.shake128;
|
||||
break;
|
||||
case 256:
|
||||
algo = SHA3.shake256;
|
||||
break;
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
|
||||
return algo(input, size);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
RIPEMD_SIZE: ["320", "256", "160", "128"],
|
||||
|
||||
/**
|
||||
* RIPEMD operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runRIPEMD: function (input, args) {
|
||||
const size = args[0];
|
||||
return Hash.runHash("ripemd" + size, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* HAS-160 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHAS: function (input, args) {
|
||||
return Hash.runHash("has160", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WHIRLPOOL_VARIANT: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"],
|
||||
|
||||
/**
|
||||
* Whirlpool operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runWhirlpool: function (input, args) {
|
||||
const variant = args[0].toLowerCase();
|
||||
return Hash.runHash(variant, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SNEFRU_ROUNDS: ["8", "4", "2"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SNEFRU_SIZE: ["256", "128"],
|
||||
|
||||
/**
|
||||
* Snefru operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSnefru: function (input, args) {
|
||||
const rounds = args[0],
|
||||
size = args[1];
|
||||
return Hash.runHash(`snefru-${rounds}-${size}`, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HMAC_FUNCTIONS: [
|
||||
"MD2",
|
||||
"MD4",
|
||||
"MD5",
|
||||
"SHA0",
|
||||
"SHA1",
|
||||
"SHA224",
|
||||
"SHA256",
|
||||
"SHA384",
|
||||
"SHA512",
|
||||
"SHA512/224",
|
||||
"SHA512/256",
|
||||
"RIPEMD128",
|
||||
"RIPEMD160",
|
||||
"RIPEMD256",
|
||||
"RIPEMD320",
|
||||
"HAS160",
|
||||
"Whirlpool",
|
||||
"Whirlpool-0",
|
||||
"Whirlpool-T"
|
||||
],
|
||||
|
||||
/**
|
||||
* HMAC operation.
|
||||
@@ -179,19 +369,12 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runHMAC: function (input, args) {
|
||||
var hashFunc = args[1];
|
||||
input = CryptoJS.enc.Latin1.parse(input);
|
||||
var execute = {
|
||||
"MD5": CryptoJS.HmacMD5(input, args[0]),
|
||||
"SHA1": CryptoJS.HmacSHA1(input, args[0]),
|
||||
"SHA224": CryptoJS.HmacSHA224(input, args[0]),
|
||||
"SHA256": CryptoJS.HmacSHA256(input, args[0]),
|
||||
"SHA384": CryptoJS.HmacSHA384(input, args[0]),
|
||||
"SHA512": CryptoJS.HmacSHA512(input, args[0]),
|
||||
"SHA3": CryptoJS.HmacSHA3(input, args[0]),
|
||||
"RIPEMD-160": CryptoJS.HmacRIPEMD160(input, args[0]),
|
||||
};
|
||||
return execute[hashFunc].toString(CryptoJS.enc.Hex);
|
||||
const password = args[0],
|
||||
hashFunc = args[1].toLowerCase(),
|
||||
hmac = CryptoApi.mac("hmac", password, hashFunc, {});
|
||||
|
||||
hmac.update(input);
|
||||
return hmac.finalize().stringify("hex");
|
||||
},
|
||||
|
||||
|
||||
@@ -203,28 +386,43 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runAll: function (input, args) {
|
||||
var byteArray = Utils.strToByteArray(input),
|
||||
let byteArray = Utils.strToByteArray(input),
|
||||
output = "MD2: " + Hash.runMD2(input, []) +
|
||||
"\nMD4: " + Hash.runMD4(input, []) +
|
||||
"\nMD5: " + Hash.runMD5(input, []) +
|
||||
"\nMD6: " + Hash.runMD6(input, []) +
|
||||
"\nSHA0: " + Hash.runSHA0(input, []) +
|
||||
"\nSHA1: " + Hash.runSHA1(input, []) +
|
||||
"\nSHA2 224: " + Hash.runSHA224(input, []) +
|
||||
"\nSHA2 256: " + Hash.runSHA256(input, []) +
|
||||
"\nSHA2 384: " + Hash.runSHA384(input, []) +
|
||||
"\nSHA2 512: " + Hash.runSHA512(input, []) +
|
||||
"\nSHA2 224: " + Hash.runSHA2(input, ["224"]) +
|
||||
"\nSHA2 256: " + Hash.runSHA2(input, ["256"]) +
|
||||
"\nSHA2 384: " + Hash.runSHA2(input, ["384"]) +
|
||||
"\nSHA2 512: " + Hash.runSHA2(input, ["512"]) +
|
||||
"\nSHA3 224: " + Hash.runSHA3(input, ["224"]) +
|
||||
"\nSHA3 256: " + Hash.runSHA3(input, ["256"]) +
|
||||
"\nSHA3 384: " + Hash.runSHA3(input, ["384"]) +
|
||||
"\nSHA3 512: " + Hash.runSHA3(input, ["512"]) +
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD160(input, []) +
|
||||
"\nKeccak 224: " + Hash.runKeccak(input, ["224"]) +
|
||||
"\nKeccak 256: " + Hash.runKeccak(input, ["256"]) +
|
||||
"\nKeccak 384: " + Hash.runKeccak(input, ["384"]) +
|
||||
"\nKeccak 512: " + Hash.runKeccak(input, ["512"]) +
|
||||
"\nShake 128: " + Hash.runShake(input, ["128", 256]) +
|
||||
"\nShake 256: " + Hash.runShake(input, ["256", 512]) +
|
||||
"\nRIPEMD-128: " + Hash.runRIPEMD(input, ["128"]) +
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD(input, ["160"]) +
|
||||
"\nRIPEMD-256: " + Hash.runRIPEMD(input, ["256"]) +
|
||||
"\nRIPEMD-320: " + Hash.runRIPEMD(input, ["320"]) +
|
||||
"\nHAS-160: " + Hash.runHAS(input, []) +
|
||||
"\nWhirlpool-0: " + Hash.runWhirlpool(input, ["Whirlpool-0"]) +
|
||||
"\nWhirlpool-T: " + Hash.runWhirlpool(input, ["Whirlpool-T"]) +
|
||||
"\nWhirlpool: " + Hash.runWhirlpool(input, ["Whirlpool"]) +
|
||||
"\n\nChecksums:" +
|
||||
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
|
||||
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
|
||||
"\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
|
||||
"\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
|
||||
"\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
|
||||
"\nCRC-32: " + Checksum.runCRC32(byteArray, []);
|
||||
"\nCRC-16: " + Checksum.runCRC16(input, []) +
|
||||
"\nCRC-32: " + Checksum.runCRC32(input, []);
|
||||
|
||||
return output;
|
||||
},
|
||||
@@ -240,7 +438,7 @@ const Hash = {
|
||||
runAnalyse: function(input, args) {
|
||||
input = input.replace(/\s/g, "");
|
||||
|
||||
var output = "",
|
||||
let output = "",
|
||||
byteLength = input.length / 2,
|
||||
bitLength = byteLength * 8,
|
||||
possibleHashFunctions = [];
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* globals app */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
@@ -32,24 +31,25 @@ const Hexdump = {
|
||||
/**
|
||||
* To Hexdump operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var length = args[0] || Hexdump.WIDTH;
|
||||
var upperCase = args[1];
|
||||
var includeFinalLength = args[2];
|
||||
const data = new Uint8Array(input);
|
||||
const length = args[0] || Hexdump.WIDTH;
|
||||
const upperCase = args[1];
|
||||
const includeFinalLength = args[2];
|
||||
|
||||
var output = "", padding = 2;
|
||||
for (var i = 0; i < input.length; i += length) {
|
||||
var buff = input.slice(i, i+length);
|
||||
var hexa = "";
|
||||
for (var j = 0; j < buff.length; j++) {
|
||||
let output = "", padding = 2;
|
||||
for (let i = 0; i < data.length; i += length) {
|
||||
const buff = data.slice(i, i+length);
|
||||
let hexa = "";
|
||||
for (let j = 0; j < buff.length; j++) {
|
||||
hexa += Utils.hex(buff[j], padding) + " ";
|
||||
}
|
||||
|
||||
var lineNo = Utils.hex(i, 8);
|
||||
let lineNo = Utils.hex(i, 8);
|
||||
|
||||
if (upperCase) {
|
||||
hexa = hexa.toUpperCase();
|
||||
@@ -57,10 +57,10 @@ const Hexdump = {
|
||||
}
|
||||
|
||||
output += lineNo + " " +
|
||||
Utils.padRight(hexa, (length*(padding+1))) +
|
||||
" |" + Utils.padRight(Utils.printable(Utils.byteArrayToChars(buff)), buff.length) + "|\n";
|
||||
hexa.padEnd(length*(padding+1), " ") +
|
||||
" |" + Utils.printable(Utils.byteArrayToChars(buff)).padEnd(buff.length, " ") + "|\n";
|
||||
|
||||
if (includeFinalLength && i+buff.length === input.length) {
|
||||
if (includeFinalLength && i+buff.length === data.length) {
|
||||
output += Utils.hex(i+buff.length, 8) + "\n";
|
||||
}
|
||||
}
|
||||
@@ -77,22 +77,22 @@ const Hexdump = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var output = [],
|
||||
let output = [],
|
||||
regex = /^\s*(?:[\dA-F]{4,16}:?)?\s*((?:[\dA-F]{2}\s){1,8}(?:\s|[\dA-F]{2}-)(?:[\dA-F]{2}\s){1,8}|(?:[\dA-F]{2}\s|[\dA-F]{4}\s)+)/igm,
|
||||
block, line;
|
||||
|
||||
while ((block = regex.exec(input))) {
|
||||
line = Utils.fromHex(block[1].replace(/-/g, " "));
|
||||
for (var i = 0; i < line.length; i++) {
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
output.push(line[i]);
|
||||
}
|
||||
}
|
||||
// Is this a CyberChef hexdump or is it from a different tool?
|
||||
var width = input.indexOf("\n");
|
||||
var w = (width - 13) / 4;
|
||||
const width = input.indexOf("\n");
|
||||
const w = (width - 13) / 4;
|
||||
// w should be the specified width of the hexdump and therefore a round number
|
||||
if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) {
|
||||
if (app) app.options.attemptHighlight = false;
|
||||
if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
||||
}
|
||||
return output;
|
||||
},
|
||||
@@ -109,7 +109,7 @@ const Hexdump = {
|
||||
*/
|
||||
highlightTo: function(pos, args) {
|
||||
// Calculate overall selection
|
||||
var w = args[0] || 16,
|
||||
let w = args[0] || 16,
|
||||
width = 14 + (w*4),
|
||||
line = Math.floor(pos[0].start / w),
|
||||
offset = pos[0].start % w,
|
||||
@@ -127,8 +127,8 @@ const Hexdump = {
|
||||
pos[0].end = line*width + 10 + offset*3 - 1;
|
||||
|
||||
// Set up multiple selections for bytes
|
||||
var startLineNum = Math.floor(pos[0].start / width);
|
||||
var endLineNum = Math.floor(pos[0].end / width);
|
||||
let startLineNum = Math.floor(pos[0].start / width);
|
||||
const endLineNum = Math.floor(pos[0].end / width);
|
||||
|
||||
if (startLineNum === endLineNum) {
|
||||
pos.push(pos[0]);
|
||||
@@ -146,10 +146,10 @@ const Hexdump = {
|
||||
}
|
||||
|
||||
// Set up multiple selections for ASCII
|
||||
var len = pos.length, lineNum = 0;
|
||||
let len = pos.length, lineNum = 0;
|
||||
start = 0;
|
||||
end = 0;
|
||||
for (var i = 1; i < len; i++) {
|
||||
for (let i = 1; i < len; i++) {
|
||||
lineNum = Math.floor(pos[i].start / width);
|
||||
start = (((pos[i].start - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width);
|
||||
end = (((pos[i].end + 1 - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width);
|
||||
@@ -169,11 +169,11 @@ const Hexdump = {
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightFrom: function(pos, args) {
|
||||
var w = args[0] || 16;
|
||||
var width = 14 + (w*4);
|
||||
const w = args[0] || 16;
|
||||
const width = 14 + (w*4);
|
||||
|
||||
var line = Math.floor(pos[0].start / width);
|
||||
var offset = pos[0].start % width;
|
||||
let line = Math.floor(pos[0].start / width);
|
||||
let offset = pos[0].start % width;
|
||||
|
||||
if (offset < 10) { // In line number section
|
||||
pos[0].start = line*w;
|
||||
|
||||
@@ -38,12 +38,12 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseIpRange: function (input, args) {
|
||||
var includeNetworkInfo = args[0],
|
||||
let includeNetworkInfo = args[0],
|
||||
enumerateAddresses = args[1],
|
||||
allowLargeList = args[2];
|
||||
|
||||
// Check what type of input we are looking at
|
||||
var ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
|
||||
let ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
|
||||
ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
|
||||
ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i,
|
||||
ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
|
||||
@@ -82,11 +82,11 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseIPv6: function (input, args) {
|
||||
var match,
|
||||
let match,
|
||||
output = "";
|
||||
|
||||
if ((match = IP.IPV6_REGEX.exec(input))) {
|
||||
var ipv6 = IP._strToIpv6(match[1]),
|
||||
let ipv6 = IP._strToIpv6(match[1]),
|
||||
longhand = IP._ipv6ToStr(ipv6),
|
||||
shorthand = IP._ipv6ToStr(ipv6, true);
|
||||
|
||||
@@ -126,7 +126,7 @@ const IP = {
|
||||
} else if (ipv6[0] === 0x2001 && ipv6[1] === 0) {
|
||||
// Teredo tunneling
|
||||
output += "\nTeredo tunneling IPv6 address detected\n";
|
||||
var serverIpv4 = (ipv6[2] << 16) + ipv6[3],
|
||||
let serverIpv4 = (ipv6[2] << 16) + ipv6[3],
|
||||
udpPort = (~ipv6[5]) & 0xffff,
|
||||
clientIpv4 = ~((ipv6[6] << 16) + ipv6[7]),
|
||||
flagCone = (ipv6[4] >>> 15) & 1,
|
||||
@@ -190,7 +190,7 @@ const IP = {
|
||||
output += "\n6to4 transition IPv6 address detected. See RFC 3056 for more details." +
|
||||
"\n6to4 prefix range: 2002::/16";
|
||||
|
||||
var v4Addr = IP._ipv4ToStr((ipv6[1] << 16) + ipv6[2]),
|
||||
let v4Addr = IP._ipv4ToStr((ipv6[1] << 16) + ipv6[2]),
|
||||
slaId = ipv6[3],
|
||||
interfaceIdStr = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16),
|
||||
interfaceId = new BigInteger(interfaceIdStr, 16);
|
||||
@@ -218,7 +218,7 @@ const IP = {
|
||||
if ((ipv6[5] & 0xff === 0xff) && (ipv6[6] >>> 8 === 0xfe)) {
|
||||
output += "\n\nThis IPv6 address contains a modified EUI-64 address, identified by the presence of FF:FE in the 12th and 13th octets.";
|
||||
|
||||
var intIdent = Utils.hex(ipv6[4] >>> 8) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" +
|
||||
let intIdent = Utils.hex(ipv6[4] >>> 8) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" +
|
||||
Utils.hex(ipv6[5] >>> 8) + ":" + Utils.hex(ipv6[5] & 0xff) + ":" +
|
||||
Utils.hex(ipv6[6] >>> 8) + ":" + Utils.hex(ipv6[6] & 0xff) + ":" +
|
||||
Utils.hex(ipv6[7] >>> 8) + ":" + Utils.hex(ipv6[7] & 0xff),
|
||||
@@ -249,16 +249,18 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runChangeIpFormat: function(input, args) {
|
||||
var inFormat = args[0],
|
||||
let inFormat = args[0],
|
||||
outFormat = args[1],
|
||||
lines = input.split("\n"),
|
||||
output = "",
|
||||
j = 0;
|
||||
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i] === "") continue;
|
||||
var baIp = [];
|
||||
let baIp = [];
|
||||
let octets;
|
||||
let decimal;
|
||||
|
||||
if (inFormat === outFormat) {
|
||||
output += lines[i] + "\n";
|
||||
@@ -268,40 +270,44 @@ const IP = {
|
||||
// Convert to byte array IP from input format
|
||||
switch (inFormat) {
|
||||
case "Dotted Decimal":
|
||||
var octets = lines[i].split(".");
|
||||
octets = lines[i].split(".");
|
||||
for (j = 0; j < octets.length; j++) {
|
||||
baIp.push(parseInt(octets[j], 10));
|
||||
}
|
||||
break;
|
||||
case "Decimal":
|
||||
var decimal = lines[i].toString();
|
||||
decimal = lines[i].toString();
|
||||
baIp.push(decimal >> 24 & 255);
|
||||
baIp.push(decimal >> 16 & 255);
|
||||
baIp.push(decimal >> 8 & 255);
|
||||
baIp.push(decimal & 255);
|
||||
break;
|
||||
case "Hex":
|
||||
baIp = Utils.hexToByteArray(lines[i]);
|
||||
baIp = Utils.fromHex(lines[i]);
|
||||
break;
|
||||
default:
|
||||
throw "Unsupported input IP format";
|
||||
}
|
||||
|
||||
let ddIp;
|
||||
let decIp;
|
||||
let hexIp;
|
||||
|
||||
// Convert byte array IP to output format
|
||||
switch (outFormat) {
|
||||
case "Dotted Decimal":
|
||||
var ddIp = "";
|
||||
ddIp = "";
|
||||
for (j = 0; j < baIp.length; j++) {
|
||||
ddIp += baIp[j] + ".";
|
||||
}
|
||||
output += ddIp.slice(0, ddIp.length-1) + "\n";
|
||||
break;
|
||||
case "Decimal":
|
||||
var decIp = ((baIp[0] << 24) | (baIp[1] << 16) | (baIp[2] << 8) | baIp[3]) >>> 0;
|
||||
decIp = ((baIp[0] << 24) | (baIp[1] << 16) | (baIp[2] << 8) | baIp[3]) >>> 0;
|
||||
output += decIp.toString() + "\n";
|
||||
break;
|
||||
case "Hex":
|
||||
var hexIp = "";
|
||||
hexIp = "";
|
||||
for (j = 0; j < baIp.length; j++) {
|
||||
hexIp += Utils.hex(baIp[j]);
|
||||
}
|
||||
@@ -340,7 +346,7 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runGroupIps: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]],
|
||||
let delim = Utils.charRep[args[0]],
|
||||
cidr = args[1],
|
||||
onlySubnets = args[2],
|
||||
ipv4Mask = cidr < 32 ? ~(0xFFFFFFFF >>> cidr) : 0xFFFFFFFF,
|
||||
@@ -352,14 +358,15 @@ const IP = {
|
||||
output = "",
|
||||
ip = null,
|
||||
network = null,
|
||||
networkStr = "";
|
||||
networkStr = "",
|
||||
i;
|
||||
|
||||
if (cidr < 0 || cidr > 127) {
|
||||
return "CIDR must be less than 32 for IPv4 or 128 for IPv6";
|
||||
}
|
||||
|
||||
// Parse all IPs and add to network dictionary
|
||||
for (var i = 0; i < ips.length; i++) {
|
||||
for (i = 0; i < ips.length; i++) {
|
||||
if ((match = IP.IPV4_REGEX.exec(ips[i]))) {
|
||||
ip = IP._strToIpv4(match[1]) >>> 0;
|
||||
network = ip & ipv4Mask;
|
||||
@@ -374,7 +381,7 @@ const IP = {
|
||||
network = [];
|
||||
networkStr = "";
|
||||
|
||||
for (var j = 0; j < 8; j++) {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
network.push(ip[j] & ipv6Mask[j]);
|
||||
}
|
||||
|
||||
@@ -434,7 +441,7 @@ const IP = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runParseIPv4Header: function(input, args) {
|
||||
var format = args[0],
|
||||
let format = args[0],
|
||||
output;
|
||||
|
||||
if (format === "Hex") {
|
||||
@@ -445,7 +452,7 @@ const IP = {
|
||||
return "Unrecognised input format.";
|
||||
}
|
||||
|
||||
var version = (input[0] >>> 4) & 0x0f,
|
||||
let version = (input[0] >>> 4) & 0x0f,
|
||||
ihl = input[0] & 0x0f,
|
||||
dscp = (input[1] >>> 2) & 0x3f,
|
||||
ecn = input[1] & 0x03,
|
||||
@@ -471,15 +478,15 @@ const IP = {
|
||||
ihl = ihl + " (Error: this should always be at least 5)";
|
||||
} else if (ihl > 5) {
|
||||
// sort out options...
|
||||
var optionsLen = ihl * 4 - 20;
|
||||
const optionsLen = ihl * 4 - 20;
|
||||
options = input.slice(20, optionsLen + 20);
|
||||
}
|
||||
|
||||
// Protocol
|
||||
var protocolInfo = IP._protocolLookup[protocol] || {keyword: "", protocol: ""};
|
||||
const protocolInfo = IP._protocolLookup[protocol] || {keyword: "", protocol: ""};
|
||||
|
||||
// Checksum
|
||||
var correctChecksum = Checksum.runTCPIP(checksumHeader, []),
|
||||
let correctChecksum = Checksum.runTCPIP(checksumHeader, []),
|
||||
givenChecksum = Utils.hex(checksum),
|
||||
checksumResult;
|
||||
if (correctChecksum === givenChecksum) {
|
||||
@@ -509,7 +516,7 @@ const IP = {
|
||||
"<tr><td>Destination IP address</td><td>" + IP._ipv4ToStr(dstIP) + "</td></tr>";
|
||||
|
||||
if (ihl > 5) {
|
||||
output += "<tr><td>Options</td><td>" + Utils.byteArrayToHex(options) + "</td></tr>";
|
||||
output += "<tr><td>Options</td><td>" + Utils.toHex(options) + "</td></tr>";
|
||||
}
|
||||
|
||||
return output + "</table>";
|
||||
@@ -534,7 +541,7 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv4CidrRange: function(cidr, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||
var output = "",
|
||||
let output = "",
|
||||
network = IP._strToIpv4(cidr[1]),
|
||||
cidrRange = parseInt(cidr[2], 10);
|
||||
|
||||
@@ -542,7 +549,7 @@ const IP = {
|
||||
return "IPv4 CIDR must be less than 32";
|
||||
}
|
||||
|
||||
var mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||
let mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||
ip1 = network & mask,
|
||||
ip2 = ip1 | ~mask;
|
||||
|
||||
@@ -574,7 +581,7 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv6CidrRange: function(cidr, includeNetworkInfo) {
|
||||
var output = "",
|
||||
let output = "",
|
||||
network = IP._strToIpv6(cidr[1]),
|
||||
cidrRange = parseInt(cidr[cidr.length-1], 10);
|
||||
|
||||
@@ -582,19 +589,19 @@ const IP = {
|
||||
return "IPv6 CIDR must be less than 128";
|
||||
}
|
||||
|
||||
var mask = IP._genIpv6Mask(cidrRange),
|
||||
let mask = IP._genIpv6Mask(cidrRange),
|
||||
ip1 = new Array(8),
|
||||
ip2 = new Array(8),
|
||||
totalDiff = "",
|
||||
total = new Array(128);
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
ip1[i] = network[i] & mask[i];
|
||||
ip2[i] = ip1[i] | (~mask[i] & 0x0000FFFF);
|
||||
totalDiff = (ip2[i] - ip1[i]).toString(2);
|
||||
|
||||
if (totalDiff !== "0") {
|
||||
for (var n = 0; n < totalDiff.length; n++) {
|
||||
for (let n = 0; n < totalDiff.length; n++) {
|
||||
total[i*16 + 16-(totalDiff.length-n)] = totalDiff[n];
|
||||
}
|
||||
}
|
||||
@@ -621,10 +628,10 @@ const IP = {
|
||||
* @returns {number[]}
|
||||
*/
|
||||
_genIpv6Mask: function(cidr) {
|
||||
var mask = new Array(8),
|
||||
let mask = new Array(8),
|
||||
shift;
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
if (cidr > ((i+1)*16)) {
|
||||
mask[i] = 0x0000FFFF;
|
||||
} else {
|
||||
@@ -650,12 +657,12 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv4HyphenatedRange: function(range, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||
var output = "",
|
||||
let output = "",
|
||||
ip1 = IP._strToIpv4(range[1]),
|
||||
ip2 = IP._strToIpv4(range[2]);
|
||||
|
||||
// Calculate mask
|
||||
var diff = ip1 ^ ip2,
|
||||
let diff = ip1 ^ ip2,
|
||||
cidr = 32,
|
||||
mask = 0;
|
||||
|
||||
@@ -666,7 +673,7 @@ const IP = {
|
||||
}
|
||||
|
||||
mask = ~mask >>> 0;
|
||||
var network = ip1 & mask,
|
||||
let network = ip1 & mask,
|
||||
subIp1 = network & mask,
|
||||
subIp2 = subIp1 | ~mask;
|
||||
|
||||
@@ -701,21 +708,18 @@ const IP = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_ipv6HyphenatedRange: function(range, includeNetworkInfo) {
|
||||
var output = "",
|
||||
let output = "",
|
||||
ip1 = IP._strToIpv6(range[1]),
|
||||
ip2 = IP._strToIpv6(range[14]);
|
||||
|
||||
var t = "",
|
||||
total = new Array(128);
|
||||
|
||||
// Initialise total array to "0"
|
||||
for (var i = 0; i < 128; i++)
|
||||
total[i] = "0";
|
||||
let t = "",
|
||||
total = new Array(128).fill(),
|
||||
i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
t = (ip2[i] - ip1[i]).toString(2);
|
||||
if (t !== "0") {
|
||||
for (var n = 0; n < t.length; n++) {
|
||||
for (let n = 0; n < t.length; n++) {
|
||||
total[i*16 + 16-(t.length-n)] = t[n];
|
||||
}
|
||||
}
|
||||
@@ -743,7 +747,7 @@ const IP = {
|
||||
* IP._strToIpv4("10.10.0.0");
|
||||
*/
|
||||
_strToIpv4: function (ipStr) {
|
||||
var blocks = ipStr.split("."),
|
||||
let blocks = ipStr.split("."),
|
||||
numBlocks = parseBlocks(blocks),
|
||||
result = 0;
|
||||
|
||||
@@ -761,8 +765,8 @@ const IP = {
|
||||
if (blocks.length !== 4)
|
||||
throw "More than 4 blocks.";
|
||||
|
||||
var numBlocks = [];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
const numBlocks = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
numBlocks[i] = parseInt(blocks[i], 10);
|
||||
if (numBlocks[i] < 0 || numBlocks[i] > 255)
|
||||
throw "Block out of range.";
|
||||
@@ -784,7 +788,7 @@ const IP = {
|
||||
* IP._ipv4ToStr(168427520);
|
||||
*/
|
||||
_ipv4ToStr: function(ipInt) {
|
||||
var blockA = (ipInt >> 24) & 255,
|
||||
let blockA = (ipInt >> 24) & 255,
|
||||
blockB = (ipInt >> 16) & 255,
|
||||
blockC = (ipInt >> 8) & 255,
|
||||
blockD = ipInt & 255;
|
||||
@@ -805,12 +809,12 @@ const IP = {
|
||||
* IP._strToIpv6("ff00::1111:2222");
|
||||
*/
|
||||
_strToIpv6: function(ipStr) {
|
||||
var blocks = ipStr.split(":"),
|
||||
let blocks = ipStr.split(":"),
|
||||
numBlocks = parseBlocks(blocks),
|
||||
j = 0,
|
||||
ipv6 = new Array(8);
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
if (isNaN(numBlocks[j])) {
|
||||
ipv6[i] = 0;
|
||||
if (i === (8-numBlocks.slice(j).length)) j++;
|
||||
@@ -827,8 +831,8 @@ const IP = {
|
||||
function parseBlocks(blocks) {
|
||||
if (blocks.length < 3 || blocks.length > 8)
|
||||
throw "Badly formatted IPv6 address.";
|
||||
var numBlocks = [];
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
const numBlocks = [];
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
numBlocks[i] = parseInt(blocks[i], 16);
|
||||
if (numBlocks[i] < 0 || numBlocks[i] > 65535)
|
||||
throw "Block out of range.";
|
||||
@@ -854,11 +858,11 @@ const IP = {
|
||||
* IP._ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], false);
|
||||
*/
|
||||
_ipv6ToStr: function(ipv6, compact) {
|
||||
var output = "",
|
||||
let output = "",
|
||||
i = 0;
|
||||
|
||||
if (compact) {
|
||||
var start = -1,
|
||||
let start = -1,
|
||||
end = -1,
|
||||
s = 0,
|
||||
e = -1;
|
||||
@@ -908,7 +912,7 @@ const IP = {
|
||||
* IP._generateIpv4Range(1, 3);
|
||||
*/
|
||||
_generateIpv4Range: function(ip, endIp) {
|
||||
var range = [];
|
||||
const range = [];
|
||||
if (endIp >= ip) {
|
||||
for (; ip <= endIp; ip++) {
|
||||
range.push(IP._ipv4ToStr(ip));
|
||||
|
||||
123
src/core/operations/Image.js
Normal file
123
src/core/operations/Image.js
Normal file
@@ -0,0 +1,123 @@
|
||||
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 {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runExtractEXIF(input, args) {
|
||||
try {
|
||||
const parser = ExifParser.create(input);
|
||||
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 {byteArray}
|
||||
*/
|
||||
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;
|
||||
@@ -1,4 +1,4 @@
|
||||
import esprima from "esprima";
|
||||
import * as esprima from "esprima";
|
||||
import escodegen from "escodegen";
|
||||
import esmangle from "esmangle";
|
||||
|
||||
@@ -48,7 +48,7 @@ const JS = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParse: function (input, args) {
|
||||
var parseLoc = args[0],
|
||||
let parseLoc = args[0],
|
||||
parseRange = args[1],
|
||||
parseTokens = args[2],
|
||||
parseComment = args[3],
|
||||
@@ -62,7 +62,7 @@ const JS = {
|
||||
tolerant: parseTolerant
|
||||
};
|
||||
|
||||
result = esprima.parse(input, options);
|
||||
result = esprima.parseScript(input, options);
|
||||
return JSON.stringify(result, null, 2);
|
||||
},
|
||||
|
||||
@@ -96,7 +96,7 @@ const JS = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runBeautify: function(input, args) {
|
||||
var beautifyIndent = args[0] || JS.BEAUTIFY_INDENT,
|
||||
let beautifyIndent = args[0] || JS.BEAUTIFY_INDENT,
|
||||
quotes = args[1].toLowerCase(),
|
||||
beautifySemicolons = args[2],
|
||||
beautifyComment = args[3],
|
||||
@@ -104,13 +104,13 @@ const JS = {
|
||||
AST;
|
||||
|
||||
try {
|
||||
AST = esprima.parse(input, {
|
||||
AST = esprima.parseScript(input, {
|
||||
range: true,
|
||||
tokens: true,
|
||||
comment: true
|
||||
});
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
format: {
|
||||
indent: {
|
||||
style: beautifyIndent
|
||||
@@ -141,8 +141,8 @@ const JS = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMinify: function(input, args) {
|
||||
var result = "",
|
||||
AST = esprima.parse(input),
|
||||
let result = "",
|
||||
AST = esprima.parseScript(input),
|
||||
optimisedAST = esmangle.optimize(AST, null),
|
||||
mangledAST = esmangle.mangle(optimisedAST);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ const MAC = {
|
||||
runFormat: function(input, args) {
|
||||
if (!input) return "";
|
||||
|
||||
var outputCase = args[0],
|
||||
let outputCase = args[0],
|
||||
noDelim = args[1],
|
||||
dashDelim = args[2],
|
||||
colonDelim = args[3],
|
||||
@@ -54,7 +54,7 @@ const MAC = {
|
||||
macs = input.toLowerCase().split(/[,\s\r\n]+/);
|
||||
|
||||
macs.forEach(function(mac) {
|
||||
var cleanMac = mac.replace(/[:.-]+/g, ""),
|
||||
let cleanMac = mac.replace(/[:.-]+/g, ""),
|
||||
macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"),
|
||||
macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"),
|
||||
macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1.");
|
||||
|
||||
213
src/core/operations/MS.js
Normal file
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;
|
||||
@@ -97,19 +97,19 @@ const MorseCode = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var format = args[0].split("/");
|
||||
var dash = format[0];
|
||||
var dot = format[1];
|
||||
const format = args[0].split("/");
|
||||
const dash = format[0];
|
||||
const dot = format[1];
|
||||
|
||||
var letterDelim = Utils.charRep[args[1]];
|
||||
var wordDelim = Utils.charRep[args[2]];
|
||||
const letterDelim = Utils.charRep[args[1]];
|
||||
const wordDelim = Utils.charRep[args[2]];
|
||||
|
||||
input = input.split(/\r?\n/);
|
||||
input = Array.prototype.map.call(input, function(line) {
|
||||
var words = line.split(/ +/);
|
||||
let words = line.split(/ +/);
|
||||
words = Array.prototype.map.call(words, function(word) {
|
||||
var letters = Array.prototype.map.call(word, function(character) {
|
||||
var letter = character.toUpperCase();
|
||||
const letters = Array.prototype.map.call(word, function(character) {
|
||||
const letter = character.toUpperCase();
|
||||
if (typeof MorseCode.MORSE_TABLE[letter] == "undefined") {
|
||||
return "";
|
||||
}
|
||||
@@ -148,12 +148,12 @@ const MorseCode = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFrom: (function() {
|
||||
var reversedTable = null;
|
||||
var reverseTable = function() {
|
||||
let reversedTable = null;
|
||||
const reverseTable = function() {
|
||||
reversedTable = {};
|
||||
|
||||
for (var letter in MorseCode.MORSE_TABLE) {
|
||||
var signal = MorseCode.MORSE_TABLE[letter];
|
||||
for (const letter in MorseCode.MORSE_TABLE) {
|
||||
const signal = MorseCode.MORSE_TABLE[letter];
|
||||
reversedTable[signal] = letter;
|
||||
}
|
||||
};
|
||||
@@ -163,17 +163,17 @@ const MorseCode = {
|
||||
reverseTable();
|
||||
}
|
||||
|
||||
var letterDelim = Utils.charRep[args[0]];
|
||||
var wordDelim = Utils.charRep[args[1]];
|
||||
const letterDelim = Utils.charRep[args[0]];
|
||||
const wordDelim = Utils.charRep[args[1]];
|
||||
|
||||
input = input.replace(/-|‐|−|_|–|—|dash/ig, "<dash>"); //hyphen-minus|hyphen|minus-sign|undersore|en-dash|em-dash
|
||||
input = input.replace(/\.|·|dot/ig, "<dot>");
|
||||
|
||||
var words = input.split(wordDelim);
|
||||
let words = input.split(wordDelim);
|
||||
words = Array.prototype.map.call(words, function(word) {
|
||||
var signals = word.split(letterDelim);
|
||||
const signals = word.split(letterDelim);
|
||||
|
||||
var letters = signals.map(function(signal) {
|
||||
const letters = signals.map(function(signal) {
|
||||
return reversedTable[signal];
|
||||
});
|
||||
|
||||
|
||||
@@ -23,12 +23,17 @@ const NetBIOS = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runEncodeName: function(input, args) {
|
||||
var output = [],
|
||||
let output = [],
|
||||
offset = args[0];
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
output.push((input[i] >> 4) + offset);
|
||||
output.push((input[i] & 0xf) + offset);
|
||||
if (input.length <= 16) {
|
||||
let len = input.length;
|
||||
input.length = 16;
|
||||
input.fill(32, len, 16);
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
output.push((input[i] >> 4) + offset);
|
||||
output.push((input[i] & 0xf) + offset);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
@@ -43,12 +48,18 @@ const NetBIOS = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runDecodeName: function(input, args) {
|
||||
var output = [],
|
||||
let output = [],
|
||||
offset = args[0];
|
||||
|
||||
for (var i = 0; i < input.length; i += 2) {
|
||||
output.push(((input[i] - offset) << 4) |
|
||||
((input[i + 1] - offset) & 0xf));
|
||||
if (input.length <= 32 && (input.length % 2) === 0) {
|
||||
for (let i = 0; i < input.length; i += 2) {
|
||||
output.push((((input[i] & 0xff) - offset) << 4) |
|
||||
(((input[i + 1] & 0xff) - offset) & 0xf));
|
||||
}
|
||||
for (let i = output.length - 1; i > 0; i--) {
|
||||
if (output[i] === 32) output.splice(i, i);
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -14,16 +14,72 @@ const Numberwang = {
|
||||
* @returns {string}
|
||||
*/
|
||||
run: function(input, args) {
|
||||
if (!input) return "Let's play Wangernumb!";
|
||||
var match = input.match(/\d+/);
|
||||
if (match) {
|
||||
return match[0] + "! That's Numberwang!";
|
||||
let output;
|
||||
if (!input) {
|
||||
output = "Let's play Wangernumb!";
|
||||
} else {
|
||||
// That's a bad miss!
|
||||
return "Sorry, that's not Numberwang. Let's rotate the board!";
|
||||
const match = input.match(/(f0rty-s1x|shinty-six|filth-hundred and neeb|-?√?\d+(\.\d+)?i?([a-z]?)%?)/i);
|
||||
if (match) {
|
||||
if (match[3]) output = match[0] + "! That's AlphaNumericWang!";
|
||||
else output = match[0] + "! That's Numberwang!";
|
||||
} else {
|
||||
// That's a bad miss!
|
||||
output = "Sorry, that's not Numberwang. Let's rotate the board!";
|
||||
}
|
||||
}
|
||||
|
||||
const rand = Math.floor(Math.random() * Numberwang._didYouKnow.length);
|
||||
return output + "\n\nDid you know: " + Numberwang._didYouKnow[rand];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Taken from http://numberwang.wikia.com/wiki/Numberwang_Wikia
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_didYouKnow: [
|
||||
"Numberwang, contrary to popular belief, is a fruit and not a vegetable.",
|
||||
"Robert Webb once got WordWang while presenting an episode of Numberwang.",
|
||||
"The 6705th digit of pi is Numberwang.",
|
||||
"Numberwang was invented on a Sevenday.",
|
||||
"Contrary to popular belief, Albert Einstein always got good grades in Numberwang at school. He once scored ^4$ on a test.",
|
||||
"680 asteroids have been named after Numberwang.",
|
||||
"Archimedes is most famous for proclaiming \"That's Numberwang!\" during an epiphany about water displacement he had while taking a bath.",
|
||||
"Numberwang Day is celebrated in Japan on every day of the year apart from June 6.",
|
||||
"Biologists recently discovered Numberwang within a strand of human DNA.",
|
||||
"Numbernot is a special type of non-Numberwang number. It is divisible by 3 and the letter \"y\".",
|
||||
"Julie once got 612.04 Numberwangs in a single episode of Emmerdale.",
|
||||
"In India, it is traditional to shout out \"Numberwang!\" instead of checkmate during games of chess.",
|
||||
"There is a rule on Countdown which states that if you get Numberwang in the numbers round, you automatically win. It has only ever been invoked twice.",
|
||||
"\"Numberwang\" was the third-most common baby name for a brief period in 1722.",
|
||||
"\"The Lion King\" was loosely based on Numberwang.",
|
||||
"\"A Numberwang a day keeps the doctor away\" is how Donny Cosy, the oldest man in the world, explained how he was in such good health at the age of 136.",
|
||||
"The \"number lock\" button on a keyboard is based on the popular round of the same name in \"Numberwang\".",
|
||||
"Cambridge became the first university to offer a course in Numberwang in 1567.",
|
||||
"Schrödinger's Numberwang is a number that has been confusing dentists for centuries.",
|
||||
"\"Harry Potter and the Numberwang of Numberwang\" was rejected by publishers -41 times before it became a bestseller.",
|
||||
"\"Numberwang\" is the longest-running British game show in history; it has aired 226 seasons, each containing 19 episodes, which makes a grand total of 132 episodes.",
|
||||
"The triple Numberwang bonus was discovered by archaeologist Thomas Jefferson in Somerset.",
|
||||
"Numberwang is illegal in parts of Czechoslovakia.",
|
||||
"Numberwang was discovered in India in the 12th century.",
|
||||
"Numberwang has the chemical formula Zn4SO2(HgEs)3.",
|
||||
"The first pack of cards ever created featured two \"Numberwang\" cards instead of jokers.",
|
||||
"Julius Caesar was killed by an overdose of Numberwang.",
|
||||
"The most Numberwang musical note is G#.",
|
||||
"In 1934, the forty-third Google Doodle promoted the upcoming television show \"Numberwang on Ice\".",
|
||||
"A recent psychology study found that toddlers were 17% faster at identifying numbers which were Numberwang.",
|
||||
"There are 700 ways to commit a foul in the television show \"Numberwang\". All 700 of these fouls were committed by Julie in one single episode in 1473.",
|
||||
"Astronomers suspect God is Numberwang.",
|
||||
"Numberwang is the official beverage of Canada.",
|
||||
"In the pilot episode of \"The Price is Right\", if a contestant got the value of an item exactly right they were told \"That's Numberwang!\" and immediately won ₹5.7032.",
|
||||
"The first person to get three Numberwangs in a row was Madonna.",
|
||||
"\"Numberwang\" has the code U+46402 in Unicode.",
|
||||
"The musical note \"Numberwang\" is between D# and E♮.",
|
||||
"Numberwang was first played on the moon in 1834.",
|
||||
],
|
||||
|
||||
};
|
||||
|
||||
export default Numberwang;
|
||||
|
||||
@@ -17,26 +17,26 @@ const OS = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseUnixPerms: function(input, args) {
|
||||
var perms = {
|
||||
d : false, // directory
|
||||
sl : false, // symbolic link
|
||||
np : false, // named pipe
|
||||
s : false, // socket
|
||||
cd : false, // character device
|
||||
bd : false, // block device
|
||||
dr : false, // door
|
||||
sb : false, // sticky bit
|
||||
su : false, // setuid
|
||||
sg : false, // setgid
|
||||
ru : false, // read user
|
||||
wu : false, // write user
|
||||
eu : false, // execute user
|
||||
rg : false, // read group
|
||||
wg : false, // write group
|
||||
eg : false, // execute group
|
||||
ro : false, // read other
|
||||
wo : false, // write other
|
||||
eo : false // execute other
|
||||
let perms = {
|
||||
d: false, // directory
|
||||
sl: false, // symbolic link
|
||||
np: false, // named pipe
|
||||
s: false, // socket
|
||||
cd: false, // character device
|
||||
bd: false, // block device
|
||||
dr: false, // door
|
||||
sb: false, // sticky bit
|
||||
su: false, // setuid
|
||||
sg: false, // setgid
|
||||
ru: false, // read user
|
||||
wu: false, // write user
|
||||
eu: false, // execute user
|
||||
rg: false, // read group
|
||||
wg: false, // write group
|
||||
eg: false, // execute group
|
||||
ro: false, // read other
|
||||
wo: false, // write other
|
||||
eo: false // execute other
|
||||
},
|
||||
d = 0,
|
||||
u = 0,
|
||||
@@ -202,7 +202,7 @@ const OS = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_permsToStr: function(perms) {
|
||||
var str = "",
|
||||
let str = "",
|
||||
type = "-";
|
||||
|
||||
if (perms.d) type = "d";
|
||||
@@ -263,7 +263,7 @@ const OS = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_permsToOctal: function(perms) {
|
||||
var d = 0,
|
||||
let d = 0,
|
||||
u = 0,
|
||||
g = 0,
|
||||
o = 0;
|
||||
|
||||
56
src/core/operations/OTP.js
Executable file
56
src/core/operations/OTP.js
Executable file
@@ -0,0 +1,56 @@
|
||||
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;
|
||||
160
src/core/operations/PHP.js
Normal file
160
src/core/operations/PHP.js
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* PHP operations.
|
||||
*
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Jarmo van Lenthe
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const PHP = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_VALID_JSON: true,
|
||||
|
||||
/**
|
||||
* PHP Deserialize operation.
|
||||
*
|
||||
* This Javascript implementation is based on the Python implementation by
|
||||
* Armin Ronacher (2016), who released it under the 3-Clause BSD license.
|
||||
* See: https://github.com/mitsuhiko/phpserialize/
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDeserialize: function (input, args) {
|
||||
/**
|
||||
* Recursive method for deserializing.
|
||||
* @returns {*}
|
||||
*/
|
||||
function handleInput() {
|
||||
/**
|
||||
* Read `length` characters from the input, shifting them out the input.
|
||||
* @param length
|
||||
* @returns {string}
|
||||
*/
|
||||
function read(length) {
|
||||
let result = "";
|
||||
for (let idx = 0; idx < length; idx++) {
|
||||
let char = inputPart.shift();
|
||||
if (char === undefined) {
|
||||
throw "End of input reached before end of script";
|
||||
}
|
||||
result += char;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from the input until `until` is found.
|
||||
* @param until
|
||||
* @returns {string}
|
||||
*/
|
||||
function readUntil(until) {
|
||||
let result = "";
|
||||
for (;;) {
|
||||
let char = read(1);
|
||||
if (char === until) {
|
||||
break;
|
||||
} else {
|
||||
result += char;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from the input that must be equal to `expect`
|
||||
* @param expect
|
||||
* @returns {string}
|
||||
*/
|
||||
function expect(expect) {
|
||||
let result = read(expect.length);
|
||||
if (result !== expect) {
|
||||
throw "Unexpected input found";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to handle deserialized arrays.
|
||||
* @returns {Array}
|
||||
*/
|
||||
function handleArray() {
|
||||
let items = parseInt(readUntil(":"), 10) * 2;
|
||||
expect("{");
|
||||
let result = [];
|
||||
let isKey = true;
|
||||
let lastItem = null;
|
||||
for (let idx = 0; idx < items; idx++) {
|
||||
let item = handleInput();
|
||||
if (isKey) {
|
||||
lastItem = item;
|
||||
isKey = false;
|
||||
} else {
|
||||
let numberCheck = lastItem.match(/[0-9]+/);
|
||||
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
|
||||
result.push("\"" + lastItem + "\": " + item);
|
||||
} else {
|
||||
result.push(lastItem + ": " + item);
|
||||
}
|
||||
isKey = true;
|
||||
}
|
||||
}
|
||||
expect("}");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
let kind = read(1).toLowerCase();
|
||||
|
||||
switch (kind) {
|
||||
case "n":
|
||||
expect(";");
|
||||
return "";
|
||||
|
||||
case "i":
|
||||
case "d":
|
||||
case "b": {
|
||||
expect(":");
|
||||
let data = readUntil(";");
|
||||
if (kind === "b") {
|
||||
return (parseInt(data, 10) !== 0);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
case "a":
|
||||
expect(":");
|
||||
return "{" + handleArray() + "}";
|
||||
|
||||
case "s": {
|
||||
expect(":");
|
||||
let length = readUntil(":");
|
||||
expect("\"");
|
||||
let value = read(length);
|
||||
expect("\";");
|
||||
if (args[0]) {
|
||||
return "\"" + value.replace(/"/g, "\\\"") + "\"";
|
||||
} else {
|
||||
return "\"" + value + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
throw "Unknown type: " + kind;
|
||||
}
|
||||
}
|
||||
|
||||
let inputPart = input.split("");
|
||||
return handleInput();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default PHP;
|
||||
@@ -27,52 +27,47 @@ const PublicKey = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseX509: function (input, args) {
|
||||
var cert = new r.X509(),
|
||||
inputFormat = args[0];
|
||||
|
||||
if (!input.length) {
|
||||
return "No input";
|
||||
}
|
||||
|
||||
let cert = new r.X509(),
|
||||
inputFormat = args[0];
|
||||
|
||||
switch (inputFormat) {
|
||||
case "DER Hex":
|
||||
input = input.replace(/\s/g, "");
|
||||
cert.hex = input;
|
||||
cert.pem = r.KJUR.asn1.ASN1Util.getPEMStringFromHex(input, "CERTIFICATE");
|
||||
cert.readCertHex(input);
|
||||
break;
|
||||
case "PEM":
|
||||
cert.hex = r.X509.pemToHex(input);
|
||||
cert.pem = input;
|
||||
cert.readCertPEM(input);
|
||||
break;
|
||||
case "Base64":
|
||||
cert.hex = Utils.toHex(Utils.fromBase64(input, null, "byteArray"), "");
|
||||
cert.pem = r.KJUR.asn1.ASN1Util.getPEMStringFromHex(cert.hex, "CERTIFICATE");
|
||||
cert.readCertHex(Utils.toHex(Utils.fromBase64(input, null, "byteArray"), ""));
|
||||
break;
|
||||
case "Raw":
|
||||
cert.hex = Utils.toHex(Utils.strToByteArray(input), "");
|
||||
cert.pem = r.KJUR.asn1.ASN1Util.getPEMStringFromHex(cert.hex, "CERTIFICATE");
|
||||
cert.readCertHex(Utils.toHex(Utils.strToByteArray(input), ""));
|
||||
break;
|
||||
default:
|
||||
throw "Undefined input format";
|
||||
}
|
||||
|
||||
var version = r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 0, 0]),
|
||||
sn = cert.getSerialNumberHex(),
|
||||
algorithm = r.KJUR.asn1.x509.OID.oid2name(r.KJUR.asn1.ASN1Util.oidHexToInt(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 2, 0]))),
|
||||
let sn = cert.getSerialNumberHex(),
|
||||
issuer = cert.getIssuerString(),
|
||||
notBefore = cert.getNotBefore(),
|
||||
notAfter = cert.getNotAfter(),
|
||||
subject = cert.getSubjectString(),
|
||||
pkAlgorithm = r.KJUR.asn1.x509.OID.oid2name(r.KJUR.asn1.ASN1Util.oidHexToInt(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 6, 0, 0]))),
|
||||
pk = r.X509.getPublicKeyFromCertPEM(cert.pem),
|
||||
pk = cert.getPublicKey(),
|
||||
pkFields = [],
|
||||
pkStr = "",
|
||||
certSigAlg = r.KJUR.asn1.x509.OID.oid2name(r.KJUR.asn1.ASN1Util.oidHexToInt(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [1, 0]))),
|
||||
certSig = r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [2]).substr(2),
|
||||
sig = cert.getSignatureValueHex(),
|
||||
sigStr = "",
|
||||
extensions = r.ASN1HEX.dump(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 7]));
|
||||
extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0];
|
||||
|
||||
// Public Key fields
|
||||
pkFields.push({
|
||||
key: "Algorithm",
|
||||
value: pk.type
|
||||
});
|
||||
|
||||
if (pk.type === "EC") { // ECDSA
|
||||
pkFields.push({
|
||||
key: "Curve Name",
|
||||
@@ -123,49 +118,54 @@ const PublicKey = {
|
||||
});
|
||||
}
|
||||
|
||||
// Signature fields
|
||||
if (r.ASN1HEX.dump(certSig).indexOf("SEQUENCE") === 0) { // DSA or ECDSA
|
||||
sigStr = " r: " + PublicKey._formatByteStr(r.ASN1HEX.getDecendantHexVByNthList(certSig, 0, [0]), 16, 18) + "\n" +
|
||||
" s: " + PublicKey._formatByteStr(r.ASN1HEX.getDecendantHexVByNthList(certSig, 0, [1]), 16, 18) + "\n";
|
||||
} else { // RSA
|
||||
sigStr = " Signature: " + PublicKey._formatByteStr(certSig, 16, 18) + "\n";
|
||||
}
|
||||
|
||||
// Format Public Key fields
|
||||
for (var i = 0; i < pkFields.length; i++) {
|
||||
for (let i = 0; i < pkFields.length; i++) {
|
||||
pkStr += " " + pkFields[i].key + ":" +
|
||||
Utils.padLeft(
|
||||
pkFields[i].value + "\n",
|
||||
(pkFields[i].value + "\n").padStart(
|
||||
18 - (pkFields[i].key.length + 3) + pkFields[i].value.length + 1,
|
||||
" "
|
||||
);
|
||||
}
|
||||
|
||||
var issuerStr = PublicKey._formatDnStr(issuer, 2),
|
||||
nbDate = PublicKey._formatDate(notBefore),
|
||||
naDate = PublicKey._formatDate(notAfter),
|
||||
// Signature fields
|
||||
let breakoutSig = false;
|
||||
try {
|
||||
breakoutSig = r.ASN1HEX.dump(sig).indexOf("SEQUENCE") === 0;
|
||||
} catch (err) {
|
||||
// Error processing signature, output without further breakout
|
||||
}
|
||||
|
||||
if (breakoutSig) { // DSA or ECDSA
|
||||
sigStr = " r: " + PublicKey._formatByteStr(r.ASN1HEX.getV(sig, 4), 16, 18) + "\n" +
|
||||
" s: " + PublicKey._formatByteStr(r.ASN1HEX.getV(sig, 48), 16, 18);
|
||||
} else { // RSA or unknown
|
||||
sigStr = " Signature: " + PublicKey._formatByteStr(sig, 16, 18);
|
||||
}
|
||||
|
||||
|
||||
let issuerStr = PublicKey._formatDnStr(issuer, 2),
|
||||
nbDate = PublicKey._formatDate(cert.getNotBefore()),
|
||||
naDate = PublicKey._formatDate(cert.getNotAfter()),
|
||||
subjectStr = PublicKey._formatDnStr(subject, 2);
|
||||
|
||||
var output = "Version: " + (parseInt(version, 16) + 1) + " (0x" + version + ")\n" +
|
||||
"Serial number: " + new r.BigInteger(sn, 16).toString() + " (0x" + sn + ")\n" +
|
||||
"Algorithm ID: " + algorithm + "\n" +
|
||||
"Validity\n" +
|
||||
" Not Before: " + nbDate + " (dd-mm-yy hh:mm:ss) (" + notBefore + ")\n" +
|
||||
" Not After: " + naDate + " (dd-mm-yy hh:mm:ss) (" + notAfter + ")\n" +
|
||||
"Issuer\n" +
|
||||
issuerStr +
|
||||
"Subject\n" +
|
||||
subjectStr +
|
||||
"Public Key\n" +
|
||||
" Algorithm: " + pkAlgorithm + "\n" +
|
||||
pkStr +
|
||||
"Certificate Signature\n" +
|
||||
" Algorithm: " + certSigAlg + "\n" +
|
||||
sigStr +
|
||||
"\nExtensions (parsed ASN.1)\n" +
|
||||
extensions;
|
||||
return `Version: ${cert.version} (0x${Utils.hex(cert.version - 1)})
|
||||
Serial number: ${new r.BigInteger(sn, 16).toString()} (0x${sn})
|
||||
Algorithm ID: ${cert.getSignatureAlgorithmField()}
|
||||
Validity
|
||||
Not Before: ${nbDate} (dd-mm-yy hh:mm:ss) (${cert.getNotBefore()})
|
||||
Not After: ${naDate} (dd-mm-yy hh:mm:ss) (${cert.getNotAfter()})
|
||||
Issuer
|
||||
${issuerStr}
|
||||
Subject
|
||||
${subjectStr}
|
||||
Public Key
|
||||
${pkStr.slice(0, -1)}
|
||||
Certificate Signature
|
||||
Algorithm: ${cert.getSignatureAlgorithmName()}
|
||||
${sigStr}
|
||||
|
||||
return output;
|
||||
Extensions
|
||||
${extensions}`;
|
||||
},
|
||||
|
||||
|
||||
@@ -185,7 +185,9 @@ const PublicKey = {
|
||||
// Add footer so that the KEYUTIL function works
|
||||
input = input + "-----END CERTIFICATE-----";
|
||||
}
|
||||
return r.KEYUTIL.getHexFromPEM(input);
|
||||
let cert = new r.X509();
|
||||
cert.readCertPEM(input);
|
||||
return cert.hex;
|
||||
},
|
||||
|
||||
|
||||
@@ -245,7 +247,7 @@ const PublicKey = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseAsn1HexString: function(input, args) {
|
||||
var truncateLen = args[1],
|
||||
let truncateLen = args[1],
|
||||
index = args[0];
|
||||
return r.ASN1HEX.dump(input.replace(/\s/g, ""), {
|
||||
"ommitLongOctet": truncateLen
|
||||
@@ -262,14 +264,15 @@ const PublicKey = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_formatDnStr: function(dnStr, indent) {
|
||||
var output = "",
|
||||
fields = dnStr.split(",/|"),
|
||||
let output = "",
|
||||
fields = dnStr.substr(1).replace(/([^\\])\//g, "$1$1/").split(/[^\\]\//),
|
||||
maxKeyLen = 0,
|
||||
key,
|
||||
value,
|
||||
i,
|
||||
str;
|
||||
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
for (i = 0; i < fields.length; i++) {
|
||||
if (!fields[i].length) continue;
|
||||
|
||||
key = fields[i].split("=")[0];
|
||||
@@ -282,12 +285,12 @@ const PublicKey = {
|
||||
|
||||
key = fields[i].split("=")[0];
|
||||
value = fields[i].split("=")[1];
|
||||
str = Utils.padRight(key, maxKeyLen) + " = " + value + "\n";
|
||||
str = key.padEnd(maxKeyLen, " ") + " = " + value + "\n";
|
||||
|
||||
output += Utils.padLeft(str, indent + str.length, " ");
|
||||
output += str.padStart(indent + str.length, " ");
|
||||
}
|
||||
|
||||
return output;
|
||||
return output.slice(0, -1);
|
||||
},
|
||||
|
||||
|
||||
@@ -303,14 +306,14 @@ const PublicKey = {
|
||||
_formatByteStr: function(byteStr, length, indent) {
|
||||
byteStr = Utils.toHex(Utils.fromHex(byteStr), ":");
|
||||
length = length * 3;
|
||||
var output = "";
|
||||
let output = "";
|
||||
|
||||
for (var i = 0; i < byteStr.length; i += length) {
|
||||
var str = byteStr.slice(i, i + length) + "\n";
|
||||
for (let i = 0; i < byteStr.length; i += length) {
|
||||
const str = byteStr.slice(i, i + length) + "\n";
|
||||
if (i === 0) {
|
||||
output += str;
|
||||
} else {
|
||||
output += Utils.padLeft(str, indent + str.length, " ");
|
||||
output += str.padStart(indent + str.length, " ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,720 +340,3 @@ const PublicKey = {
|
||||
};
|
||||
|
||||
export default PublicKey;
|
||||
|
||||
|
||||
/**
|
||||
* Overwrite X509.hex2dn function so as to join RDNs with a string which can be split on without
|
||||
* causing problems later (I hope).
|
||||
*
|
||||
* @param {string} hDN - Hex DN string
|
||||
* @returns {string}
|
||||
*/
|
||||
r.X509.hex2dn = function(hDN) {
|
||||
var s = "";
|
||||
var a = r.ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var hRDN = r.ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
|
||||
s = s + ",/|" + r.X509.hex2rdn(hRDN);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Overwrite DN attribute lookup in jsrasign library with a much more complete version from
|
||||
* https://github.com/nfephp-org/nfephp/blob/master/libs/Common/Certificate/Oids.php
|
||||
*
|
||||
* Various duplicates commented out.
|
||||
*
|
||||
* @constant
|
||||
*/
|
||||
r.X509.DN_ATTRHEX = {
|
||||
"0603550403" : "commonName",
|
||||
"0603550404" : "surname",
|
||||
"0603550406" : "countryName",
|
||||
"0603550407" : "localityName",
|
||||
"0603550408" : "stateOrProvinceName",
|
||||
"0603550409" : "streetAddress",
|
||||
"060355040a" : "organizationName",
|
||||
"060355040b" : "organizationalUnitName",
|
||||
"060355040c" : "title",
|
||||
"0603550414" : "telephoneNumber",
|
||||
"060355042a" : "givenName",
|
||||
// "0603551d0e" : "id-ce-subjectKeyIdentifier",
|
||||
// "0603551d0f" : "id-ce-keyUsage",
|
||||
// "0603551d11" : "id-ce-subjectAltName",
|
||||
// "0603551d13" : "id-ce-basicConstraints",
|
||||
// "0603551d14" : "id-ce-cRLNumber",
|
||||
// "0603551d1f" : "id-ce-CRLDistributionPoints",
|
||||
// "0603551d20" : "id-ce-certificatePolicies",
|
||||
// "0603551d23" : "id-ce-authorityKeyIdentifier",
|
||||
// "0603551d25" : "id-ce-extKeyUsage",
|
||||
// "06032a864886f70d010901" : "Email",
|
||||
// "06032a864886f70d010101" : "RSAEncryption",
|
||||
// "06032a864886f70d010102" : "md2WithRSAEncryption",
|
||||
// "06032a864886f70d010104" : "md5withRSAEncryption",
|
||||
// "06032a864886f70d010105" : "SHA-1WithRSAEncryption",
|
||||
// "06032a8648ce380403" : "id-dsa-with-sha-1",
|
||||
// "06032b06010505070302" : "idKpClientAuth",
|
||||
// "06032b06010505070304" : "idKpSecurityemail",
|
||||
"06032b06010505070201" : "idCertificatePolicies",
|
||||
"06036086480186f8420101" : "netscape-cert-type",
|
||||
"06036086480186f8420102" : "netscape-base-url",
|
||||
"06036086480186f8420103" : "netscape-revocation-url",
|
||||
"06036086480186f8420104" : "netscape-ca-revocation-url",
|
||||
"06036086480186f8420107" : "netscape-cert-renewal-url",
|
||||
"06036086480186f8420108" : "netscape-ca-policy-url",
|
||||
"06036086480186f842010c" : "netscape-ssl-server-name",
|
||||
"06036086480186f842010d" : "netscape-comment",
|
||||
"0603604c010201" : "A1",
|
||||
"0603604c010203" : "A3",
|
||||
"0603604c01020110" : "Certification Practice Statement pointer",
|
||||
"0603604c010301" : "Dados do cert parte 1",
|
||||
"0603604c010305" : "Dados do cert parte 2",
|
||||
"0603604c010306" : "Dados do cert parte 3",
|
||||
"06030992268993f22c640119" : "domainComponent",
|
||||
"06032a24a0f2a07d01010a" : "Signet pilot",
|
||||
"06032a24a0f2a07d01010b" : "Signet intraNet",
|
||||
"06032a24a0f2a07d010102" : "Signet personal",
|
||||
"06032a24a0f2a07d010114" : "Signet securityPolicy",
|
||||
"06032a24a0f2a07d010103" : "Signet business",
|
||||
"06032a24a0f2a07d010104" : "Signet legal",
|
||||
"06032a24a497a35301640101" : "Certificates Australia policyIdentifier",
|
||||
"06032a85702201" : "seis-cp",
|
||||
"06032a8570220101" : "SEIS certificatePolicy-s10",
|
||||
"06032a85702202" : "SEIS pe",
|
||||
"06032a85702203" : "SEIS at",
|
||||
"06032a8570220301" : "SEIS at-personalIdentifier",
|
||||
"06032a8648ce380201" : "holdinstruction-none",
|
||||
"06032a8648ce380202" : "holdinstruction-callissuer",
|
||||
"06032a8648ce380203" : "holdinstruction-reject",
|
||||
"06032a8648ce380401" : "dsa",
|
||||
"06032a8648ce380403" : "dsaWithSha1",
|
||||
"06032a8648ce3d01" : "fieldType",
|
||||
"06032a8648ce3d0101" : "prime-field",
|
||||
"06032a8648ce3d0102" : "characteristic-two-field",
|
||||
"06032a8648ce3d010201" : "ecPublicKey",
|
||||
"06032a8648ce3d010203" : "characteristic-two-basis",
|
||||
"06032a8648ce3d01020301" : "onBasis",
|
||||
"06032a8648ce3d01020302" : "tpBasis",
|
||||
"06032a8648ce3d01020303" : "ppBasis",
|
||||
"06032a8648ce3d02" : "publicKeyType",
|
||||
"06032a8648ce3d0201" : "ecPublicKey",
|
||||
"06032a8648ce3e0201" : "dhPublicNumber",
|
||||
"06032a864886f67d07" : "nsn",
|
||||
"06032a864886f67d0741" : "nsn-ce",
|
||||
"06032a864886f67d074100" : "entrustVersInfo",
|
||||
"06032a864886f67d0742" : "nsn-alg",
|
||||
"06032a864886f67d07420a" : "cast5CBC",
|
||||
"06032a864886f67d07420b" : "cast5MAC",
|
||||
"06032a864886f67d07420c" : "pbeWithMD5AndCAST5-CBC",
|
||||
"06032a864886f67d07420d" : "passwordBasedMac",
|
||||
"06032a864886f67d074203" : "cast3CBC",
|
||||
"06032a864886f67d0743" : "nsn-oc",
|
||||
"06032a864886f67d074300" : "entrustUser",
|
||||
"06032a864886f67d0744" : "nsn-at",
|
||||
"06032a864886f67d074400" : "entrustCAInfo",
|
||||
"06032a864886f67d07440a" : "attributeCertificate",
|
||||
"06032a864886f70d0101" : "pkcs-1",
|
||||
"06032a864886f70d010101" : "rsaEncryption",
|
||||
"06032a864886f70d010102" : "md2withRSAEncryption",
|
||||
"06032a864886f70d010103" : "md4withRSAEncryption",
|
||||
"06032a864886f70d010104" : "md5withRSAEncryption",
|
||||
"06032a864886f70d010105" : "sha1withRSAEncryption",
|
||||
"06032a864886f70d010106" : "rsaOAEPEncryptionSET",
|
||||
"06032a864886f70d010910020b" : "SMIMEEncryptionKeyPreference",
|
||||
"06032a864886f70d010c" : "pkcs-12",
|
||||
"06032a864886f70d010c01" : "pkcs-12-PbeIds",
|
||||
"06032a864886f70d010c0101" : "pbeWithSHAAnd128BitRC4",
|
||||
"06032a864886f70d010c0102" : "pbeWithSHAAnd40BitRC4",
|
||||
"06032a864886f70d010c0103" : "pbeWithSHAAnd3-KeyTripleDES-CBC",
|
||||
"06032a864886f70d010c0104" : "pbeWithSHAAnd2-KeyTripleDES-CBC",
|
||||
"06032a864886f70d010c0105" : "pbeWithSHAAnd128BitRC2-CBC",
|
||||
"06032a864886f70d010c0106" : "pbeWithSHAAnd40BitRC2-CBC",
|
||||
"06032a864886f70d010c0a" : "pkcs-12Version1",
|
||||
"06032a864886f70d010c0a01" : "pkcs-12BadIds",
|
||||
"06032a864886f70d010c0a0101" : "pkcs-12-keyBag",
|
||||
"06032a864886f70d010c0a0102" : "pkcs-12-pkcs-8ShroudedKeyBag",
|
||||
"06032a864886f70d010c0a0103" : "pkcs-12-certBag",
|
||||
"06032a864886f70d010c0a0104" : "pkcs-12-crlBag",
|
||||
"06032a864886f70d010c0a0105" : "pkcs-12-secretBag",
|
||||
"06032a864886f70d010c0a0106" : "pkcs-12-safeContentsBag",
|
||||
"06032a864886f70d010c02" : "pkcs-12-ESPVKID",
|
||||
"06032a864886f70d010c0201" : "pkcs-12-PKCS8KeyShrouding",
|
||||
"06032a864886f70d010c03" : "pkcs-12-BagIds",
|
||||
"06032a864886f70d010c0301" : "pkcs-12-keyBagId",
|
||||
"06032a864886f70d010c0302" : "pkcs-12-certAndCRLBagId",
|
||||
"06032a864886f70d010c0303" : "pkcs-12-secretBagId",
|
||||
"06032a864886f70d010c0304" : "pkcs-12-safeContentsId",
|
||||
"06032a864886f70d010c0305" : "pkcs-12-pkcs-8ShroudedKeyBagId",
|
||||
"06032a864886f70d010c04" : "pkcs-12-CertBagID",
|
||||
"06032a864886f70d010c0401" : "pkcs-12-X509CertCRLBagID",
|
||||
"06032a864886f70d010c0402" : "pkcs-12-SDSICertBagID",
|
||||
"06032a864886f70d010c05" : "pkcs-12-OID",
|
||||
"06032a864886f70d010c0501" : "pkcs-12-PBEID",
|
||||
"06032a864886f70d010c050101" : "pkcs-12-PBEWithSha1And128BitRC4",
|
||||
"06032a864886f70d010c050102" : "pkcs-12-PBEWithSha1And40BitRC4",
|
||||
"06032a864886f70d010c050103" : "pkcs-12-PBEWithSha1AndTripleDESCBC",
|
||||
"06032a864886f70d010c050104" : "pkcs-12-PBEWithSha1And128BitRC2CBC",
|
||||
"06032a864886f70d010c050105" : "pkcs-12-PBEWithSha1And40BitRC2CBC",
|
||||
"06032a864886f70d010c050106" : "pkcs-12-PBEWithSha1AndRC4",
|
||||
"06032a864886f70d010c050107" : "pkcs-12-PBEWithSha1AndRC2CBC",
|
||||
"06032a864886f70d010c0502" : "pkcs-12-EnvelopingID",
|
||||
"06032a864886f70d010c050201" : "pkcs-12-RSAEncryptionWith128BitRC4",
|
||||
"06032a864886f70d010c050202" : "pkcs-12-RSAEncryptionWith40BitRC4",
|
||||
"06032a864886f70d010c050203" : "pkcs-12-RSAEncryptionWithTripleDES",
|
||||
"06032a864886f70d010c0503" : "pkcs-12-SignatureID",
|
||||
"06032a864886f70d010c050301" : "pkcs-12-RSASignatureWithSHA1Digest",
|
||||
"06032a864886f70d0103" : "pkcs-3",
|
||||
"06032a864886f70d010301" : "dhKeyAgreement",
|
||||
"06032a864886f70d0105" : "pkcs-5",
|
||||
"06032a864886f70d010501" : "pbeWithMD2AndDES-CBC",
|
||||
"06032a864886f70d01050a" : "pbeWithSHAAndDES-CBC",
|
||||
"06032a864886f70d010503" : "pbeWithMD5AndDES-CBC",
|
||||
"06032a864886f70d010504" : "pbeWithMD2AndRC2-CBC",
|
||||
"06032a864886f70d010506" : "pbeWithMD5AndRC2-CBC",
|
||||
"06032a864886f70d010509" : "pbeWithMD5AndXOR",
|
||||
"06032a864886f70d0107" : "pkcs-7",
|
||||
"06032a864886f70d010701" : "data",
|
||||
"06032a864886f70d010702" : "signedData",
|
||||
"06032a864886f70d010703" : "envelopedData",
|
||||
"06032a864886f70d010704" : "signedAndEnvelopedData",
|
||||
"06032a864886f70d010705" : "digestData",
|
||||
"06032a864886f70d010706" : "encryptedData",
|
||||
"06032a864886f70d010707" : "dataWithAttributes",
|
||||
"06032a864886f70d010708" : "encryptedPrivateKeyInfo",
|
||||
"06032a864886f70d0109" : "pkcs-9",
|
||||
"06032a864886f70d010901" : "emailAddress",
|
||||
"06032a864886f70d01090a" : "issuerAndSerialNumber",
|
||||
"06032a864886f70d01090b" : "passwordCheck",
|
||||
"06032a864886f70d01090c" : "publicKey",
|
||||
"06032a864886f70d01090d" : "signingDescription",
|
||||
"06032a864886f70d01090e" : "extensionReq",
|
||||
"06032a864886f70d01090f" : "sMIMECapabilities",
|
||||
"06032a864886f70d01090f01" : "preferSignedData",
|
||||
"06032a864886f70d01090f02" : "canNotDecryptAny",
|
||||
"06032a864886f70d01090f03" : "receiptRequest",
|
||||
"06032a864886f70d01090f04" : "receipt",
|
||||
"06032a864886f70d01090f05" : "contentHints",
|
||||
"06032a864886f70d01090f06" : "mlExpansionHistory",
|
||||
"06032a864886f70d010910" : "id-sMIME",
|
||||
"06032a864886f70d01091000" : "id-mod",
|
||||
"06032a864886f70d0109100001" : "id-mod-cms",
|
||||
"06032a864886f70d0109100002" : "id-mod-ess",
|
||||
"06032a864886f70d01091001" : "id-ct",
|
||||
"06032a864886f70d0109100101" : "id-ct-receipt",
|
||||
"06032a864886f70d01091002" : "id-aa",
|
||||
"06032a864886f70d0109100201" : "id-aa-receiptRequest",
|
||||
"06032a864886f70d0109100202" : "id-aa-securityLabel",
|
||||
"06032a864886f70d0109100203" : "id-aa-mlExpandHistory",
|
||||
"06032a864886f70d0109100204" : "id-aa-contentHint",
|
||||
"06032a864886f70d010902" : "unstructuredName",
|
||||
"06032a864886f70d010914" : "friendlyName",
|
||||
"06032a864886f70d010915" : "localKeyID",
|
||||
"06032a864886f70d010916" : "certTypes",
|
||||
"06032a864886f70d01091601" : "x509Certificate",
|
||||
"06032a864886f70d01091602" : "sdsiCertificate",
|
||||
"06032a864886f70d010917" : "crlTypes",
|
||||
"06032a864886f70d01091701" : "x509Crl",
|
||||
"06032a864886f70d010903" : "contentType",
|
||||
"06032a864886f70d010904" : "messageDigest",
|
||||
"06032a864886f70d010905" : "signingTime",
|
||||
"06032a864886f70d010906" : "countersignature",
|
||||
"06032a864886f70d010907" : "challengePassword",
|
||||
"06032a864886f70d010908" : "unstructuredAddress",
|
||||
"06032a864886f70d010909" : "extendedCertificateAttributes",
|
||||
"06032a864886f70d02" : "digestAlgorithm",
|
||||
"06032a864886f70d0202" : "md2",
|
||||
"06032a864886f70d0204" : "md4",
|
||||
"06032a864886f70d0205" : "md5",
|
||||
"06032a864886f70d03" : "encryptionAlgorithm",
|
||||
"06032a864886f70d030a" : "desCDMF",
|
||||
"06032a864886f70d0302" : "rc2CBC",
|
||||
"06032a864886f70d0303" : "rc2ECB",
|
||||
"06032a864886f70d0304" : "rc4",
|
||||
"06032a864886f70d0305" : "rc4WithMAC",
|
||||
"06032a864886f70d0306" : "DESX-CBC",
|
||||
"06032a864886f70d0307" : "DES-EDE3-CBC",
|
||||
"06032a864886f70d0308" : "RC5CBC",
|
||||
"06032a864886f70d0309" : "RC5-CBCPad",
|
||||
"06032a864886f7140403" : "microsoftExcel",
|
||||
"06032a864886f7140404" : "titledWithOID",
|
||||
"06032a864886f7140405" : "microsoftPowerPoint",
|
||||
"06032b81051086480954" : "x9-84",
|
||||
"06032b8105108648095400" : "x9-84-Module",
|
||||
"06032b810510864809540001" : "x9-84-Biometrics",
|
||||
"06032b810510864809540002" : "x9-84-CMS",
|
||||
"06032b810510864809540003" : "x9-84-Identifiers",
|
||||
"06032b8105108648095401" : "biometric",
|
||||
"06032b810510864809540100" : "id-unknown-Type",
|
||||
"06032b810510864809540101" : "id-body-Odor",
|
||||
"06032b81051086480954010a" : "id-palm",
|
||||
"06032b81051086480954010b" : "id-retina",
|
||||
"06032b81051086480954010c" : "id-signature",
|
||||
"06032b81051086480954010d" : "id-speech-Pattern",
|
||||
"06032b81051086480954010e" : "id-thermal-Image",
|
||||
"06032b81051086480954010f" : "id-vein-Pattern",
|
||||
"06032b810510864809540110" : "id-thermal-Face-Image",
|
||||
"06032b810510864809540111" : "id-thermal-Hand-Image",
|
||||
"06032b810510864809540112" : "id-lip-Movement",
|
||||
"06032b810510864809540113" : "id-gait",
|
||||
"06032b810510864809540102" : "id-dna",
|
||||
"06032b810510864809540103" : "id-ear-Shape",
|
||||
"06032b810510864809540104" : "id-facial-Features",
|
||||
"06032b810510864809540105" : "id-finger-Image",
|
||||
"06032b810510864809540106" : "id-finger-Geometry",
|
||||
"06032b810510864809540107" : "id-hand-Geometry",
|
||||
"06032b810510864809540108" : "id-iris-Features",
|
||||
"06032b810510864809540109" : "id-keystroke-Dynamics",
|
||||
"06032b8105108648095402" : "processing-algorithm",
|
||||
"06032b8105108648095403" : "matching-method",
|
||||
"06032b8105108648095404" : "format-Owner",
|
||||
"06032b810510864809540400" : "cbeff-Owner",
|
||||
"06032b810510864809540401" : "ibia-Owner",
|
||||
"06032b81051086480954040101" : "id-ibia-SAFLINK",
|
||||
"06032b8105108648095404010a" : "id-ibia-SecuGen",
|
||||
"06032b8105108648095404010b" : "id-ibia-PreciseBiometric",
|
||||
"06032b8105108648095404010c" : "id-ibia-Identix",
|
||||
"06032b8105108648095404010d" : "id-ibia-DERMALOG",
|
||||
"06032b8105108648095404010e" : "id-ibia-LOGICO",
|
||||
"06032b8105108648095404010f" : "id-ibia-NIST",
|
||||
"06032b81051086480954040110" : "id-ibia-A3Vision",
|
||||
"06032b81051086480954040111" : "id-ibia-NEC",
|
||||
"06032b81051086480954040112" : "id-ibia-STMicroelectronics",
|
||||
"06032b81051086480954040102" : "id-ibia-Bioscrypt",
|
||||
"06032b81051086480954040103" : "id-ibia-Visionics",
|
||||
"06032b81051086480954040104" : "id-ibia-InfineonTechnologiesAG",
|
||||
"06032b81051086480954040105" : "id-ibia-IridianTechnologies",
|
||||
"06032b81051086480954040106" : "id-ibia-Veridicom",
|
||||
"06032b81051086480954040107" : "id-ibia-CyberSIGN",
|
||||
"06032b81051086480954040108" : "id-ibia-eCryp.",
|
||||
"06032b81051086480954040109" : "id-ibia-FingerprintCardsAB",
|
||||
"06032b810510864809540402" : "x9-Owner",
|
||||
"06032b0e021a05" : "sha",
|
||||
"06032b0e03020101" : "rsa",
|
||||
"06032b0e03020a" : "desMAC",
|
||||
"06032b0e03020b" : "rsaSignature",
|
||||
"06032b0e03020c" : "dsa",
|
||||
"06032b0e03020d" : "dsaWithSHA",
|
||||
"06032b0e03020e" : "mdc2WithRSASignature",
|
||||
"06032b0e03020f" : "shaWithRSASignature",
|
||||
"06032b0e030210" : "dhWithCommonModulus",
|
||||
"06032b0e030211" : "desEDE",
|
||||
"06032b0e030212" : "sha",
|
||||
"06032b0e030213" : "mdc-2",
|
||||
"06032b0e030202" : "md4WitRSA",
|
||||
"06032b0e03020201" : "sqmod-N",
|
||||
"06032b0e030214" : "dsaCommon",
|
||||
"06032b0e030215" : "dsaCommonWithSHA",
|
||||
"06032b0e030216" : "rsaKeyTransport",
|
||||
"06032b0e030217" : "keyed-hash-seal",
|
||||
"06032b0e030218" : "md2WithRSASignature",
|
||||
"06032b0e030219" : "md5WithRSASignature",
|
||||
"06032b0e03021a" : "sha1",
|
||||
"06032b0e03021b" : "dsaWithSHA1",
|
||||
"06032b0e03021c" : "dsaWithCommonSHA1",
|
||||
"06032b0e03021d" : "sha-1WithRSAEncryption",
|
||||
"06032b0e030203" : "md5WithRSA",
|
||||
"06032b0e03020301" : "sqmod-NwithRSA",
|
||||
"06032b0e030204" : "md4WithRSAEncryption",
|
||||
"06032b0e030206" : "desECB",
|
||||
"06032b0e030207" : "desCBC",
|
||||
"06032b0e030208" : "desOFB",
|
||||
"06032b0e030209" : "desCFB",
|
||||
"06032b0e030301" : "simple-strong-auth-mechanism",
|
||||
"06032b0e07020101" : "ElGamal",
|
||||
"06032b0e07020301" : "md2WithRSA",
|
||||
"06032b0e07020302" : "md2WithElGamal",
|
||||
"06032b2403" : "algorithm",
|
||||
"06032b240301" : "encryptionAlgorithm",
|
||||
"06032b24030101" : "des",
|
||||
"06032b240301010101" : "desECBPad",
|
||||
"06032b24030101010101" : "desECBPadISO",
|
||||
"06032b240301010201" : "desCBCPad",
|
||||
"06032b24030101020101" : "desCBCPadISO",
|
||||
"06032b24030102" : "idea",
|
||||
"06032b2403010201" : "ideaECB",
|
||||
"06032b240301020101" : "ideaECBPad",
|
||||
"06032b24030102010101" : "ideaECBPadISO",
|
||||
"06032b2403010202" : "ideaCBC",
|
||||
"06032b240301020201" : "ideaCBCPad",
|
||||
"06032b24030102020101" : "ideaCBCPadISO",
|
||||
"06032b2403010203" : "ideaOFB",
|
||||
"06032b2403010204" : "ideaCFB",
|
||||
"06032b24030103" : "des-3",
|
||||
"06032b240301030101" : "des-3ECBPad",
|
||||
"06032b24030103010101" : "des-3ECBPadISO",
|
||||
"06032b240301030201" : "des-3CBCPad",
|
||||
"06032b24030103020101" : "des-3CBCPadISO",
|
||||
"06032b240302" : "hashAlgorithm",
|
||||
"06032b24030201" : "ripemd160",
|
||||
"06032b24030202" : "ripemd128",
|
||||
"06032b24030203" : "ripemd256",
|
||||
"06032b24030204" : "mdc2singleLength",
|
||||
"06032b24030205" : "mdc2doubleLength",
|
||||
"06032b240303" : "signatureAlgorithm",
|
||||
"06032b24030301" : "rsa",
|
||||
"06032b2403030101" : "rsaMitSHA-1",
|
||||
"06032b2403030102" : "rsaMitRIPEMD160",
|
||||
"06032b24030302" : "ellipticCurve",
|
||||
"06032b240304" : "signatureScheme",
|
||||
"06032b24030401" : "iso9796-1",
|
||||
"06032b2403040201" : "iso9796-2",
|
||||
"06032b2403040202" : "iso9796-2rsa",
|
||||
"06032b2404" : "attribute",
|
||||
"06032b2405" : "policy",
|
||||
"06032b2406" : "api",
|
||||
"06032b240601" : "manufacturerSpecific",
|
||||
"06032b240602" : "functionalitySpecific",
|
||||
"06032b2407" : "api",
|
||||
"06032b240701" : "keyAgreement",
|
||||
"06032b240702" : "keyTransport",
|
||||
"06032b06010401927c0a0101" : "UNINETT policyIdentifier",
|
||||
"06032b0601040195180a" : "ICE-TEL policyIdentifier",
|
||||
"06032b0601040197552001" : "cryptlibEnvelope",
|
||||
"06032b0601040197552002" : "cryptlibPrivateKey",
|
||||
"060a2b060104018237" : "Microsoft OID",
|
||||
"060a2b0601040182370a" : "Crypto 2.0",
|
||||
"060a2b0601040182370a01" : "certTrustList",
|
||||
"060a2b0601040182370a0101" : "szOID_SORTED_CTL",
|
||||
"060a2b0601040182370a0a" : "Microsoft CMC OIDs",
|
||||
"060a2b0601040182370a0a01" : "szOID_CMC_ADD_ATTRIBUTES",
|
||||
"060a2b0601040182370a0b" : "Microsoft certificate property OIDs",
|
||||
"060a2b0601040182370a0b01" : "szOID_CERT_PROP_ID_PREFIX",
|
||||
"060a2b0601040182370a0c" : "CryptUI",
|
||||
"060a2b0601040182370a0c01" : "szOID_ANY_APPLICATION_POLICY",
|
||||
"060a2b0601040182370a02" : "nextUpdateLocation",
|
||||
"060a2b0601040182370a0301" : "certTrustListSigning",
|
||||
"060a2b0601040182370a030a" : "szOID_KP_QUALIFIED_SUBORDINATION",
|
||||
"060a2b0601040182370a030b" : "szOID_KP_KEY_RECOVERY",
|
||||
"060a2b0601040182370a030c" : "szOID_KP_DOCUMENT_SIGNING",
|
||||
"060a2b0601040182370a0302" : "timeStampSigning",
|
||||
"060a2b0601040182370a0303" : "serverGatedCrypto",
|
||||
"060a2b0601040182370a030301" : "szOID_SERIALIZED",
|
||||
"060a2b0601040182370a0304" : "encryptedFileSystem",
|
||||
"060a2b0601040182370a030401" : "szOID_EFS_RECOVERY",
|
||||
"060a2b0601040182370a0305" : "szOID_WHQL_CRYPTO",
|
||||
"060a2b0601040182370a0306" : "szOID_NT5_CRYPTO",
|
||||
"060a2b0601040182370a0307" : "szOID_OEM_WHQL_CRYPTO",
|
||||
"060a2b0601040182370a0308" : "szOID_EMBEDDED_NT_CRYPTO",
|
||||
"060a2b0601040182370a0309" : "szOID_ROOT_LIST_SIGNER",
|
||||
"060a2b0601040182370a0401" : "yesnoTrustAttr",
|
||||
"060a2b0601040182370a0501" : "szOID_DRM",
|
||||
"060a2b0601040182370a0502" : "szOID_DRM_INDIVIDUALIZATION",
|
||||
"060a2b0601040182370a0601" : "szOID_LICENSES",
|
||||
"060a2b0601040182370a0602" : "szOID_LICENSE_SERVER",
|
||||
"060a2b0601040182370a07" : "szOID_MICROSOFT_RDN_PREFIX",
|
||||
"060a2b0601040182370a0701" : "szOID_KEYID_RDN",
|
||||
"060a2b0601040182370a0801" : "szOID_REMOVE_CERTIFICATE",
|
||||
"060a2b0601040182370a0901" : "szOID_CROSS_CERT_DIST_POINTS",
|
||||
"060a2b0601040182370c" : "Catalog",
|
||||
"060a2b0601040182370c0101" : "szOID_CATALOG_LIST",
|
||||
"060a2b0601040182370c0102" : "szOID_CATALOG_LIST_MEMBER",
|
||||
"060a2b0601040182370c0201" : "CAT_NAMEVALUE_OBJID",
|
||||
"060a2b0601040182370c0202" : "CAT_MEMBERINFO_OBJID",
|
||||
"060a2b0601040182370d" : "Microsoft PKCS10 OIDs",
|
||||
"060a2b0601040182370d01" : "szOID_RENEWAL_CERTIFICATE",
|
||||
"060a2b0601040182370d0201" : "szOID_ENROLLMENT_NAME_VALUE_PAIR",
|
||||
"060a2b0601040182370d0202" : "szOID_ENROLLMENT_CSP_PROVIDER",
|
||||
"060a2b0601040182370d0203" : "OS Version",
|
||||
"060a2b0601040182370f" : "Microsoft Java",
|
||||
"060a2b06010401823710" : "Microsoft Outlook/Exchange",
|
||||
"060a2b0601040182371004" : "Outlook Express",
|
||||
"060a2b06010401823711" : "Microsoft PKCS12 attributes",
|
||||
"060a2b0601040182371101" : "szOID_LOCAL_MACHINE_KEYSET",
|
||||
"060a2b06010401823712" : "Microsoft Hydra",
|
||||
"060a2b06010401823713" : "Microsoft ISPU Test",
|
||||
"060a2b06010401823702" : "Authenticode",
|
||||
"060a2b06010401823702010a" : "spcAgencyInfo",
|
||||
"060a2b06010401823702010b" : "spcStatementType",
|
||||
"060a2b06010401823702010c" : "spcSpOpusInfo",
|
||||
"060a2b06010401823702010e" : "certExtensions",
|
||||
"060a2b06010401823702010f" : "spcPelmageData",
|
||||
"060a2b060104018237020112" : "SPC_RAW_FILE_DATA_OBJID",
|
||||
"060a2b060104018237020113" : "SPC_STRUCTURED_STORAGE_DATA_OBJID",
|
||||
"060a2b060104018237020114" : "spcLink",
|
||||
"060a2b060104018237020115" : "individualCodeSigning",
|
||||
"060a2b060104018237020116" : "commercialCodeSigning",
|
||||
"060a2b060104018237020119" : "spcLink",
|
||||
"060a2b06010401823702011a" : "spcMinimalCriteriaInfo",
|
||||
"060a2b06010401823702011b" : "spcFinancialCriteriaInfo",
|
||||
"060a2b06010401823702011c" : "spcLink",
|
||||
"060a2b06010401823702011d" : "SPC_HASH_INFO_OBJID",
|
||||
"060a2b06010401823702011e" : "SPC_SIPINFO_OBJID",
|
||||
"060a2b060104018237020104" : "spcIndirectDataContext",
|
||||
"060a2b0601040182370202" : "CTL for Software Publishers Trusted CAs",
|
||||
"060a2b060104018237020201" : "szOID_TRUSTED_CODESIGNING_CA_LIST",
|
||||
"060a2b060104018237020202" : "szOID_TRUSTED_CLIENT_AUTH_CA_LIST",
|
||||
"060a2b060104018237020203" : "szOID_TRUSTED_SERVER_AUTH_CA_LIST",
|
||||
"060a2b06010401823714" : "Microsoft Enrollment Infrastructure",
|
||||
"060a2b0601040182371401" : "szOID_AUTO_ENROLL_CTL_USAGE",
|
||||
"060a2b0601040182371402" : "szOID_ENROLL_CERTTYPE_EXTENSION",
|
||||
"060a2b060104018237140201" : "szOID_ENROLLMENT_AGENT",
|
||||
"060a2b060104018237140202" : "szOID_KP_SMARTCARD_LOGON",
|
||||
"060a2b060104018237140203" : "szOID_NT_PRINCIPAL_NAME",
|
||||
"060a2b0601040182371403" : "szOID_CERT_MANIFOLD",
|
||||
"06092b06010401823715" : "Microsoft CertSrv Infrastructure",
|
||||
"06092b0601040182371501" : "szOID_CERTSRV_CA_VERSION",
|
||||
"06092b0601040182371514" : "Client Information",
|
||||
"060a2b06010401823719" : "Microsoft Directory Service",
|
||||
"060a2b0601040182371901" : "szOID_NTDS_REPLICATION",
|
||||
"060a2b06010401823703" : "Time Stamping",
|
||||
"060a2b060104018237030201" : "SPC_TIME_STAMP_REQUEST_OBJID",
|
||||
"060a2b0601040182371e" : "IIS",
|
||||
"060a2b0601040182371f" : "Windows updates and service packs",
|
||||
"060a2b0601040182371f01" : "szOID_PRODUCT_UPDATE",
|
||||
"060a2b06010401823704" : "Permissions",
|
||||
"060a2b06010401823728" : "Fonts",
|
||||
"060a2b06010401823729" : "Microsoft Licensing and Registration",
|
||||
"060a2b0601040182372a" : "Microsoft Corporate PKI (ITG)",
|
||||
"060a2b06010401823758" : "CAPICOM",
|
||||
"060a2b0601040182375801" : "szOID_CAPICOM_VERSION",
|
||||
"060a2b0601040182375802" : "szOID_CAPICOM_ATTRIBUTE",
|
||||
"060a2b060104018237580201" : "szOID_CAPICOM_DOCUMENT_NAME",
|
||||
"060a2b060104018237580202" : "szOID_CAPICOM_DOCUMENT_DESCRIPTION",
|
||||
"060a2b0601040182375803" : "szOID_CAPICOM_ENCRYPTED_DATA",
|
||||
"060a2b060104018237580301" : "szOID_CAPICOM_ENCRYPTED_CONTENT",
|
||||
"06032b0601050507" : "pkix",
|
||||
"06032b060105050701" : "privateExtension",
|
||||
"06032b06010505070101" : "authorityInfoAccess",
|
||||
"06032b06010505070c02" : "CMC Data",
|
||||
"06032b060105050702" : "policyQualifierIds",
|
||||
// "06032b06010505070201" : "cps",
|
||||
"06032b06010505070202" : "unotice",
|
||||
"06032b060105050703" : "keyPurpose",
|
||||
"06032b06010505070301" : "serverAuth",
|
||||
"06032b06010505070302" : "clientAuth",
|
||||
"06032b06010505070303" : "codeSigning",
|
||||
"06032b06010505070304" : "emailProtection",
|
||||
"06032b06010505070305" : "ipsecEndSystem",
|
||||
"06032b06010505070306" : "ipsecTunnel",
|
||||
"06032b06010505070307" : "ipsecUser",
|
||||
"06032b06010505070308" : "timeStamping",
|
||||
"06032b060105050704" : "cmpInformationTypes",
|
||||
"06032b06010505070401" : "caProtEncCert",
|
||||
"06032b06010505070402" : "signKeyPairTypes",
|
||||
"06032b06010505070403" : "encKeyPairTypes",
|
||||
"06032b06010505070404" : "preferredSymmAlg",
|
||||
"06032b06010505070405" : "caKeyUpdateInfo",
|
||||
"06032b06010505070406" : "currentCRL",
|
||||
"06032b06010505073001" : "ocsp",
|
||||
"06032b06010505073002" : "caIssuers",
|
||||
"06032b06010505080101" : "HMAC-MD5",
|
||||
"06032b06010505080102" : "HMAC-SHA",
|
||||
"060360864801650201010a" : "mosaicKeyManagementAlgorithm",
|
||||
"060360864801650201010b" : "sdnsKMandSigAlgorithm",
|
||||
"060360864801650201010c" : "mosaicKMandSigAlgorithm",
|
||||
"060360864801650201010d" : "SuiteASignatureAlgorithm",
|
||||
"060360864801650201010e" : "SuiteAConfidentialityAlgorithm",
|
||||
"060360864801650201010f" : "SuiteAIntegrityAlgorithm",
|
||||
"06036086480186f84201" : "cert-extension",
|
||||
// "06036086480186f8420101" : "netscape-cert-type",
|
||||
"06036086480186f842010a" : "EntityLogo",
|
||||
"06036086480186f842010b" : "UserPicture",
|
||||
// "06036086480186f842010c" : "netscape-ssl-server-name",
|
||||
// "06036086480186f842010d" : "netscape-comment",
|
||||
// "06036086480186f8420102" : "netscape-base-url",
|
||||
// "06036086480186f8420103" : "netscape-revocation-url",
|
||||
// "06036086480186f8420104" : "netscape-ca-revocation-url",
|
||||
// "06036086480186f8420107" : "netscape-cert-renewal-url",
|
||||
// "06036086480186f8420108" : "netscape-ca-policy-url",
|
||||
"06036086480186f8420109" : "HomePage-url",
|
||||
"06036086480186f84202" : "data-type",
|
||||
"06036086480186f8420201" : "GIF",
|
||||
"06036086480186f8420202" : "JPEG",
|
||||
"06036086480186f8420203" : "URL",
|
||||
"06036086480186f8420204" : "HTML",
|
||||
"06036086480186f8420205" : "netscape-cert-sequence",
|
||||
"06036086480186f8420206" : "netscape-cert-url",
|
||||
"06036086480186f84203" : "directory",
|
||||
"06036086480186f8420401" : "serverGatedCrypto",
|
||||
"06036086480186f845010603" : "Unknown Verisign extension",
|
||||
"06036086480186f845010606" : "Unknown Verisign extension",
|
||||
"06036086480186f84501070101" : "Verisign certificatePolicy",
|
||||
"06036086480186f8450107010101" : "Unknown Verisign policy qualifier",
|
||||
"06036086480186f8450107010102" : "Unknown Verisign policy qualifier",
|
||||
"0603678105" : "TCPA",
|
||||
"060367810501" : "tcpaSpecVersion",
|
||||
"060367810502" : "tcpaAttribute",
|
||||
"06036781050201" : "tcpaAtTpmManufacturer",
|
||||
"0603678105020a" : "tcpaAtSecurityQualities",
|
||||
"0603678105020b" : "tcpaAtTpmProtectionProfile",
|
||||
"0603678105020c" : "tcpaAtTpmSecurityTarget",
|
||||
"0603678105020d" : "tcpaAtFoundationProtectionProfile",
|
||||
"0603678105020e" : "tcpaAtFoundationSecurityTarget",
|
||||
"0603678105020f" : "tcpaAtTpmIdLabel",
|
||||
"06036781050202" : "tcpaAtTpmModel",
|
||||
"06036781050203" : "tcpaAtTpmVersion",
|
||||
"06036781050204" : "tcpaAtPlatformManufacturer",
|
||||
"06036781050205" : "tcpaAtPlatformModel",
|
||||
"06036781050206" : "tcpaAtPlatformVersion",
|
||||
"06036781050207" : "tcpaAtComponentManufacturer",
|
||||
"06036781050208" : "tcpaAtComponentModel",
|
||||
"06036781050209" : "tcpaAtComponentVersion",
|
||||
"060367810503" : "tcpaProtocol",
|
||||
"06036781050301" : "tcpaPrttTpmIdProtocol",
|
||||
"0603672a00" : "contentType",
|
||||
"0603672a0000" : "PANData",
|
||||
"0603672a0001" : "PANToken",
|
||||
"0603672a0002" : "PANOnly",
|
||||
"0603672a01" : "msgExt",
|
||||
"0603672a0a" : "national",
|
||||
"0603672a0a8140" : "Japan",
|
||||
"0603672a02" : "field",
|
||||
"0603672a0200" : "fullName",
|
||||
"0603672a0201" : "givenName",
|
||||
"0603672a020a" : "amount",
|
||||
"0603672a0202" : "familyName",
|
||||
"0603672a0203" : "birthFamilyName",
|
||||
"0603672a0204" : "placeName",
|
||||
"0603672a0205" : "identificationNumber",
|
||||
"0603672a0206" : "month",
|
||||
"0603672a0207" : "date",
|
||||
"0603672a02070b" : "accountNumber",
|
||||
"0603672a02070c" : "passPhrase",
|
||||
"0603672a0208" : "address",
|
||||
"0603672a0209" : "telephone",
|
||||
"0603672a03" : "attribute",
|
||||
"0603672a0300" : "cert",
|
||||
"0603672a030000" : "rootKeyThumb",
|
||||
"0603672a030001" : "additionalPolicy",
|
||||
"0603672a04" : "algorithm",
|
||||
"0603672a05" : "policy",
|
||||
"0603672a0500" : "root",
|
||||
"0603672a06" : "module",
|
||||
"0603672a07" : "certExt",
|
||||
"0603672a0700" : "hashedRootKey",
|
||||
"0603672a0701" : "certificateType",
|
||||
"0603672a0702" : "merchantData",
|
||||
"0603672a0703" : "cardCertRequired",
|
||||
"0603672a0704" : "tunneling",
|
||||
"0603672a0705" : "setExtensions",
|
||||
"0603672a0706" : "setQualifier",
|
||||
"0603672a08" : "brand",
|
||||
"0603672a0801" : "IATA-ATA",
|
||||
"0603672a081e" : "Diners",
|
||||
"0603672a0822" : "AmericanExpress",
|
||||
"0603672a0804" : "VISA",
|
||||
"0603672a0805" : "MasterCard",
|
||||
"0603672a08ae7b" : "Novus",
|
||||
"0603672a09" : "vendor",
|
||||
"0603672a0900" : "GlobeSet",
|
||||
"0603672a0901" : "IBM",
|
||||
"0603672a090a" : "Griffin",
|
||||
"0603672a090b" : "Certicom",
|
||||
"0603672a090c" : "OSS",
|
||||
"0603672a090d" : "TenthMountain",
|
||||
"0603672a090e" : "Antares",
|
||||
"0603672a090f" : "ECC",
|
||||
"0603672a0910" : "Maithean",
|
||||
"0603672a0911" : "Netscape",
|
||||
"0603672a0912" : "Verisign",
|
||||
"0603672a0913" : "BlueMoney",
|
||||
"0603672a0902" : "CyberCash",
|
||||
"0603672a0914" : "Lacerte",
|
||||
"0603672a0915" : "Fujitsu",
|
||||
"0603672a0916" : "eLab",
|
||||
"0603672a0917" : "Entrust",
|
||||
"0603672a0918" : "VIAnet",
|
||||
"0603672a0919" : "III",
|
||||
"0603672a091a" : "OpenMarket",
|
||||
"0603672a091b" : "Lexem",
|
||||
"0603672a091c" : "Intertrader",
|
||||
"0603672a091d" : "Persimmon",
|
||||
"0603672a0903" : "Terisa",
|
||||
"0603672a091e" : "NABLE",
|
||||
"0603672a091f" : "espace-net",
|
||||
"0603672a0920" : "Hitachi",
|
||||
"0603672a0921" : "Microsoft",
|
||||
"0603672a0922" : "NEC",
|
||||
"0603672a0923" : "Mitsubishi",
|
||||
"0603672a0924" : "NCR",
|
||||
"0603672a0925" : "e-COMM",
|
||||
"0603672a0926" : "Gemplus",
|
||||
"0603672a0904" : "RSADSI",
|
||||
"0603672a0905" : "VeriFone",
|
||||
"0603672a0906" : "TrinTech",
|
||||
"0603672a0907" : "BankGate",
|
||||
"0603672a0908" : "GTE",
|
||||
"0603672a0909" : "CompuSource",
|
||||
"0603551d01" : "authorityKeyIdentifier",
|
||||
"0603551d0a" : "basicConstraints",
|
||||
"0603551d0b" : "nameConstraints",
|
||||
"0603551d0c" : "policyConstraints",
|
||||
"0603551d0d" : "basicConstraints",
|
||||
"0603551d0e" : "subjectKeyIdentifier",
|
||||
"0603551d0f" : "keyUsage",
|
||||
"0603551d10" : "privateKeyUsagePeriod",
|
||||
"0603551d11" : "subjectAltName",
|
||||
"0603551d12" : "issuerAltName",
|
||||
"0603551d13" : "basicConstraints",
|
||||
"0603551d02" : "keyAttributes",
|
||||
"0603551d14" : "cRLNumber",
|
||||
"0603551d15" : "cRLReason",
|
||||
"0603551d16" : "expirationDate",
|
||||
"0603551d17" : "instructionCode",
|
||||
"0603551d18" : "invalidityDate",
|
||||
"0603551d1a" : "issuingDistributionPoint",
|
||||
"0603551d1b" : "deltaCRLIndicator",
|
||||
"0603551d1c" : "issuingDistributionPoint",
|
||||
"0603551d1d" : "certificateIssuer",
|
||||
"0603551d03" : "certificatePolicies",
|
||||
"0603551d1e" : "nameConstraints",
|
||||
"0603551d1f" : "cRLDistributionPoints",
|
||||
"0603551d20" : "certificatePolicies",
|
||||
"0603551d21" : "policyMappings",
|
||||
"0603551d22" : "policyConstraints",
|
||||
"0603551d23" : "authorityKeyIdentifier",
|
||||
"0603551d24" : "policyConstraints",
|
||||
"0603551d25" : "extKeyUsage",
|
||||
"0603551d04" : "keyUsageRestriction",
|
||||
"0603551d05" : "policyMapping",
|
||||
"0603551d06" : "subtreesConstraint",
|
||||
"0603551d07" : "subjectAltName",
|
||||
"0603551d08" : "issuerAltName",
|
||||
"0603551d09" : "subjectDirectoryAttributes",
|
||||
"0603550400" : "objectClass",
|
||||
"0603550401" : "aliasObjectName",
|
||||
// "060355040c" : "title",
|
||||
"060355040d" : "description",
|
||||
"060355040e" : "searchGuide",
|
||||
"060355040f" : "businessCategory",
|
||||
"0603550410" : "postalAddress",
|
||||
"0603550411" : "postalCode",
|
||||
"0603550412" : "postOfficeBox",
|
||||
"0603550413" : "physicalDeliveryOfficeName",
|
||||
"0603550402" : "knowledgeInformation",
|
||||
// "0603550414" : "telephoneNumber",
|
||||
"0603550415" : "telexNumber",
|
||||
"0603550416" : "teletexTerminalIdentifier",
|
||||
"0603550417" : "facsimileTelephoneNumber",
|
||||
"0603550418" : "x121Address",
|
||||
"0603550419" : "internationalISDNNumber",
|
||||
"060355041a" : "registeredAddress",
|
||||
"060355041b" : "destinationIndicator",
|
||||
"060355041c" : "preferredDeliveryMehtod",
|
||||
"060355041d" : "presentationAddress",
|
||||
"060355041e" : "supportedApplicationContext",
|
||||
"060355041f" : "member",
|
||||
"0603550420" : "owner",
|
||||
"0603550421" : "roleOccupant",
|
||||
"0603550422" : "seeAlso",
|
||||
"0603550423" : "userPassword",
|
||||
"0603550424" : "userCertificate",
|
||||
"0603550425" : "caCertificate",
|
||||
"0603550426" : "authorityRevocationList",
|
||||
"0603550427" : "certificateRevocationList",
|
||||
"0603550428" : "crossCertificatePair",
|
||||
"0603550429" : "givenName",
|
||||
// "060355042a" : "givenName",
|
||||
"0603550405" : "serialNumber",
|
||||
"0603550434" : "supportedAlgorithms",
|
||||
"0603550435" : "deltaRevocationList",
|
||||
"060355043a" : "crossCertificatePair",
|
||||
// "0603550409" : "streetAddress",
|
||||
"06035508" : "X.500-Algorithms",
|
||||
"0603550801" : "X.500-Alg-Encryption",
|
||||
"060355080101" : "rsa",
|
||||
"0603604c0101" : "DPC"
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ const Punycode = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToAscii: function(input, args) {
|
||||
var idn = args[0];
|
||||
const idn = args[0];
|
||||
|
||||
if (idn) {
|
||||
return punycode.toASCII(input);
|
||||
@@ -44,7 +44,7 @@ const Punycode = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runToUnicode: function(input, args) {
|
||||
var idn = args[0];
|
||||
const idn = args[0];
|
||||
|
||||
if (idn) {
|
||||
return punycode.toUnicode(input);
|
||||
|
||||
@@ -40,7 +40,7 @@ const QuotedPrintable = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function (input, args) {
|
||||
var mimeEncodedStr = QuotedPrintable.mimeEncode(input);
|
||||
let mimeEncodedStr = QuotedPrintable.mimeEncode(input);
|
||||
|
||||
// fix line breaks
|
||||
mimeEncodedStr = mimeEncodedStr.replace(/\r?\n|\r/g, function() {
|
||||
@@ -61,7 +61,7 @@ const QuotedPrintable = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function (input, args) {
|
||||
var str = input.replace(/\=(?:\r?\n|$)/g, "");
|
||||
const str = input.replace(/=(?:\r?\n|$)/g, "");
|
||||
return QuotedPrintable.mimeDecode(str);
|
||||
},
|
||||
|
||||
@@ -73,13 +73,13 @@ const QuotedPrintable = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
mimeDecode: function(str) {
|
||||
var encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length,
|
||||
let encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length,
|
||||
bufferLength = str.length - encodedBytesCount * 2,
|
||||
chr, hex,
|
||||
buffer = new Array(bufferLength),
|
||||
bufferPos = 0;
|
||||
|
||||
for (var i = 0, len = str.length; i < len; i++) {
|
||||
for (let i = 0, len = str.length; i < len; i++) {
|
||||
chr = str.charAt(i);
|
||||
if (chr === "=" && (hex = str.substr(i + 1, 2)) && /[\da-fA-F]{2}/.test(hex)) {
|
||||
buffer[bufferPos++] = parseInt(hex, 16);
|
||||
@@ -100,7 +100,7 @@ const QuotedPrintable = {
|
||||
* @returns {string}
|
||||
*/
|
||||
mimeEncode: function(buffer) {
|
||||
var ranges = [
|
||||
let ranges = [
|
||||
[0x09],
|
||||
[0x0A],
|
||||
[0x0D],
|
||||
@@ -113,7 +113,7 @@ const QuotedPrintable = {
|
||||
],
|
||||
result = "";
|
||||
|
||||
for (var i = 0, len = buffer.length; i < len; i++) {
|
||||
for (let i = 0, len = buffer.length; i < len; i++) {
|
||||
if (this._checkRanges(buffer[i], ranges)) {
|
||||
result += String.fromCharCode(buffer[i]);
|
||||
continue;
|
||||
@@ -134,7 +134,7 @@ const QuotedPrintable = {
|
||||
* @returns {bolean}
|
||||
*/
|
||||
_checkRanges: function(nr, ranges) {
|
||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
||||
for (let i = ranges.length - 1; i >= 0; i--) {
|
||||
if (!ranges[i].length)
|
||||
continue;
|
||||
if (ranges[i].length === 1 && nr === ranges[i][0])
|
||||
@@ -157,7 +157,7 @@ const QuotedPrintable = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_addSoftLinebreaks: function(str, encoding) {
|
||||
var lineLengthMax = 76;
|
||||
const lineLengthMax = 76;
|
||||
|
||||
encoding = (encoding || "base64").toString().toLowerCase().trim();
|
||||
|
||||
@@ -192,7 +192,7 @@ const QuotedPrintable = {
|
||||
* @returns {string}
|
||||
*/
|
||||
_addQPSoftLinebreaks: function(mimeEncodedStr, lineLengthMax) {
|
||||
var pos = 0,
|
||||
let pos = 0,
|
||||
len = mimeEncodedStr.length,
|
||||
match, code, line,
|
||||
lineMargin = Math.floor(lineLengthMax / 3),
|
||||
@@ -219,21 +219,21 @@ const QuotedPrintable = {
|
||||
result += line;
|
||||
pos += line.length;
|
||||
continue;
|
||||
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t\.,!\?][^ \t\.,!\?]*$/))) {
|
||||
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t.,!?][^ \t.,!?]*$/))) {
|
||||
// truncate to nearest space
|
||||
line = line.substr(0, line.length - (match[0].length - 1));
|
||||
} else if (line.substr(-1) === "\r") {
|
||||
line = line.substr(0, line.length - 1);
|
||||
} else {
|
||||
if (line.match(/\=[\da-f]{0,2}$/i)) {
|
||||
if (line.match(/=[\da-f]{0,2}$/i)) {
|
||||
|
||||
// push incomplete encoding sequences to the next line
|
||||
if ((match = line.match(/\=[\da-f]{0,1}$/i))) {
|
||||
if ((match = line.match(/=[\da-f]{0,1}$/i))) {
|
||||
line = line.substr(0, line.length - match[0].length);
|
||||
}
|
||||
|
||||
// ensure that utf-8 sequences are not split
|
||||
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/ig))) {
|
||||
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/=[\da-f]{2}$/ig))) {
|
||||
code = parseInt(match[0].substr(1, 2), 16);
|
||||
if (code < 128) {
|
||||
break;
|
||||
@@ -250,7 +250,7 @@ const QuotedPrintable = {
|
||||
}
|
||||
|
||||
if (pos + line.length < len && line.substr(-1) !== "\n") {
|
||||
if (line.length === 76 && line.match(/\=[\da-f]{2}$/i)) {
|
||||
if (line.length === 76 && line.match(/=[\da-f]{2}$/i)) {
|
||||
line = line.substr(0, line.length - 3);
|
||||
} else if (line.length === 76) {
|
||||
line = line.substr(0, line.length - 1);
|
||||
|
||||
278
src/core/operations/Regex.js
Normal file
278
src/core/operations/Regex.js
Normal file
@@ -0,0 +1,278 @@
|
||||
import XRegExp from "xregexp";
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Regex operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Regex = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_PRE_POPULATE: [
|
||||
{
|
||||
name: "User defined",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "IPv4 address",
|
||||
value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?"
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
|
||||
},
|
||||
{
|
||||
name: "Email address",
|
||||
value: "(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})"
|
||||
},
|
||||
{
|
||||
name: "URL",
|
||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||
},
|
||||
{
|
||||
name: "Domain",
|
||||
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
|
||||
},
|
||||
{
|
||||
name: "Windows file path",
|
||||
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)~]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
|
||||
},
|
||||
{
|
||||
name: "UNIX file path",
|
||||
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
|
||||
},
|
||||
{
|
||||
name: "MAC address",
|
||||
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
|
||||
},
|
||||
{
|
||||
name: "Date (yyyy-mm-dd)",
|
||||
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
|
||||
},
|
||||
{
|
||||
name: "Date (dd/mm/yyyy)",
|
||||
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Date (mm/dd/yyyy)",
|
||||
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Strings",
|
||||
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISPLAY_TOTAL: false,
|
||||
|
||||
/**
|
||||
* Regular expression operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runRegex: function(input, args) {
|
||||
const userRegex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
s = args[4],
|
||||
u = args[5],
|
||||
a = args[6],
|
||||
displayTotal = args[7],
|
||||
outputFormat = args[8];
|
||||
let modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
if (s) modifiers += "s";
|
||||
if (u) modifiers += "u";
|
||||
if (a) modifiers += "A";
|
||||
|
||||
if (userRegex && userRegex !== "^" && userRegex !== "$") {
|
||||
try {
|
||||
const regex = new XRegExp(userRegex, modifiers);
|
||||
|
||||
switch (outputFormat) {
|
||||
case "Highlight matches":
|
||||
return Regex._regexHighlight(input, regex, displayTotal);
|
||||
case "List matches":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
}
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
} else {
|
||||
return Utils.escapeHtml(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_GLOBAL: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_CASE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_MULTILINE: true,
|
||||
|
||||
/**
|
||||
* Find / Replace operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFindReplace: function(input, args) {
|
||||
let find = args[0].string,
|
||||
type = args[0].option,
|
||||
replace = args[1],
|
||||
g = args[2],
|
||||
i = args[3],
|
||||
m = args[4],
|
||||
modifiers = "";
|
||||
|
||||
if (g) modifiers += "g";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (type === "Regex") {
|
||||
find = new RegExp(find, modifiers);
|
||||
return input.replace(find, replace);
|
||||
}
|
||||
|
||||
if (type.indexOf("Extended") === 0) {
|
||||
find = Utils.parseEscapedChars(find);
|
||||
}
|
||||
|
||||
find = new RegExp(Utils.escapeRegex(find), modifiers);
|
||||
|
||||
return input.replace(find, replace);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds HTML highlights to matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexHighlight: function(input, regex, displayTotal) {
|
||||
let output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (m.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
}
|
||||
|
||||
// Add up to match
|
||||
output += Utils.escapeHtml(input.slice(i, m.index));
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
|
||||
// Switch highlight
|
||||
hl = hl === 1 ? 2 : 1;
|
||||
|
||||
i = regex.lastIndex;
|
||||
total++;
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += Utils.escapeHtml(input.slice(i, input.length));
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string listing the matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @param {boolean} matches - Display full match
|
||||
* @param {boolean} captureGroups - Display each of the capture groups separately
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexList: function(input, regex, displayTotal, matches, captureGroups) {
|
||||
let output = "",
|
||||
total = 0,
|
||||
match;
|
||||
|
||||
while ((match = regex.exec(input))) {
|
||||
// Moves pointer when an empty string is matched (prevents infinite loop)
|
||||
if (match.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
}
|
||||
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (captureGroups) {
|
||||
for (let i = 1; i < match.length; i++) {
|
||||
if (matches) {
|
||||
output += " Group " + i + ": ";
|
||||
}
|
||||
output += match[i] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output.slice(0, -1);
|
||||
},
|
||||
};
|
||||
|
||||
export default Regex;
|
||||
@@ -20,7 +20,7 @@ const Rotate = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ROTATE_WHOLE: false,
|
||||
ROTATE_CARRY: false,
|
||||
|
||||
/**
|
||||
* Runs rotation operations across the input data.
|
||||
@@ -32,10 +32,10 @@ const Rotate = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_rot: function(data, amount, algo) {
|
||||
var result = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var b = data[i];
|
||||
for (var j = 0; j < amount; j++) {
|
||||
const result = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let b = data[i];
|
||||
for (let j = 0; j < amount; j++) {
|
||||
b = algo(b);
|
||||
}
|
||||
result.push(b);
|
||||
@@ -53,7 +53,7 @@ const Rotate = {
|
||||
*/
|
||||
runRotr: function(input, args) {
|
||||
if (args[1]) {
|
||||
return Rotate._rotrWhole(input, args[0]);
|
||||
return Rotate._rotrCarry(input, args[0]);
|
||||
} else {
|
||||
return Rotate._rot(input, args[0], Rotate._rotr);
|
||||
}
|
||||
@@ -69,7 +69,7 @@ const Rotate = {
|
||||
*/
|
||||
runRotl: function(input, args) {
|
||||
if (args[1]) {
|
||||
return Rotate._rotlWhole(input, args[0]);
|
||||
return Rotate._rotlCarry(input, args[0]);
|
||||
} else {
|
||||
return Rotate._rot(input, args[0], Rotate._rotl);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ const Rotate = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRot13: function(input, args) {
|
||||
var amount = args[2],
|
||||
let amount = args[2],
|
||||
output = input,
|
||||
chr,
|
||||
rot13Lowercase = args[0],
|
||||
@@ -111,7 +111,7 @@ const Rotate = {
|
||||
amount = 26 - (Math.abs(amount) % 26);
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
chr = input[i];
|
||||
if (rot13Upperacse && chr >= 65 && chr <= 90) { // Upper case
|
||||
chr = (chr - 65 + amount) % 26;
|
||||
@@ -135,13 +135,13 @@ const Rotate = {
|
||||
/**
|
||||
* ROT47 operation.
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.pw]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRot47: function(input, args) {
|
||||
var amount = args[0],
|
||||
let amount = args[0],
|
||||
output = input,
|
||||
chr;
|
||||
|
||||
@@ -150,7 +150,7 @@ const Rotate = {
|
||||
amount = 94 - (Math.abs(amount) % 94);
|
||||
}
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
chr = input[i];
|
||||
if (chr >= 33 && chr <= 126) {
|
||||
chr = (chr - 33 + amount) % 94;
|
||||
@@ -170,7 +170,7 @@ const Rotate = {
|
||||
* @returns {byte}
|
||||
*/
|
||||
_rotr: function(b) {
|
||||
var bit = (b & 1) << 7;
|
||||
const bit = (b & 1) << 7;
|
||||
return (b >> 1) | bit;
|
||||
},
|
||||
|
||||
@@ -183,7 +183,7 @@ const Rotate = {
|
||||
* @returns {byte}
|
||||
*/
|
||||
_rotl: function(b) {
|
||||
var bit = (b >> 7) & 1;
|
||||
const bit = (b >> 7) & 1;
|
||||
return ((b << 1) | bit) & 0xFF;
|
||||
},
|
||||
|
||||
@@ -197,14 +197,14 @@ const Rotate = {
|
||||
* @param {number} amount
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_rotrWhole: function(data, amount) {
|
||||
var carryBits = 0,
|
||||
_rotrCarry: function(data, amount) {
|
||||
let carryBits = 0,
|
||||
newByte,
|
||||
result = [];
|
||||
|
||||
amount = amount % 8;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var oldByte = data[i] >>> 0;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const oldByte = data[i] >>> 0;
|
||||
newByte = (oldByte >> amount) | carryBits;
|
||||
carryBits = (oldByte & (Math.pow(2, amount)-1)) << (8-amount);
|
||||
result.push(newByte);
|
||||
@@ -223,14 +223,14 @@ const Rotate = {
|
||||
* @param {number} amount
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
_rotlWhole: function(data, amount) {
|
||||
var carryBits = 0,
|
||||
_rotlCarry: function(data, amount) {
|
||||
let carryBits = 0,
|
||||
newByte,
|
||||
result = [];
|
||||
|
||||
amount = amount % 8;
|
||||
for (var i = data.length-1; i >= 0; i--) {
|
||||
var oldByte = data[i];
|
||||
for (let i = data.length-1; i >= 0; i--) {
|
||||
const oldByte = data[i];
|
||||
newByte = ((oldByte << amount) | carryBits) & 0xFF;
|
||||
carryBits = (oldByte >> (8-amount)) & (Math.pow(2, amount)-1);
|
||||
result[i] = (newByte);
|
||||
|
||||
@@ -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.
|
||||
@@ -36,7 +36,7 @@ const SeqUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSort: function (input, args) {
|
||||
var delim = Utils.charRep[args[0]],
|
||||
let delim = Utils.charRep[args[0]],
|
||||
sortReverse = args[1],
|
||||
order = args[2],
|
||||
sorted = input.split(delim);
|
||||
@@ -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();
|
||||
@@ -62,7 +64,7 @@ const SeqUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runUnique: function (input, args) {
|
||||
var delim = Utils.charRep[args[0]];
|
||||
const delim = Utils.charRep[args[0]];
|
||||
return input.split(delim).unique().join(delim);
|
||||
},
|
||||
|
||||
@@ -81,12 +83,12 @@ const SeqUtils = {
|
||||
* @returns {number}
|
||||
*/
|
||||
runCount: function(input, args) {
|
||||
var search = args[0].string,
|
||||
let search = args[0].string,
|
||||
type = args[0].option;
|
||||
|
||||
if (type === "Regex" && search) {
|
||||
try {
|
||||
var regex = new RegExp(search, "gi"),
|
||||
let regex = new RegExp(search, "gi"),
|
||||
matches = input.match(regex);
|
||||
return matches.length;
|
||||
} catch (err) {
|
||||
@@ -117,11 +119,12 @@ const SeqUtils = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runReverse: function (input, args) {
|
||||
let i;
|
||||
if (args[0] === "Line") {
|
||||
var lines = [],
|
||||
let lines = [],
|
||||
line = [],
|
||||
result = [];
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (i = 0; i < input.length; i++) {
|
||||
if (input[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
@@ -150,12 +153,12 @@ const SeqUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runAddLineNumbers: function(input, args) {
|
||||
var lines = input.split("\n"),
|
||||
let lines = input.split("\n"),
|
||||
output = "",
|
||||
width = lines.length.toString().length;
|
||||
|
||||
for (var n = 0; n < lines.length; n++) {
|
||||
output += Utils.pad((n+1).toString(), width, " ") + " " + lines[n] + "\n";
|
||||
for (let n = 0; n < lines.length; n++) {
|
||||
output += (n+1).toString().padStart(width, " ") + " " + lines[n] + "\n";
|
||||
}
|
||||
return output.slice(0, output.length-1);
|
||||
},
|
||||
@@ -207,7 +210,7 @@ const SeqUtils = {
|
||||
* @returns {number}
|
||||
*/
|
||||
_ipSort: function(a, b) {
|
||||
var a_ = a.split("."),
|
||||
let a_ = a.split("."),
|
||||
b_ = b.split(".");
|
||||
|
||||
a_ = a_[0] * 0x1000000 + a_[1] * 0x10000 + a_[2] * 0x100 + a_[3] * 1;
|
||||
@@ -220,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 a.localeCompare(b);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default SeqUtils;
|
||||
|
||||
96
src/core/operations/Shellcode.js
Normal file
96
src/core/operations/Shellcode.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import disassemble from "../lib/DisassembleX86-64.js";
|
||||
|
||||
|
||||
/**
|
||||
* Shellcode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Shellcode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MODE: ["64", "32", "16"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
COMPATIBILITY: [
|
||||
"Full x86 architecture",
|
||||
"Knights Corner",
|
||||
"Larrabee",
|
||||
"Cyrix",
|
||||
"Geode",
|
||||
"Centaur",
|
||||
"X86/486"
|
||||
],
|
||||
|
||||
/**
|
||||
* Disassemble x86 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDisassemble: function(input, args) {
|
||||
const mode = args[0],
|
||||
compatibility = args[1],
|
||||
codeSegment = args[2],
|
||||
offset = args[3],
|
||||
showInstructionHex = args[4],
|
||||
showInstructionPos = args[5];
|
||||
|
||||
switch (mode) {
|
||||
case "64":
|
||||
disassemble.setBitMode(2);
|
||||
break;
|
||||
case "32":
|
||||
disassemble.setBitMode(1);
|
||||
break;
|
||||
case "16":
|
||||
disassemble.setBitMode(0);
|
||||
break;
|
||||
default:
|
||||
throw "Invalid mode value";
|
||||
}
|
||||
|
||||
switch (compatibility) {
|
||||
case "Full x86 architecture":
|
||||
disassemble.CompatibilityMode(0);
|
||||
break;
|
||||
case "Knights Corner":
|
||||
disassemble.CompatibilityMode(1);
|
||||
break;
|
||||
case "Larrabee":
|
||||
disassemble.CompatibilityMode(2);
|
||||
break;
|
||||
case "Cyrix":
|
||||
disassemble.CompatibilityMode(3);
|
||||
break;
|
||||
case "Geode":
|
||||
disassemble.CompatibilityMode(4);
|
||||
break;
|
||||
case "Centaur":
|
||||
disassemble.CompatibilityMode(5);
|
||||
break;
|
||||
case "X86/486":
|
||||
disassemble.CompatibilityMode(6);
|
||||
break;
|
||||
}
|
||||
|
||||
disassemble.SetBasePosition(codeSegment + ":" + offset);
|
||||
disassemble.setShowInstructionHex(showInstructionHex);
|
||||
disassemble.setShowInstructionPos(showInstructionPos);
|
||||
disassemble.LoadBinCode(input.replace(/\s/g, ""));
|
||||
return disassemble.LDisassemble();
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Shellcode;
|
||||
@@ -1,5 +1,4 @@
|
||||
import Utils from "../Utils.js";
|
||||
import * as JsDiff from "diff";
|
||||
|
||||
|
||||
/**
|
||||
@@ -13,128 +12,6 @@ import * as JsDiff from "diff";
|
||||
*/
|
||||
const StrUtils = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_PRE_POPULATE: [
|
||||
{
|
||||
name: "User defined",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "IPv4 address",
|
||||
value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?"
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
|
||||
},
|
||||
{
|
||||
name: "Email address",
|
||||
value: "(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})"
|
||||
},
|
||||
{
|
||||
name: "URL",
|
||||
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
|
||||
},
|
||||
{
|
||||
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)+"
|
||||
},
|
||||
{
|
||||
name: "Windows file path",
|
||||
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
|
||||
},
|
||||
{
|
||||
name: "UNIX file path",
|
||||
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
|
||||
},
|
||||
{
|
||||
name: "MAC address",
|
||||
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
|
||||
},
|
||||
{
|
||||
name: "Date (yyyy-mm-dd)",
|
||||
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
|
||||
},
|
||||
{
|
||||
name: "Date (dd/mm/yyyy)",
|
||||
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Date (mm/dd/yyyy)",
|
||||
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
|
||||
},
|
||||
{
|
||||
name: "Strings",
|
||||
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
|
||||
},
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_CASE_INSENSITIVE: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REGEX_MULTILINE_MATCHING: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DISPLAY_TOTAL: false,
|
||||
|
||||
/**
|
||||
* Regular expression operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runRegex: function(input, args) {
|
||||
var userRegex = args[1],
|
||||
i = args[2],
|
||||
m = args[3],
|
||||
displayTotal = args[4],
|
||||
outputFormat = args[5],
|
||||
modifiers = "g";
|
||||
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (userRegex && userRegex !== "^" && userRegex !== "$") {
|
||||
try {
|
||||
var regex = new RegExp(userRegex, modifiers);
|
||||
|
||||
switch (outputFormat) {
|
||||
case "Highlight matches":
|
||||
return StrUtils._regexHighlight(input, regex, displayTotal);
|
||||
case "List matches":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, false));
|
||||
case "List capture groups":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, false, true));
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
}
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
} else {
|
||||
return Utils.escapeHtml(input);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -149,7 +26,7 @@ const StrUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runUpper: function (input, args) {
|
||||
var scope = args[0];
|
||||
const scope = args[0];
|
||||
|
||||
switch (scope) {
|
||||
case "Word":
|
||||
@@ -188,66 +65,28 @@ const StrUtils = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
|
||||
SPLIT_DELIM_OPTIONS: [
|
||||
{name: "Comma", value: ","},
|
||||
{name: "Space", value: " "},
|
||||
{name: "Line feed", value: "\\n"},
|
||||
{name: "CRLF", value: "\\r\\n"},
|
||||
{name: "Semi-colon", value: ";"},
|
||||
{name: "Colon", value: ":"},
|
||||
{name: "Nothing (separate chars)", value: ""}
|
||||
],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_GLOBAL : true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_CASE : false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
FIND_REPLACE_MULTILINE : true,
|
||||
|
||||
/**
|
||||
* Find / Replace operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runFindReplace: function(input, args) {
|
||||
var find = args[0].string,
|
||||
type = args[0].option,
|
||||
replace = args[1],
|
||||
g = args[2],
|
||||
i = args[3],
|
||||
m = args[4],
|
||||
modifiers = "";
|
||||
|
||||
if (g) modifiers += "g";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
if (type === "Regex") {
|
||||
find = new RegExp(find, modifiers);
|
||||
} else 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.
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SPLIT_DELIM: ",",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
JOIN_DELIM_OPTIONS: [
|
||||
{name: "Line feed", value: "\\n"},
|
||||
{name: "CRLF", value: "\\r\\n"},
|
||||
{name: "Space", value: " "},
|
||||
{name: "Comma", value: ","},
|
||||
{name: "Semi-colon", value: ";"},
|
||||
{name: "Colon", value: ":"},
|
||||
{name: "Nothing (join chars)", value: ""}
|
||||
],
|
||||
|
||||
/**
|
||||
* Split operation.
|
||||
@@ -257,14 +96,20 @@ const StrUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSplit: function(input, args) {
|
||||
var splitDelim = args[0] || StrUtils.SPLIT_DELIM,
|
||||
joinDelim = Utils.charRep[args[1]],
|
||||
let splitDelim = args[0],
|
||||
joinDelim = args[1],
|
||||
sections = input.split(splitDelim);
|
||||
|
||||
return sections.join(joinDelim);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
|
||||
|
||||
/**
|
||||
* Filter operation.
|
||||
*
|
||||
@@ -274,16 +119,17 @@ const StrUtils = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFilter: function(input, args) {
|
||||
var delim = Utils.charRep[args[0]],
|
||||
let delim = Utils.charRep[args[0]],
|
||||
regex,
|
||||
reverse = args[2];
|
||||
|
||||
try {
|
||||
var regex = new RegExp(args[1]);
|
||||
regex = new RegExp(args[1]);
|
||||
} catch (err) {
|
||||
return "Invalid regex. Details: " + err.message;
|
||||
}
|
||||
|
||||
var regexFilter = function(value) {
|
||||
const regexFilter = function(value) {
|
||||
return reverse ^ regex.test(value);
|
||||
};
|
||||
|
||||
@@ -291,83 +137,6 @@ const StrUtils = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DIFF_SAMPLE_DELIMITER: "\\n\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
|
||||
|
||||
/**
|
||||
* Diff operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
runDiff: function(input, args) {
|
||||
var sampleDelim = args[0],
|
||||
diffBy = args[1],
|
||||
showAdded = args[2],
|
||||
showRemoved = args[3],
|
||||
ignoreWhitespace = args[4],
|
||||
samples = input.split(sampleDelim),
|
||||
output = "",
|
||||
diff;
|
||||
|
||||
if (!samples || samples.length !== 2) {
|
||||
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
|
||||
}
|
||||
|
||||
switch (diffBy) {
|
||||
case "Character":
|
||||
diff = JsDiff.diffChars(samples[0], samples[1]);
|
||||
break;
|
||||
case "Word":
|
||||
if (ignoreWhitespace) {
|
||||
diff = JsDiff.diffWords(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Line":
|
||||
if (ignoreWhitespace) {
|
||||
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
|
||||
} else {
|
||||
diff = JsDiff.diffLines(samples[0], samples[1]);
|
||||
}
|
||||
break;
|
||||
case "Sentence":
|
||||
diff = JsDiff.diffSentences(samples[0], samples[1]);
|
||||
break;
|
||||
case "CSS":
|
||||
diff = JsDiff.diffCss(samples[0], samples[1]);
|
||||
break;
|
||||
case "JSON":
|
||||
diff = JsDiff.diffJson(samples[0], samples[1]);
|
||||
break;
|
||||
default:
|
||||
return "Invalid 'Diff by' option.";
|
||||
}
|
||||
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
if (diff[i].added) {
|
||||
if (showAdded) output += "<span class='hlgreen'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else if (diff[i].removed) {
|
||||
if (showRemoved) output += "<span class='hlred'>" + Utils.escapeHtml(diff[i].value) + "</span>";
|
||||
} else {
|
||||
output += Utils.escapeHtml(diff[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
@@ -382,9 +151,9 @@ const StrUtils = {
|
||||
* @returns {html}
|
||||
*/
|
||||
runOffsetChecker: function(input, args) {
|
||||
var sampleDelim = args[0],
|
||||
let sampleDelim = args[0],
|
||||
samples = input.split(sampleDelim),
|
||||
outputs = [],
|
||||
outputs = new Array(samples.length),
|
||||
i = 0,
|
||||
s = 0,
|
||||
match = false,
|
||||
@@ -396,9 +165,7 @@ const StrUtils = {
|
||||
}
|
||||
|
||||
// Initialise output strings
|
||||
for (s = 0; s < samples.length; s++) {
|
||||
outputs[s] = "";
|
||||
}
|
||||
outputs.fill("", 0, samples.length);
|
||||
|
||||
// Loop through each character in the first sample
|
||||
for (i = 0; i < samples[0].length; i++) {
|
||||
@@ -423,7 +190,7 @@ const StrUtils = {
|
||||
}
|
||||
|
||||
if (match && !inMatch) {
|
||||
outputs[s] += "<span class='hlgreen'>" + Utils.escapeHtml(samples[s][i]);
|
||||
outputs[s] += "<span class='hl5'>" + Utils.escapeHtml(samples[s][i]);
|
||||
if (samples[s].length === i + 1) outputs[s] += "</span>";
|
||||
if (s === samples.length - 1) inMatch = true;
|
||||
} else if (!match && inMatch) {
|
||||
@@ -449,94 +216,210 @@ const StrUtils = {
|
||||
|
||||
|
||||
/**
|
||||
* Parse escaped string operation.
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ESCAPE_REPLACEMENTS: [
|
||||
{"escaped": "\\\\", "unescaped": "\\"}, // Must be first
|
||||
{"escaped": "\\'", "unescaped": "'"},
|
||||
{"escaped": "\\\"", "unescaped": "\""},
|
||||
{"escaped": "\\n", "unescaped": "\n"},
|
||||
{"escaped": "\\r", "unescaped": "\r"},
|
||||
{"escaped": "\\t", "unescaped": "\t"},
|
||||
{"escaped": "\\b", "unescaped": "\b"},
|
||||
{"escaped": "\\f", "unescaped": "\f"},
|
||||
],
|
||||
|
||||
/**
|
||||
* Escape string operation.
|
||||
*
|
||||
* @author Vel0x [dalemy@microsoft.com]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* StrUtils.runUnescape("Don't do that", [])
|
||||
* > "Don\'t do that"
|
||||
* StrUtils.runUnescape(`Hello
|
||||
* World`, [])
|
||||
* > "Hello\nWorld"
|
||||
*/
|
||||
runEscape: function(input, args) {
|
||||
return StrUtils._replaceByKeys(input, "unescaped", "escaped");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Unescape string operation.
|
||||
*
|
||||
* @author Vel0x [dalemy@microsoft.com]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* StrUtils.runUnescape("Don\'t do that", [])
|
||||
* > "Don't do that"
|
||||
* StrUtils.runUnescape("Hello\nWorld", [])
|
||||
* > `Hello
|
||||
* World`
|
||||
*/
|
||||
runUnescape: function(input, args) {
|
||||
return StrUtils._replaceByKeys(input, "escaped", "unescaped");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Replaces all matching tokens in ESCAPE_REPLACEMENTS with the correction. The
|
||||
* ordering is determined by the patternKey and the replacementKey.
|
||||
*
|
||||
* @author Vel0x [dalemy@microsoft.com]
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {string} pattern_key
|
||||
* @param {string} replacement_key
|
||||
* @returns {string}
|
||||
*/
|
||||
_replaceByKeys: function(input, patternKey, replacementKey) {
|
||||
let output = input;
|
||||
|
||||
// Catch the \\x encoded characters
|
||||
if (patternKey === "escaped") output = Utils.parseEscapedChars(input);
|
||||
|
||||
StrUtils.ESCAPE_REPLACEMENTS.forEach(replacement => {
|
||||
output = output.split(replacement[patternKey]).join(replacement[replacementKey]);
|
||||
});
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Head lines operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runParseEscapedString: function(input, args) {
|
||||
return Utils.parseEscapedChars(input);
|
||||
runHead: function(input, args) {
|
||||
let delimiter = args[0],
|
||||
number = args[1];
|
||||
|
||||
delimiter = Utils.charRep[delimiter];
|
||||
const splitInput = input.split(delimiter);
|
||||
|
||||
return splitInput
|
||||
.filter((line, lineIndex) => {
|
||||
lineIndex += 1;
|
||||
|
||||
if (number < 0) {
|
||||
return lineIndex <= splitInput.length + number;
|
||||
} else {
|
||||
return lineIndex <= number;
|
||||
}
|
||||
})
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds HTML highlights to matches within a string.
|
||||
* Tail lines operation.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexHighlight: function(input, regex, displayTotal) {
|
||||
var output = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
total = 0;
|
||||
runTail: function(input, args) {
|
||||
let delimiter = args[0],
|
||||
number = args[1];
|
||||
|
||||
while ((m = regex.exec(input))) {
|
||||
// Add up to match
|
||||
output += Utils.escapeHtml(input.slice(i, m.index));
|
||||
delimiter = Utils.charRep[delimiter];
|
||||
const splitInput = input.split(delimiter);
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
return splitInput
|
||||
.filter((line, lineIndex) => {
|
||||
lineIndex += 1;
|
||||
|
||||
// Switch highlight
|
||||
hl = hl === 1 ? 2 : 1;
|
||||
if (number < 0) {
|
||||
return lineIndex > -number;
|
||||
} else {
|
||||
return lineIndex > splitInput.length - number;
|
||||
}
|
||||
})
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
i = regex.lastIndex;
|
||||
total++;
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HAMMING_DELIM: "\\n\\n",
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HAMMING_INPUT_TYPE: ["Raw string", "Hex"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
HAMMING_UNIT: ["Byte", "Bit"],
|
||||
|
||||
/**
|
||||
* Hamming Distance operation.
|
||||
*
|
||||
* @author GCHQ Contributor [2]
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHamming: function(input, args) {
|
||||
const delim = args[0],
|
||||
byByte = args[1] === "Byte",
|
||||
inputType = args[2],
|
||||
samples = input.split(delim);
|
||||
|
||||
if (samples.length !== 2) {
|
||||
return "Error: You can only calculae the edit distance between 2 strings. Please ensure exactly two inputs are provided, separated by the specified delimiter.";
|
||||
}
|
||||
|
||||
// Add all after final match
|
||||
output += Utils.escapeHtml(input.slice(i, input.length));
|
||||
if (samples[0].length !== samples[1].length) {
|
||||
return "Error: Both inputs must be of the same length.";
|
||||
}
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
if (inputType === "Hex") {
|
||||
samples[0] = Utils.fromHex(samples[0]);
|
||||
samples[1] = Utils.fromHex(samples[1]);
|
||||
} else {
|
||||
samples[0] = Utils.strToByteArray(samples[0]);
|
||||
samples[1] = Utils.strToByteArray(samples[1]);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
let dist = 0;
|
||||
|
||||
for (let i = 0; i < samples[0].length; i++) {
|
||||
const lhs = samples[0][i],
|
||||
rhs = samples[1][i];
|
||||
|
||||
/**
|
||||
* Creates a string listing the matches within a string.
|
||||
*
|
||||
* @private
|
||||
* @param {string} input
|
||||
* @param {RegExp} regex
|
||||
* @param {boolean} displayTotal
|
||||
* @param {boolean} matches - Display full match
|
||||
* @param {boolean} captureGroups - Display each of the capture groups separately
|
||||
* @returns {string}
|
||||
*/
|
||||
_regexList: function(input, regex, displayTotal, matches, captureGroups) {
|
||||
var output = "",
|
||||
total = 0,
|
||||
match;
|
||||
if (byByte && lhs !== rhs) {
|
||||
dist++;
|
||||
} else if (!byByte) {
|
||||
let xord = lhs ^ rhs;
|
||||
|
||||
while ((match = regex.exec(input))) {
|
||||
total++;
|
||||
if (matches) {
|
||||
output += match[0] + "\n";
|
||||
}
|
||||
if (captureGroups) {
|
||||
for (var i = 1; i < match.length; i++) {
|
||||
if (matches) {
|
||||
output += " Group " + i + ": ";
|
||||
}
|
||||
output += match[i] + "\n";
|
||||
while (xord) {
|
||||
dist++;
|
||||
xord &= xord - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayTotal)
|
||||
output = "Total found: " + total + "\n\n" + output;
|
||||
|
||||
return output;
|
||||
return dist.toString();
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default StrUtils;
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Tidy operations.
|
||||
*
|
||||
@@ -16,32 +13,32 @@ const Tidy = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_SPACES : true,
|
||||
REMOVE_SPACES: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_CARIAGE_RETURNS : true,
|
||||
REMOVE_CARIAGE_RETURNS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_LINE_FEEDS : true,
|
||||
REMOVE_LINE_FEEDS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_TABS : true,
|
||||
REMOVE_TABS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_FORM_FEEDS : true,
|
||||
REMOVE_FORM_FEEDS: true,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
REMOVE_FULL_STOPS : false,
|
||||
REMOVE_FULL_STOPS: false,
|
||||
|
||||
/**
|
||||
* Remove whitespace operation.
|
||||
@@ -51,7 +48,7 @@ const Tidy = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runRemoveWhitespace: function (input, args) {
|
||||
var removeSpaces = args[0],
|
||||
let removeSpaces = args[0],
|
||||
removeCariageReturns = args[1],
|
||||
removeLineFeeds = args[2],
|
||||
removeTabs = args[3],
|
||||
@@ -77,8 +74,8 @@ const Tidy = {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runRemoveNulls: function (input, args) {
|
||||
var output = [];
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
const output = [];
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
if (input[i] !== 0) output.push(input[i]);
|
||||
}
|
||||
return output;
|
||||
@@ -89,56 +86,64 @@ const Tidy = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
APPLY_TO_EACH_LINE : false,
|
||||
APPLY_TO_EACH_LINE: false,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DROP_START : 0,
|
||||
DROP_START: 0,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
DROP_LENGTH : 5,
|
||||
DROP_LENGTH: 5,
|
||||
|
||||
/**
|
||||
* Drop bytes operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runDropBytes: function(input, args) {
|
||||
var start = args[0],
|
||||
const start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
|
||||
if (!applyToEachLine)
|
||||
return input.slice(0, start).concat(input.slice(start+length, input.length));
|
||||
if (!applyToEachLine) {
|
||||
const left = input.slice(0, start),
|
||||
right = input.slice(start + length, input.byteLength);
|
||||
let result = new Uint8Array(left.byteLength + right.byteLength);
|
||||
result.set(new Uint8Array(left), 0);
|
||||
result.set(new Uint8Array(right), left.byteLength);
|
||||
return result.buffer;
|
||||
}
|
||||
|
||||
// Split input into lines
|
||||
var lines = [],
|
||||
line = [];
|
||||
const data = new Uint8Array(input);
|
||||
let lines = [],
|
||||
line = [],
|
||||
i;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (input[i] === 0x0a) {
|
||||
for (i = 0; i < data.length; i++) {
|
||||
if (data[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(input[i]);
|
||||
line.push(data[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
var output = [];
|
||||
let output = [];
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length)));
|
||||
output.push(0x0a);
|
||||
}
|
||||
return output.slice(0, output.length-1);
|
||||
return new Uint8Array(output.slice(0, output.length-1)).buffer;
|
||||
},
|
||||
|
||||
|
||||
@@ -156,12 +161,12 @@ const Tidy = {
|
||||
/**
|
||||
* Take bytes operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
runTakeBytes: function(input, args) {
|
||||
var start = args[0],
|
||||
const start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
|
||||
@@ -172,25 +177,27 @@ const Tidy = {
|
||||
return input.slice(start, start+length);
|
||||
|
||||
// Split input into lines
|
||||
var lines = [],
|
||||
line = [];
|
||||
const data = new Uint8Array(input);
|
||||
let lines = [],
|
||||
line = [],
|
||||
i;
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (input[i] === 0x0a) {
|
||||
for (i = 0; i < data.length; i++) {
|
||||
if (data[i] === 0x0a) {
|
||||
lines.push(line);
|
||||
line = [];
|
||||
} else {
|
||||
line.push(input[i]);
|
||||
line.push(data[i]);
|
||||
}
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
var output = [];
|
||||
let output = [];
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(start, start+length));
|
||||
output.push(0x0a);
|
||||
}
|
||||
return output.slice(0, output.length-1);
|
||||
return new Uint8Array(output.slice(0, output.length-1)).buffer;
|
||||
},
|
||||
|
||||
|
||||
@@ -198,17 +205,17 @@ const Tidy = {
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_POSITION : ["Start", "End"],
|
||||
PAD_POSITION: ["Start", "End"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_LENGTH : 5,
|
||||
PAD_LENGTH: 5,
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
PAD_CHAR : " ",
|
||||
PAD_CHAR: " ",
|
||||
|
||||
/**
|
||||
* Pad lines operation.
|
||||
@@ -218,7 +225,7 @@ const Tidy = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runPad: function(input, args) {
|
||||
var position = args[0],
|
||||
let position = args[0],
|
||||
len = args[1],
|
||||
chr = args[2],
|
||||
lines = input.split("\n"),
|
||||
@@ -227,11 +234,11 @@ const Tidy = {
|
||||
|
||||
if (position === "Start") {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output += Utils.padLeft(lines[i], lines[i].length+len, chr) + "\n";
|
||||
output += lines[i].padStart(lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
} else if (position === "End") {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output += Utils.padRight(lines[i], lines[i].length+len, chr) + "\n";
|
||||
output += lines[i].padEnd(lines[i].length+len, chr) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* globals unescape */
|
||||
import Utils from "../Utils.js";
|
||||
import url from "url";
|
||||
|
||||
|
||||
/**
|
||||
@@ -28,7 +28,7 @@ const URL_ = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
var encodeAll = args[0];
|
||||
const encodeAll = args[0];
|
||||
return encodeAll ? URL_._encodeAllChars(input) : encodeURI(input);
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@ const URL_ = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
var data = input.replace(/\+/g, "%20");
|
||||
const data = input.replace(/\+/g, "%20");
|
||||
try {
|
||||
return decodeURIComponent(data);
|
||||
} catch (err) {
|
||||
@@ -58,56 +58,36 @@ const URL_ = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParse: function(input, args) {
|
||||
if (!document) {
|
||||
throw "This operation only works in a browser.";
|
||||
}
|
||||
const uri = url.parse(input, true);
|
||||
|
||||
var a = document.createElement("a");
|
||||
let output = "";
|
||||
|
||||
// Overwrite base href which will be the current CyberChef URL to reduce confusion.
|
||||
a.href = "http://example.com/";
|
||||
a.href = input;
|
||||
if (uri.protocol) output += "Protocol:\t" + uri.protocol + "\n";
|
||||
if (uri.auth) output += "Auth:\t\t" + uri.auth + "\n";
|
||||
if (uri.hostname) output += "Hostname:\t" + uri.hostname + "\n";
|
||||
if (uri.port) output += "Port:\t\t" + uri.port + "\n";
|
||||
if (uri.pathname) output += "Path name:\t" + uri.pathname + "\n";
|
||||
if (uri.query) {
|
||||
let keys = Object.keys(uri.query),
|
||||
padding = 0;
|
||||
|
||||
if (a.protocol) {
|
||||
var output = "";
|
||||
if (a.hostname !== window.location.hostname) {
|
||||
output = "Protocol:\t" + a.protocol + "\n";
|
||||
if (a.hostname) output += "Hostname:\t" + a.hostname + "\n";
|
||||
if (a.port) output += "Port:\t\t" + a.port + "\n";
|
||||
}
|
||||
keys.forEach(k => {
|
||||
padding = (k.length > padding) ? k.length : padding;
|
||||
});
|
||||
|
||||
if (a.pathname && a.pathname !== window.location.pathname) {
|
||||
var pathname = a.pathname;
|
||||
if (pathname.indexOf(window.location.pathname) === 0)
|
||||
pathname = pathname.replace(window.location.pathname, "");
|
||||
if (pathname)
|
||||
output += "Path name:\t" + pathname + "\n";
|
||||
}
|
||||
|
||||
if (a.hash && a.hash !== window.location.hash) {
|
||||
output += "Hash:\t\t" + a.hash + "\n";
|
||||
}
|
||||
|
||||
if (a.search && a.search !== window.location.search) {
|
||||
output += "Arguments:\n";
|
||||
var args_ = (a.search.slice(1, a.search.length)).split("&");
|
||||
var splitArgs = [], padding = 0;
|
||||
for (var i = 0; i < args_.length; i++) {
|
||||
splitArgs.push(args_[i].split("="));
|
||||
padding = (splitArgs[i][0].length > padding) ? splitArgs[i][0].length : padding;
|
||||
}
|
||||
for (i = 0; i < splitArgs.length; i++) {
|
||||
output += "\t" + Utils.padRight(splitArgs[i][0], padding);
|
||||
if (splitArgs[i].length > 1 && splitArgs[i][1].length)
|
||||
output += " = " + splitArgs[i][1] + "\n";
|
||||
else output += "\n";
|
||||
output += "Arguments:\n";
|
||||
for (let key in uri.query) {
|
||||
output += "\t" + key.padEnd(padding, " ");
|
||||
if (uri.query[key].length) {
|
||||
output += " = " + uri.query[key] + "\n";
|
||||
} else {
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
if (uri.hash) output += "Hash:\t\t" + uri.hash + "\n";
|
||||
|
||||
return "Invalid URI";
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
@@ -127,7 +107,7 @@ const URL_ = {
|
||||
.replace(/\(/g, "%28")
|
||||
.replace(/\)/g, "%29")
|
||||
.replace(/\*/g, "%2A")
|
||||
.replace(/\-/g, "%2D")
|
||||
.replace(/-/g, "%2D")
|
||||
.replace(/\./g, "%2E")
|
||||
.replace(/_/g, "%5F")
|
||||
.replace(/~/g, "%7E");
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import crypto from "crypto";
|
||||
|
||||
|
||||
/**
|
||||
* UUID operations.
|
||||
*
|
||||
@@ -17,25 +20,17 @@ const UUID = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runGenerateV4: function(input, args) {
|
||||
if (window && typeof(window.crypto) !== "undefined" && typeof(window.crypto.getRandomValues) !== "undefined") {
|
||||
var buf = new Uint32Array(4),
|
||||
i = 0;
|
||||
window.crypto.getRandomValues(buf);
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
var r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
i++;
|
||||
return v.toString(16);
|
||||
});
|
||||
} else {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
var r = Math.random() * 16 | 0,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
const buf = new Uint32Array(4).map(() => {
|
||||
return crypto.randomBytes(4).readUInt32BE(0, true);
|
||||
});
|
||||
let i = 0;
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
let r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
i++;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default UUID;
|
||||
|
||||
@@ -26,7 +26,7 @@ const Unicode = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runUnescape: function(input, args) {
|
||||
var prefix = Unicode._prefixToRegex[args[0]],
|
||||
let prefix = Unicode._prefixToRegex[args[0]],
|
||||
regex = new RegExp(prefix+"([a-f\\d]{4,6})", "ig"),
|
||||
output = "",
|
||||
m,
|
||||
|
||||
@@ -7,19 +7,21 @@
|
||||
*/
|
||||
require("babel-polyfill");
|
||||
|
||||
var Chef = require("../core/Chef.js").default;
|
||||
const Chef = require("../core/Chef.js").default;
|
||||
|
||||
const CyberChef = module.exports = {
|
||||
const CyberChef = {
|
||||
|
||||
bake: function(input, recipeConfig) {
|
||||
this.chef = new Chef();
|
||||
return this.chef.bake(
|
||||
input,
|
||||
recipeConfig,
|
||||
{},
|
||||
0,
|
||||
false
|
||||
);
|
||||
input,
|
||||
recipeConfig,
|
||||
{},
|
||||
0,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = CyberChef;
|
||||
|
||||
343
src/web/App.js
343
src/web/App.js
@@ -1,5 +1,4 @@
|
||||
import Utils from "../core/Utils.js";
|
||||
import Chef from "../core/Chef.js";
|
||||
import Manager from "./Manager.js";
|
||||
import HTMLCategory from "./HTMLCategory.js";
|
||||
import HTMLOperation from "./HTMLOperation.js";
|
||||
@@ -20,21 +19,20 @@ import Split from "split.js";
|
||||
* @param {String[]} defaultFavourites - A list of default favourite operations.
|
||||
* @param {Object} options - Default setting for app options.
|
||||
*/
|
||||
var App = function(categories, operations, defaultFavourites, defaultOptions) {
|
||||
this.categories = categories;
|
||||
this.operations = operations;
|
||||
this.dfavourites = defaultFavourites;
|
||||
this.doptions = defaultOptions;
|
||||
this.options = Utils.extend({}, defaultOptions);
|
||||
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.chef = new Chef();
|
||||
this.manager = new Manager(this);
|
||||
this.manager = new Manager(this);
|
||||
|
||||
this.autoBake_ = false;
|
||||
this.progress = 0;
|
||||
this.ingId = 0;
|
||||
|
||||
window.chef = this.chef;
|
||||
this.baking = false;
|
||||
this.autoBake_ = false;
|
||||
this.autoBakePause = false;
|
||||
this.progress = 0;
|
||||
this.ingId = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +49,40 @@ App.prototype.setup = function() {
|
||||
this.manager.setup();
|
||||
this.resetLayout();
|
||||
this.setCompileMessage();
|
||||
|
||||
log.debug("App loaded");
|
||||
this.appLoaded = true;
|
||||
|
||||
this.loadURIParams();
|
||||
this.loaded();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires once all setup activities have completed.
|
||||
*
|
||||
* @fires Manager#apploaded
|
||||
*/
|
||||
App.prototype.loaded = function() {
|
||||
// Check that both the app and the worker have loaded successfully, and that
|
||||
// we haven't already loaded before attempting to remove the loading screen.
|
||||
if (!this.workerLoaded || !this.appLoaded ||
|
||||
!document.getElementById("loader-wrapper")) return;
|
||||
|
||||
// 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.loadingMsgsInt);
|
||||
|
||||
document.dispatchEvent(this.manager.apploaded);
|
||||
};
|
||||
|
||||
|
||||
@@ -59,53 +90,34 @@ App.prototype.setup = function() {
|
||||
* An error handler for displaying the error to the user.
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {boolean} [logToConsole=false]
|
||||
*/
|
||||
App.prototype.handleError = function(err) {
|
||||
console.error(err);
|
||||
var msg = err.displayStr || err.toString();
|
||||
App.prototype.handleError = function(err, logToConsole) {
|
||||
if (logToConsole) log.error(err);
|
||||
const msg = err.displayStr || err.toString();
|
||||
this.alert(msg, "danger", this.options.errorTimeout, !this.options.showErrors);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the Chef to bake the current input using the current recipe.
|
||||
* Asks the ChefWorker to bake the current input using the current recipe.
|
||||
*
|
||||
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
|
||||
* whole recipe.
|
||||
*/
|
||||
App.prototype.bake = function(step) {
|
||||
var response;
|
||||
if (this.baking) return;
|
||||
|
||||
try {
|
||||
response = this.chef.bake(
|
||||
this.getInput(), // The user's input
|
||||
this.getRecipeConfig(), // The configuration of the recipe
|
||||
this.options, // Options set by the user
|
||||
this.progress, // The current position in the recipe
|
||||
step // Whether or not to take one step or execute the whole recipe
|
||||
);
|
||||
} catch (err) {
|
||||
this.handleError(err);
|
||||
}
|
||||
// Reset attemptHighlight flag
|
||||
this.options.attemptHighlight = true;
|
||||
|
||||
if (!response) return;
|
||||
|
||||
if (response.error) {
|
||||
this.handleError(response.error);
|
||||
}
|
||||
|
||||
this.options = response.options;
|
||||
this.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result;
|
||||
this.progress = response.progress;
|
||||
this.manager.recipe.updateBreakpointIndicator(response.progress);
|
||||
this.manager.output.set(response.result, response.type, response.duration);
|
||||
|
||||
// If baking took too long, disable auto-bake
|
||||
if (response.duration > this.options.autoBakeThreshold && this.autoBake_) {
|
||||
this.manager.controls.setAutoBake(false);
|
||||
this.alert("Baking took longer than " + this.options.autoBakeThreshold +
|
||||
"ms, Auto Bake has been disabled.", "warning", 5000);
|
||||
}
|
||||
this.manager.worker.bake(
|
||||
this.getInput(), // The user's input
|
||||
this.getRecipeConfig(), // The configuration of the recipe
|
||||
this.options, // Options set by the user
|
||||
this.progress, // The current position in the recipe
|
||||
step // Whether or not to take one step or execute the whole recipe
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -113,30 +125,37 @@ App.prototype.bake = function(step) {
|
||||
* Runs Auto Bake if it is set.
|
||||
*/
|
||||
App.prototype.autoBake = function() {
|
||||
if (this.autoBake_) {
|
||||
// If autoBakePause is set, we are loading a full recipe (and potentially input), so there is no
|
||||
// need to set the staleness indicator. Just exit and wait until auto bake is called after loading
|
||||
// has completed.
|
||||
if (this.autoBakePause) return false;
|
||||
|
||||
if (this.autoBake_ && !this.baking) {
|
||||
log.debug("Auto-baking");
|
||||
this.bake();
|
||||
} else {
|
||||
this.manager.controls.showStaleIndicator();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Runs a silent bake forcing the browser to load and cache all the relevant JavaScript code needed
|
||||
* Runs a silent bake, forcing the browser to load and cache all the relevant JavaScript code needed
|
||||
* to do a real bake.
|
||||
*
|
||||
* The output will not be modified (hence "silent" bake). This will only actually execute the
|
||||
* recipe if auto-bake is enabled, otherwise it will just load the recipe, ingredients and dish.
|
||||
*
|
||||
* @returns {number} - The number of miliseconds it took to run the silent bake.
|
||||
* The output will not be modified (hence "silent" bake). This will only actually execute the recipe
|
||||
* if auto-bake is enabled, otherwise it will just wake up the ChefWorker with an empty recipe.
|
||||
*/
|
||||
App.prototype.silentBake = function() {
|
||||
var startTime = new Date().getTime(),
|
||||
recipeConfig = this.getRecipeConfig();
|
||||
let recipeConfig = [];
|
||||
|
||||
if (this.autoBake_) {
|
||||
this.chef.silentBake(recipeConfig);
|
||||
// If auto-bake is not enabled we don't want to actually run the recipe as it may be disabled
|
||||
// for a good reason.
|
||||
recipeConfig = this.getRecipeConfig();
|
||||
}
|
||||
|
||||
return new Date().getTime() - startTime;
|
||||
this.manager.worker.silentBake(recipeConfig);
|
||||
};
|
||||
|
||||
|
||||
@@ -146,13 +165,7 @@ App.prototype.silentBake = function() {
|
||||
* @returns {string}
|
||||
*/
|
||||
App.prototype.getInput = function() {
|
||||
var input = this.manager.input.get();
|
||||
|
||||
// Save to session storage in case we need to restore it later
|
||||
sessionStorage.setItem("inputLength", input.length);
|
||||
sessionStorage.setItem("input", input);
|
||||
|
||||
return input;
|
||||
return this.manager.input.get();
|
||||
};
|
||||
|
||||
|
||||
@@ -162,8 +175,6 @@ App.prototype.getInput = function() {
|
||||
* @param {string} input - The string to set the input to
|
||||
*/
|
||||
App.prototype.setInput = function(input) {
|
||||
sessionStorage.setItem("inputLength", input.length);
|
||||
sessionStorage.setItem("input", input);
|
||||
this.manager.input.set(input);
|
||||
};
|
||||
|
||||
@@ -178,15 +189,16 @@ App.prototype.populateOperationsList = function() {
|
||||
// Move edit button away before we overwrite it
|
||||
document.body.appendChild(document.getElementById("edit-favourites"));
|
||||
|
||||
var html = "";
|
||||
let html = "";
|
||||
let i;
|
||||
|
||||
for (var i = 0; i < this.categories.length; i++) {
|
||||
var catConf = this.categories[i],
|
||||
for (i = 0; i < this.categories.length; i++) {
|
||||
let catConf = this.categories[i],
|
||||
selected = i === 0,
|
||||
cat = new HTMLCategory(catConf.name, selected);
|
||||
|
||||
for (var j = 0; j < catConf.ops.length; j++) {
|
||||
var opName = catConf.ops[j],
|
||||
for (let j = 0; j < catConf.ops.length; j++) {
|
||||
let opName = catConf.ops[j],
|
||||
op = new HTMLOperation(opName, this.operations[opName], this, this.manager);
|
||||
cat.addOperation(op);
|
||||
}
|
||||
@@ -196,7 +208,7 @@ App.prototype.populateOperationsList = function() {
|
||||
|
||||
document.getElementById("categories").innerHTML = html;
|
||||
|
||||
var opLists = document.querySelectorAll("#categories .op-list");
|
||||
const opLists = document.querySelectorAll("#categories .op-list");
|
||||
|
||||
for (i = 0; i < opLists.length; i++) {
|
||||
opLists[i].dispatchEvent(this.manager.oplistcreate);
|
||||
@@ -213,7 +225,7 @@ App.prototype.populateOperationsList = function() {
|
||||
App.prototype.initialiseSplitter = function() {
|
||||
this.columnSplitter = Split(["#operations", "#recipe", "#IO"], {
|
||||
sizes: [20, 30, 50],
|
||||
minSize: [240, 325, 440],
|
||||
minSize: [240, 325, 450],
|
||||
gutterSize: 4,
|
||||
onDrag: function() {
|
||||
this.manager.controls.adjustWidth();
|
||||
@@ -236,8 +248,8 @@ App.prototype.initialiseSplitter = function() {
|
||||
*/
|
||||
App.prototype.loadLocalStorage = function() {
|
||||
// Load options
|
||||
var lOptions;
|
||||
if (localStorage.options !== undefined) {
|
||||
let lOptions;
|
||||
if (this.isLocalStorageAvailable() && localStorage.options !== undefined) {
|
||||
lOptions = JSON.parse(localStorage.options);
|
||||
}
|
||||
this.manager.options.load(lOptions);
|
||||
@@ -253,15 +265,19 @@ App.prototype.loadLocalStorage = function() {
|
||||
* If the user currently has no saved favourites, the defaults from the view constructor are used.
|
||||
*/
|
||||
App.prototype.loadFavourites = function() {
|
||||
var favourites = localStorage.favourites &&
|
||||
localStorage.favourites.length > 2 ?
|
||||
JSON.parse(localStorage.favourites) :
|
||||
this.dfavourites;
|
||||
let favourites;
|
||||
|
||||
favourites = this.validFavourites(favourites);
|
||||
this.saveFavourites(favourites);
|
||||
if (this.isLocalStorageAvailable()) {
|
||||
favourites = localStorage.favourites && localStorage.favourites.length > 2 ?
|
||||
JSON.parse(localStorage.favourites) :
|
||||
this.dfavourites;
|
||||
favourites = this.validFavourites(favourites);
|
||||
this.saveFavourites(favourites);
|
||||
} else {
|
||||
favourites = this.dfavourites;
|
||||
}
|
||||
|
||||
var favCat = this.categories.filter(function(c) {
|
||||
const favCat = this.categories.filter(function(c) {
|
||||
return c.name === "Favourites";
|
||||
})[0];
|
||||
|
||||
@@ -284,8 +300,8 @@ App.prototype.loadFavourites = function() {
|
||||
* @returns {string[]} A list of the valid favourites
|
||||
*/
|
||||
App.prototype.validFavourites = function(favourites) {
|
||||
var validFavs = [];
|
||||
for (var i = 0; i < favourites.length; i++) {
|
||||
const validFavs = [];
|
||||
for (let i = 0; i < favourites.length; i++) {
|
||||
if (this.operations.hasOwnProperty(favourites[i])) {
|
||||
validFavs.push(favourites[i]);
|
||||
} else {
|
||||
@@ -303,6 +319,15 @@ App.prototype.validFavourites = function(favourites) {
|
||||
* @param {string[]} favourites - A list of the user's favourite operations
|
||||
*/
|
||||
App.prototype.saveFavourites = function(favourites) {
|
||||
if (!this.isLocalStorageAvailable()) {
|
||||
this.alert(
|
||||
"Your security settings do not allow access to local storage so your favourites cannot be saved.",
|
||||
"danger",
|
||||
5000
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
localStorage.setItem("favourites", JSON.stringify(this.validFavourites(favourites)));
|
||||
};
|
||||
|
||||
@@ -325,7 +350,7 @@ App.prototype.resetFavourites = function() {
|
||||
* @param {string} name - The name of the operation
|
||||
*/
|
||||
App.prototype.addFavourite = function(name) {
|
||||
var favourites = JSON.parse(localStorage.favourites);
|
||||
const favourites = JSON.parse(localStorage.favourites);
|
||||
|
||||
if (favourites.indexOf(name) >= 0) {
|
||||
this.alert("'" + name + "' is already in your favourites", "info", 2000);
|
||||
@@ -344,61 +369,53 @@ 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 {};
|
||||
var b = {};
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var 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)
|
||||
// We prefer getting the hash by splitting the href rather than referencing
|
||||
// location.hash as some browsers (Firefox) automatically URL decode it,
|
||||
// which cause issues.
|
||||
const params = window.location.search ||
|
||||
window.location.href.split("#")[1] ||
|
||||
window.location.hash;
|
||||
this.uriParams = Utils.parseURIParams(params);
|
||||
|
||||
// Turn off auto-bake while loading
|
||||
var autoBakeVal = this.autoBake_;
|
||||
this.autoBake_ = false;
|
||||
|
||||
// Read in recipe from query string
|
||||
if (this.queryString.recipe) {
|
||||
// Read in recipe from URI params
|
||||
if (this.uriParams.recipe) {
|
||||
try {
|
||||
var recipeConfig = JSON.parse(this.queryString.recipe);
|
||||
const recipeConfig = Utils.parseRecipeConfig(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
|
||||
var 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);
|
||||
}
|
||||
|
||||
// Populate search with the string
|
||||
var search = document.getElementById("search");
|
||||
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) {
|
||||
this.autoBakePause = true;
|
||||
try {
|
||||
var inputData = Utils.fromBase64(this.queryString.input);
|
||||
const inputData = Utils.fromBase64(this.uriParams.input);
|
||||
this.setInput(inputData);
|
||||
} catch (err) {}
|
||||
} catch (err) {
|
||||
} finally {
|
||||
this.autoBakePause = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore auto-bake state
|
||||
this.autoBake_ = autoBakeVal;
|
||||
this.autoBake();
|
||||
};
|
||||
|
||||
@@ -419,27 +436,30 @@ App.prototype.nextIngId = function() {
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
App.prototype.getRecipeConfig = function() {
|
||||
var recipeConfig = this.manager.recipe.getConfig();
|
||||
sessionStorage.setItem("recipeConfig", JSON.stringify(recipeConfig));
|
||||
return recipeConfig;
|
||||
return this.manager.recipe.getConfig();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a recipe configuration, sets the recipe to that configuration.
|
||||
*
|
||||
* @fires Manager#statechange
|
||||
* @param {Object[]} recipeConfig - The recipe configuration
|
||||
*/
|
||||
App.prototype.setRecipeConfig = function(recipeConfig) {
|
||||
sessionStorage.setItem("recipeConfig", JSON.stringify(recipeConfig));
|
||||
document.getElementById("rec-list").innerHTML = null;
|
||||
|
||||
for (var i = 0; i < recipeConfig.length; i++) {
|
||||
var item = this.manager.recipe.addOperation(recipeConfig[i].op);
|
||||
// Pause auto-bake while loading but don't modify `this.autoBake_`
|
||||
// otherwise `manualBake` cannot trigger.
|
||||
this.autoBakePause = true;
|
||||
|
||||
for (let i = 0; i < recipeConfig.length; i++) {
|
||||
const item = this.manager.recipe.addOperation(recipeConfig[i].op);
|
||||
|
||||
// Populate arguments
|
||||
var args = item.querySelectorAll(".arg");
|
||||
for (var j = 0; j < args.length; j++) {
|
||||
const args = item.querySelectorAll(".arg");
|
||||
for (let j = 0; j < args.length; j++) {
|
||||
if (recipeConfig[i].args[j] === undefined) continue;
|
||||
if (args[j].getAttribute("type") === "checkbox") {
|
||||
// checkbox
|
||||
args[j].checked = recipeConfig[i].args[j];
|
||||
@@ -465,6 +485,9 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
|
||||
|
||||
this.progress = 0;
|
||||
}
|
||||
|
||||
// Unpause auto bake
|
||||
this.autoBakePause = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -485,20 +508,45 @@ App.prototype.resetLayout = function() {
|
||||
*/
|
||||
App.prototype.setCompileMessage = function() {
|
||||
// Display time since last build and compile message
|
||||
var now = new Date(),
|
||||
timeSinceCompile = Utils.fuzzyTime(now.getTime() - window.compileTime),
|
||||
compileInfo = "<span style=\"font-weight: normal\">Last build: " +
|
||||
timeSinceCompile.substr(0, 1).toUpperCase() + timeSinceCompile.substr(1) + " ago";
|
||||
let now = new Date(),
|
||||
timeSinceCompile = Utils.fuzzyTime(now.getTime() - window.compileTime);
|
||||
|
||||
// Calculate previous version to compare to
|
||||
let prev = PKG_VERSION.split(".").map(n => {
|
||||
return parseInt(n, 10);
|
||||
});
|
||||
if (prev[2] > 0) prev[2]--;
|
||||
else if (prev[1] > 0) prev[1]--;
|
||||
else prev[0]--;
|
||||
|
||||
const compareURL = `https://github.com/gchq/CyberChef/compare/v${prev.join(".")}...v${PKG_VERSION}`;
|
||||
|
||||
let compileInfo = `<a href='${compareURL}'>Last build: ${timeSinceCompile.substr(0, 1).toUpperCase() + timeSinceCompile.substr(1)} ago</a>`;
|
||||
|
||||
if (window.compileMessage !== "") {
|
||||
compileInfo += " - " + window.compileMessage;
|
||||
}
|
||||
|
||||
compileInfo += "</span>";
|
||||
document.getElementById("notice").innerHTML = compileInfo;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether the browser supports Local Storage and if it is accessible.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
App.prototype.isLocalStorageAvailable = function() {
|
||||
try {
|
||||
if (!localStorage) return false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
// Access to LocalStorage is denied
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pops up a message to the user and writes it to the console log.
|
||||
*
|
||||
@@ -523,15 +571,15 @@ App.prototype.setCompileMessage = function() {
|
||||
* this.alert("Happy Christmas!", "info", 5000);
|
||||
*/
|
||||
App.prototype.alert = function(str, style, timeout, silent) {
|
||||
var time = new Date();
|
||||
const time = new Date();
|
||||
|
||||
console.log("[" + time.toLocaleString() + "] " + str);
|
||||
log.info("[" + time.toLocaleString() + "] " + str);
|
||||
if (silent) return;
|
||||
|
||||
style = style || "danger";
|
||||
timeout = timeout || 0;
|
||||
|
||||
var alertEl = document.getElementById("alert"),
|
||||
let alertEl = document.getElementById("alert"),
|
||||
alertContent = document.getElementById("alert-content");
|
||||
|
||||
alertEl.classList.remove("alert-danger");
|
||||
@@ -619,10 +667,27 @@ App.prototype.alertCloseClick = function() {
|
||||
App.prototype.stateChange = function(e) {
|
||||
this.autoBake();
|
||||
|
||||
// Set title
|
||||
const recipeConfig = this.getRecipeConfig();
|
||||
let title = "CyberChef";
|
||||
if (recipeConfig.length === 1) {
|
||||
title = `${recipeConfig[0].op} - ${title}`;
|
||||
} else if (recipeConfig.length > 1) {
|
||||
// See how long the full recipe is
|
||||
const ops = recipeConfig.map(op => op.op).join(", ");
|
||||
if (ops.length < 45) {
|
||||
title = `${ops} - ${title}`;
|
||||
} else {
|
||||
// If it's too long, just use the first one and say how many more there are
|
||||
title = `${recipeConfig[0].op}, ${recipeConfig.length - 1} more - ${title}`;
|
||||
}
|
||||
}
|
||||
document.title = title;
|
||||
|
||||
// Update the current history state (not creating a new one)
|
||||
if (this.options.updateUrl) {
|
||||
this.lastStateUrl = this.manager.controls.generateStateUrl(true, true);
|
||||
window.history.replaceState({}, "CyberChef", this.lastStateUrl);
|
||||
this.lastStateUrl = this.manager.controls.generateStateUrl(true, true, recipeConfig);
|
||||
window.history.replaceState({}, title, this.lastStateUrl);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -634,9 +699,7 @@ App.prototype.stateChange = function(e) {
|
||||
* @param {event} e
|
||||
*/
|
||||
App.prototype.popState = function(e) {
|
||||
if (window.location.href.split("#")[0] !== this.lastStateUrl) {
|
||||
this.loadURIParams();
|
||||
}
|
||||
this.loadURIParams();
|
||||
};
|
||||
|
||||
|
||||
@@ -649,7 +712,7 @@ App.prototype.callApi = function(url, type, data, dataType, contentType) {
|
||||
dataType = dataType || undefined;
|
||||
contentType = contentType || "application/json";
|
||||
|
||||
var response = null,
|
||||
let response = null,
|
||||
success = false;
|
||||
|
||||
$.ajax({
|
||||
|
||||
217
src/web/BindingsWaiter.js
Normal file
217
src/web/BindingsWaiter.js
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* Waiter to handle keybindings to CyberChef functions (i.e. Bake, Step, Save, Load etc.)
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @constructor
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
const BindingsWaiter = function (app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for all keydown events
|
||||
* Checks whether valid keyboard shortcut has been instated
|
||||
*
|
||||
* @fires Manager#statechange
|
||||
* @param {event} e
|
||||
*/
|
||||
BindingsWaiter.prototype.parseInput = function(e) {
|
||||
const modKey = this.app.options.useMetaKey ? e.metaKey : e.altKey;
|
||||
|
||||
if (e.ctrlKey && modKey) {
|
||||
let elem;
|
||||
switch (e.code) {
|
||||
case "KeyF": // Focus search
|
||||
e.preventDefault();
|
||||
document.getElementById("search").focus();
|
||||
break;
|
||||
case "KeyI": // Focus input
|
||||
e.preventDefault();
|
||||
document.getElementById("input-text").focus();
|
||||
break;
|
||||
case "KeyO": // Focus output
|
||||
e.preventDefault();
|
||||
document.getElementById("output-text").focus();
|
||||
break;
|
||||
case "Period": // Focus next operation
|
||||
e.preventDefault();
|
||||
try {
|
||||
elem = document.activeElement.closest(".operation") || document.querySelector("#rec-list .operation");
|
||||
if (elem.parentNode.lastChild === elem) {
|
||||
// If operation is last in recipe, loop around to the top operation's first argument
|
||||
elem.parentNode.firstChild.querySelectorAll(".arg")[0].focus();
|
||||
} else {
|
||||
// Focus first argument of next operation
|
||||
elem.nextSibling.querySelectorAll(".arg")[0].focus();
|
||||
}
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
break;
|
||||
case "KeyB": // Set breakpoint
|
||||
e.preventDefault();
|
||||
try {
|
||||
elem = document.activeElement.closest(".operation").querySelectorAll(".breakpoint")[0];
|
||||
if (elem.getAttribute("break") === "false") {
|
||||
elem.setAttribute("break", "true"); // add break point if not already enabled
|
||||
elem.classList.add("breakpoint-selected");
|
||||
} else {
|
||||
elem.setAttribute("break", "false"); // remove break point if already enabled
|
||||
elem.classList.remove("breakpoint-selected");
|
||||
}
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
break;
|
||||
case "KeyD": // Disable operation
|
||||
e.preventDefault();
|
||||
try {
|
||||
elem = document.activeElement.closest(".operation").querySelectorAll(".disable-icon")[0];
|
||||
if (elem.getAttribute("disabled") === "false") {
|
||||
elem.setAttribute("disabled", "true"); // disable operation if enabled
|
||||
elem.classList.add("disable-elem-selected");
|
||||
elem.parentNode.parentNode.classList.add("disabled");
|
||||
} else {
|
||||
elem.setAttribute("disabled", "false"); // enable operation if disabled
|
||||
elem.classList.remove("disable-elem-selected");
|
||||
elem.parentNode.parentNode.classList.remove("disabled");
|
||||
}
|
||||
this.app.progress = 0;
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
break;
|
||||
case "Space": // Bake
|
||||
e.preventDefault();
|
||||
this.app.bake();
|
||||
break;
|
||||
case "Quote": // Step through
|
||||
e.preventDefault();
|
||||
this.app.bake(true);
|
||||
break;
|
||||
case "KeyC": // Clear recipe
|
||||
e.preventDefault();
|
||||
this.manager.recipe.clearRecipe();
|
||||
break;
|
||||
case "KeyS": // Save output to file
|
||||
e.preventDefault();
|
||||
this.manager.output.saveClick();
|
||||
break;
|
||||
case "KeyL": // Load recipe
|
||||
e.preventDefault();
|
||||
this.manager.controls.loadClick();
|
||||
break;
|
||||
case "KeyM": // Switch input and output
|
||||
e.preventDefault();
|
||||
this.manager.output.switchClick();
|
||||
break;
|
||||
default:
|
||||
if (e.code.match(/Digit[0-9]/g)) { // Select nth operation
|
||||
e.preventDefault();
|
||||
try {
|
||||
// Select the first argument of the operation corresponding to the number pressed
|
||||
document.querySelector(`li:nth-child(${e.code.substr(-1)}) .arg`).focus();
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates keybinding list when metaKey option is toggled
|
||||
*
|
||||
*/
|
||||
BindingsWaiter.prototype.updateKeybList = function() {
|
||||
let modWinLin = "Alt";
|
||||
let modMac = "Opt";
|
||||
if (this.app.options.useMetaKey) {
|
||||
modWinLin = "Win";
|
||||
modMac = "Cmd";
|
||||
}
|
||||
document.getElementById("keybList").innerHTML = `
|
||||
<tr>
|
||||
<td><b>Command</b></td>
|
||||
<td><b>Shortcut (Win/Linux)</b></td>
|
||||
<td><b>Shortcut (Mac)</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in search field</td>
|
||||
<td>Ctrl+${modWinLin}+f</td>
|
||||
<td>Ctrl+${modMac}+f</td>
|
||||
<tr>
|
||||
<td>Place cursor in input box</td>
|
||||
<td>Ctrl+${modWinLin}+i</td>
|
||||
<td>Ctrl+${modMac}+i</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in output box</td>
|
||||
<td>Ctrl+${modWinLin}+o</td>
|
||||
<td>Ctrl+${modMac}+o</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in first argument field of the next operation in the recipe</td>
|
||||
<td>Ctrl+${modWinLin}+.</td>
|
||||
<td>Ctrl+${modMac}+.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in first argument field of the nth operation in the recipe</td>
|
||||
<td>Ctrl+${modWinLin}+[1-9]</td>
|
||||
<td>Ctrl+${modMac}+[1-9]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Disable current operation</td>
|
||||
<td>Ctrl+${modWinLin}+d</td>
|
||||
<td>Ctrl+${modMac}+d</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Set/clear breakpoint</td>
|
||||
<td>Ctrl+${modWinLin}+b</td>
|
||||
<td>Ctrl+${modMac}+b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bake</td>
|
||||
<td>Ctrl+${modWinLin}+Space</td>
|
||||
<td>Ctrl+${modMac}+Space</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Step</td>
|
||||
<td>Ctrl+${modWinLin}+'</td>
|
||||
<td>Ctrl+${modMac}+'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Clear recipe</td>
|
||||
<td>Ctrl+${modWinLin}+c</td>
|
||||
<td>Ctrl+${modMac}+c</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Save to file</td>
|
||||
<td>Ctrl+${modWinLin}+s</td>
|
||||
<td>Ctrl+${modMac}+s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Load recipe</td>
|
||||
<td>Ctrl+${modWinLin}+l</td>
|
||||
<td>Ctrl+${modMac}+l</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Move output to input</td>
|
||||
<td>Ctrl+${modWinLin}+m</td>
|
||||
<td>Ctrl+${modMac}+m</td>
|
||||
</tr>
|
||||
`;
|
||||
};
|
||||
|
||||
export default BindingsWaiter;
|
||||
@@ -12,7 +12,7 @@ import Utils from "../core/Utils.js";
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
var ControlsWaiter = function(app, manager) {
|
||||
const ControlsWaiter = function(app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
};
|
||||
@@ -23,14 +23,14 @@ var ControlsWaiter = function(app, manager) {
|
||||
* without wrapping or overflowing.
|
||||
*/
|
||||
ControlsWaiter.prototype.adjustWidth = function() {
|
||||
var 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";
|
||||
@@ -66,7 +66,7 @@ ControlsWaiter.prototype.adjustWidth = function() {
|
||||
* @param {boolean} value - The new value for Auto Bake.
|
||||
*/
|
||||
ControlsWaiter.prototype.setAutoBake = function(value) {
|
||||
var autoBakeCheckbox = document.getElementById("auto-bake");
|
||||
const autoBakeCheckbox = document.getElementById("auto-bake");
|
||||
|
||||
if (autoBakeCheckbox.checked !== value) {
|
||||
autoBakeCheckbox.click();
|
||||
@@ -78,10 +78,11 @@ ControlsWaiter.prototype.setAutoBake = function(value) {
|
||||
* Handler to trigger baking.
|
||||
*/
|
||||
ControlsWaiter.prototype.bakeClick = function() {
|
||||
this.app.bake();
|
||||
var outputText = document.getElementById("output-text");
|
||||
outputText.focus();
|
||||
outputText.setSelectionRange(0, 0);
|
||||
if (document.getElementById("bake").textContent.indexOf("Bake") > 0) {
|
||||
this.app.bake();
|
||||
} else {
|
||||
this.manager.worker.cancelBake();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -90,9 +91,6 @@ ControlsWaiter.prototype.bakeClick = function() {
|
||||
*/
|
||||
ControlsWaiter.prototype.stepClick = function() {
|
||||
this.app.bake(true);
|
||||
var outputText = document.getElementById("output-text");
|
||||
outputText.focus();
|
||||
outputText.setSelectionRange(0, 0);
|
||||
};
|
||||
|
||||
|
||||
@@ -100,17 +98,17 @@ ControlsWaiter.prototype.stepClick = function() {
|
||||
* Handler for changes made to the Auto Bake checkbox.
|
||||
*/
|
||||
ControlsWaiter.prototype.autoBakeChange = function() {
|
||||
var 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");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,9 +126,9 @@ ControlsWaiter.prototype.clearRecipeClick = function() {
|
||||
* recipe.
|
||||
*/
|
||||
ControlsWaiter.prototype.clearBreaksClick = function() {
|
||||
var bps = document.querySelectorAll("#rec-list li.operation .breakpoint");
|
||||
const bps = document.querySelectorAll("#rec-list li.operation .breakpoint");
|
||||
|
||||
for (var i = 0; i < bps.length; i++) {
|
||||
for (let i = 0; i < bps.length; i++) {
|
||||
bps[i].setAttribute("break", "false");
|
||||
bps[i].classList.remove("breakpoint-selected");
|
||||
}
|
||||
@@ -145,10 +143,10 @@ ControlsWaiter.prototype.clearBreaksClick = function() {
|
||||
ControlsWaiter.prototype.initialiseSaveLink = function(recipeConfig) {
|
||||
recipeConfig = recipeConfig || this.app.getRecipeConfig();
|
||||
|
||||
var 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 +165,28 @@ ControlsWaiter.prototype.initialiseSaveLink = function(recipeConfig) {
|
||||
ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput, recipeConfig, baseURL) {
|
||||
recipeConfig = recipeConfig || this.app.getRecipeConfig();
|
||||
|
||||
var 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 = Utils.generatePrettyRecipe(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}=${Utils.encodeURIFragment(value)}`)
|
||||
.join("&");
|
||||
|
||||
if (hash) {
|
||||
return `${link}#${hash}`;
|
||||
}
|
||||
|
||||
return link;
|
||||
@@ -193,9 +196,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
||||
/**
|
||||
* Handler for changes made to the save dialog text area. Re-initialises the save link.
|
||||
*/
|
||||
ControlsWaiter.prototype.saveTextChange = function() {
|
||||
ControlsWaiter.prototype.saveTextChange = function(e) {
|
||||
try {
|
||||
var recipeConfig = JSON.parse(document.getElementById("save-text").value);
|
||||
const recipeConfig = Utils.parseRecipeConfig(e.target.value);
|
||||
this.initialiseSaveLink(recipeConfig);
|
||||
} catch (err) {}
|
||||
};
|
||||
@@ -205,10 +208,17 @@ ControlsWaiter.prototype.saveTextChange = function() {
|
||||
* Handler for the 'Save' command. Pops up the save dialog box.
|
||||
*/
|
||||
ControlsWaiter.prototype.saveClick = function() {
|
||||
var recipeConfig = this.app.getRecipeConfig(),
|
||||
recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
|
||||
const recipeConfig = this.app.getRecipeConfig();
|
||||
const recipeStr = JSON.stringify(recipeConfig);
|
||||
|
||||
document.getElementById("save-text").value = recipeStr;
|
||||
document.getElementById("save-text-chef").value = Utils.generatePrettyRecipe(recipeConfig, true);
|
||||
document.getElementById("save-text-clean").value = JSON.stringify(recipeConfig, null, 2)
|
||||
.replace(/{\n\s+"/g, "{ \"")
|
||||
.replace(/\[\n\s{3,}/g, "[")
|
||||
.replace(/\n\s{3,}]/g, "]")
|
||||
.replace(/\s*\n\s*}/g, " }")
|
||||
.replace(/\n\s{6,}/g, " ");
|
||||
document.getElementById("save-text-compact").value = recipeStr;
|
||||
|
||||
this.initialiseSaveLink(recipeConfig);
|
||||
$("#save-modal").modal();
|
||||
@@ -244,15 +254,24 @@ ControlsWaiter.prototype.loadClick = function() {
|
||||
* Saves the recipe specified in the save textarea to local storage.
|
||||
*/
|
||||
ControlsWaiter.prototype.saveButtonClick = function() {
|
||||
var recipeName = document.getElementById("save-name").value,
|
||||
recipeStr = document.getElementById("save-text").value;
|
||||
if (!this.app.isLocalStorageAvailable()) {
|
||||
this.app.alert(
|
||||
"Your security settings do not allow access to local storage so your recipe cannot be saved.",
|
||||
"danger",
|
||||
5000
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
|
||||
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
|
||||
|
||||
if (!recipeName) {
|
||||
this.app.alert("Please enter a recipe name", "danger", 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
var savedRecipes = localStorage.savedRecipes ?
|
||||
let savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [],
|
||||
recipeId = localStorage.recipeId || 0;
|
||||
|
||||
@@ -273,22 +292,25 @@ ControlsWaiter.prototype.saveButtonClick = function() {
|
||||
* Populates the list of saved recipes in the load dialog box from local storage.
|
||||
*/
|
||||
ControlsWaiter.prototype.populateLoadRecipesList = function() {
|
||||
var loadNameEl = document.getElementById("load-name");
|
||||
if (!this.app.isLocalStorageAvailable()) return false;
|
||||
|
||||
const loadNameEl = document.getElementById("load-name");
|
||||
|
||||
// Remove current recipes from select
|
||||
var i = loadNameEl.options.length;
|
||||
let i = loadNameEl.options.length;
|
||||
while (i--) {
|
||||
loadNameEl.remove(i);
|
||||
}
|
||||
|
||||
// Add recipes to select
|
||||
var savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
const savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
|
||||
for (i = 0; i < savedRecipes.length; i++) {
|
||||
var opt = document.createElement("option");
|
||||
const opt = document.createElement("option");
|
||||
opt.value = savedRecipes[i].id;
|
||||
opt.innerHTML = savedRecipes[i].name;
|
||||
// Unescape then re-escape in case localStorage has been corrupted
|
||||
opt.innerHTML = Utils.escapeHtml(Utils.unescapeHtml(savedRecipes[i].name));
|
||||
|
||||
loadNameEl.appendChild(opt);
|
||||
}
|
||||
@@ -302,13 +324,13 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
|
||||
* Removes the currently selected recipe from local storage.
|
||||
*/
|
||||
ControlsWaiter.prototype.loadDeleteClick = function() {
|
||||
var id = parseInt(document.getElementById("load-name").value, 10),
|
||||
savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
if (!this.app.isLocalStorageAvailable()) return false;
|
||||
|
||||
savedRecipes = savedRecipes.filter(function(r) {
|
||||
return r.id !== id;
|
||||
});
|
||||
const id = parseInt(document.getElementById("load-name").value, 10);
|
||||
const rawSavedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
|
||||
const savedRecipes = rawSavedRecipes.filter(r => r.id !== id);
|
||||
|
||||
localStorage.savedRecipes = JSON.stringify(savedRecipes);
|
||||
this.populateLoadRecipesList();
|
||||
@@ -319,14 +341,14 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
|
||||
* Displays the selected recipe in the load text box.
|
||||
*/
|
||||
ControlsWaiter.prototype.loadNameChange = function(e) {
|
||||
var el = e.target,
|
||||
savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [],
|
||||
id = parseInt(el.value, 10);
|
||||
if (!this.app.isLocalStorageAvailable()) return false;
|
||||
|
||||
var recipe = savedRecipes.filter(function(r) {
|
||||
return r.id === id;
|
||||
})[0];
|
||||
const el = e.target;
|
||||
const savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
const id = parseInt(el.value, 10);
|
||||
|
||||
const recipe = savedRecipes.find(r => r.id === id);
|
||||
|
||||
document.getElementById("load-text").value = recipe.recipe;
|
||||
};
|
||||
@@ -337,8 +359,9 @@ ControlsWaiter.prototype.loadNameChange = function(e) {
|
||||
*/
|
||||
ControlsWaiter.prototype.loadButtonClick = function() {
|
||||
try {
|
||||
var recipeConfig = JSON.parse(document.getElementById("load-text").value);
|
||||
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
|
||||
this.app.setRecipeConfig(recipeConfig);
|
||||
this.app.autoBake();
|
||||
|
||||
$("#rec-list [data-toggle=popover]").popover();
|
||||
} catch (e) {
|
||||
@@ -349,14 +372,66 @@ ControlsWaiter.prototype.loadButtonClick = function() {
|
||||
|
||||
/**
|
||||
* Populates the bug report information box with useful technical info.
|
||||
*
|
||||
* @param {event} e
|
||||
*/
|
||||
ControlsWaiter.prototype.supportButtonClick = function() {
|
||||
var reportBugInfo = document.getElementById("report-bug-info"),
|
||||
saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
|
||||
ControlsWaiter.prototype.supportButtonClick = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
reportBugInfo.innerHTML = "* CyberChef compile time: " + COMPILE_TIME + "\n" +
|
||||
"* User-Agent: \n" + navigator.userAgent + "\n" +
|
||||
"* [Link to reproduce](" + saveLink + ")\n\n";
|
||||
const reportBugInfo = document.getElementById("report-bug-info");
|
||||
const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
|
||||
|
||||
if (reportBugInfo) {
|
||||
reportBugInfo.innerHTML = "* Version: " + PKG_VERSION + "\n" +
|
||||
"* Compile time: " + COMPILE_TIME + "\n" +
|
||||
"* User-Agent: \n" + navigator.userAgent + "\n" +
|
||||
"* [Link to reproduce](" + saveLink + ")\n\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows the stale indicator to show that the input or recipe has changed
|
||||
* since the last bake.
|
||||
*/
|
||||
ControlsWaiter.prototype.showStaleIndicator = function() {
|
||||
const staleIndicator = document.getElementById("stale-indicator");
|
||||
|
||||
staleIndicator.style.visibility = "visible";
|
||||
staleIndicator.style.opacity = 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hides the stale indicator to show that the input or recipe has not changed
|
||||
* since the last bake.
|
||||
*/
|
||||
ControlsWaiter.prototype.hideStaleIndicator = function() {
|
||||
const staleIndicator = document.getElementById("stale-indicator");
|
||||
|
||||
staleIndicator.style.opacity = 0;
|
||||
staleIndicator.style.visibility = "hidden";
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Switches the Bake button between 'Bake' and 'Cancel' functions.
|
||||
*
|
||||
* @param {boolean} cancel - Whether to change to cancel or not
|
||||
*/
|
||||
ControlsWaiter.prototype.toggleBakeButtonFunction = function(cancel) {
|
||||
const bakeButton = document.getElementById("bake"),
|
||||
btnText = bakeButton.querySelector("span");
|
||||
|
||||
if (cancel) {
|
||||
btnText.innerText = "Cancel";
|
||||
bakeButton.classList.remove("btn-success");
|
||||
bakeButton.classList.add("btn-danger");
|
||||
} else {
|
||||
btnText.innerText = "Bake!";
|
||||
bakeButton.classList.remove("btn-danger");
|
||||
bakeButton.classList.add("btn-success");
|
||||
}
|
||||
};
|
||||
|
||||
export default ControlsWaiter;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* @param {string} name - The name of the category.
|
||||
* @param {boolean} selected - Whether this category is pre-selected or not.
|
||||
*/
|
||||
var HTMLCategory = function(name, selected) {
|
||||
const HTMLCategory = function(name, selected) {
|
||||
this.name = name;
|
||||
this.selected = selected;
|
||||
this.opList = [];
|
||||
@@ -32,8 +32,8 @@ HTMLCategory.prototype.addOperation = function(operation) {
|
||||
* @returns {string}
|
||||
*/
|
||||
HTMLCategory.prototype.toHtml = function() {
|
||||
var catName = "cat" + this.name.replace(/[\s/-:_]/g, "");
|
||||
var html = "<div class='panel category'>\
|
||||
const catName = "cat" + this.name.replace(/[\s/-:_]/g, "");
|
||||
let html = "<div class='panel category'>\
|
||||
<a class='category-title' data-toggle='collapse'\
|
||||
data-parent='#categories' href='#" + catName + "'>\
|
||||
" + this.name + "\
|
||||
@@ -41,7 +41,7 @@ HTMLCategory.prototype.toHtml = function() {
|
||||
<div id='" + catName + "' class='panel-collapse collapse\
|
||||
" + (this.selected ? " in" : "") + "'><ul class='op-list'>";
|
||||
|
||||
for (var i = 0; i < this.opList.length; i++) {
|
||||
for (let i = 0; i < this.opList.length; i++) {
|
||||
html += this.opList[i].toStubHtml();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
var HTMLIngredient = function(config, app, manager) {
|
||||
const HTMLIngredient = function(config, app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
|
||||
@@ -32,7 +32,7 @@ var HTMLIngredient = function(config, app, manager) {
|
||||
* @returns {string}
|
||||
*/
|
||||
HTMLIngredient.prototype.toHtml = function() {
|
||||
var inline = (this.type === "boolean" ||
|
||||
let inline = (this.type === "boolean" ||
|
||||
this.type === "number" ||
|
||||
this.type === "option" ||
|
||||
this.type === "shortString" ||
|
||||
@@ -158,15 +158,14 @@ HTMLIngredient.prototype.toHtml = function() {
|
||||
* @param {event} e
|
||||
*/
|
||||
HTMLIngredient.prototype.toggleDisableArgs = function(e) {
|
||||
var 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 (var i = 0; i < this.disableArgs.length; i++) {
|
||||
els = args[this.disableArgs[i]].querySelectorAll("input, select, button");
|
||||
for (let i = 0; i < this.disableArgs.length; i++) {
|
||||
const els = args[this.disableArgs[i]].querySelectorAll("input, select, button");
|
||||
|
||||
for (var j = 0; j < els.length; j++) {
|
||||
for (let j = 0; j < els.length; j++) {
|
||||
if (els[j].getAttribute("disabled")) {
|
||||
els[j].removeAttribute("disabled");
|
||||
} else {
|
||||
@@ -186,9 +185,9 @@ HTMLIngredient.prototype.toggleDisableArgs = function(e) {
|
||||
* @param {event} e
|
||||
*/
|
||||
HTMLIngredient.prototype.populateOptionChange = function(e) {
|
||||
var 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");
|
||||
|
||||
@@ -203,7 +202,7 @@ HTMLIngredient.prototype.populateOptionChange = function(e) {
|
||||
* @param {event} e
|
||||
*/
|
||||
HTMLIngredient.prototype.editableOptionChange = function(e) {
|
||||
var select = e.target,
|
||||
let select = e.target,
|
||||
input = select.nextSibling;
|
||||
|
||||
input.value = select.childNodes[select.selectedIndex].value;
|
||||
|
||||
@@ -14,7 +14,7 @@ import HTMLIngredient from "./HTMLIngredient.js";
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
var HTMLOperation = function(name, config, app, manager) {
|
||||
const HTMLOperation = function(name, config, app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
|
||||
@@ -24,8 +24,8 @@ var HTMLOperation = function(name, config, app, manager) {
|
||||
this.config = config;
|
||||
this.ingList = [];
|
||||
|
||||
for (var i = 0; i < config.args.length; i++) {
|
||||
var ing = new HTMLIngredient(config.args[i], this.app, this.manager);
|
||||
for (let i = 0; i < config.args.length; i++) {
|
||||
const ing = new HTMLIngredient(config.args[i], this.app, this.manager);
|
||||
this.ingList.push(ing);
|
||||
}
|
||||
};
|
||||
@@ -47,7 +47,7 @@ HTMLOperation.REMOVE_ICON = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABwkl
|
||||
* @returns {string}
|
||||
*/
|
||||
HTMLOperation.prototype.toStubHtml = function(removeIcon) {
|
||||
var html = "<li class='operation'";
|
||||
let html = "<li class='operation'";
|
||||
|
||||
if (this.description) {
|
||||
html += " data-container='body' data-toggle='popover' data-placement='auto right'\
|
||||
@@ -77,9 +77,9 @@ HTMLOperation.prototype.toStubHtml = function(removeIcon) {
|
||||
* @returns {string}
|
||||
*/
|
||||
HTMLOperation.prototype.toFullHtml = function() {
|
||||
var html = "<div class='arg-title'>" + this.name + "</div>";
|
||||
let html = "<div class='arg-title'>" + this.name + "</div>";
|
||||
|
||||
for (var i = 0; i < this.ingList.length; i++) {
|
||||
for (let i = 0; i < this.ingList.length; i++) {
|
||||
html += this.ingList[i].toHtml();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import Utils from "../core/Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
* Waiter to handle events related to highlighting in CyberChef.
|
||||
*
|
||||
@@ -10,9 +7,11 @@ import Utils from "../core/Utils.js";
|
||||
*
|
||||
* @constructor
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
var HighlighterWaiter = function(app) {
|
||||
const HighlighterWaiter = function(app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
|
||||
this.mouseButtonDown = false;
|
||||
this.mouseTarget = null;
|
||||
@@ -41,11 +40,11 @@ HighlighterWaiter.OUTPUT = 1;
|
||||
* @returns {boolean}
|
||||
*/
|
||||
HighlighterWaiter.prototype._isSelectionBackwards = function() {
|
||||
var backwards = false,
|
||||
let backwards = false,
|
||||
sel = window.getSelection();
|
||||
|
||||
if (!sel.isCollapsed) {
|
||||
var range = document.createRange();
|
||||
const range = document.createRange();
|
||||
range.setStart(sel.anchorNode, sel.anchorOffset);
|
||||
range.setEnd(sel.focusNode, sel.focusOffset);
|
||||
backwards = range.collapsed;
|
||||
@@ -64,8 +63,8 @@ HighlighterWaiter.prototype._isSelectionBackwards = function() {
|
||||
* @returns {number}
|
||||
*/
|
||||
HighlighterWaiter.prototype._getOutputHtmlOffset = function(node, offset) {
|
||||
var 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 +84,8 @@ HighlighterWaiter.prototype._getOutputHtmlOffset = function(node, offset) {
|
||||
* @returns {number} pos.end
|
||||
*/
|
||||
HighlighterWaiter.prototype._getOutputHtmlSelectionOffsets = function() {
|
||||
var sel = window.getSelection(),
|
||||
range,
|
||||
const sel = window.getSelection();
|
||||
let range,
|
||||
start = 0,
|
||||
end = 0,
|
||||
backwards = false;
|
||||
@@ -121,7 +120,7 @@ HighlighterWaiter.prototype._getOutputHtmlSelectionOffsets = function() {
|
||||
* @param {event} e
|
||||
*/
|
||||
HighlighterWaiter.prototype.inputScroll = function(e) {
|
||||
var el = e.target;
|
||||
const el = e.target;
|
||||
document.getElementById("input-highlighter").scrollTop = el.scrollTop;
|
||||
document.getElementById("input-highlighter").scrollLeft = el.scrollLeft;
|
||||
};
|
||||
@@ -134,7 +133,7 @@ HighlighterWaiter.prototype.inputScroll = function(e) {
|
||||
* @param {event} e
|
||||
*/
|
||||
HighlighterWaiter.prototype.outputScroll = function(e) {
|
||||
var el = e.target;
|
||||
const el = e.target;
|
||||
document.getElementById("output-highlighter").scrollTop = el.scrollTop;
|
||||
document.getElementById("output-highlighter").scrollLeft = el.scrollLeft;
|
||||
};
|
||||
@@ -151,9 +150,9 @@ HighlighterWaiter.prototype.inputMousedown = function(e) {
|
||||
this.mouseTarget = HighlighterWaiter.INPUT;
|
||||
this.removeHighlights();
|
||||
|
||||
var 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 +172,9 @@ HighlighterWaiter.prototype.outputMousedown = function(e) {
|
||||
this.mouseTarget = HighlighterWaiter.OUTPUT;
|
||||
this.removeHighlights();
|
||||
|
||||
var 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);
|
||||
@@ -194,7 +193,7 @@ HighlighterWaiter.prototype.outputHtmlMousedown = function(e) {
|
||||
this.mouseButtonDown = true;
|
||||
this.mouseTarget = HighlighterWaiter.OUTPUT;
|
||||
|
||||
var sel = this._getOutputHtmlSelectionOffsets();
|
||||
const sel = this._getOutputHtmlSelectionOffsets();
|
||||
if (sel.start !== 0 || sel.end !== 0) {
|
||||
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(sel.start, sel.end);
|
||||
}
|
||||
@@ -244,9 +243,9 @@ HighlighterWaiter.prototype.inputMousemove = function(e) {
|
||||
this.mouseTarget !== HighlighterWaiter.INPUT)
|
||||
return;
|
||||
|
||||
var 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 +267,9 @@ HighlighterWaiter.prototype.outputMousemove = function(e) {
|
||||
this.mouseTarget !== HighlighterWaiter.OUTPUT)
|
||||
return;
|
||||
|
||||
var 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);
|
||||
@@ -292,7 +291,7 @@ HighlighterWaiter.prototype.outputHtmlMousemove = function(e) {
|
||||
this.mouseTarget !== HighlighterWaiter.OUTPUT)
|
||||
return;
|
||||
|
||||
var sel = this._getOutputHtmlSelectionOffsets();
|
||||
const sel = this._getOutputHtmlSelectionOffsets();
|
||||
if (sel.start !== 0 || sel.end !== 0) {
|
||||
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(sel.start, sel.end);
|
||||
}
|
||||
@@ -308,11 +307,11 @@ HighlighterWaiter.prototype.outputHtmlMousemove = function(e) {
|
||||
* @returns {string}
|
||||
*/
|
||||
HighlighterWaiter.prototype.selectionInfo = function(start, end) {
|
||||
var width = end.toString().length;
|
||||
width = width < 2 ? 2 : width;
|
||||
var startStr = Utils.pad(start.toString(), width, " ").replace(/ /g, " "),
|
||||
endStr = Utils.pad(end.toString(), width, " ").replace(/ /g, " "),
|
||||
lenStr = Utils.pad((end-start).toString(), width, " ").replace(/ /g, " ");
|
||||
const len = end.toString().length;
|
||||
const width = len < 2 ? 2 : len;
|
||||
const startStr = start.toString().padStart(width, " ").replace(/ /g, " ");
|
||||
const endStr = end.toString().padStart(width, " ").replace(/ /g, " ");
|
||||
const lenStr = (end-start).toString().padStart(width, " ").replace(/ /g, " ");
|
||||
|
||||
return "start: " + startStr + "<br>end: " + endStr + "<br>length: " + lenStr;
|
||||
};
|
||||
@@ -329,41 +328,6 @@ HighlighterWaiter.prototype.removeHighlights = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
|
||||
* entire recipe supports highlighting.
|
||||
*
|
||||
* @returns {Object[]} highlights
|
||||
* @returns {function} highlights[].f
|
||||
* @returns {function} highlights[].b
|
||||
* @returns {Object[]} highlights[].args
|
||||
*/
|
||||
HighlighterWaiter.prototype.generateHighlightList = function() {
|
||||
var recipeConfig = this.app.getRecipeConfig(),
|
||||
highlights = [];
|
||||
|
||||
for (var i = 0; i < recipeConfig.length; i++) {
|
||||
if (recipeConfig[i].disabled) continue;
|
||||
|
||||
// If any breakpoints are set, do not attempt to highlight
|
||||
if (recipeConfig[i].breakpoint) return false;
|
||||
|
||||
var op = this.app.operations[recipeConfig[i].op];
|
||||
|
||||
// If any of the operations do not support highlighting, fail immediately.
|
||||
if (op.highlight === false || op.highlight === undefined) return false;
|
||||
|
||||
highlights.push({
|
||||
f: op.highlight,
|
||||
b: op.highlightReverse,
|
||||
args: recipeConfig[i].args
|
||||
});
|
||||
}
|
||||
|
||||
return highlights;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Highlights the given offsets in the output.
|
||||
* We will only highlight if:
|
||||
@@ -376,26 +340,8 @@ HighlighterWaiter.prototype.generateHighlightList = function() {
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
HighlighterWaiter.prototype.highlightOutput = function(pos) {
|
||||
var highlights = this.generateHighlightList();
|
||||
|
||||
if (!highlights || !this.app.autoBake_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < highlights.length; i++) {
|
||||
// Remove multiple highlights before processing again
|
||||
pos = [pos[0]];
|
||||
|
||||
if (typeof highlights[i].f == "function") {
|
||||
pos = highlights[i].f(pos, highlights[i].args);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
|
||||
this.highlight(
|
||||
document.getElementById("output-text"),
|
||||
document.getElementById("output-highlighter"),
|
||||
pos);
|
||||
if (!this.app.autoBake_ || this.app.baking) return false;
|
||||
this.manager.worker.highlight(this.app.getRecipeConfig(), "forward", pos);
|
||||
};
|
||||
|
||||
|
||||
@@ -411,25 +357,28 @@ HighlighterWaiter.prototype.highlightOutput = function(pos) {
|
||||
* @param {number} pos.end - The end offset.
|
||||
*/
|
||||
HighlighterWaiter.prototype.highlightInput = function(pos) {
|
||||
var highlights = this.generateHighlightList();
|
||||
if (!this.app.autoBake_ || this.app.baking) return false;
|
||||
this.manager.worker.highlight(this.app.getRecipeConfig(), "reverse", pos);
|
||||
};
|
||||
|
||||
if (!highlights || !this.app.autoBake_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < highlights.length; i++) {
|
||||
// Remove multiple highlights before processing again
|
||||
pos = [pos[0]];
|
||||
/**
|
||||
* Displays highlight offsets sent back from the Chef.
|
||||
*
|
||||
* @param {Object} pos - The position object for the highlight.
|
||||
* @param {number} pos.start - The start offset.
|
||||
* @param {number} pos.end - The end offset.
|
||||
* @param {string} direction
|
||||
*/
|
||||
HighlighterWaiter.prototype.displayHighlights = function(pos, direction) {
|
||||
if (!pos) return;
|
||||
|
||||
if (typeof highlights[i].b == "function") {
|
||||
pos = highlights[i].b(pos, highlights[i].args);
|
||||
}
|
||||
}
|
||||
const io = direction === "forward" ? "output" : "input";
|
||||
|
||||
document.getElementById("input-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
|
||||
document.getElementById(io + "-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
|
||||
this.highlight(
|
||||
document.getElementById("input-text"),
|
||||
document.getElementById("input-highlighter"),
|
||||
document.getElementById(io + "-text"),
|
||||
document.getElementById(io + "-highlighter"),
|
||||
pos);
|
||||
};
|
||||
|
||||
@@ -450,13 +399,13 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
|
||||
|
||||
// Check if there is a carriage return in the output dish as this will not
|
||||
// be displayed by the HTML textarea and will mess up highlighting offsets.
|
||||
if (!this.app.dishStr || this.app.dishStr.indexOf("\r") >= 0) return false;
|
||||
if (this.manager.output.containsCR()) return false;
|
||||
|
||||
var 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
|
||||
@@ -468,11 +417,11 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
|
||||
text.slice(pos[0].end, text.length);
|
||||
} else {
|
||||
// O(n^2) - Can anyone improve this without overwriting placeholders?
|
||||
var result = "",
|
||||
let result = "",
|
||||
endPlaced = true;
|
||||
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
for (var j = 1; j < pos.length; j++) {
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
for (let j = 1; j < pos.length; j++) {
|
||||
if (pos[j].end < pos[j].start) continue;
|
||||
if (pos[j].start === i) {
|
||||
result += startPlaceholder;
|
||||
@@ -489,17 +438,18 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
|
||||
text = result;
|
||||
}
|
||||
|
||||
var cssClass = "hl1";
|
||||
const cssClass = "hl1";
|
||||
//if (colour) cssClass += "-"+colour;
|
||||
|
||||
// Remove HTML tags
|
||||
text = text.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\n/g, " ")
|
||||
// Convert placeholders to tags
|
||||
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
|
||||
.replace(endPlaceholderRegex, "</span>") + " ";
|
||||
text = text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\n/g, " ")
|
||||
// Convert placeholders to tags
|
||||
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
|
||||
.replace(endPlaceholderRegex, "</span>") + " ";
|
||||
|
||||
// Adjust width to allow for scrollbars
|
||||
highlighter.style.width = textarea.clientWidth + "px";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user