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

Compare commits

...

410 Commits

Author SHA1 Message Date
n1474335
4c40c6fa74 9.0.0 2019-07-09 14:34:13 +01:00
n1474335
fe6d86622b Updated CHANGELOG 2019-07-09 14:32:28 +01:00
n1474335
d1ad2d0845 Rejigged grunt tasks. 2019-07-09 14:31:18 +01:00
n1474335
29cb273d08 Fixed module replacement issue. 2019-07-09 13:42:42 +01:00
n1474335
566517d20f Imports now specify the file extension to support Node v12 2019-07-09 12:23:59 +01:00
n1474335
d7d50337f9 Fixed node tests and config generation for node v12 2019-07-05 14:47:05 +01:00
d98762625
0de89f3145 Merge branch 'v9' of github.com:gchq/CyberChef into node-lib 2019-07-05 13:10:44 +01:00
n1474335
aa362ba18b Removed async from detectDishType 2019-07-05 12:41:47 +01:00
n1474335
b272d3b32f Linted to satisfy new rules 2019-07-05 12:36:15 +01:00
n1474335
e4e32a9c56 Merge branch 'master' into v9 2019-07-05 12:30:28 +01:00
n1474335
4bae718f40 8.38.2 2019-07-05 12:23:02 +01:00
n1474335
5eb3979504 Updated dependencies and linter 2019-07-05 12:22:52 +01:00
d98762625
e03ff22ba8 update more ENVIRONMENT_IS_* calls after merge, update some test paths, comments. Remove vulnerability 2019-07-05 11:35:59 +01:00
d98762625
368f508b17 Merge branch 'v9' of github.com:gchq/CyberChef into node-lib 2019-07-05 11:07:31 +01:00
d98762625
a1cf20bd67 gitignore fix 2019-07-05 10:24:29 +01:00
d98762625
d2ff2ec9c6 improve comments and re-add some excluded operations 2019-07-05 10:22:14 +01:00
d98762625
1c24c05647 swap ENVIRONMENT_IS_* functions for Utils named exports 2019-07-05 10:17:52 +01:00
d98762625
c70f14419a rename dishTranslationTypes 2019-07-05 09:44:01 +01:00
n1474335
80386f1c86 Merge branch 'master' into v9 2019-07-04 18:44:07 +01:00
n1474335
4f70a79638 8.38.1 2019-07-04 18:43:47 +01:00
n1474335
080886a2d1 Added support for psb, hdr, arw, raf, mrw, bct, mdi, au, auf, aif, aifc, arj, ace, hqx, alz, kgb, and torrent file detection. 2019-07-04 18:43:38 +01:00
n1474335
5f9112b565 Merge branch 'j433866-multiple-input-files' into v9 2019-07-04 15:44:16 +01:00
n1474335
2007cfd3a0 Improved efficiency of Dish title generation 2019-07-04 15:43:50 +01:00
n1474335
e49974beaa Merge branch 'multiple-input-files' of https://github.com/j433866/CyberChef into j433866-multiple-input-files 2019-07-04 13:52:26 +01:00
n1474335
e863c8c549 Fixed typo in CHANGELOG 2019-07-03 17:34:17 +01:00
n1474335
e4b4e8afca Added Streebog and GOST to 'Generate all hashes' op 2019-07-03 17:33:27 +01:00
n1474335
4d4ebf7279 8.38.0 2019-07-03 17:28:23 +01:00
n1474335
892632a814 Updated CHANGELOG 2019-07-03 17:28:19 +01:00
n1474335
2ba6a3fd8d Merge branch 'MShwed-feature/streebog-hash' 2019-07-03 17:24:23 +01:00
n1474335
09bea6e231 Added 'GOST Hash' operation 2019-07-03 17:24:11 +01:00
n1474335
99f4091c1a Tidied up Streebog operation, splitting out GOST hash into a separate op. 2019-07-03 17:23:45 +01:00
j433866
6964bbc232 Improve layout of addInput parameters. 2019-07-03 16:15:14 +01:00
j433866
367d30e421 Use reduce for finding previous and next inputNums 2019-07-03 16:09:48 +01:00
j433866
30a66f1441 Use reduce to find smallest and largest inputNums.
Tab shadows are now displayed using css classes
2019-07-03 16:05:20 +01:00
n1474335
666c447e36 Merge branch 'feature/streebog-hash' of https://github.com/MShwed/CyberChef into MShwed-feature/streebog-hash 2019-07-03 15:21:44 +01:00
n1474335
a43dff558a 8.37.0 2019-07-03 15:10:03 +01:00
n1474335
f39006ea1d Updated CHANGELOG 2019-07-03 15:09:59 +01:00
n1474335
2355ef9d31 Merge branch 'MShwed-feature/crc-8-checksum' 2019-07-03 15:07:38 +01:00
n1474335
13b0ab73d0 Tidied up CRC-8 operation and added it to 'Generate all hashes' 2019-07-03 15:07:26 +01:00
n1474335
3766982734 Merge branch 'feature/crc-8-checksum' of https://github.com/MShwed/CyberChef into MShwed-feature/crc-8-checksum 2019-07-03 14:54:41 +01:00
n1474335
54a864e18c 8.36.1 2019-07-03 14:50:23 +01:00
n1474335
9a1f4e40dd Merge branch 'MShwed-bugfix/missing-html-entities' 2019-07-03 14:50:15 +01:00
n1474335
5a83ef4f48 Tidied up HTML Entity operations 2019-07-03 14:49:57 +01:00
j433866
b3fa1eaae2 Fix output heights being incorrect 2019-07-03 14:24:05 +01:00
j433866
6d95cb01c8 Change tab element height using stylesheet.
Debounce bake button function changes.
2019-07-03 13:52:56 +01:00
j433866
a7eefa88fa Merge remote-tracking branch 'upstream/master' into multiple-input-files 2019-07-03 13:20:21 +01:00
n1474335
a7d4e37851 Merge branch 'bugfix/missing-html-entities' of https://github.com/MShwed/CyberChef into MShwed-bugfix/missing-html-entities 2019-07-03 12:43:58 +01:00
n1474335
57e71f0e1a 8.36.0 2019-07-03 12:41:59 +01:00
n1474335
30be3cab53 Updated CHANGELOG 2019-07-03 12:41:52 +01:00
n1474335
0e6626bf39 Merge branch 'pgp-verify' of https://github.com/artemisbot/CyberChef into artemisbot-pgp-verify 2019-07-03 12:38:10 +01:00
n1474335
bb0eaf4597 8.35.0 2019-07-03 12:34:17 +01:00
n1474335
8ada3bae0c Updated CHANGELOG 2019-07-03 12:34:13 +01:00
n1474335
db72cad610 Merge branch 'more-image-ops' of https://github.com/j433866/CyberChef into j433866-more-image-ops 2019-07-03 12:24:03 +01:00
j433866
455b42aa85 Fix whitespace and comment typos.
Add comment to inputworker default values.
2019-07-03 11:53:38 +01:00
j433866
2d95092479 Remove no file extension error 2019-07-03 11:45:36 +01:00
j433866
0f87c70cee Add comma to CSS rule 2019-07-03 11:41:31 +01:00
j433866
4312d39624 Show or hide thumbnail when the option is changed. 2019-07-03 11:41:22 +01:00
j433866
cf500b7296 Fix getInputValue not returning inputs that are arraybuffers 2019-07-03 11:39:24 +01:00
j433866
7a0180213d Update inputWorker description 2019-07-03 10:34:15 +01:00
j433866
160e4a0479 Change ZipWorker to use Dish.get() 2019-07-03 10:34:02 +01:00
j433866
bed66298d1 Change jpeg test data to be a full image 2019-07-03 08:53:44 +01:00
mshwed
44643c151a Fixed linting issues and added CRC-8 tests 2019-07-02 15:30:59 -04:00
mshwed
bc1bd2427d Added checksum calculation and helper functions 2019-07-02 15:13:11 -04:00
j433866
1135ca5fb4 Remove duplicate function.
Fix reading QR codes with transparent backgrounds
2019-07-02 16:31:26 +01:00
j433866
be08a62f52 Add webpack config for font files 2019-07-02 15:31:29 +01:00
j433866
f473807459 Bring up to date with master 2019-07-02 14:23:17 +01:00
j433866
3a197379d5 Remove unused self.port variable 2019-07-02 13:44:04 +01:00
j433866
a9f8dac656 Fix stepping.
Move stepping logic into App.
Change toggleBakeButtonFunction to use a str instead of booleans.
Tidy up handleLoaderMessage in InputWaiter.
2019-07-02 12:23:46 +01:00
j433866
3dc57c4a4a Update copyright year on solarized themes 2019-07-02 10:35:06 +01:00
mshwed
4c9a61f5a7 Added bit reversal 2019-07-01 19:02:07 -04:00
j433866
ba4740a245 Correct documentation 2019-07-01 13:42:06 +01:00
j433866
86c37bab3f Clone dish instead of using the current dish.
Use Dish.STRING instead of "string" for get()
2019-07-01 13:41:48 +01:00
j433866
dd5038c15b Bring up to date with master 2019-07-01 11:51:17 +01:00
mshwed
550ab403f6 Initial operation setup 2019-06-30 21:28:00 -04:00
Matt
c46928aefe Added tests 2019-06-27 17:51:37 +01:00
Matt
4c27a46d35 Added PGP verify operation
Added some more metadata to decrypt & verify
Fixes gchq/CyberChef#581
2019-06-27 16:48:03 +01:00
mshwed
824d8e929a Fixed linting issues 2019-06-20 13:26:35 -04:00
mshwed
862d2adf1d Added missing HTML entities 2019-06-20 13:08:20 -04:00
j433866
906ece0c02 Remove loading files modal 2019-06-20 13:47:30 +01:00
j433866
0bcf57e89c Improve printing text to improve output quality.
Now resizes the text instead of the image
2019-06-20 12:58:02 +01:00
j433866
c529a406cd Fix switchClick not always being fired.
Run detectFileType on switched output
2019-06-18 15:10:51 +01:00
j433866
05d81eb734 Merge remote-tracking branch 'upstream/master' into multiple-input-files 2019-06-14 14:56:16 +01:00
j433866
370cae3c8d Fix incorrect value being sent to dishworker 2019-06-13 15:39:11 +01:00
j433866
5731f5c75c Add dishworker 2019-06-13 14:48:38 +01:00
j433866
34d03973f9 Improve queueing for getDish... messages.
Force wheel event to be not passive.
Change maxworkers to be navigator.hardwareConcurrency - 1
2019-06-13 14:48:28 +01:00
j433866
84204c1d12 Add mime type detection to tab title.
Move addition of close tab button back
2019-06-13 11:13:53 +01:00
j433866
6ee76e3bf0 Add getDishTitle function 2019-06-13 09:43:58 +01:00
j433866
f497dc3170 Handle progressMessage in background waiter.
Don't update tab progress if there's no set recipe
2019-06-11 10:01:40 +01:00
j433866
749ffdd5d1 Move input tab code 2019-06-11 09:50:29 +01:00
j433866
713f10e63a Turn input tabs into progress bars 2019-06-10 16:07:01 +01:00
j433866
9d60ef5f72 Turn output tabs into progress bars! 2019-06-10 15:39:21 +01:00
j433866
5a52e5e9b3 Remove new lines from input tab header 2019-06-10 13:08:03 +01:00
j433866
d99cf9d499 Use function in TabWaiter 2019-06-10 13:03:07 +01:00
j433866
be0e12589d Display preview of output in output tab headers.
Remove unused argument from setLogLevel()
2019-06-10 12:47:27 +01:00
j433866
ad982746dd Display recipe progress in status message 2019-06-07 13:52:47 +01:00
j433866
8c2cc5b6d2 Improve removing tabs experience 2019-06-07 13:52:04 +01:00
j433866
97f86af6b9 Improve speed of changing input tabs.
Handle not finding an active tab
2019-06-06 16:53:58 +01:00
j433866
c2087f6d5f Move tab logic into a new TabWaiter 2019-06-06 16:33:35 +01:00
j433866
98af95a6ce Change pasting to keep cursor position.
Move output scrolling to changeTab() instead of set()
2019-06-06 10:26:16 +01:00
j433866
39101610d5 Scroll I/O areas to the top when switching tabs 2019-06-06 09:33:51 +01:00
j433866
b77239fc15 Move waiters and workers into separate folders. 2019-06-06 09:09:48 +01:00
j433866
31a3af1f84 Remove step and progress from Chef.
It's now all handled by the App!
2019-06-04 14:02:45 +01:00
j433866
0e5944e9c6 Set URL input parameter when setting input.
(e.g. when tab changed or removed)
2019-06-04 11:59:44 +01:00
j433866
99e9df0211 Holding down on tab change buttons will scroll.
Hide loading stats when there's only one input
2019-06-04 11:42:27 +01:00
j433866
15b5cf7c20 Correctly handle clicking cancel on go to dialog 2019-06-04 09:41:47 +01:00
j433866
f55102716e Add min / max tabs to go to tab dialog (output) 2019-06-04 09:39:47 +01:00
j433866
17b95f1609 Add min / max inputNums on go to tab dialog 2019-06-04 09:36:50 +01:00
j433866
2575a762e1 Make input and output tab areas scrollable 2019-06-03 16:10:05 +01:00
j433866
f5cf7bb1f2 Rename 'move output to input' to 'replace input with output'
Shrink close tab buttons
2019-06-03 15:37:14 +01:00
j433866
d3e8616e90 Add close all tabs button to input tab dropdown 2019-06-03 15:12:59 +01:00
j433866
87dc325932 Move debouncer to App.
Debounce drag of splitter and window resize
2019-06-03 14:59:41 +01:00
j433866
eb91dd7a7d Add documentation for getURIParams 2019-06-03 14:23:00 +01:00
j433866
89c4f54ce8 Only show bake stats when theres more than 1 input
Better handle canceling a bake when inputs are loading
Don't create chefworkers if we don't need them
Fix capitalisation of bake stats
2019-06-03 14:09:03 +01:00
j433866
b3cb800f35 Default inputNum to -1 when one isn't sent.
Improve jsdoc comments
2019-06-03 14:01:00 +01:00
j433866
4a0f62b636 Change getLargest/getSmallest to use a for loop.
Math.max() and Math.min() were exceeding call stack size
2019-06-03 13:48:49 +01:00
j433866
bcaefe39aa Improve transferable object syntax.
Fix capitalisation on loading info.
Improve error when an action isnt sent by inputworker
2019-06-03 11:20:06 +01:00
j433866
54bb17c109 Remove getAllInput() function.
Improve documentation.
2019-06-03 11:16:54 +01:00
j433866
dc74a389d8 Add documentation for inputNum.
Fix syntax for transferable objects.
2019-06-03 11:15:48 +01:00
j433866
784b3b58ca Fix to stop find tab CSS affecting operations 2019-06-03 11:15:10 +01:00
j433866
34b7c47533 Fix highlighting not working 2019-05-31 15:37:20 +01:00
j433866
d6a80b4865 Use toLocaleString for final bake stats 2019-05-31 09:59:23 +01:00
j433866
1d20fe13f3 Reset displayed load progress when clearing IO 2019-05-31 08:54:01 +01:00
j433866
7586c3ef8a Merge remote-tracking branch 'upstream/master' into multiple-input-files 2019-05-30 15:02:14 +01:00
j433866
b232069631 If a tab can't be added, show the shadow on the...
last tab to indicate there are more tabs
2019-05-30 14:32:05 +01:00
j433866
11d2a96ecb Pause for a second to allow autobake to finish.
Otherwise nightwatch was clicking cancel instead of bake
2019-05-30 14:18:34 +01:00
j433866
586e5a3db8 Further improvements to tab search UI 2019-05-30 14:08:02 +01:00
j433866
d94a431537 Improve searching for tabs UI.
Content / filename search is now a regex.
Use .toLocaleString() for loading / baking stats
2019-05-30 13:28:45 +01:00
j433866
9b2f44efb1 Turn extract click listener back on.
Add shadow to tabs when there are more tabs that aren't displayed
2019-05-29 16:29:34 +01:00
j433866
12e4fe4120 Fix clear all button breaking everything.
Rearrange baking a bit to hopefully fix firefox
2019-05-29 14:08:37 +01:00
j433866
476d9c8034 Remove unused parameter 2019-05-29 14:07:46 +01:00
j433866
85809efcc0 Adjust number of tabs shown when resizing window.
Improve refresh tabs logic.
Fix input not being shown when loaded from a URL
2019-05-29 13:25:12 +01:00
j433866
722edcc274 Display file size in header 2019-05-29 11:46:21 +01:00
j433866
919c3fd999 Fix display file slice displaying raw instead of presented data.
Fix errored filter when searching for tabs.
2019-05-28 15:01:49 +01:00
j433866
6c711ec211 Add and remove chefworkers when adding or removing inputs.
This increases the responsiveness of baking as it means we don't have to...
spin up workers when bake is clicked
2019-05-28 14:11:05 +01:00
j433866
7528065d4d Fix stepping again.
Add new getInput function to inputWorker
2019-05-28 11:59:57 +01:00
d98762625
79e2ca6284 remove symlink 2019-05-24 18:42:47 +01:00
d98762625
d22d22d24c Try and include symlink at project root to make deep import specifier easier 2019-05-24 17:48:38 +01:00
d98762625
1a9c9a5ddf Actually need to return the translation 2019-05-24 16:46:07 +01:00
j433866
0bced35931 Fix stepping again 2019-05-23 15:31:18 +01:00
j433866
4dcd60adc0 Improve handling of displaying large outputs.
Bring getDishStr and getDishBuffer back.
2019-05-23 15:29:58 +01:00
d98762625
d51e8ec378 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-05-23 15:07:28 +01:00
j433866
e95f92cdeb Bake inputs after clearing IO 2019-05-21 11:24:44 +01:00
j433866
cb86cb1882 Change baking to not send all inputs at once.
Add input debouncer.
Remove old HTML comments and unnecessary CSS
(Step is currently a bit broken!)
2019-05-20 16:53:56 +01:00
j433866
c50f5769db Add key bindings for tabs 2019-05-16 15:02:32 +01:00
j433866
6df9b649a1 Terminate zipworker when clearing all io 2019-05-16 13:04:04 +01:00
j433866
a750b0f08a Use transferable objects to send arraybuffers back to the workerwaiter 2019-05-16 10:42:27 +01:00
j433866
0e850b2a85 Fix stepping not working.
Use transferable object for sending arraybuffers to workers
2019-05-16 10:42:07 +01:00
j433866
d326cad611 Remove unused parameter 2019-05-16 09:38:34 +01:00
j433866
2ddb9b8f7c Remove unecessary progress item 2019-05-16 09:33:28 +01:00
j433866
6237db9ba6 Use detectFileType to autodetect file extensions in zip 2019-05-16 09:27:46 +01:00
j433866
0cff7bdd04 Improve handling of OperationErrors.
Make output filter refresh when changing stale or errored checkboxes
2019-05-15 16:24:49 +01:00
j433866
413e80ed3e Add clicking on output search result 2019-05-15 16:03:18 +01:00
j433866
5d52f4a760 Add searching for output tabs.
Remove all existing chefworkers before starting a bake.
Clear breakpoint when starting a bake
2019-05-15 09:37:07 +01:00
j433866
0855dc617f Add comments to inputWorker.
Slightly improve logic for getNearbyNums
2019-05-14 16:13:36 +01:00
j433866
04587a8a47 Merge branch 'multiple-input-files' of github.com:j433866/CyberChef into multiple-input-files 2019-05-14 11:45:22 +01:00
j433866
392b96dc34 Commenting 2019-05-14 11:45:13 +01:00
j433866
84cc3d16ed Fix close tab buttons not working in old firefox. 2019-05-10 16:54:28 +01:00
j433866
e34d521dcc Improve UI for searching for input tabs 2019-05-10 13:48:03 +01:00
j433866
2c02900edf Improve handling of errors.
Add parameter to some update functions for whether or not to set the output
2019-05-10 13:47:48 +01:00
j433866
f5442c307a Only set the input of the active input if the progress has changed.
Autobake when the input loads instead of when all load.
2019-05-10 13:45:27 +01:00
j433866
802879ced2 Merge pull request #2 from gchq/master
Bring branch up to date with gchq/master
2019-05-10 09:09:58 +01:00
j433866
aff0416405 Remove some comments 2019-05-09 09:07:28 +01:00
j433866
6d9a14feed Display when an input errors on load.
Autobake when all inputs have loaded.
Improve load experience.
2019-05-08 16:44:11 +01:00
j433866
3c2e5c143a Set bake button to "Loading..." when an autobake is started 2019-05-08 16:42:19 +01:00
j433866
cbf1d2feb0 Add specific handling for DOMExceptions 2019-05-08 16:42:06 +01:00
j433866
65bb7f32e9 Fix refreshTabs not always hiding the tab bar 2019-05-08 14:58:09 +01:00
j433866
3b8c365f7e Remove unused zip dependency 2019-05-08 14:48:37 +01:00
j433866
43747accd5 Change to add input tabs as inputs are added, instead of at the end.
Change outputWaiter to use outputExists instead of getOutput
2019-05-08 14:47:05 +01:00
j433866
50f9bbeac3 Make set() asynchronous 2019-05-08 13:46:29 +01:00
j433866
3cffd9334f Fix file slice not always being displayed 2019-05-08 12:54:55 +01:00
j433866
f72749304d Improve handling of errors in operations.
Remove unused dependencies.
2019-05-08 11:57:22 +01:00
j433866
689d08416b Don't create more ChefWorkers than we need. 2019-05-08 10:53:04 +01:00
j433866
28182713bf Fix showing slice of output not working.
Fix output status message not being reset.
Hide magic button when baking.
2019-05-08 10:10:14 +01:00
j433866
8190c7aac7 Add maximise output button 2019-05-07 15:36:42 +01:00
j433866
6268f091b8 Bring back moving the output into the input.
Change wording for download as zip button
2019-05-07 15:34:36 +01:00
j433866
cbfde7ddb1 Don't highlight if the input and output tab numbers are different 2019-05-07 14:33:38 +01:00
j433866
35d6c7d79e Bring highlighting back.
Fix backgroundMagic using output result instead of dish value
2019-05-07 14:20:18 +01:00
j433866
f1a2cf7efc Add cancellation of zipping 2019-05-07 12:00:53 +01:00
j433866
ec4eb22a72 Don't include loading inputs in complete percentage 2019-05-07 12:00:37 +01:00
j433866
97c218cb4c Fix where zipworker was using output presented result.
Now uses the raw dish value
2019-05-07 12:00:14 +01:00
j433866
07021b8dd5 Add new worker for zipping outputs.
Use bakeId to track which outputs are stale.
2019-05-07 09:26:55 +01:00
d98762625
aa9bf08157 amend comments, remove return type from Dish translate 2019-05-03 14:38:29 +01:00
d98762625
90dd7037c8 update TestRegister location for new tests 2019-05-03 13:54:10 +01:00
d98762625
6084759907 Merge branch 'use-node-lts' into node-lib 2019-05-03 13:42:45 +01:00
d98762625
0a3d87dfe3 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-05-03 13:41:05 +01:00
d98762625
65a3897f87 add dish translation tests for node 2019-05-03 13:36:08 +01:00
j433866
df20196201 Fix magic not always working 2019-05-03 11:49:14 +01:00
j433866
e9d60f73f4 Fix some more autobake weirdness.
Input passed in the URL is now set on load.
Added a new progress bar.
2019-05-02 15:44:31 +01:00
j433866
8e9717906f Improve autobake further to behave more like it did before.
Improve generation of state URI.
2019-05-02 13:54:15 +01:00
j433866
82183bf204 Improve queueing of inputs to avoid baking the same input twice.
Fix generation of input URL.
Fix worker log levels not being set correctly.
2019-05-02 11:29:54 +01:00
j433866
b2406b0465 Run set() when a bake is cancelled.
This will make sure the output shows the most recently baked data,
and also shows the stale indicator if needed
2019-05-02 09:20:28 +01:00
j433866
1bdef97dc7 Wait for stale indicator to disappear before clicking bake.
As the new inputWorker is slower, nightwatch was clicking cancel and thus showing the stale indicator.
2019-05-01 17:09:13 +01:00
j433866
ff9c68db56 Update handling of bake errors.
Add preview thumbnail for image input.
2019-05-01 17:08:36 +01:00
j433866
1cedc94652 Fix status messages for baking 2019-05-01 15:19:01 +01:00
j433866
02bda3250b Fix magic button.
Fix download all files not working
2019-05-01 14:46:05 +01:00
j433866
f6f60e8203 Update LoaderWorker to not use messagechannels 2019-05-01 14:13:40 +01:00
j433866
55beb433f3 Go back to sending messages via the main thread.
A MessageChannel is faster on Chrome, but causes issues in Firefox.
Bake button now says "Loading..." when the inputWorker is gathering inputs for baking
2019-05-01 14:12:36 +01:00
j433866
2fff18cb61 Don't create a new loaderWorker until we need one.
This was causing issues on single core systems after I got rid of the active status as we had already reached the max number of workers.
Instead, we just create a loaderWorker when needed as loaderWorkers are small enough!
2019-04-30 15:23:41 +01:00
j433866
6d8bf3a08a Enable filter buttons in manager 2019-04-30 14:45:34 +01:00
j433866
13ee79a06b Add searching for inputs 2019-04-30 14:15:05 +01:00
j433866
b4208ede3b Add clear io button.
Fix some weirdness with removing tabs
2019-04-30 13:34:00 +01:00
j433866
a96cb3f99f Add clear all io button. 2019-04-30 13:18:22 +01:00
j433866
1f39a922d1 Reset bake button background when state changed 2019-04-30 12:58:29 +01:00
j433866
145fba5949 Input pasting now works 2019-04-30 11:48:01 +01:00
j433866
8cb86c364d Increase file limit 2019-04-26 15:19:17 +01:00
j433866
6d98014ad2 New max limit for files 2019-04-26 15:16:15 +01:00
j433866
1cf83c2485 Change baking to send all inputs individually.
Re-enable go to tab button.
Active tab is now autobaked on load completion.
Handle (ish) loaderWorker errors.
Improve load performance.
2019-04-26 15:15:44 +01:00
j433866
f638bd4ded If sending arraybuffer back, use a transferable object 2019-04-26 14:01:49 +01:00
j433866
7b169fb798 Add css for search box 2019-04-25 16:33:02 +01:00
j433866
406cbb0f41 Move input logic into a new worker (InputWorker)
Change OutputWaiter to use dict of outputs instead of list
LoaderWorker communicates with InputWorker using a messagechannel
2019-04-25 16:32:48 +01:00
d98762625
aeb08caf77 move NodeDish tests out into own file 2019-04-24 08:47:37 +01:00
j433866
6d8daac5ca Merge remote-tracking branch 'upstream/master' into multiple-input-files 2019-04-23 09:02:04 +01:00
j433866
82186c8592 Add search box for input tabs 2019-04-23 09:02:00 +01:00
j433866
f099a352b3 Change get input function calls 2019-04-23 09:01:25 +01:00
d98762625
de8c99eceb merge init-dish & update tests 2019-04-08 18:06:01 +01:00
d98762625
e764ddf0b8 update TestRegister references 2019-04-05 18:45:47 +01:00
d98762625
a210f951da more linting 2019-04-05 17:40:52 +01:00
d98762625
367532cf8d linting and comment for readFileSync 2019-04-05 17:35:20 +01:00
d98762625
d3e6200385 remove babel-polyfill and update plugins to work with uplifted version 2019-04-05 17:15:21 +01:00
d98762625
af504891e4 incorporate ArrayBuffer base Dish type. Add global file shim to node index. Fix Buffer -> ArrayBuffer transformation 2019-04-05 16:51:14 +01:00
j433866
bd3777f9de Change maximum file size in readme 2019-04-05 10:51:39 +01:00
d98762625
e4ee0fc397 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-04-04 15:21:52 +01:00
j433866
9690ccd8a0 Fix being unable to go to tab 1 2019-04-04 14:42:21 +01:00
j433866
0804647441 Load in the right order 2019-04-04 13:14:45 +01:00
j433866
76da287cca Bake in the right order 2019-04-04 13:13:38 +01:00
j433866
8739dd97d6 Change srcElement to target
(srcElement is non-standard)
2019-04-04 13:13:21 +01:00
d98762625
a7874cc351 improve naming in API 2019-04-04 11:28:46 +01:00
j433866
de21f14fd8 Move the tab buttons onto the tab bar 2019-04-04 10:57:01 +01:00
j433866
b90cca77a9 Fix more tab weirdness.
Move tab buttons onto tab bar.
Calculate size of maxTabs automatically on page load.
Display total execution time when a bake finishes.
2019-04-04 10:15:13 +01:00
j433866
1eadc08098 Fix some weirdness with tabs.
Adjust worker logic to avoid closing and reopening a worker as often
2019-04-03 16:05:10 +01:00
j433866
9df26b8c84 Output tabs now (mostly) work.
Add downloading files as an archive (needs work)
Add option for keeping the tabs in sync
2019-04-03 12:00:47 +01:00
j433866
e0c9aba25e Improve WorkerWaiter and OutputWaiter.
- Will run and display outputs in the output area as they're baked
- Creates output tabs
- Can change output tabs (only the first 4 at the moment)
2019-04-02 16:58:36 +01:00
j433866
2cb33bfec4 Bring up to date with master 2019-04-02 16:54:34 +01:00
j433866
2aad7647ef Add tab buttons (don't work yet).
Change some of the HTML around the tab bar
2019-04-02 16:53:15 +01:00
j433866
6430129b2a Remove some inputNum stuff for now 2019-04-02 16:52:43 +01:00
mshwed
4496d7762b Converted js files to mjs. Added test cases for hashing 2019-04-02 09:41:49 -04:00
mshwed
37389a62c1 Added support for hashing version 1994 and 2012. Added S-Box selection for 1994 version. Added length selection 2019-04-01 23:14:40 -04:00
mshwed
aef65620da Merge remote-tracking branch 'origin/master' into feature/streebog-hash 2019-04-01 21:57:33 -04:00
j433866
cd094d1475 Change "input-tabs" id to be for the actual ul element.
Automatically disable auto-bake if more than 20 files are input.
2019-04-01 16:15:09 +01:00
j433866
99bef09e0e Fix invalid file type error 2019-04-01 14:13:30 +01:00
j433866
c97e77c765 Merge with qr-improvements.
Change QR code ops to use ArrayBuffer.
Add new function to Utils to convert a string to arraybuffer.
2019-04-01 14:11:37 +01:00
j433866
e44a22e143 Change ops to use ArrayBuffer instead of byteArray 2019-04-01 10:54:46 +01:00
j433866
c2496fe63e Change to use Promise.all 2019-04-01 09:00:41 +01:00
j433866
7bf8467637 Add maximum limit to the thumbnail image size 2019-04-01 08:53:52 +01:00
j433866
eb5809fd17 Fix tab info not being updated in refreshTabs() 2019-03-29 14:51:11 +00:00
j433866
f6ab82faaf Fix file preview not working 2019-03-29 13:42:07 +00:00
j433866
0d8584f499 Merge with ui-improvements 2019-03-29 13:35:30 +00:00
j433866
c289e1beef Rewrite InputWaiter to be less messy.
Don't create a DOM element for every tab, just reuse the same ones.
Display file information while the files are loading.
(Output tabs no longer work)
2019-03-29 13:29:24 +00:00
mshwed
db491cbb09 Added initial hashing for Streebog GOST R 34.11-94 2019-03-28 11:46:04 -04:00
j433866
a2cc7a84db Sync output tabs to input tabs.
Output tabs are created when input tabs are.
Fix initial bake not working
2019-03-27 13:48:54 +00:00
j433866
90dd2b5ac2 Add css for output tabs 2019-03-27 09:39:38 +00:00
j433866
3597aacce9 Add wrapper to output 2019-03-27 09:38:13 +00:00
j433866
61bc5436a2 Fix number of running workers not being correct.
(This needs some work!)
2019-03-27 09:26:01 +00:00
j433866
37428fbe3b Bake all inputs, not just the active tab.
Limits number of workers to number of cpu threads (4 if not supported)
Creates output tabs (switching doesn't work yet)
Disabled some highlighting for now.
2019-03-27 09:05:10 +00:00
j433866
fbe1e2c2cc Show tab number on tab title.
Don't show lines value if tab contents is a file.
2019-03-22 15:55:35 +00:00
j433866
9b86ed7c45 Fix input highlighter size 2019-03-22 15:19:03 +00:00
j433866
c0c83c5cdc Stores inputs in memory instead of in textareas.
Allow selecting multiple files.
Allow drag and dropping multiple files.
Clear all IO button will close all tabs.
Will now spawn multiple loaderworkers simultaneously.
Improve tab logic to break less and work in Firefox.
2019-03-22 15:10:19 +00:00
d98762625
638093d40e correct translation from node Buffer to byte array 2019-03-22 09:42:25 +00:00
j433866
37218c1e81 Add UI for input tabs.
Can add, remove and switch tabs
2019-03-21 12:31:01 +00:00
d98762625
b98cab7d62 pass full dish into NodeDish Apply to allow apply from ArrayBuffer type to work 2019-03-20 17:46:01 +00:00
d98762625
656cf32753 remove extra step from grunt test-node command 2019-03-20 16:41:44 +00:00
d98762625
9e2aac0696 update tests file name and linting 2019-03-20 16:34:20 +00:00
d98762625
8c48d73b03 debug why travis fails 2019-03-20 16:30:43 +00:00
d98762625
b48a55bd74 add all options to argOptions. Add some extra test case for Zip 2019-03-20 16:27:35 +00:00
d98762625
a1b116d2f5 update travis build to include node tests. Minor refactor to grunt jobs for node 2019-03-20 15:10:16 +00:00
d98762625
aad1bc898e update file shim to use detectFileType. 2019-03-20 12:38:49 +00:00
d98762625
4add484d2a update TestRegister relative path in some tests 2019-03-20 12:00:22 +00:00
d98762625
8eed2232ee add immutable presentAs method to Dish for node REPL display. add test for exact match help 2019-03-20 11:57:47 +00:00
j433866
6a01e40394 Fix bug where GIF input would error on output.
Also minor corrections to jsdocs in ImageManipulation
2019-03-20 11:20:34 +00:00
j433866
757176727d Fix the aspect ratio fix 2019-03-20 10:52:00 +00:00
j433866
d9fdae9175 Adjust css to keep aspect ratio of previewed image 2019-03-20 10:40:59 +00:00
j433866
4a84cf3ac7 Add css styling option for banner URL 2019-03-20 10:23:09 +00:00
d98762625
8f5f3e56cb prefer exact matches in help function 2019-03-20 10:23:03 +00:00
j433866
e03e51c450 Add styling of checkboxes.
Change fonts in solarized themes to match classic.
Add styling of input fields to modals
2019-03-20 10:01:19 +00:00
d98762625
f61e33aa71 update disassemble test after vendor code change 2019-03-20 09:46:53 +00:00
d98762625
4bc3fc274b Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-03-20 09:42:09 +00:00
d98762625
e3cdf6361e make unzip test accurate 2019-03-20 09:41:59 +00:00
j433866
674f879fb8 Change file thumb to normal icon when file closed 2019-03-19 16:54:50 +00:00
j433866
b195fc69dd Remove old css file 2019-03-19 14:39:46 +00:00
j433866
2049e4e1d5 Add image preview to input file overlay.
This can be turned off
2019-03-19 14:38:46 +00:00
j433866
d09ab4a153 Add new solarized light and dark themes.
Add more elements to be controlled by theme css:
- Preloader spinner colours
- Operation disable / breakpoint icons
- Auto bake checkbox
- Search highlight colour
- Categories header colour
2019-03-19 14:37:46 +00:00
j433866
b312e17904 Change title to title case 2019-03-19 13:54:39 +00:00
j433866
2cd3e9cacd Add new implementation of gaussian blur.
Changed SharpenImage to use the new algorithm.
2019-03-19 13:54:26 +00:00
j433866
ce72acdd61 Add 'add text to image' operation.
Included variants of the Roboto fonts as bitmap fonts for jimp.
Changed webpack config to import the font files.
2019-03-19 13:53:09 +00:00
j433866
8e74acbf3e Add opaque background option 2019-03-18 09:43:37 +00:00
d98762625
76cc7f1169 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-03-14 17:57:53 +00:00
d98762625
b8cb7e9ba8 add tests for File and test based operations. Only unzip to go 2019-03-14 17:54:06 +00:00
d98762625
2019ae43d7 File shim now translates correctly 2019-03-14 16:33:09 +00:00
d98762625
d080c5dd14 debugging File shim 2019-03-14 08:27:06 +00:00
j433866
4fafa39e54 Fix magic library to better handle operation error 2019-03-13 13:09:02 +00:00
j433866
bb7487c476 Change to use new FileType library 2019-03-13 09:20:13 +00:00
j433866
308195279c Bring up to date with master 2019-03-13 09:17:43 +00:00
j433866
e95b7075b9 Add convert image format operation 2019-03-12 16:29:20 +00:00
j433866
dfbc1beccd Add sharpen image operation 2019-03-12 16:24:43 +00:00
d98762625
14d591caa1 more debugging 2019-03-11 09:47:58 +00:00
j433866
3e428c044a Add min values to operation args 2019-03-08 13:38:59 +00:00
j433866
11451ac6b9 Add image format pattern.
("borrowed" from RenderImage)
2019-03-07 13:35:37 +00:00
j433866
21a8d03201 Move parsing and generation of QR codes to lib folder.
Also rewrote QR code parsing to be more readable and actually error out properly.
2019-03-07 13:21:26 +00:00
d98762625
e4b688a2c3 Make Frequency dist test more sensible 2019-03-01 16:58:43 +00:00
d98762625
6d219ade2d remove legacy async api from NodeRecipe 2019-03-01 16:56:14 +00:00
d98762625
b48c16b4db Refactor Dish _translate to handle sync and async depending on environment. 2019-03-01 16:38:54 +00:00
d98762625
0a1ca18de5 refactor Dish get to handle sync and async 2019-03-01 08:59:18 +00:00
d98762625
ff2521aa9f WIP Dish now working on dev with dynamically loaded _translate and get functions 2019-02-15 16:26:22 +00:00
d98762625
9094e8bde9 WIP tidy up. WHy is dish being passed back with chef.bake now? 2019-02-15 16:11:13 +00:00
d98762625
573a292e16 WIP dynamically define async functions in Dish, only if needed 2019-02-15 15:40:29 +00:00
d98762625
04b7f2fa8c WIP HAD to move NodeDish out - NONE of it is async! 2019-02-15 15:20:05 +00:00
d98762625
aafde8986d tidy up gruntfile for node 2019-02-13 14:48:55 +00:00
d98762625
03e3ab5599 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-02-12 15:32:59 +00:00
d98762625
c76322c40d force webpack to only emit one file when using dynamic import 2019-02-11 17:21:16 +00:00
d98762625
39c68ff26e Merge branch 'dynamic-import' into node-lib-dynamic 2019-02-11 16:56:50 +00:00
d98762625
dd51b675b0 removed OpModules bodge from index generation scripts 2019-02-08 14:49:19 +00:00
d98762625
7679705369 Merge branch 'dynamic-import' into node-lib-dynamic 2019-02-08 14:42:07 +00:00
d98762625
781ff956e3 add dev builds for node 2019-01-23 10:06:55 +00:00
d98762625
7522e5de33 remove unnecessary operationConfig manipulation 2019-01-23 09:55:29 +00:00
d98762625
dd4a7f9fac Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-01-21 10:46:54 +00:00
d98762625
f7d425189a update test sample data 2019-01-04 16:31:06 +00:00
d98762625
6ca78ce8cb Merge branch 'node-lib-tests' into node-lib 2019-01-04 16:25:48 +00:00
d98762625
4b7c927ca4 remove old node tests from ops test suite 2019-01-04 16:25:06 +00:00
d98762625
9d674ce5a7 move node test suite into its own grunt command 2019-01-04 12:14:02 +00:00
d98762625
f22e9ceec6 refactor TestRegister and some test suite functions into common area 2019-01-04 12:00:01 +00:00
d98762625
a4de937eb6 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2019-01-04 09:27:32 +00:00
d98762625
83fa50bf13 linting 2018-12-21 10:24:20 +00:00
d98762625
3efe9309ef Merge branch 'arg-options' into node-lib 2018-12-21 09:48:01 +00:00
d98762625
456b85ed03 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2018-12-21 09:47:28 +00:00
d98762625
6bc5f87cb7 Merge branch 'master' of github.com:gchq/CyberChef into arg-options 2018-12-21 09:47:14 +00:00
d98762625
a010bba047 add test and change name of property to argOptions 2018-12-21 09:46:30 +00:00
d98762625
19366e3624 arg array options to wrapped func 2018-12-07 15:46:05 +00:00
d98762625
18f6ab451d pull from master 2018-12-07 13:27:23 +00:00
d98762625
b19f8f65a4 update HMAC test after merge and add loader to allow external uglifyjs plugin to work for node builds 2018-11-09 14:40:40 +00:00
d98762625
97255bbb33 merge upstream 2018-11-09 12:33:19 +00:00
d98762625
214d6c4405 merge from upstream 2018-10-12 11:46:50 +01:00
d98762625
fa87fc8325 replace operations on Dish with apply 2018-10-12 11:44:19 +01:00
d98762625
48f3a3b18f Do not mangle names on minification for Node prod build - property names are used for search in bake 2018-10-05 18:24:06 +01:00
d98762625
25e0585742 Improve use of files as input. Add dish to repl 2018-10-05 18:06:15 +01:00
d98762625
431f1d4be0 housekeeping & add repl command to package 2018-09-27 17:51:44 +01:00
d98762625
cc840c050b Add header to repl. Use uppercase Dish in chef export. Fix SyncDish constructor call 2018-09-21 12:24:34 +01:00
d98762625
e19d3d0d06 simplify repl-index - no longer needs its own config script. Just needs grunt node. 2018-09-04 10:08:05 +01:00
d98762625
749a587eb2 fix tests after merge; remove detectFileType as it behaves erratically 2018-09-04 09:55:41 +01:00
d98762625
5047619e54 Merge branch 'master' of github.com:gchq/CyberChef into node-lib 2018-09-04 09:42:05 +01:00
d98762625
63a23e4dcc make chef.help emulate search function in UI. Didnt extract search logic from web as it is fairly entwined. 2018-09-04 09:34:55 +01:00
d98762625
3466f4e452 add help, bake to top level export so theyre in the expected place in ES5 chef 2018-08-31 15:17:33 +01:00
d98762625
b36e3adf7c add assertions for chef.bake leniancy on op names 2018-08-31 15:03:53 +01:00
d98762625
c6a292bccb rename node Recipe > NodeRecipe to avoid naming confusion 2018-08-31 14:52:14 +01:00
d98762625
f51d924ec9 Remove duplicate wiping of opconfig in node index config script 2018-08-31 14:48:46 +01:00
d98762625
96d5930f05 Throw ExcludedOperationError when excluded operation is called from API 2018-08-31 14:43:14 +01:00
d98762625
7c9ebafd00 toggleString args now additionally accept just input value, taking first option as default. 2018-08-31 13:45:12 +01:00
d98762625
f6c4b5073c Expose Dish (SyncDish) in API and make it composable. 2018-08-31 13:09:22 +01:00
d98762625
f73452e01f making SyncDish composable! we want to exclude certain ops from top level api export (chef, etc) and make an Order (or something) class to start the chain off maybe? 2018-08-31 13:09:22 +01:00
d98762625
55f7cac526 Remove Buffer from Dish. Convert into ByteArray in api and then pass in as ArrayBuffer. Add some PNG files to tests 2018-08-31 13:08:55 +01:00
d98762625
20bb104006 use utils.inspect.custom Rready for node v12 2018-08-19 22:34:50 +01:00
d98762625
1f771a9e01 fix scan embedded files, bson. Only RemoveExif remains 2018-08-17 17:36:15 +01:00
d98762625
223e2e0b73 add Buffer translation to Dish. Cannot work in SyncDish as typeEnums are static. Seeing as they will never be hit in the broswer, shouldnt be an issue 2018-08-17 17:16:24 +01:00
d98762625
fbcb626fd0 add test timer. Remove operations related to esprima 2018-08-16 18:14:02 +01:00
d98762625
8f85e57fc5 fix translatreDateTimeFormat args assignment error 2018-08-16 17:19:23 +01:00
d98762625
7557f43f77 Wrap async ops in an async wrapper 2018-08-16 17:14:28 +01:00
d98762625
a6c0db47ab Finished first run through of tests 2018-08-16 09:58:27 +01:00
d98762625
8675d1a666 add more tests 2018-08-15 17:54:26 +01:00
d98762625
1f634ed341 add more tests 2018-08-14 17:46:15 +01:00
d98762625
50c916216c adding more tests 2018-08-14 12:03:10 +01:00
d98762625
f100356078 started on full op test suite 2018-08-13 17:57:53 +01:00
d98762625
a2f4e34866 need to inclide src/node/index for module use 2018-08-11 22:22:07 +01:00
d98762625
7c1ac4392e merge 8.0.1 release -> node-lib 2018-08-11 22:15:09 +01:00
d98762625
20452fe3cb include crypto-api src into lib to get around mjs import issue. compiled node lib now requires successfully. 2018-08-10 17:44:40 +01:00
d98762625
91eb692d99 Merge branch 'bake' into node-lib 2018-07-20 14:02:21 +01:00
d98762625
9abaadf1b6 Build chef.bake. 2018-07-20 13:55:11 +01:00
d98762625
2480dca473 Make help function use OperationConfig.json file
Tidy up Gruntfile execs
2018-07-06 11:42:56 +01:00
n1474335
f101eefc56 'From Hexdump' now supports an alternative style of Wireshark hexdumps. Test added. 2018-07-06 11:42:56 +01:00
d98762625
fa8736b1a4 Make help function use OperationConfig.json file
Tidy up Gruntfile execs
2018-07-06 11:34:06 +01:00
d98762625
db7b52d84c Merge branch 'node-lib' into help 2018-07-06 09:27:40 +01:00
d98762625
2027b643b1 Merge branch 'esm' of github.com:gchq/CyberChef into node-lib 2018-07-06 09:27:27 +01:00
d98762625
a4d7065e42 add operation input case to chef.search 2018-06-25 17:58:57 +01:00
d98762625
2ff7b5902c fix args transformation for ops with editableOptions 2018-06-25 11:38:05 +01:00
d98762625
e04f66f599 export help function on chef object 2018-06-19 17:10:04 +01:00
d98762625
27ee7f8592 exclude File operations until File API can be mimicked 2018-06-19 09:12:55 +01:00
d98762625
f95f01b895 Add ability to exclude operations from Node API. Exclude flow control ops 2018-06-19 09:08:45 +01:00
d98762625
866b36729c edit logging on gruntfile 2018-06-19 08:53:29 +01:00
d98762625
471009bc17 remove example and remove cap issues for SyncDish 2018-06-18 13:15:29 +01:00
d98762625
c90f30a7a1 update editableOptions wrapper 2018-06-18 11:17:17 +01:00
d98762625
ffb65d8ea1 add more wrapper tests for node api 2018-06-18 10:52:45 +01:00
d98762625
a5d58071cd WIP: start testing ops with various arg types. AESENCRYPT result encoding error 2018-06-15 11:33:13 +01:00
d98762625
fc1b8917a8 add node index to clean. generate node index before test 2018-06-07 10:06:44 +01:00
d98762625
ec00413a4b add example usage file 2018-06-06 17:57:16 +01:00
d98762625
33f2c89716 update tests to reflect new API behaviour 2018-06-06 17:29:30 +01:00
d98762625
45d2fbc5fc create SyncDish and wrap results in it. 2018-06-06 16:37:12 +01:00
d98762625
d00b9e0928 generate node index needs to be without other generate scripts 2018-06-06 09:13:26 +01:00
d98762625
58a7f7b739 Merge branch 'esm' of github.com:gchq/CyberChef into node-lib 2018-06-06 08:28:08 +01:00
d98762625
dcf6564d0a linting for generated node/index.mjs 2018-05-30 11:35:36 +01:00
d98762625
6db9521419 re-add translateTo call to chef export 2018-05-30 11:29:38 +01:00
d98762625
336810cbf4 amend generateNodeIndex script 2018-05-30 11:12:57 +01:00
d98762625
9d5e533e32 Merge branch 'esm' of github.com:gchq/CyberChef into top-export 2018-05-30 08:52:27 +01:00
d98762625
b45fc630ae Merge branch 'esm' of github.com:gchq/CyberChef into top-export 2018-05-29 08:58:20 +01:00
d98762625
9a471d2a26 remove extra preamble for grunt task. improve index script 2018-05-25 12:20:56 +01:00
d98762625
0a0240e520 WIP: generate top level node exports - manually mock lib files 2018-05-25 11:26:28 +01:00
d98762625
0977e82170 Merge branch 'esm' into node-lib 2018-05-24 16:12:26 +01:00
d98762625
0a0316a000 Make optional args in operation call use named properties rather than array 2018-05-11 19:25:14 +01:00
d98762625
7e8f78acaa dont decapitalise all-caps operation names 2018-05-11 17:33:14 +01:00
d98762625
615cb561e4 add some chef.translateTo tests 2018-05-11 11:58:09 +01:00
d98762625
c96a1df8e1 add namespaces to docas 2018-05-11 11:09:04 +01:00
d98762625
5efc3f15f2 linting 2018-05-03 13:58:15 +01:00
d98762625
5fb50a1759 OperationErrors now bubble up to the top of the API.
Added test functionality for node api
refactor TestRegister into class
2018-05-03 13:53:40 +01:00
d98762625
e50758f0a6 Merge branch 'esm' of github.com:gchq/CyberChef into node-lib 2018-05-03 13:52:50 +01:00
d98762625
3d672802a3 remove find Type - not used any more 2018-04-27 16:47:52 +01:00
d98762625
c238862efe in/out typing working. Added translateTo function 2018-04-27 16:45:02 +01:00
d98762625
7e7e5e7466 Merge branch 'op-errors' into node-lib 2018-04-27 11:33:27 +01:00
n1474335
b0a8ca56bc Added File and JSON Dish types and updated types for compression ops. 2018-04-27 10:44:40 +01:00
n1474335
fbec0a1c7d The raw, unpresented dish is now returned to the app after baking, where it can be retrieved as various different data types. 2018-04-27 10:44:40 +01:00
d98762625
d5b5443a84 update readme 2018-04-27 09:01:45 +01:00
d98762625
b8b98358d0 function tidy, add comments 2018-04-20 12:23:20 +01:00
d98762625
fca4ed7013 simplified API 2018-04-20 10:55:17 +01:00
d98762625
59877b5138 Exporing options with API. 2018-04-13 12:14:40 +01:00
528 changed files with 28702 additions and 3788 deletions

View File

@@ -38,6 +38,8 @@
// disable rules from base configurations
"no-control-regex": "off",
"require-atomic-updates": "off",
"no-async-promise-executor": "off",
// stylistic conventions
"brace-style": ["error", "1tbs"],
@@ -106,9 +108,6 @@
"COMPILE_TIME": false,
"COMPILE_MSG": false,
"PKG_VERSION": false,
"ENVIRONMENT_IS_WORKER": false,
"ENVIRONMENT_IS_NODE": false,
"ENVIRONMENT_IS_WEB": false
"PKG_VERSION": false
}
}

View File

@@ -22,7 +22,7 @@ Before your contributions can be accepted, you must:
* Line endings: UNIX style (\n)
## Design Principals
## Design Principles
1. If at all possible, all operations and features should be client-side and not rely on connections to an external server. This increases the utility of CyberChef on closed networks and in virtual machines that are not connected to the Internet. Calls to external APIs may be accepted if there is no other option, but not for critical components.
2. Latency should be kept to a minimum to enhance the user experience. This means that all operation code should sit on the client, rather than being loaded dynamically from a server.
@@ -30,7 +30,7 @@ Before your contributions can be accepted, you must:
4. Minimise the use of large libraries, especially for niche operations that won't be used very often - these will be downloaded by everyone using the app, whether they use that operation or not (due to principal 2).
With these principals in mind, any changes or additions to CyberChef should keep it:
With these principles in mind, any changes or additions to CyberChef should keep it:
- Standalone
- Efficient

3
.gitignore vendored
View File

@@ -11,5 +11,8 @@ docs/*
src/core/config/modules/*
src/core/config/OperationConfig.json
src/core/operations/index.mjs
src/node/config/OperationConfig.json
src/node/index.mjs
**/*.DS_Store
tests/browser/output/*

View File

@@ -1,6 +1,7 @@
language: node_js
node_js:
- lts/*
cache: npm
addons:
chrome: stable
install: npm install
@@ -11,7 +12,7 @@ script:
- grunt lint
- grunt test
- grunt docs
- grunt node
- npm run node-prod
- grunt prod --msg="$COMPILE_MSG"
- xvfb-run --server-args="-screen 0 1200x800x24" grunt testui
before_deploy:

View File

@@ -2,6 +2,24 @@
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
## [9.0.0] - 2019-07-09
- [Multiple inputs](https://github.com/gchq/CyberChef/wiki/Multiple-Inputs) are now supported in the main web UI, allowing you to upload and process multiple files at once [@j433866] [#566]
- A [Node.js API](https://github.com/gchq/CyberChef/wiki/Node-API) has been implemented, meaning that CyberChef can now be used as a library, either to provide specific operations, or an entire baking environment [@d98762625] [#291]
- A [read-eval-print loop (REPL)](https://github.com/gchq/CyberChef/wiki/Node-API#repl) is also included to enable prototyping and experimentation with the API [@d98762625] [#291]
- Light and dark Solarized themes added [@j433866] [#566]
### [8.38.0] - 2019-07-03
- 'Streebog' and 'GOST hash' operations added [@MShwed] [@n1474335] | [#530]
### [8.37.0] - 2019-07-03
- 'CRC-8 Checksum' operation added [@MShwed] | [#591]
### [8.36.0] - 2019-07-03
- 'PGP Verify' operation added [@artemisbot] | [#585]
### [8.35.0] - 2019-07-03
- 'Sharpen Image', 'Convert Image Format' and 'Add Text To Image' operations added [@j433866] | [#515]
### [8.34.0] - 2019-06-28
- Various new visualisations added to the 'Entropy' operation [@MShwed] | [#535]
- Efficiency improvements made to the 'Entropy' operation for large file support [@n1474335]
@@ -10,7 +28,7 @@ All major and minor version changes will be documented in this file. Details of
- 'Bzip2 Compress' operation added and 'Bzip2 Decompress' operation greatly improved [@artemisbot] | [#531]
### [8.32.0] - 2019-06-27
- 'Indec of Coincidence' operation added [@Ge0rg3] | [#571]
- 'Index of Coincidence' operation added [@Ge0rg3] | [#571]
### [8.31.0] - 2019-04-12
- The downloadable version of CyberChef is now a .zip file containing separate modules rather than a single .htm file. It is still completely standalone and will not make any external network requests. This change reduces the complexity of the build process significantly. [@n1474335]
@@ -140,6 +158,11 @@ All major and minor version changes will be documented in this file. Details of
[9.0.0]: https://github.com/gchq/CyberChef/releases/tag/v9.0.0
[8.38.0]: https://github.com/gchq/CyberChef/releases/tag/v8.38.0
[8.37.0]: https://github.com/gchq/CyberChef/releases/tag/v8.37.0
[8.36.0]: https://github.com/gchq/CyberChef/releases/tag/v8.36.0
[8.35.0]: https://github.com/gchq/CyberChef/releases/tag/v8.35.0
[8.34.0]: https://github.com/gchq/CyberChef/releases/tag/v8.34.0
[8.33.0]: https://github.com/gchq/CyberChef/releases/tag/v8.33.0
[8.32.0]: https://github.com/gchq/CyberChef/releases/tag/v8.32.0
@@ -215,6 +238,7 @@ All major and minor version changes will be documented in this file. Details of
[#277]: https://github.com/gchq/CyberChef/issues/277
[#281]: https://github.com/gchq/CyberChef/pull/281
[#284]: https://github.com/gchq/CyberChef/pull/284
[#291]: https://github.com/gchq/CyberChef/pull/291
[#294]: https://github.com/gchq/CyberChef/pull/294
[#296]: https://github.com/gchq/CyberChef/pull/296
[#298]: https://github.com/gchq/CyberChef/pull/298
@@ -244,9 +268,14 @@ All major and minor version changes will be documented in this file. Details of
[#489]: https://github.com/gchq/CyberChef/pull/489
[#496]: https://github.com/gchq/CyberChef/pull/496
[#506]: https://github.com/gchq/CyberChef/pull/506
[#515]: https://github.com/gchq/CyberChef/pull/515
[#516]: https://github.com/gchq/CyberChef/pull/516
[#525]: https://github.com/gchq/CyberChef/pull/525
[#530]: https://github.com/gchq/CyberChef/pull/530
[#531]: https://github.com/gchq/CyberChef/pull/531
[#533]: https://github.com/gchq/CyberChef/pull/533
[#535]: https://github.com/gchq/CyberChef/pull/535
[#566]: https://github.com/gchq/CyberChef/pull/566
[#571]: https://github.com/gchq/CyberChef/pull/571
[#585]: https://github.com/gchq/CyberChef/pull/585
[#591]: https://github.com/gchq/CyberChef/pull/591

View File

@@ -15,6 +15,8 @@ const path = require("path");
* @license Apache-2.0
*/
const NODE_PROD = process.env.NODE_ENV === "production";
module.exports = function (grunt) {
grunt.file.defaultEncoding = "utf8";
grunt.file.preserveBOM = false;
@@ -24,13 +26,26 @@ module.exports = function (grunt) {
"A persistent task which creates a development build whenever source files are modified.",
["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"]);
grunt.registerTask("prod",
"Creates a production-ready build. Use the --msg flag to add a compile message.",
[
"eslint", "clean:prod", "clean:config", "exec:generateConfig", "webpack:web",
"copy:standalone", "zip:standalone", "clean:standalone", "chmod"
]);
grunt.registerTask("node",
"Compiles CyberChef into a single NodeJS module.",
["clean:node", "clean:config", "exec:generateConfig", "webpack:node", "chmod:build"]);
[
"clean:node", "clean:config", "clean:nodeConfig", "exec:generateConfig",
"exec:generateNodeIndex", "webpack:node", "webpack:nodeRepl", "chmod:build"
]);
grunt.registerTask("test",
"A task which runs all the operation tests in the tests directory.",
["exec:generateConfig", "exec:opTests"]);
[
"clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex",
"exec:nodeTests", "exec:opTests"
]);
grunt.registerTask("testui",
"A task which runs all the UI tests in the tests directory. The prod task must already have been run.",
@@ -40,12 +55,6 @@ module.exports = function (grunt) {
"Compiles documentation in the /docs directory.",
["clean:docs", "jsdoc", "chmod:docs"]);
grunt.registerTask("prod",
"Creates a production-ready build. Use the --msg flag to add a compile message.",
[
"eslint", "clean:prod", "clean:config", "exec:generateConfig", "webpack:web",
"copy:standalone", "zip:standalone", "clean:standalone", "chmod"
]);
grunt.registerTask("default",
"Lints the code base",
@@ -80,15 +89,6 @@ module.exports = function (grunt) {
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();
@@ -114,6 +114,7 @@ module.exports = function (grunt) {
prod: ["build/prod/*"],
node: ["build/node/*"],
config: ["src/core/config/OperationConfig.json", "src/core/config/modules/*", "src/code/operations/index.mjs"],
nodeConfig: ["src/node/index.mjs", "src/node/config/OperationConfig.json"],
docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico", "!docs/*.png"],
standalone: ["build/prod/CyberChef*.html"]
},
@@ -174,7 +175,7 @@ module.exports = function (grunt) {
},
resolve: {
alias: {
"./config/modules/OpModules": "./config/modules/Default"
"./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
}
},
plugins: [
@@ -201,10 +202,12 @@ module.exports = function (grunt) {
};
},
node: {
mode: "production",
mode: NODE_PROD ? "production" : "development",
target: "node",
entry: "./src/node/index.mjs",
externals: [NodeExternals()],
externals: [NodeExternals({
whitelist: ["crypto-api/src/crypto-api"]
})],
output: {
filename: "CyberChef.js",
path: __dirname + "/build/node",
@@ -212,8 +215,31 @@ module.exports = function (grunt) {
libraryTarget: "commonjs2"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS)
]
new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
],
},
nodeRepl: {
mode: NODE_PROD ? "production" : "development",
target: "node",
entry: "./src/node/repl-index.mjs",
externals: [NodeExternals({
whitelist: ["crypto-api/src/crypto-api"]
})],
output: {
filename: "CyberChef-repl.js",
path: __dirname + "/build/node",
library: "CyberChef",
libraryTarget: "commonjs2"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
],
}
},
"webpack-dev-server": {
@@ -246,12 +272,9 @@ module.exports = function (grunt) {
}, moduleEntryPoints),
resolve: {
alias: {
"./config/modules/OpModules": "./config/modules/Default"
"./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
}
},
output: {
globalObject: "this",
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new HtmlWebpackPlugin({
@@ -358,7 +381,7 @@ module.exports = function (grunt) {
watch: {
config: {
files: ["src/core/operations/**/*", "!src/core/operations/index.mjs"],
tasks: ["exec:generateConfig"]
tasks: ["exec:generateNodeIndex", "exec:generateConfig"]
}
},
concurrent: {
@@ -390,11 +413,21 @@ module.exports = function (grunt) {
"echo '--- Config scripts finished. ---\n'"
].join(";")
},
generateNodeIndex: {
command: [
"echo '\n--- Regenerating node index ---'",
"node --experimental-modules --no-warnings --no-deprecation src/node/config/scripts/generateNodeIndex.mjs",
"echo '--- Node index generated. ---\n'"
].join(";"),
},
opTests: {
command: "node --experimental-modules --no-warnings --no-deprecation tests/operations/index.mjs"
},
browserTests: {
command: "./node_modules/.bin/nightwatch --env prod"
},
nodeTests: {
command: "node --experimental-modules --no-warnings --no-deprecation tests/node/index.mjs"
}
},
});

View File

@@ -50,7 +50,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Drag and drop
- Operations can be dragged in and out of the recipe list, or reorganised.
- Files up to 500MB can be dragged over the input box to load them directly into the browser.
- Files up to 2GB 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.
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
@@ -67,7 +67,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- 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][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. 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.
- 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 2GB 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 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.

View File

@@ -10,7 +10,7 @@ module.exports = function(api) {
}]
],
"plugins": [
"babel-plugin-syntax-dynamic-import",
"dynamic-import-node",
[
"babel-plugin-transform-builtin-extend", {
"globals": ["Error"]

2892
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "8.34.3",
"version": "9.0.0",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -28,6 +28,7 @@
"url": "https://github.com/gchq/CyberChef/"
},
"main": "build/node/CyberChef.js",
"module": "src/node/index.mjs",
"bugs": "https://github.com/gchq/CyberChef/issues",
"browserslist": [
"Chrome >= 40",
@@ -36,14 +37,14 @@
"node >= 6.5"
],
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-env": "^7.4.5",
"@babel/core": "^7.5.0",
"@babel/plugin-transform-runtime": "^7.5.0",
"@babel/preset-env": "^7.5.0",
"autoprefixer": "^9.6.0",
"babel-eslint": "^10.0.2",
"babel-loader": "^8.0.6",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"chromedriver": "^75.0.0",
"babel-plugin-dynamic-import-node": "^2.2.0",
"chromedriver": "^75.0.1",
"colors": "^1.3.3",
"css-loader": "^3.0.0",
"eslint": "^6.0.1",
@@ -57,7 +58,7 @@
"grunt-contrib-connect": "^2.0.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^21.1.0",
"grunt-eslint": "^22.0.0",
"grunt-exec": "~3.0.0",
"grunt-jsdoc": "^2.4.0",
"grunt-webpack": "^3.1.3",
@@ -67,18 +68,18 @@
"ink-docstrap": "^1.3.2",
"jsdoc-babel": "^0.5.0",
"mini-css-extract-plugin": "^0.7.0",
"nightwatch": "^1.1.12",
"nightwatch": "^1.1.13",
"node-sass": "^4.12.0",
"postcss-css-variables": "^0.13.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"prompt": "^1.0.0",
"sass-loader": "^7.1.0",
"sitemap": "^2.2.0",
"sitemap": "^3.2.0",
"style-loader": "^0.23.1",
"svg-url-loader": "^2.3.3",
"svg-url-loader": "^3.0.0",
"url-loader": "^2.0.1",
"webpack": "^4.35.0",
"webpack": "^4.35.2",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-server": "^3.7.2",
"webpack-node-externals": "^1.7.2",
@@ -86,14 +87,14 @@
},
"dependencies": {
"@babel/polyfill": "^7.4.4",
"@babel/runtime": "^7.4.5",
"@babel/runtime": "^7.5.0",
"arrive": "^2.4.1",
"babel-plugin-transform-builtin-extend": "1.1.2",
"bcryptjs": "^2.4.3",
"bignumber.js": "^9.0.0",
"blakejs": "^1.1.0",
"bootstrap": "4.3.1",
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-colorpicker": "^3.1.2",
"bootstrap-material-design": "^4.1.2",
"bson": "^4.0.2",
"chi-squared": "^1.1.0",
@@ -102,7 +103,7 @@
"crypto-api": "^0.8.3",
"crypto-js": "^3.1.9-1",
"ctph.js": "0.0.5",
"d3": "^5.9.4",
"d3": "^5.9.7",
"d3-hexbin": "^0.2.2",
"diff": "^4.0.1",
"es6-promisify": "^6.0.1",
@@ -155,7 +156,11 @@
"scripts": {
"start": "grunt dev",
"build": "grunt prod",
"node": "NODE_ENV=development grunt node",
"node-prod": "NODE_ENV=production grunt node",
"repl": "grunt node && node build/node/CyberChef-repl.js",
"test": "grunt test",
"test-node": "grunt test-node",
"testui": "grunt testui",
"docs": "grunt docs",
"lint": "grunt lint",

View File

@@ -4,9 +4,10 @@
* @license Apache-2.0
*/
import Dish from "./Dish";
import Recipe from "./Recipe";
import Dish from "./Dish.mjs";
import Recipe from "./Recipe.mjs";
import log from "loglevel";
import { isWorkerEnvironment } from "./Utils.mjs";
/**
* The main controller for CyberChef.
@@ -28,8 +29,6 @@ class Chef {
* @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
* @param {number} progress - The position in the recipe to start from
* @param {number} [step] - Whether to only execute one operation in the recipe
*
* @returns {Object} response
* @returns {string} response.result - The output of the recipe
@@ -38,46 +37,20 @@ class Chef {
* @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)
*/
async bake(input, recipeConfig, options, progress, step) {
async bake(input, recipeConfig, options) {
log.debug("Chef baking");
const startTime = new Date().getTime(),
recipe = new Recipe(recipeConfig),
containsFc = recipe.containsFlowControl(),
notUTF8 = options && options.hasOwnProperty("treatAsUtf8") && !options.treatAsUtf8;
let error = false;
if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
// Clean up progress
if (progress >= recipeConfig.length) {
notUTF8 = options && "treatAsUtf8" in options && !options.treatAsUtf8;
let error = false,
progress = 0;
}
if (step) {
// Unset breakpoint on this step
recipe.setBreakpoint(progress, false);
// Set breakpoint on next step
recipe.setBreakpoint(progress + 1, true);
}
if (containsFc && isWorkerEnvironment()) self.setOption("attemptHighlight", false);
// If the previously run operation presented a different value to its
// normal output, we need to recalculate it.
if (recipe.lastOpPresented(progress)) {
progress = 0;
}
// If stepping with flow control, we have to start from the beginning
// but still want to skip all previous breakpoints
if (progress > 0 && containsFc) {
recipe.removeBreaksUpTo(progress);
progress = 0;
}
// If starting from scratch, load data
if (progress === 0) {
const type = input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING;
this.dish.set(input, type);
}
// Load data
const type = input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING;
this.dish.set(input, type);
try {
progress = await recipe.execute(this.dish, progress);
@@ -196,6 +169,18 @@ class Chef {
return await newDish.get(type);
}
/**
* Gets the title of a dish and returns it
*
* @param {Dish} dish
* @param {number} [maxLength=100]
* @returns {string}
*/
async getDishTitle(dish, maxLength=100) {
const newDish = new Dish(dish);
return await newDish.getTitle(maxLength);
}
}
export default Chef;

View File

@@ -6,9 +6,9 @@
* @license Apache-2.0
*/
import Chef from "./Chef";
import Chef from "./Chef.mjs";
import OperationConfig from "./config/OperationConfig.json";
import OpModules from "./config/modules/OpModules";
import OpModules from "./config/modules/OpModules.mjs";
// Add ">" to the start of all log messages in the Chef Worker
import loglevelMessagePrefix from "loglevel-message-prefix";
@@ -25,6 +25,8 @@ self.chef = new Chef();
self.OpModules = OpModules;
self.OperationConfig = OperationConfig;
self.inputNum = -1;
// Tell the app that the worker has loaded and is ready to operate
self.postMessage({
@@ -35,6 +37,9 @@ self.postMessage({
/**
* Respond to message from parent thread.
*
* inputNum is optional and only used for baking multiple inputs.
* Defaults to -1 when one isn't sent with the bake message.
*
* Messages should have the following format:
* {
* action: "bake" | "silentBake",
@@ -43,8 +48,9 @@ self.postMessage({
* recipeConfig: {[Object]},
* options: {Object},
* progress: {number},
* step: {boolean}
* } | undefined
* step: {boolean},
* [inputNum=-1]: {number}
* }
* }
*/
self.addEventListener("message", function(e) {
@@ -62,6 +68,9 @@ self.addEventListener("message", function(e) {
case "getDishAs":
getDishAs(r.data);
break;
case "getDishTitle":
getDishTitle(r.data);
break;
case "docURL":
// Used to set the URL of the current document so that scripts can be
// imported into an inline worker.
@@ -91,30 +100,35 @@ self.addEventListener("message", function(e) {
async function bake(data) {
// Ensure the relevant modules are loaded
self.loadRequiredModules(data.recipeConfig);
try {
self.inputNum = (data.inputNum !== undefined) ? data.inputNum : -1;
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
data.options // Options set by the user
);
const transferable = (data.input instanceof ArrayBuffer) ? [data.input] : undefined;
self.postMessage({
action: "bakeComplete",
data: Object.assign(response, {
id: data.id
id: data.id,
inputNum: data.inputNum,
bakeId: data.bakeId
})
});
}, transferable);
} catch (err) {
self.postMessage({
action: "bakeError",
data: Object.assign(err, {
id: data.id
})
data: {
error: err.message || err,
id: data.id,
inputNum: data.inputNum
}
});
}
self.inputNum = -1;
}
@@ -136,13 +150,33 @@ function silentBake(data) {
*/
async function getDishAs(data) {
const value = await self.chef.getDishAs(data.dish, data.type);
const transferable = (data.type === "ArrayBuffer") ? [value] : undefined;
self.postMessage({
action: "dishReturned",
data: {
value: value,
id: data.id
}
}, transferable);
}
/**
* Gets the dish title
*
* @param {object} data
* @param {Dish} data.dish
* @param {number} data.maxLength
* @param {number} data.id
*/
async function getDishTitle(data) {
const title = await self.chef.getDishTitle(data.dish, data.maxLength);
self.postMessage({
action: "dishReturned",
data: {
value: title,
id: data.id
}
});
}
@@ -175,7 +209,7 @@ self.loadRequiredModules = function(recipeConfig) {
recipeConfig.forEach(op => {
const module = self.OperationConfig[op.op].module;
if (!OpModules.hasOwnProperty(module)) {
if (!(module in OpModules)) {
log.info(`Loading ${module} module`);
self.sendStatusMessage(`Loading ${module} module`);
self.importScripts(`${self.docURL}/modules/${module}.js`);
@@ -193,7 +227,28 @@ self.loadRequiredModules = function(recipeConfig) {
self.sendStatusMessage = function(msg) {
self.postMessage({
action: "statusMessage",
data: msg
data: {
message: msg,
inputNum: self.inputNum
}
});
};
/**
* Send progress update to the app.
*
* @param {number} progress
* @param {number} total
*/
self.sendProgressMessage = function(progress, total) {
self.postMessage({
action: "progressMessage",
data: {
progress: progress,
total: total,
inputNum: self.inputNum
}
});
};

View File

@@ -5,11 +5,22 @@
* @license Apache-2.0
*/
import Utils from "./Utils";
import DishError from "./errors/DishError";
import Utils, { isNodeEnvironment } from "./Utils.mjs";
import DishError from "./errors/DishError.mjs";
import BigNumber from "bignumber.js";
import { detectFileType } from "./lib/FileType.mjs";
import log from "loglevel";
import DishByteArray from "./dishTypes/DishByteArray.mjs";
import DishBigNumber from "./dishTypes/DishBigNumber.mjs";
import DishFile from "./dishTypes/DishFile.mjs";
import DishHTML from "./dishTypes/DishHTML.mjs";
import DishJSON from "./dishTypes/DishJSON.mjs";
import DishListFile from "./dishTypes/DishListFile.mjs";
import DishNumber from "./dishTypes/DishNumber.mjs";
import DishString from "./dishTypes/DishString.mjs";
/**
* The data being operated on by each operation.
*/
@@ -18,16 +29,27 @@ class Dish {
/**
* Dish constructor
*
* @param {Dish} [dish=null] - A dish to clone
* @param {Dish || *} [dishOrInput=null] - A dish to clone OR an object
* literal to make into a dish
* @param {Enum} [type=null] (optional) - A type to accompany object
* literal input
*/
constructor(dish=null) {
constructor(dishOrInput=null, type = null) {
this.value = new ArrayBuffer(0);
this.type = Dish.ARRAY_BUFFER;
if (dish &&
dish.hasOwnProperty("value") &&
dish.hasOwnProperty("type")) {
this.set(dish.value, dish.type);
// Case: dishOrInput is dish object
if (dishOrInput &&
Object.prototype.hasOwnProperty.call(dishOrInput, "value") &&
Object.prototype.hasOwnProperty.call(dishOrInput, "type")) {
this.set(dishOrInput.value, dishOrInput.type);
// input and type defined separately
} else if (dishOrInput && type !== null) {
this.set(dishOrInput, type);
// No type declared, so infer it.
} else if (dishOrInput) {
const inferredType = Dish.typeEnum(dishOrInput.constructor.name);
this.set(dishOrInput, inferredType);
}
}
@@ -56,6 +78,7 @@ class Dish {
case "big number":
return Dish.BIG_NUMBER;
case "json":
case "object": // object constructor name. To allow JSON input in node.
return Dish.JSON;
case "file":
return Dish.FILE;
@@ -99,6 +122,43 @@ class Dish {
}
/**
* Returns the value of the data in the type format specified.
*
* If running in a browser, get is asynchronous.
*
* @param {number} type - The data type of value, see Dish enums.
* @param {boolean} [notUTF8=false] - Do not treat strings as UTF8.
* @returns {* | Promise} - (Broswer) A promise | (Node) value of dish in given type
*/
get(type, notUTF8=false) {
if (typeof type === "string") {
type = Dish.typeEnum(type);
}
if (this.type !== type) {
// Node environment => _translate is sync
if (isNodeEnvironment()) {
this._translate(type, notUTF8);
return this.value;
// Browser environment => _translate is async
} else {
return new Promise((resolve, reject) => {
this._translate(type, notUTF8)
.then(() => {
resolve(this.value);
})
.catch(reject);
});
}
}
return this.value;
}
/**
* Sets the data value and type and then validates them.
*
@@ -122,116 +182,77 @@ class Dish {
}
}
/**
* Returns the value of the data in the type format specified.
* Returns the Dish as the given type, without mutating the original dish.
*
* If running in a browser, get is asynchronous.
*
* @Node
*
* @param {number} type - The data type of value, see Dish enums.
* @param {boolean} [notUTF8=false] - Do not treat strings as UTF8.
* @returns {*} - The value of the output data.
* @returns {Dish | Promise} - (Broswer) A promise | (Node) value of dish in given type
*/
async get(type, notUTF8=false) {
if (typeof type === "string") {
type = Dish.typeEnum(type);
}
if (this.type !== type) {
await this._translate(type, notUTF8);
}
return this.value;
presentAs(type, notUTF8=false) {
const clone = this.clone();
return clone.get(type, notUTF8);
}
/**
* Translates the data to the given type format.
*
* @param {number} toType - The data type of value, see Dish enums.
* @param {boolean} [notUTF8=false] - Do not treat strings as UTF8.
* Detects the MIME type of the current dish
* @returns {string}
*/
async _translate(toType, notUTF8=false) {
log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`);
detectDishType() {
const data = new Uint8Array(this.value.slice(0, 2048)),
types = detectFileType(data);
// Convert data to intermediate ArrayBuffer type
try {
switch (this.type) {
case Dish.STRING:
this.value = this.value ? Utils.strToArrayBuffer(this.value) : new ArrayBuffer;
break;
case Dish.NUMBER:
this.value = typeof this.value === "number" ? Utils.strToArrayBuffer(this.value.toString()) : new ArrayBuffer;
break;
case Dish.HTML:
this.value = this.value ? Utils.strToArrayBuffer(Utils.unescapeHtml(Utils.stripHtmlTags(this.value, true))) : new ArrayBuffer;
break;
case Dish.BYTE_ARRAY:
this.value = new Uint8Array(this.value).buffer;
break;
case Dish.BIG_NUMBER:
this.value = BigNumber.isBigNumber(this.value) ? Utils.strToArrayBuffer(this.value.toFixed()) : new ArrayBuffer;
break;
case Dish.JSON:
this.value = this.value ? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4)) : new ArrayBuffer;
break;
case Dish.FILE:
this.value = (await Utils.readFile(this.value)).buffer;
break;
case Dish.LIST_FILE:
this.value = await Promise.all(this.value.map(async f => Utils.readFile(f)));
this.value = concatenateTypedArrays(...this.value).buffer;
break;
default:
break;
}
} catch (err) {
throw new DishError(`Error translating from ${Dish.enumLookup(this.type)} to ArrayBuffer: ${err}`);
}
this.type = Dish.ARRAY_BUFFER;
// Convert from ArrayBuffer to toType
try {
switch (toType) {
case Dish.STRING:
case Dish.HTML:
this.value = this.value ? Utils.arrayBufferToStr(this.value, !notUTF8) : "";
this.type = Dish.STRING;
break;
case Dish.NUMBER:
this.value = this.value ? parseFloat(Utils.arrayBufferToStr(this.value, !notUTF8)) : 0;
this.type = Dish.NUMBER;
break;
case Dish.BYTE_ARRAY:
this.value = Array.prototype.slice.call(new Uint8Array(this.value));
this.type = Dish.ARRAY_BUFFER;
break;
case Dish.BIG_NUMBER:
try {
this.value = new BigNumber(Utils.arrayBufferToStr(this.value, !notUTF8));
} catch (err) {
this.value = new BigNumber(NaN);
}
this.type = Dish.BIG_NUMBER;
break;
case Dish.JSON:
this.value = JSON.parse(Utils.arrayBufferToStr(this.value, !notUTF8));
this.type = Dish.JSON;
break;
case Dish.FILE:
this.value = new File(this.value, "unknown");
this.type = Dish.FILE;
break;
case Dish.LIST_FILE:
this.value = [new File(this.value, "unknown")];
this.type = Dish.LIST_FILE;
break;
default:
break;
}
} catch (err) {
throw new DishError(`Error translating from ArrayBuffer to ${Dish.enumLookup(toType)}: ${err}`);
if (!types.length || !types[0].mime || !types[0].mime === "text/plain") {
return null;
} else {
return types[0].mime;
}
}
/**
* Returns the title of the data up to the specified length
*
* @param {number} maxLength - The maximum title length
* @returns {string}
*/
async getTitle(maxLength) {
let title = "";
let cloned;
switch (this.type) {
case Dish.FILE:
title = this.value.name;
break;
case Dish.LIST_FILE:
title = `${this.value.length} file(s)`;
break;
case Dish.JSON:
title = "application/json";
break;
case Dish.ARRAY_BUFFER:
case Dish.BYTE_ARRAY:
title = this.detectDishType();
if (title !== null) break;
// fall through if no mime type was detected
default:
try {
cloned = this.clone();
cloned.value = cloned.value.slice(0, 256);
title = await cloned.get(Dish.STRING);
} catch (err) {
log.error(`${Dish.enumLookup(this.type)} cannot be sliced. ${err}`);
}
}
return title.slice(0, maxLength);
}
/**
* Validates that the value is the type that has been specified.
* May have to disable parts of BYTE_ARRAY validation if it effects performance.
@@ -241,7 +262,7 @@ class Dish {
valid() {
switch (this.type) {
case Dish.BYTE_ARRAY:
if (!(this.value instanceof Array)) {
if (!(this.value instanceof Uint8Array) && !(this.value instanceof Array)) {
return false;
}
@@ -369,26 +390,109 @@ class Dish {
return newDish;
}
}
/**
* Translates the data to the given type format.
*
* If running in the browser, _translate is asynchronous.
*
* @param {number} toType - The data type of value, see Dish enums.
* @param {boolean} [notUTF8=false] - Do not treat strings as UTF8.
* @returns {Promise || undefined}
*/
_translate(toType, notUTF8=false) {
log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`);
// Node environment => translate is sync
if (isNodeEnvironment()) {
this._toArrayBuffer();
this.type = Dish.ARRAY_BUFFER;
this._fromArrayBuffer(toType, notUTF8);
// Browser environment => translate is async
} else {
return new Promise((resolve, reject) => {
this._toArrayBuffer()
.then(() => this.type = Dish.ARRAY_BUFFER)
.then(() => {
this._fromArrayBuffer(toType);
resolve();
})
.catch(reject);
});
}
/**
* Concatenates a list of Uint8Arrays together
*
* @param {Uint8Array[]} arrays
* @returns {Uint8Array}
*/
function concatenateTypedArrays(...arrays) {
let totalLength = 0;
for (const arr of arrays) {
totalLength += arr.length;
}
const result = new Uint8Array(totalLength);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
/**
* Convert this.value to an ArrayBuffer
*
* If running in a browser, _toByteArray is asynchronous.
*
* @returns {Promise || undefined}
*/
_toArrayBuffer() {
// Using 'bind' here to allow this.value to be mutated within translation functions
const toByteArrayFuncs = {
browser: {
[Dish.STRING]: () => Promise.resolve(DishString.toArrayBuffer.bind(this)()),
[Dish.NUMBER]: () => Promise.resolve(DishNumber.toArrayBuffer.bind(this)()),
[Dish.HTML]: () => Promise.resolve(DishHTML.toArrayBuffer.bind(this)()),
[Dish.ARRAY_BUFFER]: () => Promise.resolve(),
[Dish.BIG_NUMBER]: () => Promise.resolve(DishBigNumber.toArrayBuffer.bind(this)()),
[Dish.JSON]: () => Promise.resolve(DishJSON.toArrayBuffer.bind(this)()),
[Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(),
[Dish.LIST_FILE]: () => Promise.resolve(DishListFile.toArrayBuffer.bind(this)()),
[Dish.BYTE_ARRAY]: () => Promise.resolve(DishByteArray.toArrayBuffer.bind(this)()),
},
node: {
[Dish.STRING]: () => DishString.toArrayBuffer.bind(this)(),
[Dish.NUMBER]: () => DishNumber.toArrayBuffer.bind(this)(),
[Dish.HTML]: () => DishHTML.toArrayBuffer.bind(this)(),
[Dish.ARRAY_BUFFER]: () => {},
[Dish.BIG_NUMBER]: () => DishBigNumber.toArrayBuffer.bind(this)(),
[Dish.JSON]: () => DishJSON.toArrayBuffer.bind(this)(),
[Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(),
[Dish.LIST_FILE]: () => DishListFile.toArrayBuffer.bind(this)(),
[Dish.BYTE_ARRAY]: () => DishByteArray.toArrayBuffer.bind(this)(),
}
};
try {
return toByteArrayFuncs[isNodeEnvironment() && "node" || "browser"][this.type]();
} catch (err) {
throw new DishError(`Error translating from ${Dish.enumLookup(this.type)} to ArrayBuffer: ${err}`);
}
}
return result;
/**
* Convert this.value to the given type from ArrayBuffer
*
* @param {number} toType - the Dish enum to convert to
* @param {boolean} [notUTF8=false] - Do not treat strings as UTF8.
*/
_fromArrayBuffer(toType, notUTF8) {
// Using 'bind' here to allow this.value to be mutated within translation functions
const toTypeFunctions = {
[Dish.STRING]: () => DishString.fromArrayBuffer.bind(this)(notUTF8),
[Dish.NUMBER]: () => DishNumber.fromArrayBuffer.bind(this)(notUTF8),
[Dish.HTML]: () => DishHTML.fromArrayBuffer.bind(this)(notUTF8),
[Dish.ARRAY_BUFFER]: () => {},
[Dish.BIG_NUMBER]: () => DishBigNumber.fromArrayBuffer.bind(this)(notUTF8),
[Dish.JSON]: () => DishJSON.fromArrayBuffer.bind(this)(notUTF8),
[Dish.FILE]: () => DishFile.fromArrayBuffer.bind(this)(),
[Dish.LIST_FILE]: () => DishListFile.fromArrayBuffer.bind(this)(),
[Dish.BYTE_ARRAY]: () => DishByteArray.fromArrayBuffer.bind(this)(),
};
try {
toTypeFunctions[toType]();
this.type = toType;
} catch (err) {
throw new DishError(`Error translating from ArrayBuffer to ${Dish.enumLookup(toType)}: ${err}`);
}
}
}

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Utils from "./Utils";
import {fromHex} from "./lib/Hex";
import Utils from "./Utils.mjs";
import {fromHex} from "./lib/Hex.mjs";
/**
* The arguments to operations.

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Dish from "./Dish";
import Ingredient from "./Ingredient";
import Dish from "./Dish.mjs";
import Ingredient from "./Ingredient.mjs";
/**
* The Operation specified by the user to be run.

View File

@@ -5,10 +5,11 @@
*/
import OperationConfig from "./config/OperationConfig.json";
import OperationError from "./errors/OperationError";
import Operation from "./Operation";
import DishError from "./errors/DishError";
import OperationError from "./errors/OperationError.mjs";
import Operation from "./Operation.mjs";
import DishError from "./errors/DishError.mjs";
import log from "loglevel";
import { isWorkerEnvironment } from "./Utils.mjs";
// Cache container for modules
let modules = null;
@@ -61,7 +62,7 @@ class Recipe {
if (!modules) {
// Using Webpack Magic Comments to force the dynamic import to be included in the main chunk
// https://webpack.js.org/api/module-methods/
modules = await import(/* webpackMode: "eager" */ "./config/modules/OpModules");
modules = await import(/* webpackMode: "eager" */ "./config/modules/OpModules.mjs");
modules = modules.default;
}
@@ -200,7 +201,12 @@ class Recipe {
try {
input = await dish.get(op.inputType);
log.debug("Executing operation");
log.debug(`Executing operation '${op.name}'`);
if (isWorkerEnvironment()) {
self.sendStatusMessage(`Baking... (${i+1}/${this.opList.length})`);
self.sendProgressMessage(i + 1, this.opList.length);
}
if (op.flowControl) {
// Package up the current state

View File

@@ -5,11 +5,10 @@
*/
import utf8 from "utf8";
import {fromBase64, toBase64} from "./lib/Base64";
import {fromHex} from "./lib/Hex";
import {fromDecimal} from "./lib/Decimal";
import {fromBinary} from "./lib/Binary";
import {fromBase64, toBase64} from "./lib/Base64.mjs";
import {fromHex} from "./lib/Hex.mjs";
import {fromDecimal} from "./lib/Decimal.mjs";
import {fromBinary} from "./lib/Binary.mjs";
/**
* Utility functions for use in operations, the core framework and the stage.
@@ -95,7 +94,7 @@ class Utils {
const paddedBytes = new Array(numBytes);
paddedBytes.fill(padByte);
Array.prototype.map.call(arr, function(b, i) {
[...arr].forEach((b, i) => {
paddedBytes[i] = b;
});
@@ -174,10 +173,11 @@ class Utils {
* @returns {string}
*/
static printable(str, preserveWs=false) {
if (ENVIRONMENT_IS_WEB() && window.app && !window.app.options.treatAsUtf8) {
if (isWebEnvironment() && window.app && !window.app.options.treatAsUtf8) {
str = Utils.byteArrayToChars(Utils.strToByteArray(str));
}
// eslint-disable-next-line no-misleading-character-class
const re = /[\0-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BB-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]/g;
const wsRe = /[\x09-\x10\x0D\u2028\u2029]/g;
@@ -420,9 +420,9 @@ class Utils {
const utf8Str = utf8.encode(str);
if (str.length !== utf8Str.length) {
if (ENVIRONMENT_IS_WORKER()) {
if (isWorkerEnvironment()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
} else if (isWebEnvironment()) {
window.app.options.attemptHighlight = false;
}
}
@@ -475,9 +475,9 @@ class Utils {
const utf8Str = utf8.encode(str);
if (str.length !== utf8Str.length) {
if (ENVIRONMENT_IS_WORKER()) {
if (isWorkerEnvironment()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
} else if (isWebEnvironment()) {
window.app.options.attemptHighlight = false;
}
}
@@ -537,11 +537,10 @@ class Utils {
const str = Utils.byteArrayToChars(byteArray);
try {
const utf8Str = utf8.decode(str);
if (str.length !== utf8Str.length) {
if (ENVIRONMENT_IS_WORKER()) {
if (isWorkerEnvironment()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
} else if (isWebEnvironment()) {
window.app.options.attemptHighlight = false;
}
}
@@ -994,7 +993,7 @@ class Utils {
/**
* Reads a File and returns the data as a Uint8Array.
*
* @param {File} file
* @param {File | for node: array|arrayBuffer|buffer|string} file
* @returns {Uint8Array}
*
* @example
@@ -1002,33 +1001,57 @@ class Utils {
* await Utils.readFile(new File(["hello"], "test"))
*/
static readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
const data = new Uint8Array(file.size);
let offset = 0;
const CHUNK_SIZE = 10485760; // 10MiB
const seek = function() {
if (offset >= file.size) {
resolve(data);
return;
}
const slice = file.slice(offset, offset + CHUNK_SIZE);
reader.readAsArrayBuffer(slice);
};
if (isNodeEnvironment()) {
return Buffer.from(file).buffer;
} else {
return new Promise((resolve, reject) => {
const reader = new FileReader();
const data = new Uint8Array(file.size);
let offset = 0;
const CHUNK_SIZE = 10485760; // 10MiB
const seek = function() {
if (offset >= file.size) {
resolve(data);
return;
}
const slice = file.slice(offset, offset + CHUNK_SIZE);
reader.readAsArrayBuffer(slice);
};
reader.onload = function(e) {
data.set(new Uint8Array(reader.result), offset);
offset += CHUNK_SIZE;
seek();
};
reader.onerror = function(e) {
reject(reader.error.message);
};
reader.onload = function(e) {
data.set(new Uint8Array(reader.result), offset);
offset += CHUNK_SIZE;
seek();
};
});
}
}
reader.onerror = function(e) {
reject(reader.error.message);
};
/**
* Synchronously read the raw data from a File object.
*
* Only works in the Node environment
*
* @param {File} file - a File shim object (see src/node/File.mjs)
* @returns {ArrayBuffer} the data from the file in an ArrayBuffer
* @throws {TypeError} thrown if the method is called from a browser environment
*/
static readFileSync(file) {
if (!isNodeEnvironment()) {
throw new TypeError("Browser environment cannot support readFileSync");
}
seek();
});
const arrayBuffer = Uint8Array.from(file.data);
return arrayBuffer.buffer;
}
@@ -1130,6 +1153,30 @@ class Utils {
}
/**
* Check whether the code is running in a Node.js environment
* @returns {boolean}
*/
export function isNodeEnvironment() {
return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
}
/**
* Check whether the code is running in a web environment
* @returns {boolean}
*/
export function isWebEnvironment() {
return typeof window === "object";
}
/**
* Check whether the code is running in a worker
* @returns {boolean}
*/
export function isWorkerEnvironment() {
return typeof importScripts === "function";
}
export default Utils;
@@ -1148,7 +1195,7 @@ export default Utils;
Array.prototype.unique = function() {
const u = {}, a = [];
for (let i = 0, l = this.length; i < l; i++) {
if (u.hasOwnProperty(this[i])) {
if (Object.prototype.hasOwnProperty.call(u, this[i])) {
continue;
}
a.push(this[i]);
@@ -1247,12 +1294,13 @@ String.prototype.count = function(chr) {
* @param {string} msg
*/
export function sendStatusMessage(msg) {
if (ENVIRONMENT_IS_WORKER())
if (isWorkerEnvironment())
self.sendStatusMessage(msg);
else if (ENVIRONMENT_IS_WEB())
else if (isWebEnvironment())
app.alert(msg, 10000);
else if (ENVIRONMENT_IS_NODE())
log.debug(msg);
else if (isNodeEnvironment())
// eslint-disable-next-line no-console
console.debug(msg);
}

View File

@@ -197,8 +197,8 @@
"Remove null bytes",
"To Upper case",
"To Lower case",
"To Case Insensitive Regex",
"From Case Insensitive Regex",
"To Case Insensitive Regex",
"From Case Insensitive Regex",
"Add line numbers",
"Remove line numbers",
"To Table",
@@ -302,6 +302,8 @@
"Snefru",
"BLAKE2b",
"BLAKE2s",
"GOST hash",
"Streebog",
"SSDEEP",
"CTPH",
"Compare SSDEEP hashes",
@@ -316,6 +318,7 @@
"Fletcher-32 Checksum",
"Fletcher-64 Checksum",
"Adler-32 Checksum",
"CRC-8 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum"
@@ -384,6 +387,9 @@
"Contain Image",
"Cover Image",
"Image Hue/Saturation/Lightness",
"Sharpen Image",
"Convert Image Format",
"Add Text To Image",
"Hex Density chart",
"Scatter chart",
"Series chart",

View File

@@ -14,7 +14,7 @@
import path from "path";
import fs from "fs";
import process from "process";
import * as Ops from "../../operations/index";
import * as Ops from "../../operations/index.mjs";
const dir = path.join(process.cwd() + "/src/core/config/");
if (!fs.existsSync(dir)) {
@@ -45,11 +45,11 @@ for (const opObj in Ops) {
args: op.args
};
if (op.hasOwnProperty("patterns")) {
if ("patterns" in op) {
operationConfig[op.name].patterns = op.patterns;
}
if (!modules.hasOwnProperty(op.module))
if (!(op.module in modules))
modules[op.module] = {};
modules[op.module][op.name] = opObj;
}
@@ -84,7 +84,7 @@ for (const module in modules) {
for (const opName in modules[module]) {
const objName = modules[module][opName];
code += `import ${objName} from "../../operations/${objName}";\n`;
code += `import ${objName} from "../../operations/${objName}.mjs";\n`;
}
code += `
@@ -124,7 +124,7 @@ let opModulesCode = `/**
`;
for (const module in modules) {
opModulesCode += `import ${module}Module from "./${module}";\n`;
opModulesCode += `import ${module}Module from "./${module}.mjs";\n`;
}
opModulesCode += `

View File

@@ -39,7 +39,7 @@ let code = `/**
`;
opObjs.forEach(obj => {
code += `import ${obj} from "./${obj}";\n`;
code += `import ${obj} from "./${obj}.mjs";\n`;
});
code += `

View File

@@ -13,7 +13,7 @@ import colors from "colors";
import process from "process";
import fs from "fs";
import path from "path";
import EscapeString from "../../operations/EscapeString";
import EscapeString from "../../operations/EscapeString.mjs";
const dir = path.join(process.cwd() + "/src/core/operations/");
@@ -130,8 +130,8 @@ prompt.get(schema, (err, result) => {
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* ${result.opName} operation

View File

@@ -0,0 +1,39 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
import Utils from "../Utils.mjs";
import BigNumber from "bignumber.js";
/**
* translation methods for BigNumber Dishes
*/
class DishBigNumber extends DishType {
/**
* convert the given value to a ArrayBuffer
* @param {BigNumber} value
*/
static toArrayBuffer() {
DishBigNumber.checkForValue(this.value);
this.value = BigNumber.isBigNumber(this.value) ? Utils.strToArrayBuffer(this.value.toFixed()) : new ArrayBuffer;
}
/**
* convert the given value from a ArrayBuffer
* @param {boolean} notUTF8
*/
static fromArrayBuffer(notUTF8) {
DishBigNumber.checkForValue(this.value);
try {
this.value = new BigNumber(Utils.arrayBufferToStr(this.value, !notUTF8));
} catch (err) {
this.value = new BigNumber(NaN);
}
}
}
export default DishBigNumber;

View File

@@ -0,0 +1,31 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
/**
* Translation methods for ArrayBuffer Dishes
*/
class DishByteArray extends DishType {
/**
* convert the given value to a ArrayBuffer
*/
static toArrayBuffer() {
DishByteArray.checkForValue(this.value);
this.value = new Uint8Array(this.value).buffer;
}
/**
* convert the given value from a ArrayBuffer
*/
static fromArrayBuffer() {
DishByteArray.checkForValue(this.value);
this.value = Array.prototype.slice.call(new Uint8Array(this.value));
}
}
export default DishByteArray;

View File

@@ -0,0 +1,42 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
import Utils, { isNodeEnvironment } from "../Utils.mjs";
/**
* Translation methods for file Dishes
*/
class DishFile extends DishType {
/**
* convert the given value to an ArrayBuffer
* @param {File} value
*/
static toArrayBuffer() {
DishFile.checkForValue(this.value);
if (isNodeEnvironment()) {
this.value = Utils.readFileSync(this.value);
} else {
return new Promise((resolve, reject) => {
Utils.readFile(this.value)
.then(v => this.value = v.buffer)
.then(resolve)
.catch(reject);
});
}
}
/**
* convert the given value from an ArrayBuffer
*/
static fromArrayBuffer() {
DishFile.checkForValue(this.value);
this.value = new File(this.value, "unknown");
}
}
export default DishFile;

View File

@@ -0,0 +1,26 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishString from "./DishString.mjs";
import Utils from "../Utils.mjs";
/**
* Translation methods for HTML Dishes
*/
class DishHTML extends DishString {
/**
* convert the given value to a ArrayBuffer
* @param {String} value
*/
static toArrayBuffer() {
DishHTML.checkForValue(this.value);
this.value = this.value ? Utils.strToArrayBuffer(Utils.unescapeHtml(Utils.stripHtmlTags(this.value, true))) : new ArrayBuffer;
}
}
export default DishHTML;

View File

@@ -0,0 +1,33 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
import Utils from "../Utils.mjs";
/**
* Translation methods for JSON dishes
*/
class DishJSON extends DishType {
/**
* convert the given value to a ArrayBuffer
*/
static toArrayBuffer() {
DishJSON.checkForValue(this.value);
this.value = this.value ? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4)) : new ArrayBuffer;
}
/**
* convert the given value from a ArrayBuffer
* @param {boolean} notUTF8
*/
static fromArrayBuffer(notUTF8) {
DishJSON.checkForValue(this.value);
this.value = JSON.parse(Utils.arrayBufferToStr(this.value, !notUTF8));
}
}
export default DishJSON;

View File

@@ -0,0 +1,58 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
import { isNodeEnvironment } from "../Utils.mjs";
/**
* Translation methods for ListFile Dishes
*/
class DishListFile extends DishType {
/**
* convert the given value to a ArrayBuffer
*/
static toArrayBuffer() {
DishListFile.checkForValue(this.value);
if (isNodeEnvironment()) {
this.value = this.value.map(file => Uint8Array.from(file.data));
}
this.value = DishListFile.concatenateTypedArrays(...this.value).buffer;
}
/**
* convert the given value from a ArrayBuffer
*/
static fromArrayBuffer() {
DishListFile.checkForValue(this.value);
this.value = [new File(this.value, "unknown")];
}
/**
* Concatenates a list of Uint8Arrays together
*
* @param {Uint8Array[]} arrays
* @returns {Uint8Array}
*/
static concatenateTypedArrays(...arrays) {
let totalLength = 0;
for (const arr of arrays) {
totalLength += arr.length;
}
const result = new Uint8Array(totalLength);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
}
}
export default DishListFile;

View File

@@ -0,0 +1,34 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
import Utils from "../Utils.mjs";
/**
* Translation methods for number dishes
*/
class DishNumber extends DishType {
/**
* convert the given value to a ArrayBuffer
*/
static toArrayBuffer() {
DishNumber.checkForValue(this.value);
this.value = typeof this.value === "number" ? Utils.strToArrayBuffer(this.value.toString()) : new ArrayBuffer;
}
/**
* convert the given value from a ArrayBuffer
* @param {boolean} notUTF8
*/
static fromArrayBuffer(notUTF8) {
DishNumber.checkForValue(this.value);
this.value = this.value ? parseFloat(Utils.arrayBufferToStr(this.value, !notUTF8)) : 0;
}
}
export default DishNumber;

View File

@@ -0,0 +1,34 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishType from "./DishType.mjs";
import Utils from "../Utils.mjs";
/**
* Translation methods for string dishes
*/
class DishString extends DishType {
/**
* convert the given value to a ArrayBuffer
*/
static toArrayBuffer() {
DishString.checkForValue(this.value);
this.value = this.value ? Utils.strToArrayBuffer(this.value) : new ArrayBuffer;
}
/**
* convert the given value from a ArrayBuffer
* @param {boolean} notUTF8
*/
static fromArrayBuffer(notUTF8) {
DishString.checkForValue(this.value);
this.value = this.value ? Utils.arrayBufferToStr(this.value, !notUTF8) : "";
}
}
export default DishString;

View File

@@ -0,0 +1,39 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
/**
* Abstract class for dish translation methods
*/
class DishType {
/**
* Warn translations dont work without value from bind
*/
static checkForValue(value) {
if (value === undefined) {
throw new Error("only use translation methods with .bind");
}
}
/**
* convert the given value to a ArrayBuffer
* @param {*} value
*/
static toArrayBuffer() {
throw new Error("toArrayBuffer has not been implemented");
}
/**
* convert the given value from a ArrayBuffer
* @param {boolean} notUTF8
*/
static fromArrayBuffer(notUTF8=undefined) {
throw new Error("fromArrayBuffer has not been implemented");
}
}
export default DishType;

View File

@@ -0,0 +1,26 @@
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import DishByteArray from "./DishByteArray.mjs";
import DishBigNumber from "./DishBigNumber.mjs";
import DishFile from "./DishFile.mjs";
import DishHTML from "./DishHTML.mjs";
import DishJSON from "./DishJSON.mjs";
import DishListFile from "./DishListFile.mjs";
import DishNumber from "./DishNumber.mjs";
import DishString from "./DishString.mjs";
export {
DishByteArray,
DishBigNumber,
DishFile,
DishHTML,
DishJSON,
DishListFile,
DishNumber,
DishString,
};

View File

@@ -0,0 +1,25 @@
/**
* Custom error type for handling operation that isnt included in node.js API
*
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
class ExcludedOperationError extends Error {
/**
* Standard error constructor. Adds no new behaviour.
*
* @param args - Standard error args
*/
constructor(...args) {
super(...args);
this.type = "ExcludedOperationError";
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ExcludedOperationError);
}
}
}
export default ExcludedOperationError;

View File

@@ -5,7 +5,7 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Utils from "../Utils.mjs";
import BigNumber from "bignumber.js";

View File

@@ -6,7 +6,7 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Utils from "../Utils.mjs";
/**

View File

@@ -6,7 +6,7 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Utils from "../Utils.mjs";
/**

View File

@@ -7,9 +7,9 @@
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import {Rotor, Plugboard, a2i, i2a} from "./Enigma";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import {Rotor, Plugboard, a2i, i2a} from "./Enigma.mjs";
/**
* Convenience/optimisation subclass of Rotor

View File

@@ -5,7 +5,7 @@
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* @constant

View File

@@ -9,7 +9,7 @@
*
*/
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
import CryptoJS from "crypto-js";
/**

View File

@@ -8,7 +8,7 @@
import geohash from "ngeohash";
import geodesy from "geodesy";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* Co-ordinate formats

View File

@@ -6,7 +6,7 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Utils from "../Utils.mjs";
/**

View File

@@ -5,8 +5,8 @@
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
/**
* Provided default Enigma rotor set.
@@ -184,10 +184,10 @@ class PairMapBase {
// self-stecker
return;
}
if (this.map.hasOwnProperty(a)) {
if (Object.prototype.hasOwnProperty.call(this.map, a)) {
throw new OperationError(`${name} connects ${pair[0]} more than once`);
}
if (this.map.hasOwnProperty(b)) {
if (Object.prototype.hasOwnProperty.call(this.map, b)) {
throw new OperationError(`${name} connects ${pair[1]} more than once`);
}
this.map[a] = b;
@@ -203,7 +203,7 @@ class PairMapBase {
* @returns {number}
*/
transform(c) {
if (!this.map.hasOwnProperty(c)) {
if (!Object.prototype.hasOwnProperty.call(this.map, c)) {
return c;
}
return this.map[c];

View File

@@ -6,7 +6,7 @@
* @license Apache-2.0
*
*/
import Stream from "./Stream";
import Stream from "./Stream.mjs";
/**
* A categorised table of file types, including signatures to identify them and functions
@@ -170,7 +170,7 @@ export const FILE_SIGNATURES = {
mime: "image/vnd.adobe.photoshop",
description: "",
signature: {
0: 0x38,
0: 0x38, // 8BPS
1: 0x42,
2: 0x50,
3: 0x53,
@@ -185,6 +185,28 @@ export const FILE_SIGNATURES = {
},
extractor: null
},
{
name: "Photoshop Large Document",
extension: "psb",
mime: "application/x-photoshop",
description: "",
signature: {
0: 0x38, // 8BPS
1: 0x42,
2: 0x50,
3: 0x53,
4: 0x0,
5: 0x2,
6: 0x0,
7: 0x0,
8: 0x0,
9: 0x0,
10: 0x0,
11: 0x0,
12: 0x0
},
extractor: null
},
{
name: "Paint Shop Pro image",
extension: "psp",
@@ -233,10 +255,114 @@ export const FILE_SIGNATURES = {
5: 0x0,
6: [0x10, 0x20, 0x30, 0x40, 0x80],
7: [0x10, 0x20, 0x30, 0x40, 0x80],
9: 0x00,
9: 0x0,
10: [0x0, 0x1]
},
extractor: null
},
{
name: "Radiance High Dynamic Range image",
extension: "hdr",
mime: "image/vnd.radiance",
description: "",
signature: {
0: 0x23, // #?RADIANCE
1: 0x3f,
2: 0x52,
3: 0x41,
4: 0x44,
5: 0x49,
6: 0x41,
7: 0x4e,
8: 0x43,
9: 0x45,
10: 0x0a
},
extractor: null
},
{
name: "Sony ARW image",
extension: "arw",
mime: "image/x-raw",
description: "",
signature: {
0: 0x05,
1: 0x0,
2: 0x0,
3: 0x0,
4: 0x41,
5: 0x57,
6: 0x31,
7: 0x2e
},
extractor: null
},
{
name: "Fujifilm Raw Image",
extension: "raf",
mime: "image/x-raw",
description: "",
signature: {
0: 0x46, // FUJIFILMCCD-RAW
1: 0x55,
2: 0x4a,
3: 0x49,
4: 0x46,
5: 0x49,
6: 0x4c,
7: 0x4d,
8: 0x43,
9: 0x43,
10: 0x44,
11: 0x2d,
12: 0x52,
13: 0x41,
14: 0x57
},
extractor: null
},
{
name: "Minolta RAW image",
extension: "mrw",
mime: "image/x-raw",
description: "",
signature: {
0: 0x0,
1: 0x4d, // MRM
2: 0x52,
3: 0x4d
},
extractor: null
},
{
name: "Adobe Bridge Thumbnail Cache",
extension: "bct",
mime: "application/octet-stream",
description: "",
signature: {
0: 0x6c,
1: 0x6e,
2: 0x62,
3: 0x74,
4: 0x02,
5: 0x0,
6: 0x0,
7: 0x0
},
extractor: null
},
{
name: "Microsoft Document Imaging",
extension: "mdi",
mime: "image/vnd.ms-modi",
description: "",
signature: {
0: 0x45,
1: 0x50,
2: 0x2a,
3: 0x00
},
extractor: null
}
],
"Video": [
@@ -534,6 +660,97 @@ export const FILE_SIGNATURES = {
},
extractor: null
},
{
name: "Audacity",
extension: "au",
mime: "audio/x-au",
description: "",
signature: {
0: 0x64, // dns.
1: 0x6e,
2: 0x73,
3: 0x2e,
24: 0x41, // AudacityBlockFile
25: 0x75,
26: 0x64,
27: 0x61,
28: 0x63,
29: 0x69,
30: 0x74,
31: 0x79,
32: 0x42,
33: 0x6c,
34: 0x6f,
35: 0x63,
36: 0x6b,
37: 0x46,
38: 0x69,
39: 0x6c,
40: 0x65
},
extractor: null
},
{
name: "Audacity Block",
extension: "auf",
mime: "application/octet-stream",
description: "",
signature: {
0: 0x41, // AudacityBlockFile
1: 0x75,
2: 0x64,
3: 0x61,
4: 0x63,
5: 0x69,
6: 0x74,
7: 0x79,
8: 0x42,
9: 0x6c,
10: 0x6f,
11: 0x63,
12: 0x6b,
13: 0x46,
14: 0x69,
15: 0x6c,
16: 0x65
},
extractor: null
},
{
name: "Audio Interchange File",
extension: "aif",
mime: "audio/x-aiff",
description: "",
signature: {
0: 0x46, // FORM
1: 0x4f,
2: 0x52,
3: 0x4d,
8: 0x41, // AIFF
9: 0x49,
10: 0x46,
11: 0x46
},
extractor: null
},
{
name: "Audio Interchange File (compressed)",
extension: "aifc",
mime: "audio/x-aifc",
description: "",
signature: {
0: 0x46, // FORM
1: 0x4f,
2: 0x52,
3: 0x4d,
8: 0x41, // AIFC
9: 0x49,
10: 0x46,
11: 0x43
},
extractor: null
}
],
"Documents": [
{
@@ -898,6 +1115,110 @@ export const FILE_SIGNATURES = {
},
extractor: null
},
{
name: "ARJ Archive",
extension: "arj",
mime: "application/x-arj-compressed",
description: "",
signature: {
0: 0x60,
1: 0xea,
8: [0x0, 0x10, 0x14],
9: 0x0,
10: 0x2
},
extractor: null
},
{
name: "WinAce Archive",
extension: "ace",
mime: "application/x-ace-compressed",
description: "",
signature: {
7: 0x2a, // **ACE**
8: 0x2a,
9: 0x41,
10: 0x43,
11: 0x45,
12: 0x2a,
13: 0x2a
},
extractor: null
},
{
name: "Macintosh BinHex Encoded File",
extension: "hqx",
mime: "application/mac-binhex",
description: "",
signature: {
11: 0x6d, // must be converted with BinHex
12: 0x75,
13: 0x73,
14: 0x74,
15: 0x20,
16: 0x62,
17: 0x65,
18: 0x20,
19: 0x63,
20: 0x6f,
21: 0x6e,
22: 0x76,
23: 0x65,
24: 0x72,
25: 0x74,
26: 0x65,
27: 0x64,
28: 0x20,
29: 0x77,
30: 0x69,
31: 0x74,
32: 0x68,
33: 0x20,
34: 0x42,
35: 0x69,
36: 0x6e,
37: 0x48,
38: 0x65,
39: 0x78
},
extractor: null
},
{
name: "ALZip Archive",
extension: "alz",
mime: "application/octet-stream",
description: "",
signature: {
0: 0x41, // ALZ
1: 0x4c,
2: 0x5a,
3: 0x01,
4: 0x0a,
5: 0x0,
6: 0x0,
7: 0x0
},
extractor: null
},
{
name: "KGB Compressed Archive",
extension: "kgb",
mime: "application/x-kgb-compressed",
description: "",
signature: {
0: 0x4b, // KGB_arch -
1: 0x47,
2: 0x42,
3: 0x5f,
4: 0x61,
5: 0x72,
6: 0x63,
7: 0x68,
8: 0x20,
9: 0x2d
},
extractor: null
}
],
"Miscellaneous": [
{
@@ -1041,6 +1362,43 @@ export const FILE_SIGNATURES = {
},
extractor: null
},
{
name: "BitTorrent link",
extension: "torrent",
mime: "application/x-bittorrent",
description: "",
signature: [
{
0: 0x64, // d8:announce##:
1: 0x38,
2: 0x3a,
3: 0x61,
4: 0x6e,
5: 0x6e,
6: 0x6f,
7: 0x75,
8: 0x6e,
9: 0x63,
10: 0x65,
11: 0x23,
12: 0x23,
13: 0x3a
},
{
0: 0x64, // d4:infod
1: 0x34,
2: 0x3a,
3: 0x69,
4: 0x6e,
5: 0x66,
6: 0x6f,
7: 0x64,
8: [0x34, 0x35, 0x36],
9: 0x3a
}
],
extractor: null
}
]
};

View File

@@ -6,8 +6,8 @@
* @license Apache-2.0
*
*/
import {FILE_SIGNATURES} from "./FileSignatures";
import {sendStatusMessage} from "../Utils";
import {FILE_SIGNATURES} from "./FileSignatures.mjs";
import {sendStatusMessage} from "../Utils.mjs";
/**

View File

@@ -7,8 +7,8 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import CryptoApi from "crypto-api/src/crypto-api";
import Utils from "../Utils.mjs";
import CryptoApi from "crypto-api/src/crypto-api.mjs";
/**

View File

@@ -6,13 +6,13 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Utils from "../Utils.mjs";
/**
* Convert a byte array into a hex string.
*
* @param {Uint8Array|byteArray} data
* @param {byteArray|Uint8Array|ArrayBuffer} data
* @param {string} [delim=" "]
* @param {number} [padding=2]
* @returns {string}
@@ -26,6 +26,7 @@ import Utils from "../Utils";
*/
export function toHex(data, delim=" ", padding=2) {
if (!data) return "";
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
let output = "";
@@ -47,7 +48,7 @@ export function toHex(data, delim=" ", padding=2) {
/**
* Convert a byte array into a hex string as efficiently as possible with no options.
*
* @param {byteArray} data
* @param {byteArray|Uint8Array|ArrayBuffer} data
* @returns {string}
*
* @example
@@ -56,6 +57,7 @@ export function toHex(data, delim=" ", padding=2) {
*/
export function toHexFast(data) {
if (!data) return "";
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
const output = [];

View File

@@ -8,8 +8,8 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import OperationError from "../errors/OperationError";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Parses an IPv4 CIDR range (e.g. 192.168.0.0/24) and displays information about it.

View File

@@ -0,0 +1,251 @@
/**
* Image manipulation resources
*
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
/**
* Gaussian blurs an image.
*
* @param {jimp} input
* @param {number} radius
* @param {boolean} fast
* @returns {jimp}
*/
export function gaussianBlur (input, radius) {
try {
// From http://blog.ivank.net/fastest-gaussian-blur.html
const boxes = boxesForGauss(radius, 3);
for (let i = 0; i < 3; i++) {
input = boxBlur(input, (boxes[i] - 1) / 2);
}
} catch (err) {
throw new OperationError(`Error blurring image. (${err})`);
}
return input;
}
/**
*
* @param {number} radius
* @param {number} numBoxes
* @returns {Array}
*/
function boxesForGauss(radius, numBoxes) {
const idealWidth = Math.sqrt((12 * radius * radius / numBoxes) + 1);
let wl = Math.floor(idealWidth);
if (wl % 2 === 0) {
wl--;
}
const wu = wl + 2;
const mIdeal = (12 * radius * radius - numBoxes * wl * wl - 4 * numBoxes * wl - 3 * numBoxes) / (-4 * wl - 4);
const m = Math.round(mIdeal);
const sizes = [];
for (let i = 0; i < numBoxes; i++) {
sizes.push(i < m ? wl : wu);
}
return sizes;
}
/**
* Applies a box blur effect to the image
*
* @param {jimp} source
* @param {number} radius
* @returns {jimp}
*/
function boxBlur (source, radius) {
const width = source.bitmap.width;
const height = source.bitmap.height;
let output = source.clone();
output = boxBlurH(source, output, width, height, radius);
source = boxBlurV(output, source, width, height, radius);
return source;
}
/**
* Applies the horizontal blur
*
* @param {jimp} source
* @param {jimp} output
* @param {number} width
* @param {number} height
* @param {number} radius
* @returns {jimp}
*/
function boxBlurH (source, output, width, height, radius) {
const iarr = 1 / (radius + radius + 1);
for (let i = 0; i < height; i++) {
let ti = 0,
li = ti,
ri = ti + radius;
const idx = source.getPixelIndex(ti, i);
const firstValRed = source.bitmap.data[idx],
firstValGreen = source.bitmap.data[idx + 1],
firstValBlue = source.bitmap.data[idx + 2],
firstValAlpha = source.bitmap.data[idx + 3];
const lastIdx = source.getPixelIndex(width - 1, i),
lastValRed = source.bitmap.data[lastIdx],
lastValGreen = source.bitmap.data[lastIdx + 1],
lastValBlue = source.bitmap.data[lastIdx + 2],
lastValAlpha = source.bitmap.data[lastIdx + 3];
let red = (radius + 1) * firstValRed;
let green = (radius + 1) * firstValGreen;
let blue = (radius + 1) * firstValBlue;
let alpha = (radius + 1) * firstValAlpha;
for (let j = 0; j < radius; j++) {
const jIdx = source.getPixelIndex(ti + j, i);
red += source.bitmap.data[jIdx];
green += source.bitmap.data[jIdx + 1];
blue += source.bitmap.data[jIdx + 2];
alpha += source.bitmap.data[jIdx + 3];
}
for (let j = 0; j <= radius; j++) {
const jIdx = source.getPixelIndex(ri++, i);
red += source.bitmap.data[jIdx] - firstValRed;
green += source.bitmap.data[jIdx + 1] - firstValGreen;
blue += source.bitmap.data[jIdx + 2] - firstValBlue;
alpha += source.bitmap.data[jIdx + 3] - firstValAlpha;
const tiIdx = source.getPixelIndex(ti++, i);
output.bitmap.data[tiIdx] = Math.round(red * iarr);
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
}
for (let j = radius + 1; j < width - radius; j++) {
const riIdx = source.getPixelIndex(ri++, i);
const liIdx = source.getPixelIndex(li++, i);
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
const tiIdx = source.getPixelIndex(ti++, i);
output.bitmap.data[tiIdx] = Math.round(red * iarr);
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
}
for (let j = width - radius; j < width; j++) {
const liIdx = source.getPixelIndex(li++, i);
red += lastValRed - source.bitmap.data[liIdx];
green += lastValGreen - source.bitmap.data[liIdx + 1];
blue += lastValBlue - source.bitmap.data[liIdx + 2];
alpha += lastValAlpha - source.bitmap.data[liIdx + 3];
const tiIdx = source.getPixelIndex(ti++, i);
output.bitmap.data[tiIdx] = Math.round(red * iarr);
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
}
}
return output;
}
/**
* Applies the vertical blur
*
* @param {jimp} source
* @param {jimp} output
* @param {number} width
* @param {number} height
* @param {number} radius
* @returns {jimp}
*/
function boxBlurV (source, output, width, height, radius) {
const iarr = 1 / (radius + radius + 1);
for (let i = 0; i < width; i++) {
let ti = 0,
li = ti,
ri = ti + radius;
const idx = source.getPixelIndex(i, ti);
const firstValRed = source.bitmap.data[idx],
firstValGreen = source.bitmap.data[idx + 1],
firstValBlue = source.bitmap.data[idx + 2],
firstValAlpha = source.bitmap.data[idx + 3];
const lastIdx = source.getPixelIndex(i, height - 1),
lastValRed = source.bitmap.data[lastIdx],
lastValGreen = source.bitmap.data[lastIdx + 1],
lastValBlue = source.bitmap.data[lastIdx + 2],
lastValAlpha = source.bitmap.data[lastIdx + 3];
let red = (radius + 1) * firstValRed;
let green = (radius + 1) * firstValGreen;
let blue = (radius + 1) * firstValBlue;
let alpha = (radius + 1) * firstValAlpha;
for (let j = 0; j < radius; j++) {
const jIdx = source.getPixelIndex(i, ti + j);
red += source.bitmap.data[jIdx];
green += source.bitmap.data[jIdx + 1];
blue += source.bitmap.data[jIdx + 2];
alpha += source.bitmap.data[jIdx + 3];
}
for (let j = 0; j <= radius; j++) {
const riIdx = source.getPixelIndex(i, ri++);
red += source.bitmap.data[riIdx] - firstValRed;
green += source.bitmap.data[riIdx + 1] - firstValGreen;
blue += source.bitmap.data[riIdx + 2] - firstValBlue;
alpha += source.bitmap.data[riIdx + 3] - firstValAlpha;
const tiIdx = source.getPixelIndex(i, ti++);
output.bitmap.data[tiIdx] = Math.round(red * iarr);
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
}
for (let j = radius + 1; j < height - radius; j++) {
const riIdx = source.getPixelIndex(i, ri++);
const liIdx = source.getPixelIndex(i, li++);
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
const tiIdx = source.getPixelIndex(i, ti++);
output.bitmap.data[tiIdx] = Math.round(red * iarr);
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
}
for (let j = height - radius; j < height; j++) {
const liIdx = source.getPixelIndex(i, li++);
red += lastValRed - source.bitmap.data[liIdx];
green += lastValGreen - source.bitmap.data[liIdx + 1];
blue += lastValBlue - source.bitmap.data[liIdx + 2];
alpha += lastValAlpha - source.bitmap.data[liIdx + 3];
const tiIdx = source.getPixelIndex(i, ti++);
output.bitmap.data[tiIdx] = Math.round(red * iarr);
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
}
}
return output;
}

View File

@@ -1,8 +1,8 @@
import OperationConfig from "../config/OperationConfig.json";
import Utils from "../Utils";
import Recipe from "../Recipe";
import Dish from "../Dish";
import {detectFileType} from "./FileType";
import Utils, { isWorkerEnvironment } from "../Utils.mjs";
import Recipe from "../Recipe.mjs";
import Dish from "../Dish.mjs";
import {detectFileType} from "./FileType.mjs";
import chiSquared from "chi-squared";
/**
@@ -312,6 +312,11 @@ class Magic {
return;
}
// If the recipe returned an empty buffer, do not continue
if (_buffersEqual(output, new ArrayBuffer())) {
return;
}
const magic = new Magic(output, this.opPatterns),
speculativeResults = await magic.speculativeExecution(
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful, crib);
@@ -333,7 +338,7 @@ class Magic {
}
// Prune branches that result in unhelpful outputs
results = results.filter(r =>
const prunedResults = results.filter(r =>
(r.useful || r.data.length > 0) && // The operation resulted in ""
( // One of the following must be true
r.languageScores[0].probability > 0 || // Some kind of language was found
@@ -344,7 +349,7 @@ class Magic {
);
// Return a sorted list of possible recipes along with their properties
return results.sort((a, b) => {
return prunedResults.sort((a, b) => {
// Each option is sorted based on its most likely language (lower is better)
let aScore = a.languageScores[0].score,
bScore = b.languageScores[0].score;
@@ -390,12 +395,17 @@ class Magic {
const dish = new Dish();
dish.set(input, Dish.ARRAY_BUFFER);
if (ENVIRONMENT_IS_WORKER()) self.loadRequiredModules(recipeConfig);
if (isWorkerEnvironment()) self.loadRequiredModules(recipeConfig);
const recipe = new Recipe(recipeConfig);
try {
await recipe.execute(dish);
return dish.get(Dish.ARRAY_BUFFER);
// Return an empty buffer if the recipe did not run to completion
if (recipe.lastRunOp === recipe.opList[recipe.opList.length - 1]) {
return dish.get(Dish.ARRAY_BUFFER);
} else {
return new ArrayBuffer();
}
} catch (err) {
// If there are errors, return an empty buffer
return new ArrayBuffer();
@@ -440,7 +450,7 @@ class Magic {
const opPatterns = [];
for (const op in OperationConfig) {
if (!OperationConfig[op].hasOwnProperty("patterns")) continue;
if (!("patterns" in OperationConfig[op])) continue;
OperationConfig[op].patterns.forEach(pattern => {
opPatterns.push({

View File

@@ -10,7 +10,8 @@
*
*/
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import kbpgp from "kbpgp";
import * as es6promisify from "es6-promisify";
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
@@ -45,7 +46,7 @@ export const ASP = kbpgp.ASP({
msg = `Stage: ${info.what}`;
}
if (ENVIRONMENT_IS_WORKER())
if (isWorkerEnvironment())
self.sendStatusMessage(msg);
}
});

View File

@@ -1,4 +1,4 @@
import Utils from "../Utils";
import Utils from "../Utils.mjs";
/**
* Protobuf lib. Contains functions to decode protobuf serialised
@@ -124,7 +124,7 @@ class Protobuf {
// Get the field key/values
const key = field.key;
const value = field.value;
object[key] = object.hasOwnProperty(key) ?
object[key] = Object.prototype.hasOwnProperty.call(object, key) ?
object[key] instanceof Array ?
object[key].concat([value]) :
[object[key], value] :

View File

@@ -6,7 +6,7 @@
* @license Apache-2.0
*/
import { toHex, fromHex } from "./Hex";
import { toHex, fromHex } from "./Hex.mjs";
/**
* Formats Distinguished Name (DN) strings.

93
src/core/lib/QRCode.mjs Normal file
View File

@@ -0,0 +1,93 @@
/**
* QR code resources
*
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import jsQR from "jsqr";
import qr from "qr-image";
import jimp from "jimp";
import Utils from "../Utils.mjs";
/**
* Parses a QR code image from an image
*
* @param {ArrayBuffer} input
* @param {boolean} normalise
* @returns {string}
*/
export async function parseQrCode(input, normalise) {
let image;
try {
image = await jimp.read(input);
} catch (err) {
throw new OperationError(`Error opening image. (${err})`);
}
try {
if (normalise) {
image.rgba(false);
image.background(0xFFFFFFFF);
image.normalize();
image.greyscale();
image = await image.getBufferAsync(jimp.MIME_JPEG);
image = await jimp.read(image);
}
} catch (err) {
throw new OperationError(`Error normalising iamge. (${err})`);
}
const qrData = jsQR(image.bitmap.data, image.getWidth(), image.getHeight());
if (qrData) {
return qrData.data;
} else {
throw new OperationError("Could not read a QR code from the image.");
}
}
/**
* Generates a QR code from the input string
*
* @param {string} input
* @param {string} format
* @param {number} moduleSize
* @param {number} margin
* @param {string} errorCorrection
* @returns {ArrayBuffer}
*/
export function generateQrCode(input, format, moduleSize, margin, errorCorrection) {
const formats = ["SVG", "EPS", "PDF", "PNG"];
if (!formats.includes(format.toUpperCase())) {
throw new OperationError("Unsupported QR code format.");
}
let qrImage;
try {
qrImage = qr.imageSync(input, {
type: format,
size: moduleSize,
margin: margin,
"ec_level": errorCorrection.charAt(0).toUpperCase()
});
} catch (err) {
throw new OperationError(`Error generating QR code. (${err})`);
}
if (!qrImage) {
throw new OperationError("Error generating QR code.");
}
switch (format) {
case "SVG":
case "EPS":
case "PDF":
return Utils.strToArrayBuffer(qrImage);
case "PNG":
return qrImage.buffer;
default:
throw new OperationError("Unsupported QR code format.");
}
}

View File

@@ -6,9 +6,9 @@
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError";
import * as Enigma from "../lib/Enigma";
import Utils from "../Utils";
import OperationError from "../errors/OperationError.mjs";
import * as Enigma from "../lib/Enigma.mjs";
import Utils from "../Utils.mjs";
/**
* A set of example Typex rotors. No Typex rotor wirings are publicly available, so these are
@@ -98,14 +98,14 @@ export class TypexMachine extends Enigma.EnigmaBase {
if (x === " ") {
inputMod += "X";
} else if (mode) {
if (KEYBOARD_REV.hasOwnProperty(x)) {
if (Object.prototype.hasOwnProperty.call(KEYBOARD_REV, x)) {
inputMod += KEYBOARD_REV[x];
} else {
mode = false;
inputMod += "V" + x;
}
} else {
if (KEYBOARD_REV.hasOwnProperty(x)) {
if (Object.prototype.hasOwnProperty.call(KEYBOARD_REV, x)) {
mode = true;
inputMod += "Z" + KEYBOARD_REV[x];
} else {

View File

@@ -6,7 +6,7 @@
* @license Apache-2.0
*/
import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min";
import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js";
const Zlib = zlibAndGzip.Zlib;

View File

@@ -4,10 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import {DELIM_OPTIONS} from "../lib/Delim";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* A1Z26 Cipher Decode operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import {DELIM_OPTIONS} from "../lib/Delim";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
/**
* A1Z26 Cipher Encode operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import { bitOp, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import { bitOp, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs";
/**
* ADD operation

View File

@@ -4,10 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import forge from "node-forge/dist/forge.min.js";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* AES Decrypt operation

View File

@@ -4,10 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import forge from "node-forge/dist/forge.min.js";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* AES Encrypt operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import { bitOp, and, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import { bitOp, and, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs";
/**
* AND operation

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* Add line numbers operation

View File

@@ -0,0 +1,267 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
/**
* Add Text To Image operation
*/
class AddTextToImage extends Operation {
/**
* AddTextToImage constructor
*/
constructor() {
super();
this.name = "Add Text To Image";
this.module = "Image";
this.description = "Adds text onto an image.<br><br>Text can be horizontally or vertically aligned, or the position can be manually specified.<br>Variants of the Roboto font face are available in any size or colour.";
this.infoURL = "";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.presentType = "html";
this.args = [
{
name: "Text",
type: "string",
value: ""
},
{
name: "Horizontal align",
type: "option",
value: ["None", "Left", "Center", "Right"]
},
{
name: "Vertical align",
type: "option",
value: ["None", "Top", "Middle", "Bottom"]
},
{
name: "X position",
type: "number",
value: 0
},
{
name: "Y position",
type: "number",
value: 0
},
{
name: "Size",
type: "number",
value: 32,
min: 8
},
{
name: "Font face",
type: "option",
value: [
"Roboto",
"Roboto Black",
"Roboto Mono",
"Roboto Slab"
]
},
{
name: "Red",
type: "number",
value: 255,
min: 0,
max: 255
},
{
name: "Green",
type: "number",
value: 255,
min: 0,
max: 255
},
{
name: "Blue",
type: "number",
value: 255,
min: 0,
max: 255
},
{
name: "Alpha",
type: "number",
value: 255,
min: 0,
max: 255
}
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {byteArray}
*/
async run(input, args) {
const text = args[0],
hAlign = args[1],
vAlign = args[2],
size = args[5],
fontFace = args[6],
red = args[7],
green = args[8],
blue = args[9],
alpha = args[10];
let xPos = args[3],
yPos = args[4];
if (!isImage(new Uint8Array(input))) {
throw new OperationError("Invalid file type.");
}
let image;
try {
image = await jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
try {
if (isWorkerEnvironment())
self.sendStatusMessage("Adding text to image...");
const fontsMap = {};
const fonts = [
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.fnt"),
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.fnt"),
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.fnt"),
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.fnt")
];
await Promise.all(fonts)
.then(fonts => {
fontsMap.Roboto = fonts[0];
fontsMap["Roboto Black"] = fonts[1];
fontsMap["Roboto Mono"] = fonts[2];
fontsMap["Roboto Slab"] = fonts[3];
});
// Make Webpack load the png font images
await Promise.all([
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.png"),
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.png"),
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.png"),
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.png")
]);
const font = fontsMap[fontFace];
// LoadFont needs an absolute url, so append the font name to self.docURL
const jimpFont = await jimp.loadFont(self.docURL + "/" + font.default);
jimpFont.pages.forEach(function(page) {
if (page.bitmap) {
// Adjust the RGB values of the image pages to change the font colour.
const pageWidth = page.bitmap.width;
const pageHeight = page.bitmap.height;
for (let ix = 0; ix < pageWidth; ix++) {
for (let iy = 0; iy < pageHeight; iy++) {
const idx = (iy * pageWidth + ix) << 2;
const newRed = page.bitmap.data[idx] - (255 - red);
const newGreen = page.bitmap.data[idx + 1] - (255 - green);
const newBlue = page.bitmap.data[idx + 2] - (255 - blue);
const newAlpha = page.bitmap.data[idx + 3] - (255 - alpha);
// Make sure the bitmap values don't go below 0 as that makes jimp very unhappy
page.bitmap.data[idx] = (newRed > 0) ? newRed : 0;
page.bitmap.data[idx + 1] = (newGreen > 0) ? newGreen : 0;
page.bitmap.data[idx + 2] = (newBlue > 0) ? newBlue : 0;
page.bitmap.data[idx + 3] = (newAlpha > 0) ? newAlpha : 0;
}
}
}
});
// Create a temporary image to hold the rendered text
const textImage = new jimp(jimp.measureText(jimpFont, text), jimp.measureTextHeight(jimpFont, text));
textImage.print(jimpFont, 0, 0, text);
// Scale the rendered text image to the correct size
const scaleFactor = size / 72;
if (size !== 1) {
// Use bicubic for decreasing size
if (size > 1) {
textImage.scale(scaleFactor, jimp.RESIZE_BICUBIC);
} else {
textImage.scale(scaleFactor, jimp.RESIZE_BILINEAR);
}
}
// If using the alignment options, calculate the pixel values AFTER the image has been scaled
switch (hAlign) {
case "Left":
xPos = 0;
break;
case "Center":
xPos = (image.getWidth() / 2) - (textImage.getWidth() / 2);
break;
case "Right":
xPos = image.getWidth() - textImage.getWidth();
break;
}
switch (vAlign) {
case "Top":
yPos = 0;
break;
case "Middle":
yPos = (image.getHeight() / 2) - (textImage.getHeight() / 2);
break;
case "Bottom":
yPos = image.getHeight() - textImage.getHeight();
break;
}
// Blit the rendered text image onto the original source image
image.blit(textImage, xPos, yPos);
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
throw new OperationError(`Error adding text to image. (${err})`);
}
}
/**
* Displays the blurred image using HTML for web apps
*
* @param {ArrayBuffer} data
* @returns {html}
*/
present(data) {
if (!data.byteLength) return "";
const dataArray = new Uint8Array(data);
const type = isImage(dataArray);
if (!type) {
throw new OperationError("Invalid file type.");
}
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
}
}
export default AddTextToImage;

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
/**
* Adler-32 Checksum operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Affine Cipher Decode operation

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import { affineEncode } from "../lib/Ciphers";
import Operation from "../Operation.mjs";
import { affineEncode } from "../lib/Ciphers.mjs";
/**
* Affine Cipher Encode operation

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Analyse hash operation

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import { affineEncode } from "../lib/Ciphers";
import Operation from "../Operation.mjs";
import { affineEncode } from "../lib/Ciphers.mjs";
/**
* Atbash Cipher operation

View File

@@ -4,11 +4,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import blakejs from "blakejs";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import { toBase64 } from "../lib/Base64";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toBase64 } from "../lib/Base64.mjs";
/**
* BLAKE2b operation

View File

@@ -4,11 +4,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import blakejs from "blakejs";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import { toBase64 } from "../lib/Base64";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toBase64 } from "../lib/Base64.mjs";
/**
* BLAKE2s Operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import bson from "bson";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* BSON deserialise operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import bson from "bson";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* BSON serialise operation

View File

@@ -4,8 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import bcrypt from "bcryptjs";
import { isWorkerEnvironment } from "../Utils.mjs";
/**
* Bcrypt operation
@@ -44,7 +45,7 @@ class Bcrypt extends Operation {
return await bcrypt.hash(input, salt, null, p => {
// Progress callback
if (ENVIRONMENT_IS_WORKER())
if (isWorkerEnvironment())
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
});

View File

@@ -4,8 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import bcrypt from "bcryptjs";
import { isWorkerEnvironment } from "../Utils.mjs";
/**
* Bcrypt compare operation
@@ -43,7 +45,7 @@ class BcryptCompare extends Operation {
const match = await bcrypt.compare(input, hash, null, p => {
// Progress callback
if (ENVIRONMENT_IS_WORKER())
if (isWorkerEnvironment())
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
});

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import bcrypt from "bcryptjs";
/**

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import { genPolybiusSquare } from "../lib/Ciphers";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import { genPolybiusSquare } from "../lib/Ciphers.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Bifid Cipher Decode operation

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import { genPolybiusSquare } from "../lib/Ciphers";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { genPolybiusSquare } from "../lib/Ciphers.mjs";
/**
* Bifid Cipher Encode operation

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* Bit shift left operation

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* Bit shift right operation

View File

@@ -4,12 +4,12 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import OperationError from "../errors/OperationError";
import { Blowfish } from "../vendor/Blowfish";
import { toBase64 } from "../lib/Base64";
import { toHexFast } from "../lib/Hex";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
import { Blowfish } from "../vendor/Blowfish.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { toHexFast } from "../lib/Hex.mjs";
/**
* Lookup table for Blowfish output types.

View File

@@ -4,11 +4,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import OperationError from "../errors/OperationError";
import { Blowfish } from "../vendor/Blowfish";
import { toBase64 } from "../lib/Base64";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
import { Blowfish } from "../vendor/Blowfish.mjs";
import { toBase64 } from "../lib/Base64.mjs";
/**
* Lookup table for Blowfish output types.

View File

@@ -4,11 +4,13 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import { isImage } from "../lib/FileType";
import { toBase64 } from "../lib/Base64";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import jimp from "jimp";
import { gaussianBlur } from "../lib/ImageManipulation.mjs";
/**
* Blur Image operation
@@ -25,8 +27,8 @@ class BlurImage extends Operation {
this.module = "Image";
this.description = "Applies a blur effect to the image.<br><br>Gaussian blur is much slower than fast blur, but produces better results.";
this.infoURL = "https://wikipedia.org/wiki/Gaussian_blur";
this.inputType = "byteArray";
this.outputType = "byteArray";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.presentType = "html";
this.args = [
{
@@ -44,37 +46,44 @@ class BlurImage extends Operation {
}
/**
* @param {byteArray} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {byteArray}
*/
async run(input, args) {
const [blurAmount, blurType] = args;
if (!isImage(input)) {
if (!isImage(new Uint8Array(input))) {
throw new OperationError("Invalid file type.");
}
let image;
try {
image = await jimp.read(Buffer.from(input));
image = await jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
try {
switch (blurType){
case "Fast":
if (isWorkerEnvironment())
self.sendStatusMessage("Fast blurring image...");
image.blur(blurAmount);
break;
case "Gaussian":
if (ENVIRONMENT_IS_WORKER())
self.sendStatusMessage("Gaussian blurring image. This may take a while...");
image.gaussian(blurAmount);
if (isWorkerEnvironment())
self.sendStatusMessage("Gaussian blurring image...");
image = gaussianBlur(image, blurAmount);
break;
}
const imageBuffer = await image.getBufferAsync(jimp.AUTO);
return [...imageBuffer];
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
throw new OperationError(`Error blurring image. (${err})`);
}
@@ -83,18 +92,19 @@ class BlurImage extends Operation {
/**
* Displays the blurred image using HTML for web apps
*
* @param {byteArray} data
* @param {ArrayBuffer} data
* @returns {html}
*/
present(data) {
if (!data.length) return "";
if (!data.byteLength) return "";
const dataArray = new Uint8Array(data);
const type = isImage(data);
const type = isImage(dataArray);
if (!type) {
throw new OperationError("Invalid file type.");
}
return `<img src="data:${type};base64,${toBase64(data)}">`;
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
}
}

View File

@@ -6,10 +6,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import {BombeMachine} from "../lib/Bombe";
import {ROTORS, ROTORS_FOURTH, REFLECTORS, Reflector} from "../lib/Enigma";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import { BombeMachine } from "../lib/Bombe.mjs";
import { ROTORS, ROTORS_FOURTH, REFLECTORS, Reflector } from "../lib/Enigma.mjs";
/**
* Bombe operation
@@ -139,7 +140,7 @@ class Bombe extends Operation {
const ciphertext = input.slice(offset);
const reflector = new Reflector(reflectorstr);
let update;
if (ENVIRONMENT_IS_WORKER()) {
if (isWorkerEnvironment()) {
update = this.updateStatus;
} else {
update = undefined;

View File

@@ -4,9 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Bzip2 from "libbzip2-wasm";
import { isWorkerEnvironment } from "../Utils.mjs";
/**
* Bzip2 Compress operation
@@ -51,10 +52,10 @@ class Bzip2Compress extends Operation {
if (input.byteLength <= 0) {
throw new OperationError("Please provide an input.");
}
if (ENVIRONMENT_IS_WORKER()) self.sendStatusMessage("Loading Bzip2...");
if (isWorkerEnvironment()) self.sendStatusMessage("Loading Bzip2...");
return new Promise((resolve, reject) => {
Bzip2().then(bzip2 => {
if (ENVIRONMENT_IS_WORKER()) self.sendStatusMessage("Compressing data...");
if (isWorkerEnvironment()) self.sendStatusMessage("Compressing data...");
const inpArray = new Uint8Array(input);
const bzip2cc = bzip2.compressBZ2(inpArray, blockSize, workFactor);
if (bzip2cc.error !== 0) {

View File

@@ -4,9 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Bzip2 from "libbzip2-wasm";
import { isWorkerEnvironment } from "../Utils.mjs";
/**
* Bzip2 Decompress operation
@@ -51,10 +52,10 @@ class Bzip2Decompress extends Operation {
if (input.byteLength <= 0) {
throw new OperationError("Please provide an input.");
}
if (ENVIRONMENT_IS_WORKER()) self.sendStatusMessage("Loading Bzip2...");
if (isWorkerEnvironment()) self.sendStatusMessage("Loading Bzip2...");
return new Promise((resolve, reject) => {
Bzip2().then(bzip2 => {
if (ENVIRONMENT_IS_WORKER()) self.sendStatusMessage("Decompressing data...");
if (isWorkerEnvironment()) self.sendStatusMessage("Decompressing data...");
const inpArray = new Uint8Array(input);
const bzip2cc = bzip2.decompressBZ2(inpArray, small ? 1 : 0);
if (bzip2cc.error !== 0) {

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import JSCRC from "js-crc";
/**

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import JSCRC from "js-crc";
/**

View File

@@ -0,0 +1,157 @@
/**
* @author mshwed [m@ttshwed.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { toHexFast } from "../lib/Hex.mjs";
/**
* CRC-8 Checksum operation
*/
class CRC8Checksum extends Operation {
/**
* CRC8Checksum constructor
*/
constructor() {
super();
this.name = "CRC-8 Checksum";
this.module = "Crypto";
this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.";
this.infoURL = "https://wikipedia.org/wiki/Cyclic_redundancy_check";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
"name": "Algorithm",
"type": "option",
"value": [
"CRC-8",
"CRC-8/CDMA2000",
"CRC-8/DARC",
"CRC-8/DVB-S2",
"CRC-8/EBU",
"CRC-8/I-CODE",
"CRC-8/ITU",
"CRC-8/MAXIM",
"CRC-8/ROHC",
"CRC-8/WCDMA"
]
}
];
}
/**
* Generates the pre-computed lookup table for byte division
*
* @param polynomial
*/
calculateCRC8LookupTable(polynomial) {
const crc8Table = new Uint8Array(256);
let currentByte;
for (let i = 0; i < 256; i++) {
currentByte = i;
for (let bit = 0; bit < 8; bit++) {
if ((currentByte & 0x80) !== 0) {
currentByte <<= 1;
currentByte ^= polynomial;
} else {
currentByte <<= 1;
}
}
crc8Table[i] = currentByte;
}
return crc8Table;
}
/**
* Calculates the CRC-8 Checksum from an input
*
* @param {ArrayBuffer} input
* @param {number} polynomial
* @param {number} initializationValue
* @param {boolean} inputReflection
* @param {boolean} outputReflection
* @param {number} xorOut
*/
calculateCRC8(input, polynomial, initializationValue, inputReflection, outputReflection, xorOut) {
const crcSize = 8;
const crcTable = this.calculateCRC8LookupTable(polynomial);
let crc = initializationValue !== 0 ? initializationValue : 0;
let currentByte, position;
input = new Uint8Array(input);
for (const inputByte of input) {
currentByte = inputReflection ? this.reverseBits(inputByte, crcSize) : inputByte;
position = (currentByte ^ crc) & 255;
crc = crcTable[position];
}
crc = outputReflection ? this.reverseBits(crc, crcSize) : crc;
if (xorOut !== 0) crc = crc ^ xorOut;
return toHexFast(new Uint8Array([crc]));
}
/**
* Reverse the bits for a given input byte.
*
* @param {number} input
*/
reverseBits(input, hashSize) {
let reversedByte = 0;
for (let i = hashSize - 1; i >= 0; i--) {
reversedByte |= ((input & 1) << i);
input >>= 1;
}
return reversedByte;
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const algorithm = args[0];
switch (algorithm) {
case "CRC-8":
return this.calculateCRC8(input, 0x7, 0x0, false, false, 0x0);
case "CRC-8/CDMA2000":
return this.calculateCRC8(input, 0x9B, 0xFF, false, false, 0x0);
case "CRC-8/DARC":
return this.calculateCRC8(input, 0x39, 0x0, true, true, 0x0);
case "CRC-8/DVB-S2":
return this.calculateCRC8(input, 0xD5, 0x0, false, false, 0x0);
case "CRC-8/EBU":
return this.calculateCRC8(input, 0x1D, 0xFF, true, true, 0x0);
case "CRC-8/I-CODE":
return this.calculateCRC8(input, 0x1D, 0xFD, false, false, 0x0);
case "CRC-8/ITU":
return this.calculateCRC8(input, 0x7, 0x0, false, false, 0x55);
case "CRC-8/MAXIM":
return this.calculateCRC8(input, 0x31, 0x0, true, true, 0x0);
case "CRC-8/ROHC":
return this.calculateCRC8(input, 0x7, 0xFF, true, true, 0x0);
case "CRC-8/WCDMA":
return this.calculateCRC8(input, 0x9B, 0x0, true, true, 0x0);
default:
throw new OperationError("Unknown checksum algorithm");
}
}
}
export default CRC8Checksum;

View File

@@ -5,7 +5,7 @@
*/
import vkbeautify from "vkbeautify";
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* CSS Beautify operation

View File

@@ -5,7 +5,7 @@
*/
import vkbeautify from "vkbeautify";
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* CSS Minify operation

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import xmldom from "xmldom";
import nwmatcher from "nwmatcher";

View File

@@ -4,9 +4,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
/**
* CSV to JSON operation

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import ctphjs from "ctph.js";
/**

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Set cartesian product operation

View File

@@ -4,10 +4,10 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import {fromHex} from "../lib/Hex";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import {fromHex} from "../lib/Hex.mjs";
/**
* Change IP format operation

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* Chi Square operation

View File

@@ -4,8 +4,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import cptable from "../vendor/js-codepage/cptable.js";
/**

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
import cptable from "../vendor/js-codepage/cptable.js";
/**

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Operation from "../Operation.mjs";
/**
* Comment operation

View File

@@ -4,11 +4,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import {HASH_DELIM_OPTIONS} from "../lib/Delim";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {HASH_DELIM_OPTIONS} from "../lib/Delim.mjs";
import ctphjs from "ctph.js";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* Compare CTPH hashes operation

View File

@@ -4,11 +4,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import {HASH_DELIM_OPTIONS} from "../lib/Delim";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {HASH_DELIM_OPTIONS} from "../lib/Delim.mjs";
import ssdeepjs from "ssdeep.js";
import OperationError from "../errors/OperationError";
import OperationError from "../errors/OperationError.mjs";
/**
* Compare SSDEEP hashes operation

Some files were not shown because too many files have changed in this diff Show More