Compare commits

..

256 Commits

Author SHA1 Message Date
Armin Schrenk
58eb6a6dee change status view from Label to Stackpane & adjust spinner size computation 2021-06-30 20:22:22 +02:00
Armin Schrenk
b256670bcc replace static icon in vault detail screen by statusView 2021-06-30 13:50:06 +02:00
Armin Schrenk
91162d3d8f use RotateTranslation isntead of custom Animation 2021-06-30 13:20:34 +02:00
Armin Schrenk
683f17ef24 sum status indication with icon up in single class and apply proper css 2021-06-30 11:04:41 +02:00
Armin Schrenk
e626104c06 Add progress indicator skin to light theme & correct attribution of origin 2021-06-29 17:59:15 +02:00
Armin Schrenk
f73bcc0a9e clean up 2021-06-29 17:19:13 +02:00
Armin Schrenk
4167fdc850 create custom spinner 2021-06-29 16:30:52 +02:00
Armin Schrenk
f544f72327 test impl 2021-06-29 15:59:45 +02:00
Armin Schrenk
a96115ecd6 Feature: revamp health workflow init (#1695)
* Add health tab to vault options:
* health tool is started from there
* health tool closes old Window and creates new one
* added info and remarks about health tool
* adds confirmation checkbox before starting health tool
* close vault options window when starting health workflow
* Remove AutoLock tab, move options to general tab

Co-authored-by: Snyk bot <snyk-bot@snyk.io>
Co-authored-by: Tobias Hagemann <tobias.hagemann@skymatic.de>
Co-authored-by: Sebastian Stenzel <sebastian.stenzel@skymatic.de >
2021-06-29 09:57:45 +02:00
Sebastian Stenzel
c6aceb3e59 don't setPassphraseStored to true after changing pw, when it isn't actually stored 2021-06-28 18:52:34 +02:00
Sebastian Stenzel
cadd071ebd update cryptofs 2021-06-28 18:42:10 +02:00
Sebastian Stenzel
b64264ef8b updated 3rd party licenses
[ci skip]
2021-06-26 17:49:18 +02:00
Sebastian Stenzel
46691f057e dependency update 2021-06-26 17:42:40 +02:00
Sebastian Stenzel
f1b40e32a7 dependency update 2021-06-26 17:25:00 +02:00
Snyk bot
b4a97803ff [Snyk] Security upgrade org.cryptomator:webdav-nio-adapter from 1.2.2 to 1.2.3 (#1698)
* fix: pom.xml to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JAVA-ORGECLIPSEJETTY-1313686

* adjusted suppression config

* bump webdav version

Co-authored-by: Sebastian Stenzel <sebastian.stenzel@gmail.com>
2021-06-24 09:58:47 +02:00
JaniruTEC
8ac253504f Merge pull request #1697 from cryptomator/refactoring/spellchecking
Enabled spellchecking, added dictionaries, fixed spelling mistakes
2021-06-23 22:49:57 +02:00
JaniruTEC
135b61070d Fixed misspelled key 2021-06-23 22:48:18 +02:00
Armin Schrenk
903f55a24f improve health check gui:
* convert milliseconds to hours, minutes and seconds
* spelling
* adjust to dark theme
2021-06-22 17:17:28 +02:00
Julian Raufelder
f2fadafa66 Fix snyk.io badge in README due to switch to single maven module 2021-06-16 16:11:31 +02:00
Julian Raufelder
0676732796 Merge pull request #1693 from cryptomator/feature/sign-src-tarball
Sign tarball in release using GPG
2021-06-16 12:54:37 +00:00
Julian Raufelder
08cbfd47ea Prefix signature of tarball in release with cryptomator
To apply convention of the other release assets
2021-06-16 14:20:52 +02:00
Julian Raufelder
b15cda260e Apply suggestions from code review
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2021-06-16 12:13:49 +00:00
Julian Raufelder
74355b128a Sign tarball in release using GPG 2021-06-16 13:49:26 +02:00
JaniruTEC
000f27e166 Fixed spelling mistakes that required API breaking changes 2021-06-12 01:56:15 +02:00
JaniruTEC
e1d83c996e Fixed independent spelling mistakes
Added @SuppressWarnings("SpellCheckingInspection") to binary data (e.g. keys) or deliberately misspelled strings
2021-06-12 01:45:31 +02:00
JaniruTEC
0dc401883f Enabled proofreading
Removed dict_* files from .gitignore
Added dict_de.xml
Added dict_project.xml
2021-06-12 01:35:36 +02:00
JaniruTEC
364d59fdf7 Added ".idea/**/shelf" to .gitignore
See: 991e760c1c/Global/JetBrains.gitignore (L9)
2021-06-11 18:28:25 +02:00
Sebastian Stenzel
210050d9d5 update cryptofs 2021-06-09 18:15:39 +02:00
Sebastian Stenzel
f10d2b713b made tests public to avoid reflection and "open modules"
see also https://issues.apache.org/jira/browse/SUREFIRE-1909
2021-06-09 10:14:08 +02:00
JaniruTEC
f9545b5532 Refactored MPC priority 2021-06-09 01:16:51 +02:00
Sebastian Stenzel
58376bddef Merge pull request #1685 from cryptomator/feature/provider-agnostic-keychains
Remove all references to specific keychain access providers
2021-06-08 14:42:56 +02:00
Sebastian Stenzel
72e2f64a68 show provided display name 2021-06-07 16:24:42 +02:00
Sebastian Stenzel
48ad74715e * store class name of selected keychain in settings.json
* prepared GeneralPreferencesController to use a provider-supplied display name
2021-06-07 15:17:58 +02:00
Ralph Plawetzki
2e1f33ca82 Fix instructions for building (#1682) 2021-06-06 21:56:28 +02:00
Cryptobot
2d3f4d1c03 New Crowdin updates (#1678)
[ci skip]

Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2021-06-05 09:11:48 +02:00
Sebastian Stenzel
04c13ba242 New Crowdin updates (#1677)
[ci skip]

Co-authored-by: Cryptobot <cryptobot@users.noreply.github.com>
2021-06-04 21:00:56 +02:00
Cryptobot
b70033e777 Update Crowdin configuration file 2021-06-04 20:48:48 +02:00
Sebastian Stenzel
fafb7b229f update i18n config
[ci skip]
2021-06-04 20:29:15 +02:00
Sebastian Stenzel
7fac6da448 Single maven module (#1676)
combined all sources into single maven module
2021-06-04 20:09:10 +02:00
Sebastian Stenzel
72bd9c1fdf New Crowdin updates (#1643)
[ci skip]
2021-06-04 15:44:48 +02:00
Sebastian Stenzel
39b8e25f4f Merge pull request #1596 from eas5/test_improvement
Improved grouped assertions
2021-06-04 15:42:16 +02:00
Sebastian Stenzel
c8fa7f1edd fix NPE in autolocker, when reading "lastActivity" before any activity happened 2021-06-04 09:40:23 +02:00
Sebastian Stenzel
95b98b8a36 Merge pull request #1603 from cryptomator/feature/autoLock
fixes #274
2021-06-02 16:24:26 +02:00
Sebastian Stenzel
005d2a82fe use stopwatch item for autolock tab 2021-06-02 16:22:19 +02:00
Sebastian Stenzel
820f7989d0 remove debug log statement
[ci skip]
2021-06-02 16:10:42 +02:00
Sebastian Stenzel
751a6079c3 use explicit imports
[ci skip]
2021-06-02 16:09:23 +02:00
Sebastian Stenzel
9be95efd10 store autolock time in seconds instead of minutes 2021-06-02 16:08:46 +02:00
Sebastian Stenzel
8f8fa0248c converted lock after "time" to "idle time" 2021-06-02 15:53:57 +02:00
Sebastian Stenzel
cd7acea54e Use of NumericTextField 2021-06-02 14:52:27 +02:00
Sebastian Stenzel
18152e4f3d Merge branch 'develop' into feature/autoLock 2021-06-02 14:31:28 +02:00
Ralph Plawetzki
7b689c6b78 Keychain is locked (#1550)
Fixes #1526

Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
Co-authored-by: Sebastian Stenzel <sebastian.stenzel@gmail.com>
2021-06-02 14:24:51 +02:00
Armin Schrenk
1159681824 Merge pull request #1615 from cryptomator/feature/sanitizer
Add Vault Health Check

Fixes #312 and fixes #1224.
2021-06-01 18:09:22 +02:00
Armin Schrenk
c868ac32cc Change localized text and tweak ui 2021-06-01 18:01:54 +02:00
Sebastian Stenzel
f85f953668 Bind countOfWarnSeverity and countOfCritSeverity to list 2021-06-01 15:01:23 +02:00
Armin Schrenk
5185df631d rather add functionality to formattedLabel class than to extend it 2021-06-01 13:22:56 +02:00
Armin Schrenk
617feec111 deactivate fix button 2021-06-01 13:14:31 +02:00
Armin Schrenk
eb196165c5 move healthcheck button to vault options 2021-06-01 11:53:33 +02:00
Armin Schrenk
8c37ab3675 Closes #961 2021-06-01 10:45:48 +02:00
Armin Schrenk
7eaade1555 Depeding on state of selected task, show appropiate status text in check detail view 2021-06-01 10:29:41 +02:00
Armin Schrenk
186c129a30 Replace stub check detail description with info about check duration and count of warnings and critical errors 2021-05-31 15:28:30 +02:00
Armin Schrenk
f74b9d3347 Remove Scope 2021-05-26 15:50:50 +02:00
Armin Schrenk
6038559172 Localization and small ui fixes 2021-05-26 15:50:03 +02:00
Armin Schrenk
98a899c7e2 scope checklist cell and properly update graphic property 2021-05-25 13:21:13 +02:00
Armin Schrenk
783c8718c1 add localization for health check names 2021-05-25 13:20:18 +02:00
Armin Schrenk
b47382811f apply ugly workaround for new vault config loading 2021-05-25 12:37:29 +02:00
Armin Schrenk
62f279b9f7 Merge branch 'develop' into feature/sanitizer 2021-05-25 11:16:27 +02:00
Armin Schrenk
ab961f1a8b update thrid party licences 2021-05-25 11:16:17 +02:00
Armin Schrenk
9562db7e13 Closes 1659 2021-05-25 11:10:03 +02:00
Armin Schrenk
1ca2e029dc method loadVaultConfig() throws exception instead of returning optional (#1661) 2021-05-21 18:51:49 +02:00
Sebastian Stenzel
944e3e6c50 placeholder: use identifier to look up human-readable names from ResourceBundle instead of if/elsing on classes
(e.g. `resourceBundle.getString(identifier() + ".name")`)

TODO @infeo
2021-05-21 17:55:39 +02:00
Sebastian Stenzel
e134d2f422 keep more ui code in fxml 2021-05-21 17:48:20 +02:00
Sebastian Stenzel
04e5170403 * Made DiagnosticResultAction a "pseudo-singleton" that consumes diagnostic results
* renamed FxmlFile.HEALTH_CHECK to match fxml file name
* added missing DI scopes
* simplified cell layout
2021-05-21 17:47:42 +02:00
Armin Schrenk
ea008df9f7 Add error screen to vault check start screen 2021-05-21 16:25:37 +02:00
Armin Schrenk
e25dfaad35 clean up 2021-05-21 15:59:43 +02:00
Armin Schrenk
e98f92c63f Only use CheckTask title in UI instead of HealthCheck::identifier 2021-05-21 15:56:32 +02:00
Armin Schrenk
85b761a9d7 show error screen when unable to write report 2021-05-21 15:29:14 +02:00
Armin Schrenk
be8dcd4dc4 remove obsolete TODOs 2021-05-21 13:41:19 +02:00
Armin Schrenk
c01c405f20 add select all checkbox 2021-05-21 13:16:14 +02:00
Armin Schrenk
b4f268f551 more ui & clean up 2021-05-21 13:15:51 +02:00
Armin Schrenk
21f9e72cc5 preselect correct check in check screen 2021-05-21 12:48:58 +02:00
Armin Schrenk
4845984a35 ui sugar
* show correct name for health check tasks
* some padding
* resize window when run button is hit
2021-05-21 12:45:00 +02:00
Armin Schrenk
b6f5ddaf30 Only show button when severity is WARN 2021-05-21 12:40:44 +02:00
Armin Schrenk
1abf0e1bfa Replace result table by result list 2021-05-21 12:00:46 +02:00
Armin Schrenk
a8364a8c1a show directory containing exported health report 2021-05-20 16:52:28 +02:00
Armin Schrenk
13c95868fa fix report writer. Ignore not run tests 2021-05-20 16:46:34 +02:00
Armin Schrenk
85ff7542f1 rework gui to be more wizard like:
* show first only checkbox list of checks and single run button
* then show list of check run status with results
2021-05-20 16:35:37 +02:00
Armin Schrenk
432be6dd80 more ui alignments 2021-05-19 13:18:54 +02:00
Armin Schrenk
ca0402aaf0 clear styleclass of icon view when content of ResultSeverityCell changes. 2021-05-19 12:38:04 +02:00
Armin Schrenk
c7ef0056f9 let UI take space if window size is increased 2021-05-19 09:47:38 +02:00
Armin Schrenk
cf13311665 add style class to used icon in result view 2021-05-19 09:32:55 +02:00
Armin Schrenk
a7133dbebe Add icon to severity column 2021-05-18 17:12:37 +02:00
Armin Schrenk
168f9b9fb9 fix report writer 2021-05-18 16:57:25 +02:00
Armin Schrenk
2b332c3831 Add column with action button 2021-05-18 16:53:48 +02:00
Armin Schrenk
66e3625a0b Wrap diagnostic result in object to prepare it for possible fix action 2021-05-18 16:49:39 +02:00
Armin Schrenk
20f88e203a simplification and cleanup 2021-05-18 13:40:56 +02:00
Armin Schrenk
66a8dc9811 Revert d2680b9857 2021-05-18 13:36:00 +02:00
Armin Schrenk
9d89efc98c Unify interface:
* move all buttons to one button bar
* switch between runAll and runSelected, depending on list selection
* add a little localization
2021-05-18 09:09:53 +02:00
Armin Schrenk
dfbe017316 Partially revert 8e1be4c 2021-05-18 08:47:40 +02:00
Armin Schrenk
d2680b9857 Rename controller and fxml file which represents the whole health check screen 2021-05-17 13:06:28 +02:00
Armin Schrenk
8e1be4c67b remove redundant property, fix logic error 2021-05-17 12:49:08 +02:00
Armin Schrenk
749e0ac02d disable export-button as long as no batch run is finished 2021-05-17 12:40:29 +02:00
Armin Schrenk
a2ad7d69ab Simplify password creation (#1646)
* Remove the password properties and directly access password fields from included fxml files
* wipe the password fields when closing a window
2021-05-17 10:18:10 +02:00
Sebastian Stenzel
a47c05c87d hide/disable elements if not relevant in current state 2021-05-10 15:56:46 +02:00
Sebastian Stenzel
6b871e56c8 hide results until task is started 2021-05-10 15:38:52 +02:00
Sebastian Stenzel
40dbc0ba48 cleanup 2021-05-10 15:38:37 +02:00
Sebastian Stenzel
2e52afed51 write report synchronously, reducing complexity 2021-05-10 13:39:46 +02:00
Sebastian Stenzel
64d54133f8 split up check view:
- checkListController is responsible for selecting and (batch)running checks
- checkDetailController is responsible for displaying results
2021-05-07 15:51:47 +02:00
Sebastian Stenzel
ac289cc3f7 Merge branch 'develop' into feature/sanitizer
# Conflicts:
#	main/pom.xml
2021-05-07 09:20:54 +02:00
Armin Schrenk
189699d359 sh*te happens
check value instead reference for null
2021-05-06 15:44:27 +02:00
Sebastian Stenzel
0ce41e7ac3 New Crowdin updates (#1628)
New translations strings.properties

Japanese; Polish; Spanish; Dutch; Czech; Norwegian Bokmal; Korean; Greek; Catalan; Slovak; Russian; Punjabi; Italian; Arabic; Bosnian; Hungarian; German; Cyrillic); Latin); Romanian; French; Chinese Simplified; Croatian; Chinese Traditional; Portuguese; Latvian; Hindi; Indonesian; Turkish; Portuguese, Brazilian; Swedish; Norwegian Nynorsk; 

[ci skip]
2021-05-06 14:25:59 +02:00
Armin Schrenk
c1a249fd7f Merge pull request #1454 from cryptomator/feature/vault-format-8
Vault Format 8
2021-05-06 14:05:26 +02:00
Armin Schrenk
c266c7583b bump dependencies (same as in cryptofs) 2021-05-06 13:59:37 +02:00
Armin Schrenk
00331d4857 check for vaultpath existence instead of catching (undocumented) exception 2021-05-06 13:51:30 +02:00
Armin Schrenk
8fd484e2bb Revert "Move window placements of "popup dialogs" to their corresponding controller"
This reverts commit bc83e23a34.
2021-05-06 13:44:05 +02:00
Armin Schrenk
165d740acd if vault directory is not present, declare it as missing 2021-05-06 12:51:39 +02:00
Armin Schrenk
fd4010c6c9 cleanup 2021-05-06 12:43:15 +02:00
Armin Schrenk
aa2900fa9e ensure to use cryptolib rc 2021-05-06 12:27:07 +02:00
Sebastian Stenzel
76d1875e01 adjusted to new CryptoFileSystemProvider.checkDirStructureForVault API 2021-05-06 09:56:50 +02:00
Armin Schrenk
bc83e23a34 Move window placements of "popup dialogs" to their corresponding controller 2021-05-05 15:03:09 +02:00
Armin Schrenk
6a326bcbce remove password of migration window, when window is closed 2021-05-04 10:51:12 +02:00
Armin Schrenk
573ad03d68 bug fixin' 2021-05-03 17:33:28 +02:00
Sebastian Stenzel
07efb3e94d Merge branch 'feature/vault-format-8' into feature/sanitizer
# Conflicts:
#	main/pom.xml
2021-05-03 12:34:28 +02:00
Armin Schrenk
89e680fb45 reveal report storage location when task is finished. 2021-04-30 11:42:31 +02:00
Armin Schrenk
54128a0016 Refined exportet health report 2021-04-30 11:32:56 +02:00
Armin Schrenk
e2565097cd add function to export a report of health checks 2021-04-29 16:31:39 +02:00
Armin Schrenk
f827b1fc89 Refactor HealthCheckTask execution:
* new class HealthCheckSupervisor which encapsulates execution of all selected health checks
* checkControllor only users supervisor
2021-04-29 16:31:05 +02:00
Armin Schrenk
c0baab2329 change comments 2021-04-28 09:58:14 +02:00
Armin Schrenk
70baa4d09f Rework sanitizer workflow:
* select set of performed HealthChecks prior to loading masterkey
* two predefined healthcheck sets and custom one
* start sequential execution of checks after successful masterkey loading
* removed vault config info
* destroy masterkey on window close, on cancellation, on check finish
2021-04-27 17:41:28 +02:00
Armin Schrenk
d710d406d0 Merge branch 'master' into develop 2021-04-23 10:30:12 +02:00
Armin Schrenk
554f245f5d Merge branch 'hotfix/1.5.16' 2021-04-23 10:27:48 +02:00
Sebastian Stenzel
34995088ba addressed some issues identified during code review 2021-04-23 10:24:31 +02:00
Sebastian Stenzel
69c63702f2 pass a single keyloader to cryptofs 2021-04-23 09:55:08 +02:00
Armin Schrenk
db7e731554 bumping dokany-nio-adapter 2021-04-23 09:48:56 +02:00
Armin Schrenk
e08b43bf17 preparing hotfix 1.5.16 2021-04-23 09:48:40 +02:00
Sebastian Stenzel
58b45bacd1 Merge branch 'develop' into feature/vault-format-8
[ci skip]
2021-04-21 13:27:54 +02:00
Sebastian Stenzel
4f942bc23f reset version
[ci skip]
2021-04-21 13:27:25 +02:00
Armin Schrenk
09a8618fa0 Merge tag '1.5.15' into develop
1.5.15
2021-04-21 12:26:46 +02:00
Armin Schrenk
52af530d1b Merge branch 'release/1.5.15' 2021-04-21 12:26:45 +02:00
Armin Schrenk
86a42234c6 preparing 1.5.15 2021-04-21 12:21:50 +02:00
Armin Schrenk
37c4e78b1d update third party licenses
[ci skip]
2021-04-21 12:05:37 +02:00
Sebastian Stenzel
9c2c234bee New Crowdin updates (#1604)
New translations strings.properties

Slovak; Czech; Italian; French; Catalan; Romanian; Polish; Chinese Simplified; Dutch; Chinese Traditional;
Norwegian Nynorsk; Croatian; Turkish; German; Spanish; Russian; Hungarian; Punjabi; Portuguese;
Norwegian Bokmal; Indonesian; Hindi; Bosnian; Cyrillic); Swedish; Greek; Korean; Portuguese, Brazilian; Latin); Arabic; Latvian; Japanese; 

[ci skip]
2021-04-21 12:01:09 +02:00
Sebastian Stenzel
59f91267ae fix save password 2021-04-21 11:20:44 +02:00
Sebastian Stenzel
b3ff9423b4 Merge branch 'develop' into feature/vault-format-8
# Conflicts:
#	main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java
#	main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java
#	main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java
2021-04-21 11:20:31 +02:00
Armin Schrenk
e3f3090341 bump javafx to version 16 2021-04-21 11:08:42 +02:00
Armin Schrenk
83be6c0864 enhanced release template for ci 2021-04-21 10:41:58 +02:00
Sebastian Stenzel
c654951dc1 removed ambiguous filenameLengthLimit from settings, added maxCleartextFilenameLength, shortening is now a 100% independent setting stored in the vault rather than the device settings 2021-04-20 18:15:25 +02:00
Armin Schrenk
4e177c9ea7 Correcting misleading log message 2021-04-20 16:53:59 +02:00
Armin Schrenk
dc3a951a1b add hotkeys to remove a vault 2021-04-20 15:07:14 +02:00
Armin Schrenk
defa9c75eb add hotkeys for vault selection 2021-04-20 12:18:15 +02:00
Nour Agha
c1f498a114 Add MEGA & pCloud providers to vault location presets (#1622)
Fixes #1621
2021-04-20 08:09:17 +02:00
Armin Schrenk
8457c50ebc add muted style class to status text of newVaultLocationScreen 2021-04-19 16:11:28 +02:00
Armin Schrenk
0144cbb99f Merge pull request #1618 from cryptomator/feature/#1508-observable-mounts
Closes #1508
2021-04-16 16:27:40 +02:00
Armin Schrenk
d6e4c7d177 Rework choose-location-screen in add vault wizard: (#1620)
* more checks for the chosen vault path
* every check has own error message
* perform checks when vault path changes
* if any radio button selected, enable vault path field (no-edit)
2021-04-16 16:18:01 +02:00
Armin Schrenk
3376b16b7b Rename Donation Key to Supporter Certificate (#1613)
Renamed all occurences of donation key to supporter certificate and adjust ui.

Co-authored-by: Tobias Hagemann <tobias.hagemann@skymatic.de>
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2021-04-16 12:18:03 +02:00
Sebastian Stenzel
673fdcd095 stupid. 2021-04-15 13:45:20 +02:00
Armin Schrenk
0d00520ac1 Throw specifc exception on not completed lock of a vault 2021-04-15 12:54:19 +02:00
Armin Schrenk
22a0d3a9a5 bump fuse/dokany-nio versions 2021-04-15 11:11:05 +02:00
Sebastian Stenzel
24baa44e70 stronger encapsulation of vault state await/signal mechanism 2021-04-15 10:30:29 +02:00
Armin Schrenk
03886f88e8 Fix lock workflow for webdav:
* internally, wait for condition that onExit-Method is exceuted (with timeout)
* store and execute onExitAction also for webdav
2021-04-15 10:14:28 +02:00
Armin Schrenk
642816b631 rebuild tray menu when vaultname changes 2021-04-14 17:26:04 +02:00
Sebastian Stenzel
f3a03c71ec implemented cancellable health checks 2021-04-14 10:20:34 +02:00
Sebastian Stenzel
1fab246fcd ugly PoC for new UI 2021-04-13 15:43:59 +02:00
Armin Schrenk
cd5c55aad7 Refactor lock/unlock workflows:
* don't set vault state on successful lock workflow
* improved error handling
2021-04-13 11:22:42 +02:00
Armin Schrenk
b066b4b045 opening a vault in read-only always assumes a filename length limit of 220
references #1605
2021-04-12 18:06:09 +02:00
JaniruTEC
41d2a2c77e Added .idea/uiDesigner.xml to .gitignore 2021-04-10 23:16:00 +02:00
Sebastian Stenzel
69186b916c adjusted to new async health check api 2021-04-09 16:04:52 +02:00
Armin Schrenk
0840695e0a Refactor lock/unlock convinience methods in FxApplication:
* execute vault state transition here
* on failed transition show error window
* only start worfklow on successful transition
2021-04-08 17:28:49 +02:00
Armin Schrenk
8447f105b0 rename instance variables 2021-04-08 13:08:05 +02:00
Sebastian Stenzel
c306d8df04 alternative thread-safe vault state without requiring explicit synchronization 2021-04-08 11:23:57 +02:00
Armin Schrenk
beba6490c3 Add locking mechanism to change the vault state t 2021-04-06 13:26:58 +02:00
Armin Schrenk
fb1078b35b bump to SNAPSHOT nio-adapter and refactor Volume.mount() method:
* returns void
* add onExitAction parameter
* adjust classes
2021-04-06 10:05:32 +02:00
Armin Schrenk
be0912e6ca Merge branch 'develop' into feature/#1508-observable-mounts 2021-04-06 09:00:05 +02:00
Sebastian Stenzel
13db1aa9b9 Actually run tests from within Sanitizer UI 2021-04-01 17:40:53 +02:00
Sebastian Stenzel
d2cd2c923d unlock for health check 2021-04-01 13:26:33 +02:00
Martin Beyer
92de05b3db Changed textfield to only accept Integers, Using scheduled Executor as Timer 2021-04-01 11:42:41 +02:00
Sebastian Stenzel
c1000d9958 Merge branch 'feature/vault-format-8' into feature/sanitizer 2021-04-01 09:26:21 +02:00
Sebastian Stenzel
2810c044ea reduced visibility 2021-03-31 16:23:54 +02:00
Sebastian Stenzel
e09bd160b7 Made masterkey loading strategies reusable 2021-03-31 16:12:31 +02:00
Sebastian Stenzel
e6d1e4697c Merge develop into feature/vault-format-8 2021-03-31 11:39:16 +02:00
Sebastian Stenzel
497e5ce73f Add health check window 2021-03-31 11:37:55 +02:00
Armin Schrenk
cf7cbae567 Set dev branch back to SNAPSHOT version
[ci skip]
2021-03-31 11:32:06 +02:00
Armin Schrenk
803f517c62 Merge tag '1.5.14' into develop
1.5.14
2021-03-31 11:11:34 +02:00
Armin Schrenk
0afa7b8e37 Merge branch 'release/1.5.14' 2021-03-31 11:11:27 +02:00
Armin Schrenk
1a0f70f8e8 updating third-party-licenses 2021-03-31 10:59:21 +02:00
Armin Schrenk
8737eb83f0 Bumping webdav-nio-adapter dependency 2021-03-31 10:58:23 +02:00
Armin Schrenk
a96239a19f closes #1245 2021-03-31 10:52:30 +02:00
Armin Schrenk
2b7cfcd1dc preparing 1.5.14 2021-03-31 09:52:24 +02:00
Sebastian Stenzel
ebccb61750 New Crowdin updates (#1560) 2021-03-31 09:46:45 +02:00
Armin Schrenk
285f2aec23 unify wording
[ci skip]
2021-03-30 16:10:24 +02:00
Armin Schrenk
217e31fbd7 Merge pull request #1595 from cryptomator/feature/MCGA
Feature: Make Context menu Great Again
* adding additional entries
* fixes #1478
* only appears on a selected vault
2021-03-30 16:03:41 +02:00
Sebastian Stenzel
f0ebf7a638 EasyBind rulez 2021-03-30 14:20:05 +02:00
Armin Schrenk
c05c5e3f90 closes #961 2021-03-30 13:57:21 +02:00
Sebastian Stenzel
30f0c5e697 split VaultList and ContextMenu into two separate controllers 2021-03-30 13:43:37 +02:00
Armin Schrenk
f989b8627c Update java-jwt 2021-03-30 13:10:54 +02:00
Armin Schrenk
ff84230566 structure constructor 2021-03-30 11:53:30 +02:00
Armin Schrenk
3b4f6276b5 Improve selection model of list view:
* Clear selection if an empty space is clicked
* only open context menu if an item is selected
2021-03-30 11:25:22 +02:00
Armin Schrenk
2be7a050a4 refine wording
[ci skip]
2021-03-30 09:47:11 +02:00
Martin Beyer
1c01228778 Removing LockOnSleep UI elements (not implemented yet) 2021-03-29 19:29:17 +02:00
Martin Beyer
1c35780d9e Cleaned up integrations implementation and added Regex for input 2021-03-29 19:10:05 +02:00
Armin Schrenk
96a612127c add reveal entry to context menu. 2021-03-29 16:23:24 +02:00
Armin Schrenk
0bdfb7c9f9 Distinct between "unlock" and "unlock now" in context menu:
* inject keychainManager
* bind/unbind passphraseStored property to selected vault
* rename bindings to show possible action
* removed unused binding
* initialize properties properly
2021-03-29 12:59:48 +02:00
Armin Schrenk
f556301249 fix suggestion 2021-03-29 12:47:46 +02:00
Armin Schrenk
f77b237e59 simplify private function
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2021-03-29 12:44:57 +02:00
Armin Schrenk
61b7a39aad change level of a log message from warn to debug
[ci skip]
2021-03-29 10:53:48 +02:00
Martin Beyer
2cee6e45f1 Merge remote-tracking branch 'upstream/develop' into feature/autoLock 2021-03-29 10:45:32 +02:00
Martin Beyer
1292548042 Implementing new settings and locking after a certain amount of minutes 2021-03-29 10:44:39 +02:00
Tobias Hagemann
16bd84ee62 Update README.md
[ci skip]
2021-03-26 10:46:49 +01:00
Tobias Hagemann
3d0a97fcdf Update README.md
[ci skip]
2021-03-25 17:06:15 +01:00
Elvys Soares
5ae2419e6d Improved grouped assertions
Signed-off-by: Elvys Soares <eas5@cin.ufpe.br>
2021-03-23 21:46:32 -03:00
Armin Schrenk
786d156b9f change wording in context menu entries 2021-03-23 15:08:23 +01:00
Armin Schrenk
629b6fb97d execute Service tasks on application thread 2021-03-23 12:53:17 +01:00
Armin Schrenk
17dc32bb79 lock vault on external unmount 2021-03-23 12:52:38 +01:00
Armin Schrenk
c05e00d32a Change volume interface to observe mounts 2021-03-23 12:37:36 +01:00
Armin Schrenk
9dc8b2cb47 Use Bindings instead of properties 2021-03-23 10:50:04 +01:00
Armin Schrenk
0e32e96c7d made context menu great again:
* added entry to unlock / lock a vault
* added entry to show vault options
2021-03-22 17:10:45 +01:00
Armin Schrenk
97afadd7b9 fixes #1478 2021-03-22 12:58:45 +01:00
Armin Schrenk
b199b65e38 closes #176 2021-03-22 12:51:07 +01:00
Tobias Hagemann
999abf3c13 Update README.md
[ci skip]
2021-03-22 12:24:54 +01:00
Sebastian Stenzel
2cdde54db6 updated mockito due to build errors caused by bytebuddy 2021-03-17 13:14:55 +01:00
Sebastian Stenzel
6941603cdd update to latest cryptolib/cryptofs beta 2021-03-17 13:03:55 +01:00
Sebastian Stenzel
cdca4e047d Merge branch 'develop' into feature/vault-format-8 2021-03-17 12:55:47 +01:00
Sebastian Stenzel
31e938de6a Merge pull request #1587 from cryptomator/feature/jdk-16
Update to JDK 16
2021-03-17 12:29:29 +01:00
Sebastian Stenzel
4c10ab764a updated README 2021-03-17 09:33:43 +01:00
Sebastian Stenzel
4e075ab0ca using pattern-matching instanceof where applicable 2021-03-17 09:22:16 +01:00
Sebastian Stenzel
f73ae9759f use new Stream.toList() where applicable 2021-03-17 09:16:44 +01:00
Sebastian Stenzel
f6283b2f7e using text blocks where applicable 2021-03-17 09:12:54 +01:00
Sebastian Stenzel
b23d2e4def allow use of reflection in codacy coverage reporter 2021-03-17 08:19:58 +01:00
Sebastian Stenzel
91a2943599 update to JDK 16 2021-03-17 08:16:26 +01:00
Sebastian Stenzel
e32ce22d24 Merge branch 'develop' into feature/vault-format-8 2021-03-10 12:48:58 +01:00
Armin Schrenk
e75c415b46 Load vault config on demand and don't cache it
* fixes issue with unlock after vault migration
2021-03-10 12:03:46 +01:00
Martin Beyer
8592e3667b Applying a SystemListener when the notify gets called with SLEEP 2021-03-09 18:55:35 +01:00
Martin Beyer
5a11d02fa8 Splitting the "Lock after X minutes" Checkbox in to two string resources. 2021-03-09 18:52:53 +01:00
Sebastian Stenzel
0ab28602d1 bumped cryptofs version 2021-03-05 17:33:58 +01:00
Sebastian Stenzel
62c8edff04 Choose key loading workflow depending on vaultconfig's key ID and allow KeyLoadingComponent to decide itself, what exceptions it can handle 2021-03-03 17:41:17 +01:00
Sebastian Stenzel
d01c6268f8 remove unused field
[ci skip]
2021-03-02 16:16:24 +01:00
Sebastian Stenzel
e083fd0bcc skip certain steps on forks 2021-03-02 11:55:20 +01:00
Cryptobot
ff687f1bae fix: main/pom.xml to reduce vulnerabilities (#1569)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JAVA-ORGECLIPSEJETTY-1080611

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2021-03-02 08:43:10 +01:00
Sebastian Stenzel
557aaa2480 Removed unused imports
[ci skip]
2021-03-01 15:59:13 +01:00
Sebastian Stenzel
78e43d401d split package org.cryptoamtor.ui.unlock to allow for different kinds of unlock workflows 2021-03-01 15:58:00 +01:00
Sebastian Stenzel
7b08c5d287 Merge branch 'develop' into feature/vault-format-8
# Conflicts:
#	main/pom.xml
#	main/ui/src/main/resources/license/THIRD-PARTY.txt
[ci skip]
2021-02-26 10:10:50 +01:00
Sebastian Stenzel
84d2644f19 fix wrong versions that have been merged from main branch 2021-02-26 10:05:26 +01:00
Martin Beyer
d13dfe3526 First take at UI implementation of a Auto-Lock Tab 2021-02-24 16:23:49 +01:00
Armin Schrenk
f9a9d7b870 Merge tag '1.5.13' into develop
1.5.13
2021-02-24 16:21:07 +01:00
Martin Beyer
8fccb1b8f0 Added some Settings 2021-02-24 16:20:34 +01:00
Martin Beyer
c82e5577a1 New Tab AutoLock in VaultOptions 2021-02-24 15:17:23 +01:00
Sebastian Stenzel
9ad217ca55 Merge branch 'develop' into feature/vault-format-8
[ci skip]
2021-02-04 12:38:01 +01:00
Sebastian Stenzel
1a0bc92bde Merge branch 'develop' into feature/vault-format-8 2021-02-01 12:08:23 +01:00
Sebastian Stenzel
21038212c1 remove unused property
[ci skip]
2021-02-01 11:54:21 +01:00
Sebastian Stenzel
b15471b4ff add new (optional) "choose masterkey file" step to unlock dialog 2021-01-29 17:44:45 +01:00
Sebastian Stenzel
ff17b60f56 Refactored UnlockWorkflow using new vault format 8 APIs 2021-01-27 12:09:09 +01:00
Sebastian Stenzel
3284578445 Merge branch 'develop' into feature/vault-format-8
# Conflicts:
#	main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java
2021-01-25 21:42:13 +01:00
Sebastian Stenzel
4b670a59a3 adjusted to new cryptolib/cryptofs API 2021-01-25 21:31:16 +01:00
Sebastian Stenzel
3f928cf958 Merge branch 'develop' into feature/vault-format-8
[ci skip]
2021-01-22 22:47:54 +01:00
Sebastian Stenzel
efebbc059a keep CTR+HMAC for now (until GCM is supported on all platforms) 2021-01-19 15:09:47 +01:00
Sebastian Stenzel
6e860d293a Merge branch 'develop' into feature/vault-format-8
[ci skip]
2021-01-19 15:05:15 +01:00
Sebastian Stenzel
c0a9a95e4f Adjusted to CryptoFS 2.0.0 2020-12-08 14:39:46 +01:00
441 changed files with 6854 additions and 2532 deletions

View File

@@ -1,5 +1,6 @@
commit_message: "[ci skip]"
escape_special_characters: 0
commit_message: '[ci skip]'
files:
- source: /main/ui/src/main/resources/i18n/strings.properties
translation: /main/ui/src/main/resources/i18n/strings_%two_letters_code%.properties
- source: /src/main/resources/i18n/strings.properties
translation: /src/main/resources/i18n/strings_%two_letters_code%.properties
escape_quotes: 0
escape_special_characters: 0

View File

@@ -22,7 +22,7 @@ include:
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
* The use of sexual language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment

2
.github/SUPPORT.md vendored
View File

@@ -14,5 +14,5 @@ For _everything else_, please visit our official [Cryptomator Community](https:/
- Discussions about the apps
- [Development discussions](https://community.cryptomator.org/c/development)
- General questions
- Discussions regarding our design decissions
- Discussions regarding our design decisions
- Our roadmap

View File

@@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 14
java-version: 16
- uses: actions/cache@v1
with:
path: ~/.m2/repository
@@ -20,47 +20,46 @@ jobs:
restore-keys: |
${{ runner.os }}-maven-
- name: Ensure to use tagged version
run: mvn versions:set --file main/pom.xml -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
run: mvn versions:set -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
if: startsWith(github.ref, 'refs/tags/')
- name: Build and Test
run: mvn -B install --file main/pom.xml -Pcoverage
- name: Run Codacy Coverage Reporter
run: |
curl -o ~/codacy-coverage-reporter.jar https://repo.maven.apache.org/maven2/com/codacy/codacy-coverage-reporter/7.1.0/codacy-coverage-reporter-7.1.0-assembly.jar
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/commons/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/ui/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/launcher/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar final
run: mvn -B clean install jacoco:report -Pcoverage,dependency-check
- name: Upload code coverage report
id: codacyCoverageReporter
run: bash <(curl -Ls https://coverage.codacy.com/get.sh)
env:
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
continue-on-error: true
### TODO: move to matrix build:
- name: Assemble buildkit-linux.zip
run: mvn -B clean package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease,linux
run: mvn -B clean package -DskipTests -Plinux
- name: Upload buildkit-linux.zip
uses: actions/upload-artifact@v1
with:
name: buildkit-linux.zip
path: main/buildkit/target/buildkit-linux.zip
path: target/buildkit-linux.zip
- name: Assemble buildkit-mac.zip
run: mvn -B clean package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease,mac
run: mvn -B clean package -DskipTests -Pmac
- name: Upload buildkit-mac.zip
uses: actions/upload-artifact@v1
with:
name: buildkit-mac.zip
path: main/buildkit/target/buildkit-mac.zip
path: target/buildkit-mac.zip
- name: Assemble buildkit-win.zip
run: mvn -B clean package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease,windows
run: mvn -B clean package -DskipTests -Pwindows
- name: Upload buildkit-win.zip
uses: actions/upload-artifact@v1
with:
name: buildkit-win.zip
path: main/buildkit/target/buildkit-win.zip
path: target/buildkit-win.zip
release:
name: Draft a Release on GitHub Releases
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/')
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'cryptomator/cryptomator'
steps:
- uses: actions/checkout@v2
- name: Download buildkit-linux.zip
uses: actions/download-artifact@v1
with:
@@ -76,6 +75,15 @@ jobs:
with:
name: buildkit-win.zip
path: .
- name: Create tarball
run: git archive --prefix="cryptomator-${{ github.ref }}/" -o "cryptomator-${{ github.ref }}.tar.gz" ${{ github.ref }}
- name: Sign tarball with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a "cryptomator-${{ github.ref }}.tar.gz"
env:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Create Release
id: create_release
uses: actions/create-release@v1
@@ -91,6 +99,16 @@ jobs:
* [ ] add Linux appimage, zsync file and signature file
* [ ] add Windows installer and signature file
* [ ] add MacOs disk image and signature file
## What's new
## Bugfixes
## Misc
---
:scroll: A complete list of closed issues is available [here](LINK)
draft: true
prerelease: false
- name: Upload buildkit-linux.zip to GitHub Releases
@@ -119,4 +137,13 @@ jobs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: buildkit-win.zip
asset_name: buildkit-win.zip
asset_content_type: application/zip
asset_content_type: application/zip
- name: Upload tarball signature to GitHub Releases
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: "cryptomator-${{ github.ref }}.tar.gz.asc"
asset_name: "cryptomator-${{ github.ref }}.tar.gz.asc"
asset_content_type: application/octet-stream

5
.gitignore vendored
View File

@@ -17,9 +17,12 @@ pom.xml.versionsBackup
# IntelliJ Settings Files (https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems) #
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
.idea/**/shelf
.idea/dictionaries/**
!.idea/dictionaries/dict_*
.idea/compiler.xml
.idea/encodings.xml
.idea/jarRepositories.xml
.idea/uiDesigner.xml
.idea/**/libraries/
*.iml

15
.idea/dictionaries/dict_de.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<component name="ProjectDictionaryState">
<dictionary name="dict_de">
<words>
<w>tresorinhalt</w>
<w>tresorkonfigurationsdatei</w>
<w>tresorlaufwerk</w>
<w>tresorliste</w>
<w>tresorname</w>
<w>tresoroptionen</w>
<w>tresorstatistik</w>
<w>ungespeicherten</w>
<w>ungespeicherter</w>
</words>
</dictionary>
</component>

106
.idea/dictionaries/dict_project.xml generated Normal file
View File

@@ -0,0 +1,106 @@
<component name="ProjectDictionaryState">
<dictionary name="dict_project">
<words>
<w>addvault</w>
<w>addvaultwizard</w>
<w>adoptopenjdk</w>
<w>affero</w>
<w>aquafx</w>
<w>autolock</w>
<w>autolocked</w>
<w>autolocking</w>
<w>baos</w>
<w>bkup</w>
<w>buildkit</w>
<w>changepassword</w>
<w>checkerframework</w>
<w>crit</w>
<w>crowdin</w>
<w>cryptofs</w>
<w>cryptomator</w>
<w>cryptomator's</w>
<w>cryptor</w>
<w>csprng</w>
<w>dcryptomator</w>
<w>dfuse</w>
<w>dirid</w>
<w>djdk</w>
<w>dokany</w>
<w>dragboard</w>
<w>easybind</w>
<w>encr</w>
<w>errorprone</w>
<w>failureaccess</w>
<w>fbidis</w>
<w>fldinst</w>
<w>fldrslt</w>
<w>fontawesomefx</w>
<w>gdrive</w>
<w>gvfs</w>
<w>hmmss</w>
<w>httpcomponents</w>
<w>httpcore</w>
<w>iclouddrive</w>
<w>jensd</w>
<w>jffi</w>
<w>keyloading</w>
<w>kibs</w>
<w>listcell</w>
<w>listenablefuture</w>
<w>lopp</w>
<w>mainwindow</w>
<w>masterkey</w>
<w>masterkeyfile</w>
<w>mibs</w>
<w>mountpath</w>
<w>mpc's</w>
<w>needsmigration</w>
<w>noncommercially</w>
<w>noël</w>
<w>nulab</w>
<w>oatomic</w>
<w>oauto</w>
<w>objectgraph</w>
<w>odefault</w>
<w>ogid</w>
<w>onoappledouble</w>
<w>ordonly</w>
<w>ouid</w>
<w>ovolname</w>
<w>passthrough</w>
<w>patreon</w>
<w>pcloud</w>
<w>probot</w>
<w>recoverykey</w>
<w>relicensing</w>
<w>removevault</w>
<w>revealer</w>
<w>serceman</w>
<w>setolabs</w>
<w>skymatic</w>
<w>socio</w>
<w>spof</w>
<w>stenzel</w>
<w>styleclass</w>
<w>sublicenses</w>
<w>sublicensing</w>
<w>systemkeychain</w>
<w>tada</w>
<w>tidelift</w>
<w>tmpmountpoint</w>
<w>tobiasdiez</w>
<w>toggler</w>
<w>traymenu</w>
<w>unknownerror</w>
<w>unlockable</w>
<w>vaultconfig</w>
<w>vaultlist</w>
<w>vaultname</w>
<w>vaultoptions</w>
<w>wrongfilealert</w>
<w>xattr</w>
<w>zillmann</w>
<w>zxcvbn</w>
</words>
</dictionary>
</component>

View File

@@ -1,7 +1,7 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="true">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />

4
.idea/misc.xml generated
View File

@@ -4,11 +4,11 @@
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/main/pom.xml" />
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="false" project-jdk-name="14" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="16" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Desktop.iml" filepath="$PROJECT_DIR$/.idea/Desktop.iml" />
</modules>
</component>
</project>

View File

@@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="launcher" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath=&quot;~/.config/Cryptomator/settings.json&quot; -Dcryptomator.ipcPortPath=&quot;~/.config/Cryptomator/ipcPort.bin&quot; -Dcryptomator.logDir=&quot;~/.local/share/Cryptomator/logs&quot; -Dcryptomator.mountPointsDir=&quot;~/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m" />
<method v="2">
<option name="Make" enabled="true" />

View File

@@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="launcher" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath=&quot;~/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcPortPath=&quot;~/.config/Cryptomator-Dev/ipcPort.bin&quot; -Dcryptomator.logDir=&quot;~/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.mountPointsDir=&quot;~/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m" />
<method v="2">
<option name="Make" enabled="true" />

View File

@@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="launcher" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath=&quot;~/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcPortPath=&quot;~/AppData/Roaming/Cryptomator/ipcPort.bin&quot; -Dcryptomator.logDir=&quot;~/AppData/Roaming/Cryptomator&quot; -Dcryptomator.keychainPath=&quot;~/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.mountPointsDir=&quot;~/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
<method v="2">
<option name="Make" enabled="true" />

View File

@@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="launcher" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath=&quot;~/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcPortPath=&quot;~/AppData/Roaming/Cryptomator-Dev/ipcPort.bin&quot; -Dcryptomator.logDir=&quot;~/AppData/Roaming/Cryptomator-Dev&quot; -Dcryptomator.keychainPath=&quot;~/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.mountPointsDir=&quot;~/Cryptomator-Dev&quot; -Dfuse.experimental=&quot;true&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
<method v="2">
<option name="Make" enabled="true" />

View File

@@ -4,7 +4,7 @@
<env name="LD_LIBRARY_PATH" value="/usr/local/lib" />
</envs>
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="launcher" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath=&quot;~/Library/Application Support/Cryptomator/settings.json&quot; -Dcryptomator.ipcPortPath=&quot;~/Library/Application Support/Cryptomator/ipcPort.bin&quot; -Dcryptomator.logDir=&quot;~/Library/Logs/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
<method v="2">
<option name="Make" enabled="true" />

View File

@@ -4,7 +4,7 @@
<env name="LD_LIBRARY_PATH" value="/usr/local/lib" />
</envs>
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="launcher" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath=&quot;~/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcPortPath=&quot;~/Library/Application Support/Cryptomator-Dev/ipcPort.bin&quot; -Dcryptomator.logDir=&quot;~/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
<method v="2">
<option name="Make" enabled="true" />

View File

@@ -1,8 +1,8 @@
[![cryptomator](cryptomator.png)](https://cryptomator.org/)
[![Build](https://github.com/cryptomator/cryptomator/workflows/Build/badge.svg)](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild)
[![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptomator/badge.svg?targetFile=main%2Fpom.xml)](https://snyk.io/test/github/cryptomator/cryptomator?targetFile=main%2Fpom.xml)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2a0adf3cec6a4143b91035d3924178f1)](https://www.codacy.com/app/cryptomator/cryptomator?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cryptomator/cryptomator&amp;utm_campaign=Badge_Grade)
[![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptomator/badge.svg)](https://snyk.io/test/github/cryptomator/cryptomator)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/2a0adf3cec6a4143b91035d3924178f1)](https://www.codacy.com/gh/cryptomator/cryptomator/dashboard)
[![Twitter](https://img.shields.io/badge/twitter-@Cryptomator-blue.svg?style=flat)](http://twitter.com/Cryptomator)
[![Crowdin](https://badges.crowdin.net/cryptomator/localized.svg)](https://translate.cryptomator.org/)
[![Latest Release](https://img.shields.io/github/release/cryptomator/cryptomator.svg)](https://github.com/cryptomator/cryptomator/releases/latest)
@@ -17,11 +17,26 @@ Cryptomator is provided free of charge as an open-source project despite the hig
### Gold Sponsors
[<img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="96">](https://www.gee-whiz.de/)
<table>
<tbody>
<tr>
<td><a href="https://www.gee-whiz.de/"><img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="80"></a></td>
<td><a href="https://proxy-hub.com/"><img src="https://cryptomator.org/img/sponsors/proxyhub.svg" alt="Proxy-Hub" height="80"></a></td>
</tr>
</tbody>
</table>
### Silver Sponsors
[![TheBestVPN](https://cryptomator.org/img/sponsors/thebestvpn.png)](https://thebestvpn.com/)
<table>
<tbody>
<tr>
<td><a href="https://thebestvpn.com/"><img src="https://cryptomator.org/img/sponsors/thebestvpn@2x.png" alt="TheBestVPN" height="64"></a></td>
</tr>
</tbody>
</table>
- [Jameson Lopp](https://www.lopp.net/)
---
@@ -33,7 +48,7 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator
## Features
- Works with Dropbox, Google Drive, OneDrive, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
- Works with Dropbox, Google Drive, OneDrive, MEGA, pCloud, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
- Open Source means: No backdoors, control is better than trust
- Client-side: No accounts, no data shared with any online service
- Totally transparent: Just work on the virtual drive as if it were a USB flash drive
@@ -65,20 +80,20 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies
* JDK 14 (e.g. adoptopenjdk)
* JDK 16 (e.g. adoptopenjdk)
* Maven 3
* Optional: OS-dependent build tools for native packaging (see [Windows](https://github.com/cryptomator/cryptomator-win), [OS X](https://github.com/cryptomator/cryptomator-osx), [Linux](https://github.com/cryptomator/builder-containers))
### Run Maven
```
cd main
mvn clean install -Prelease,windows
# or mvn clean install -Prelease,mac
# or mvn clean install -Prelease,linux
mvn clean install
# or mvn clean install -Pwindows
# or mvn clean install -Pmac
# or mvn clean install -Plinux
```
This will build all the jars and bundle them together with their OS-specific dependencies under `main/buildkit/target`. This can now be used to build native packages.
This will build all the jars and bundle them together with their OS-specific dependencies under `target`. This can now be used to build native packages.
### Start Cryptomator

View File

@@ -29,6 +29,13 @@
<outputDirectory></outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>target/</directory>
<includes>
<include>cryptomator-*.jar</include>
</includes>
<outputDirectory>libs</outputDirectory>
</fileSet>
<fileSet>
<directory>target/libs</directory>
<includes>

View File

@@ -29,6 +29,13 @@
<outputDirectory></outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>target/</directory>
<includes>
<include>cryptomator-*.jar</include>
</includes>
<outputDirectory>libs</outputDirectory>
</fileSet>
<fileSet>
<directory>target/libs</directory>
<includes>

View File

@@ -29,6 +29,13 @@
<outputDirectory></outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>target/</directory>
<includes>
<include>cryptomator-*.jar</include>
</includes>
<outputDirectory>libs</outputDirectory>
</fileSet>
<fileSet>
<directory>target/libs</directory>
<includes>

View File

@@ -1,216 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.5.13</version>
</parent>
<artifactId>buildkit</artifactId>
<packaging>pom</packaging>
<name>Cryptomator Build Kit</name>
<description>Builds a package that can be built with Ant locally</description>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>launcher</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- copy resources -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>version.txt</include>
<include>ffi-version.txt</include>
<include>launcher-mac.sh</include>
<include>launcher-linux.sh</include>
<include>launcher-win.bat</include>
<include>LICENSE.txt</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- copy libraries to target/libs/: -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<excludeClassifiers>linux,mac,win</excludeClassifiers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>linux</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble-linux</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly-linux.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>buildkit-linux</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-linux-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<includeGroupIds>org.openjfx</includeGroupIds>
<classifier>linux</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>mac</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble-mac</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly-mac.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>buildkit-mac</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-mac-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<includeGroupIds>org.openjfx</includeGroupIds>
<classifier>mac</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>windows</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble-win</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly-win.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>buildkit-win</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-win-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<includeGroupIds>org.openjfx</includeGroupIds>
<classifier>win</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.5.13</version>
</parent>
<artifactId>commons</artifactId>
<name>Cryptomator Commons</name>
<description>Shared utilities</description>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>fuse-nio-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>dokany-nio-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-api</artifactId>
</dependency>
<!-- JavaFx -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
</dependency>
<!-- EasyBind -->
<dependency>
<groupId>com.tobiasdiez</groupId>
<artifactId>easybind</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,7 +0,0 @@
package org.cryptomator.common;
public interface Constants {
String MASTERKEY_FILENAME = "masterkey.cryptomator";
}

View File

@@ -1,19 +0,0 @@
package org.cryptomator.common.settings;
public enum KeychainBackend {
GNOME("org.cryptomator.linux.keychain.SecretServiceKeychainAccess"),
KDE("org.cryptomator.linux.keychain.KDEWalletKeychainAccess"),
MAC_SYSTEM_KEYCHAIN("org.cryptomator.macos.keychain.MacSystemKeychainAccess"),
WIN_SYSTEM_KEYCHAIN("org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess");
private final String providerClass;
KeychainBackend(String providerClass) {
this.providerClass = providerClass;
}
public String getProviderClass() {
return providerClass;
}
}

View File

@@ -1,34 +0,0 @@
package org.cryptomator.common.vaults;
public enum VaultState {
/**
* No vault found at the provided path
*/
MISSING,
/**
* Vault requires migration to a newer vault format
*/
NEEDS_MIGRATION,
/**
* Vault ready to be unlocked
*/
LOCKED,
/**
* Vault in transition between two other states
*/
PROCESSING,
/**
* Vault is unlocked
*/
UNLOCKED,
/**
* Unknown state due to preceeding unrecoverable exceptions.
*/
ERROR;
}

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.5.13</version>
</parent>
<artifactId>launcher</artifactId>
<name>Cryptomator Launcher</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>ui</artifactId>
</dependency>
<!-- Libs -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<!-- Logging -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,451 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.5.13</version>
<packaging>pom</packaging>
<name>Cryptomator</name>
<organization>
<name>cryptomator.org</name>
<url>https://cryptomator.org</url>
</organization>
<developers>
<developer>
<name>Sebastian Stenzel</name>
<email>sebastian.stenzel@gmail.com</email>
<timezone>+1</timezone>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>14</project.jdk.version>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>1.9.14</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.0.0-beta2</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.0.0-beta2</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.0.0-beta2</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.0.0-beta1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>1.2.9</cryptomator.fuse.version>
<cryptomator.dokany.version>1.2.4</cryptomator.dokany.version>
<cryptomator.webdav.version>1.1.3</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<javafx.version>15</javafx.version>
<commons-lang3.version>3.11</commons-lang3.version>
<jwt.version>3.12.0</jwt.version>
<easybind.version>2.1.0</easybind.version>
<guava.version>30.0-jre</guava.version>
<dagger.version>2.32</dagger.version>
<gson.version>2.8.6</gson.version>
<slf4j.version>1.7.30</slf4j.version>
<logback.version>1.2.3</logback.version>
<!-- test dependencies -->
<junit.jupiter.version>5.7.0</junit.jupiter.version>
<mockito.version>3.6.0</mockito.version>
<hamcrest.version>2.2</hamcrest.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- modules -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>ui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>launcher</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Cryptomator Libs -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
<version>${cryptomator.cryptofs.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>fuse-nio-adapter</artifactId>
<version>${cryptomator.fuse.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>dokany-nio-adapter</artifactId>
<version>${cryptomator.dokany.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter</artifactId>
<version>${cryptomator.webdav.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-api</artifactId>
<version>${cryptomator.integrations.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-win</artifactId>
<version>${cryptomator.integrations.win.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-mac</artifactId>
<version>${cryptomator.integrations.mac.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-linux</artifactId>
<version>${cryptomator.integrations.linux.version}</version>
</dependency>
<!-- JavaFX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- EasyBind -->
<dependency>
<groupId>com.tobiasdiez</groupId>
<artifactId>easybind</artifactId>
<version>${easybind.version}</version>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
<version>${dagger.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<!-- JUnit / Mockito / Hamcrest -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>${javafx.version}</version>
<scope>test</scope>
</dependency>
<!-- TODO: temporary fix for XXE attack, can be removed once java-jwt is updated -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.5.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- common dependencies for all modules -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>commons</module>
<module>ui</module>
<module>launcher</module>
</modules>
<profiles>
<profile>
<id>release</id>
<modules>
<module>buildkit</module>
</modules>
</profile>
<profile>
<id>coverage</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>mac</id>
<activation>
<os>
<family>mac</family>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-mac</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>linux</id>
<activation>
<os>
<family>unix</family>
<name>Linux</name>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-linux</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-win</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>dependency-check</id>
<build>
<plugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.0.3</version>
<configuration>
<cveValidForHours>24</cveValidForHours>
<failBuildOnCVSS>0</failBuildOnCVSS>
<skipTestScope>true</skipTestScope>
<detail>true</detail>
<suppressionFile>suppression.xml</suppressionFile>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<!-- adds Implementation-Version which can be read during runtime -->
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/*_*</exclude>
<exclude>**/Dagger*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>${project.jdk.version}</release>
<annotationProcessorPaths>
<path>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>${dagger.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.5.13</version>
</parent>
<artifactId>ui</artifactId>
<name>Cryptomator GUI</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<!-- JavaFx -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
</dependency>
<!-- EasyBind -->
<dependency>
<groupId>com.tobiasdiez</groupId>
<artifactId>easybind</artifactId>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<!-- Zxcvbn -->
<dependency>
<groupId>com.nulab-inc</groupId>
<artifactId>zxcvbn</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
<!-- Testing -->
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<executions>
<execution>
<id>add-third-party</id>
<goals>
<goal>add-third-party</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.basedir}/src/main/resources/license</outputDirectory>
<thirdPartyFilename>THIRD-PARTY.txt</thirdPartyFilename>
<includedScopes>compile</includedScopes>
<excludedGroups>org\.cryptomator</excludedGroups>
<licenseMerges>
<licenseMerge>Apache License v2.0|Apache License, Version 2.0|The Apache Software License, Version 2.0|Apache 2.0|Apache Software License - Version 2.0</licenseMerge>
<licenseMerge>MIT License|The MIT License (MIT)|The MIT License|MIT license</licenseMerge>
<licenseMerge>LGPL 2.1|LGPL, version 2.1|GNU Lesser/Library General Public License version 2|GNU Lesser General Public License Version 2.1</licenseMerge>
<licenseMerge>GPLv2|GNU General Public License Version 2</licenseMerge>
<licenseMerge>GPLv2+CE|CDDL + GPLv2 with classpath exception</licenseMerge>
</licenseMerges>
<fileTemplate>${project.basedir}/src/license/template.ftl</fileTemplate>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,100 +0,0 @@
package org.cryptomator.ui.mainwindow;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.removevault.RemoveVaultComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
@MainWindowScoped
public class VaultListController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class);
private final ObservableList<Vault> vaults;
private final ObjectProperty<Vault> selectedVault;
private final VaultListCellFactory cellFactory;
private final AddVaultWizardComponent.Builder addVaultWizard;
private final RemoveVaultComponent.Builder removeVault;
private final BooleanBinding noVaultSelected;
private final BooleanBinding emptyVaultList;
public ListView<Vault> vaultList;
@Inject
VaultListController(ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVault) {
this.vaults = vaults;
this.selectedVault = selectedVault;
this.cellFactory = cellFactory;
this.addVaultWizard = addVaultWizard;
this.removeVault = removeVault;
this.noVaultSelected = selectedVault.isNull();
this.emptyVaultList = Bindings.isEmpty(vaults);
selectedVault.addListener(this::selectedVaultDidChange);
}
public void initialize() {
vaultList.setItems(vaults);
vaultList.setCellFactory(cellFactory);
selectedVault.bind(vaultList.getSelectionModel().selectedItemProperty());
vaults.addListener((ListChangeListener.Change<? extends Vault> c) -> {
while (c.next()) {
if (c.wasAdded()) {
Vault anyAddedVault = c.getAddedSubList().get(0);
vaultList.getSelectionModel().select(anyAddedVault);
}
}
});
}
private void selectedVaultDidChange(@SuppressWarnings("unused") ObservableValue<? extends Vault> observableValue, @SuppressWarnings("unused") Vault oldValue, Vault newValue) {
if (newValue == null) {
return;
}
VaultListManager.redetermineVaultState(newValue);
}
@FXML
public void didClickAddVault() {
addVaultWizard.build().showAddVaultWizard();
}
@FXML
public void didClickRemoveVault() {
Vault v = selectedVault.get();
if (v != null) {
removeVault.vault(v).build().showRemoveVault();
} else {
LOG.debug("Cannot remove a vault if none is selected.");
}
}
// Getter and Setter
public BooleanBinding emptyVaultListProperty() {
return emptyVaultList;
}
public boolean isEmptyVaultList() {
return emptyVaultList.get();
}
public BooleanBinding noVaultSelectedProperty() {
return noVaultSelected;
}
public boolean isNoVaultSelected() {
return noVaultSelected.get();
}
}

View File

@@ -1,141 +0,0 @@
# Locale Specific CSS files such as CJK, RTL,...
# Generics
## Button
generic.button.apply=Terapkan
generic.button.back=Kembali
generic.button.cancel=Batalkan
generic.button.change=Ganti
generic.button.close=Tutup
generic.button.copy=Salin
generic.button.copied=Tersalin!
generic.button.done=Selesai
generic.button.next=Lanjut
generic.button.print=Cetak
## Error
generic.error.title=Telah terjadi kesalahan tak terduga
generic.error.instruction=Ini harusnya tidak terjadi. Harap laporkan pesan kesalahan dibawah dan tulis deskripsi kenapa ini bisa terjadi.
# Defaults
defaults.vault.vaultName=Brankas
# Tray Menu
traymenu.showMainWindow=Tampilkan
traymenu.showPreferencesWindow=Preferensi
traymenu.lockAllVaults=Gembok Semua
traymenu.quitApplication=Keluar
traymenu.vault.unlock=Buka Gembok
traymenu.vault.lock=Gembok
traymenu.vault.reveal=Perlihatkan
# Add Vault Wizard
addvaultwizard.title=Tambah Brankas
## Welcome
addvaultwizard.welcome.newButton=Buat Brankas Baru
addvaultwizard.welcome.existingButton=Buka Brankas yg Sudah Ada
## New
### Name
addvaultwizard.new.nameInstruction=Buat sebuah nama untuk brankas
addvaultwizard.new.namePrompt=Nama Brankas
### Location
addvaultwizard.new.locationInstruction=Dimana Cryptomator seharusnya menyimpan brankas berkas terenkripsi kamu?
addvaultwizard.new.locationLabel=Lokasi penyimpanan
addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerLabel=Sesuaikan Lokasi
addvaultwizard.new.directoryPickerButton=Pilih…
addvaultwizard.new.directoryPickerTitle=Pilih Folder
addvaultwizard.new.fileAlreadyExists=Brankas tidak dibuat disini karena beberapa item telah ada disini.
addvaultwizard.new.locationDoesNotExist=Brankas tidak bisa dibuat disini karena setidaknya satu jalur komponen tidak ada.
addvaultwizard.new.invalidName=Nama brankas salah. Harap pilih nama folder yang umum.
### Password
addvaultwizard.new.createVaultBtn=Buat Brankas
addvaultwizard.new.generateRecoveryKeyChoice=Kamu tidak dapat mengakses data tanpa kata sandi kamu. Apa kamu ingin sebuah kunci pemulihan buat jaga-jaga?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Ya, sedia payung sebelum hujan
addvaultwizard.new.generateRecoveryKeyChoice.no=Tidak, terima kasih, Saya tidak akan kehilangan kata sandi saya
### Information
addvault.new.readme.storageLocation.fileName=PENTING.rtf
addvault.new.readme.storageLocation.1=⚠️ BERKAS BRANKAS ⚠️
addvault.new.readme.storageLocation.2=Ini adalah lokasi penyimpanan brankas kamu.
addvault.new.readme.storageLocation.3=JANGAN
addvault.new.readme.storageLocation.6=Jika kamu ingin mengenkripsi berkas dan melihat isi brankas, lakukan hal berikut:
addvault.new.readme.storageLocation.7=1. Tambahkan brankas ini ke Cryptomator.
addvault.new.readme.storageLocation.8=2. Buka gembok brankas di Cryptomator.
addvault.new.readme.storageLocation.9=3. Buka akses lokasi dengan mengklik tombol "Perlihatkan".
addvault.new.readme.storageLocation.10=Jika kamu butuh bantuan, kunjungi dokumentasi: %s
addvault.new.readme.accessLocation.fileName=SELAMAT_DATANG.rtf
addvault.new.readme.accessLocation.1=🔐️ ISI TERENKRIPSI 🔐️
addvault.new.readme.accessLocation.2=Ini adalah lokasi akses brankas kamu.
## Existing
addvaultwizard.existing.chooseBtn=Pilih…
## Success
# Remove Vault
# Change Password
# Forget Password
# Unlock
unlock.unlockBtn=Buka Gembok
## Success
## Failure
### Invalid Mount Point
# Lock
## Force
## Failure
# Migration
## Start
## Run
## Sucess
## Missing file system capabilities
## Impossible
# Preferences
preferences.title=Preferensi
## General
## Volume
## Updates
## Donation Key
## About
# Vault Statistics
## Read
## Write
# Main Window
main.closeBtn.tooltip=Tutup
main.preferencesBtn.tooltip=Preferensi
## Drag 'n' Drop
## Vault List
main.vaultlist.addVaultBtn=Tambah Brankas
## Vault Detail
### Welcome
### Locked
### Unlocked
main.vaultDetail.lockBtn=Gembok
### Missing
### Needs Migration
# Wrong File Alert
# Vault Options
## General
vaultOptions.general.vaultName=Nama Brankas
## Mount
vaultOptions.mount.mountPoint.directoryPickerButton=Pilih…
## Master Key
# Recovery Key
# New Password
passwordStrength.messageLabel.0=Sangat lemah
passwordStrength.messageLabel.1=Lemah
passwordStrength.messageLabel.2=Cukup
passwordStrength.messageLabel.3=Kuat
passwordStrength.messageLabel.4=Sangat kuat
# Quit
quit.prompt=Keluar aplikasi? Terdapat brankas yg belum digembok.
quit.lockAndQuit=Gembok dan Keluar

601
pom.xml Normal file
View File

@@ -0,0 +1,601 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId>
<version>1.6.0-SNAPSHOT</version>
<name>Cryptomator Desktop App</name>
<organization>
<name>cryptomator.org</name>
<url>https://cryptomator.org</url>
</organization>
<developers>
<developer>
<name>Sebastian Stenzel</name>
<email>sebastian.stenzel@gmail.com</email>
<timezone>+1</timezone>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>16</project.jdk.version>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.1.0-beta8</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.0.0-rc1</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.0.0-beta2</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.0.0-beta2</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.0.0-beta1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>1.3.1</cryptomator.fuse.version>
<cryptomator.dokany.version>1.3.1</cryptomator.dokany.version>
<cryptomator.webdav.version>1.2.4</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<javafx.version>16</javafx.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<jwt.version>3.17.0</jwt.version>
<easybind.version>2.2</easybind.version>
<guava.version>30.1.1-jre</guava.version>
<dagger.version>2.37</dagger.version>
<gson.version>2.8.6</gson.version>
<slf4j.version>1.7.31</slf4j.version>
<logback.version>1.2.3</logback.version>
<!-- test dependencies -->
<junit.jupiter.version>5.7.2</junit.jupiter.version>
<mockito.version>3.11.2</mockito.version>
<hamcrest.version>2.2</hamcrest.version>
</properties>
<dependencies>
<!-- Cryptomator Libs -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
<version>${cryptomator.cryptofs.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>fuse-nio-adapter</artifactId>
<version>${cryptomator.fuse.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>dokany-nio-adapter</artifactId>
<version>${cryptomator.dokany.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter</artifactId>
<version>${cryptomator.webdav.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-api</artifactId>
<version>${cryptomator.integrations.version}</version>
</dependency>
<!-- JavaFX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- EasyBind -->
<dependency>
<groupId>com.tobiasdiez</groupId>
<artifactId>easybind</artifactId>
<version>${easybind.version}</version>
</dependency>
<!-- Zxcvbn -->
<dependency>
<groupId>com.nulab-inc</groupId>
<artifactId>zxcvbn</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
<version>${dagger.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<!-- JUnit / Mockito / Hamcrest -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>${javafx.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
</plugin>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.0.3</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>${project.jdk.version}</release>
<annotationProcessorPaths>
<path>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>${dagger.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!-- adds Implementation-Version which can be read during runtime -->
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/package</directory>
<includes>
<include>version.txt</include>
<include>ffi-version.txt</include>
<include>launcher-mac.sh</include>
<include>launcher-linux.sh</include>
<include>launcher-win.bat</include>
<include>LICENSE.txt</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<excludeClassifiers>linux,mac,win</excludeClassifiers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<executions>
<execution>
<id>add-third-party</id>
<goals>
<goal>add-third-party</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.basedir}/src/main/resources/license</outputDirectory>
<thirdPartyFilename>THIRD-PARTY.txt</thirdPartyFilename>
<includedScopes>compile</includedScopes>
<excludedGroups>org\.cryptomator</excludedGroups>
<licenseMerges>
<licenseMerge>Apache License v2.0|Apache License, Version 2.0|The Apache Software License, Version 2.0|Apache 2.0|Apache Software License - Version 2.0</licenseMerge>
<licenseMerge>MIT License|The MIT License (MIT)|The MIT License|MIT license</licenseMerge>
<licenseMerge>LGPL 2.1|LGPL, version 2.1|GNU Lesser/Library General Public License version 2|GNU Lesser General Public License Version 2.1</licenseMerge>
<licenseMerge>GPLv2|GNU General Public License Version 2</licenseMerge>
<licenseMerge>GPLv2+CE|CDDL + GPLv2 with classpath exception</licenseMerge>
</licenseMerges>
<fileTemplate>${project.basedir}/src/license/template.ftl</fileTemplate>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>coverage</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/*_*</exclude>
<exclude>**/Dagger*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>dependency-check</id>
<build>
<plugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<configuration>
<cveValidForHours>24</cveValidForHours>
<failBuildOnCVSS>0</failBuildOnCVSS>
<skipTestScope>true</skipTestScope>
<detail>true</detail>
<suppressionFile>suppression.xml</suppressionFile>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>mac</id>
<activation>
<os>
<family>mac</family>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-mac</artifactId>
<version>${cryptomator.integrations.mac.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble-mac</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly-mac.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>buildkit-mac</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-mac-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<includeGroupIds>org.openjfx</includeGroupIds>
<classifier>mac</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>linux</id>
<activation>
<os>
<family>unix</family>
<name>Linux</name>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-linux</artifactId>
<version>${cryptomator.integrations.linux.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble-linux</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly-linux.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>buildkit-linux</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-linux-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<includeGroupIds>org.openjfx</includeGroupIds>
<classifier>linux</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-win</artifactId>
<version>${cryptomator.integrations.win.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble-win</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly-win.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>buildkit-win</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-win-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<includeGroupIds>org.openjfx</includeGroupIds>
<classifier>win</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -15,6 +15,8 @@ import org.cryptomator.common.settings.SettingsProvider;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultComponent;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.common.vaults.VaultListModule;
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.cryptomator.frontend.webdav.WebDavServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,6 +27,8 @@ import javafx.beans.binding.Binding;
import javafx.beans.binding.Bindings;
import javafx.collections.ObservableList;
import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Comparator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -34,7 +38,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@Module(subcomponents = {VaultComponent.class}, includes = {KeychainModule.class})
@Module(subcomponents = {VaultComponent.class}, includes = {VaultListModule.class, KeychainModule.class})
public abstract class CommonsModule {
private static final Logger LOG = LoggerFactory.getLogger(CommonsModule.class);
@@ -42,15 +46,34 @@ public abstract class CommonsModule {
private static final int NUM_CORE_BG_THREADS = 6;
private static final long BG_THREAD_KEEPALIVE_SECONDS = 60l;
@SuppressWarnings("SpellCheckingInspection")
@Provides
@Singleton
@Named("licensePublicKey")
static String provideLicensePublicKey() {
// in PEM format without the dash-escaped begin/end lines
return "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB7NfnqiZbg2KTmoflmZ71PbXru7oW" //
+ "fmnV2yv3eDjlDfGruBrqz9TtXBZV/eYWt31xu1osIqaT12lKBvZ511aaAkIBeOEV" //
+ "gwcBIlJr6kUw7NKzeJt7r2rrsOyQoOG2nWc/Of/NBqA3mIZRHk5Aq1YupFdD26QE" //
+ "r0DzRyj4ixPIt38CQB8=";
return """
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB7NfnqiZbg2KTmoflmZ71PbXru7oW\
fmnV2yv3eDjlDfGruBrqz9TtXBZV/eYWt31xu1osIqaT12lKBvZ511aaAkIBeOEV\
gwcBIlJr6kUw7NKzeJt7r2rrsOyQoOG2nWc/Of/NBqA3mIZRHk5Aq1YupFdD26QE\
r0DzRyj4ixPIt38CQB8=\
""";
}
@Provides
@Singleton
static SecureRandom provideCSPRNG() {
try {
return SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("A strong algorithm must exist in every Java platform.", e);
}
}
@Provides
@Singleton
static MasterkeyFileAccess provideMasterkeyFileAccess(SecureRandom csprng) {
return new MasterkeyFileAccess(Constants.PEPPER, csprng);
}
@Provides
@@ -66,12 +89,6 @@ public abstract class CommonsModule {
return settingsProvider.get();
}
@Provides
@Singleton
static ObservableList<Vault> provideVaultList(VaultListManager vaultListManager) {
return vaultListManager.getVaultList();
}
@Provides
@Singleton
static ScheduledExecutorService provideScheduledExecutorService(ShutdownHook shutdownHook) {

View File

@@ -0,0 +1,10 @@
package org.cryptomator.common;
public interface Constants {
String MASTERKEY_FILENAME = "masterkey.cryptomator";
String MASTERKEY_BACKUP_SUFFIX = ".bkup";
String VAULTCONFIG_FILENAME = "vault.cryptomator";
byte[] PEPPER = new byte[0];
}

View File

@@ -99,12 +99,12 @@ public class Environment {
}
// visible for testing
Path getHomeDir() {
public Path getHomeDir() {
return getPath("user.home").orElseThrow();
}
// visible for testing
Stream<Path> getPaths(String propertyName) {
public Stream<Path> getPaths(String propertyName) {
Stream<String> rawSettingsPaths = getRawList(propertyName, PATH_LIST_SEP);
return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Paths::get).map(this::replaceHomeDir);
}
@@ -123,8 +123,8 @@ public class Environment {
return Stream.empty();
} else {
Iterable<String> iter = Splitter.on(separator).split(value);
Spliterator<String> spliter = Spliterators.spliteratorUnknownSize(iter.iterator(), Spliterator.ORDERED | Spliterator.IMMUTABLE);
return StreamSupport.stream(spliter, false);
Spliterator<String> spliterator = Spliterators.spliteratorUnknownSize(iter.iterator(), Spliterator.ORDERED | Spliterator.IMMUTABLE);
return StreamSupport.stream(spliterator, false);
}
}
}

View File

@@ -33,8 +33,8 @@ class LicenseChecker {
try {
byte[] keyBytes = BaseEncoding.base64().decode(pemEncodedPublicKey);
PublicKey key = KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(keyBytes));
if (key instanceof ECPublicKey) {
return (ECPublicKey) key;
if (key instanceof ECPublicKey k) {
return k;
} else {
throw new IllegalStateException("Key not an EC public key.");
}

View File

@@ -60,17 +60,17 @@ public class SemVerComparator implements Comparator<String> {
final int commonCompCount = Math.min(vComps1.length, vComps2.length);
for (int i = 0; i < commonCompCount; i++) {
int subversionComparisionResult = 0;
int subversionComparisonResult = 0;
try {
final int v1 = Integer.parseInt(vComps1[i]);
final int v2 = Integer.parseInt(vComps2[i]);
subversionComparisionResult = v1 - v2;
subversionComparisonResult = v1 - v2;
} catch (NumberFormatException ex) {
// ok, lets compare this fragment lexicographically
subversionComparisionResult = vComps1[i].compareTo(vComps2[i]);
subversionComparisonResult = vComps1[i].compareTo(vComps2[i]);
}
if (subversionComparisionResult != 0) {
return subversionComparisionResult;
if (subversionComparisonResult != 0) {
return subversionComparisonResult;
}
}

View File

@@ -59,8 +59,10 @@ public class KeychainManager implements KeychainAccessProvider {
@Override
public void changePassphrase(String key, CharSequence passphrase) throws KeychainAccessException {
getKeychainOrFail().changePassphrase(key, passphrase);
setPassphraseStored(key, true);
if (isPassphraseStored(key)) {
getKeychainOrFail().changePassphrase(key, passphrase);
setPassphraseStored(key, true);
}
}
@Override

View File

@@ -34,11 +34,11 @@ public class KeychainModule {
@Singleton
static ObjectExpression<KeychainAccessProvider> provideKeychainAccessProvider(Settings settings, Set<KeychainAccessProvider> providers) {
return Bindings.createObjectBinding(() -> {
var selectedProviderClass = settings.keychainBackend().get().getProviderClass();
var selectedProviderClass = settings.keychainProvider().get();
var selectedProvider = providers.stream().filter(provider -> provider.getClass().getName().equals(selectedProviderClass)).findAny();
var fallbackProvider = providers.stream().findAny().orElse(null);
return selectedProvider.orElse(fallbackProvider);
}, settings.keychainBackend());
}, settings.keychainProvider());
}
}

View File

@@ -1,6 +1,6 @@
package org.cryptomator.common.mountpoint;
import com.google.common.base.Preconditions;
import dagger.multibindings.IntKey;
import org.cryptomator.common.vaults.Volume;
import java.nio.file.Path;
@@ -12,13 +12,13 @@ import java.util.SortedSet;
* preparation of a mountpoint or an exception otherwise.<br>
* <p>All <i>MountPointChoosers (MPCs)</i> need to implement this class and must be added to
* the pool of possible MPCs by the {@link MountPointChooserModule MountPointChooserModule.}
* The MountPointChooserModule will sort them according to their {@link #getPriority() priority.}
* The MountPointChooserModule will sort them according to their {@link IntKey IntKey priority.}
* The priority must be defined by the developer to reflect a useful execution order.<br>
* A specific priority <b>must not</b> be assigned to more than one MPC at a time;
* the result of having two MPCs with equal priority is undefined.
*
* <p>MPCs are executed by a {@link Volume} in ascending order of their priority
* (smaller priorities are tried first) to find and prepare a suitable mountpoint for the volume.
* <p>MPCs are executed by a {@link Volume} in descending order of their priority
* (higher priorities are tried first) to find and prepare a suitable mountpoint for the volume.
* The volume has access to a {@link SortedSet} of MPCs in this specific order,
* that is provided by the Module. The Set contains all available Choosers, even if they
* are not {@link #isApplicable(Volume) applicable} for the Vault/Volume. The Volume must

View File

@@ -9,6 +9,7 @@ import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.PerVault;
import javax.inject.Named;
import java.util.Comparator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -24,16 +25,22 @@ public abstract class MountPointChooserModule {
@Binds
@IntoMap
@IntKey(0)
@IntKey(1000)
@PerVault
public abstract MountPointChooser bindCustomMountPointChooser(CustomMountPointChooser chooser);
@Binds
@IntoMap
@IntKey(100)
@IntKey(900)
@PerVault
public abstract MountPointChooser bindCustomDriveLetterChooser(CustomDriveLetterChooser chooser);
@Binds
@IntoMap
@IntKey(800)
@PerVault
public abstract MountPointChooser bindAvailableDriveLetterChooser(AvailableDriveLetterChooser chooser);
@Binds
@IntoMap
@IntKey(101)
@@ -42,13 +49,7 @@ public abstract class MountPointChooserModule {
@Binds
@IntoMap
@IntKey(200)
@PerVault
public abstract MountPointChooser bindAvailableDriveLetterChooser(AvailableDriveLetterChooser chooser);
@Binds
@IntoMap
@IntKey(999)
@IntKey(100)
@PerVault
public abstract MountPointChooser bindTemporaryMountPointChooser(TemporaryMountPointChooser chooser);
@@ -56,7 +57,8 @@ public abstract class MountPointChooserModule {
@PerVault
@Named("orderedMountPointChoosers")
public static Iterable<MountPointChooser> provideOrderedMountPointChoosers(Map<Integer, MountPointChooser> choosers) {
SortedMap<Integer, MountPointChooser> sortedChoosers = new TreeMap<>(choosers);
SortedMap<Integer, MountPointChooser> sortedChoosers = new TreeMap<>(Comparator.reverseOrder());
sortedChoosers.putAll(choosers);
return Iterables.unmodifiableIterable(sortedChoosers.values());
}
}

View File

@@ -30,7 +30,7 @@ public class Settings {
public static final int MIN_PORT = 1024;
public static final int MAX_PORT = 65535;
public static final boolean DEFAULT_ASKED_FOR_UPDATE_CHECK = false;
public static final boolean DEFAULT_CHECK_FOR_UDPATES = false;
public static final boolean DEFAULT_CHECK_FOR_UPDATES = false;
public static final boolean DEFAULT_START_HIDDEN = false;
public static final int DEFAULT_PORT = 42427;
public static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
@@ -38,14 +38,15 @@ public class Settings {
public static final boolean DEFAULT_DEBUG_MODE = false;
public static final VolumeImpl DEFAULT_PREFERRED_VOLUME_IMPL = SystemUtils.IS_OS_WINDOWS ? VolumeImpl.DOKANY : VolumeImpl.FUSE;
public static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
public static final KeychainBackend DEFAULT_KEYCHAIN_BACKEND = SystemUtils.IS_OS_WINDOWS ? KeychainBackend.WIN_SYSTEM_KEYCHAIN : SystemUtils.IS_OS_MAC ? KeychainBackend.MAC_SYSTEM_KEYCHAIN : KeychainBackend.GNOME;
@Deprecated // to be changed to "whatever is available" eventually
public static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : "org.cryptomator.linux.keychain.SecretServiceKeychainAccess";
public static final NodeOrientation DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT;
public static final String DEFAULT_LICENSE_KEY = "";
public static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
private final BooleanProperty askedForUpdateCheck = new SimpleBooleanProperty(DEFAULT_ASKED_FOR_UPDATE_CHECK);
private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UDPATES);
private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UPDATES);
private final BooleanProperty startHidden = new SimpleBooleanProperty(DEFAULT_START_HIDDEN);
private final IntegerProperty port = new SimpleIntegerProperty(DEFAULT_PORT);
private final IntegerProperty numTrayNotifications = new SimpleIntegerProperty(DEFAULT_NUM_TRAY_NOTIFICATIONS);
@@ -53,7 +54,7 @@ public class Settings {
private final BooleanProperty debugMode = new SimpleBooleanProperty(DEFAULT_DEBUG_MODE);
private final ObjectProperty<VolumeImpl> preferredVolumeImpl = new SimpleObjectProperty<>(DEFAULT_PREFERRED_VOLUME_IMPL);
private final ObjectProperty<UiTheme> theme = new SimpleObjectProperty<>(DEFAULT_THEME);
private final ObjectProperty<KeychainBackend> keychainBackend = new SimpleObjectProperty<>(DEFAULT_KEYCHAIN_BACKEND);
private final ObjectProperty<String> keychainProvider = new SimpleObjectProperty<>(DEFAULT_KEYCHAIN_PROVIDER);
private final ObjectProperty<NodeOrientation> userInterfaceOrientation = new SimpleObjectProperty<>(DEFAULT_USER_INTERFACE_ORIENTATION);
private final StringProperty licenseKey = new SimpleStringProperty(DEFAULT_LICENSE_KEY);
private final BooleanProperty showMinimizeButton = new SimpleBooleanProperty(DEFAULT_SHOW_MINIMIZE_BUTTON);
@@ -77,7 +78,7 @@ public class Settings {
debugMode.addListener(this::somethingChanged);
preferredVolumeImpl.addListener(this::somethingChanged);
theme.addListener(this::somethingChanged);
keychainBackend.addListener(this::somethingChanged);
keychainProvider.addListener(this::somethingChanged);
userInterfaceOrientation.addListener(this::somethingChanged);
licenseKey.addListener(this::somethingChanged);
showMinimizeButton.addListener(this::somethingChanged);
@@ -140,7 +141,7 @@ public class Settings {
return theme;
}
public ObjectProperty<KeychainBackend> keychainBackend() { return keychainBackend; }
public ObjectProperty<String> keychainProvider() { return keychainProvider; }
public ObjectProperty<NodeOrientation> userInterfaceOrientation() {
return userInterfaceOrientation;

View File

@@ -48,7 +48,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
out.name("preferredVolumeImpl").value(value.preferredVolumeImpl().get().name());
out.name("theme").value(value.theme().get().name());
out.name("uiOrientation").value(value.userInterfaceOrientation().get().name());
out.name("keychainBackend").value(value.keychainBackend().get().name());
out.name("keychainProvider").value(value.keychainProvider().get());
out.name("licenseKey").value(value.licenseKey().get());
out.name("showMinimizeButton").value(value.showMinimizeButton().get());
out.name("showTrayIcon").value(value.showTrayIcon().get());
@@ -82,7 +82,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
case "preferredVolumeImpl" -> settings.preferredVolumeImpl().set(parsePreferredVolumeImplName(in.nextString()));
case "theme" -> settings.theme().set(parseUiTheme(in.nextString()));
case "uiOrientation" -> settings.userInterfaceOrientation().set(parseUiOrientation(in.nextString()));
case "keychainBackend" -> settings.keychainBackend().set(parseKeychainBackend(in.nextString()));
case "keychainProvider" -> settings.keychainProvider().set(in.nextString());
case "licenseKey" -> settings.licenseKey().set(in.nextString());
case "showMinimizeButton" -> settings.showMinimizeButton().set(in.nextBoolean());
case "showTrayIcon" -> settings.showTrayIcon().set(in.nextBoolean());
@@ -124,15 +124,6 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
}
}
private KeychainBackend parseKeychainBackend(String backendName) {
try {
return KeychainBackend.valueOf(backendName.toUpperCase());
} catch (IllegalArgumentException e) {
LOG.warn("Invalid keychain backend {}. Defaulting to {}.", backendName, Settings.DEFAULT_KEYCHAIN_BACKEND);
return Settings.DEFAULT_KEYCHAIN_BACKEND;
}
}
private NodeOrientation parseUiOrientation(String uiOrientationName) {
try {
return NodeOrientation.valueOf(uiOrientationName.toUpperCase());

View File

@@ -101,7 +101,7 @@ public class SettingsProvider implements Supplier<Settings> {
if (settings == null) {
return;
}
final Optional<Path> settingsPath = env.getSettingsPath().findFirst(); // alway save to preferred (first) path
final Optional<Path> settingsPath = env.getSettingsPath().findFirst(); // always save to preferred (first) path
settingsPath.ifPresent(path -> {
Runnable saveCommand = () -> this.save(settings, path);
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, SAVE_DELAY_MS, TimeUnit.MILLISECONDS);

View File

@@ -24,8 +24,6 @@ import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
/**
* The settings specific to a single vault.
@@ -33,12 +31,14 @@ import java.util.stream.Collectors;
public class VaultSettings {
public static final boolean DEFAULT_UNLOCK_AFTER_STARTUP = false;
public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true;
public static final boolean DEFAULT_REVEAL_AFTER_MOUNT = true;
public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false;
public static final boolean DEFAULT_USES_READONLY_MODE = false;
public static final String DEFAULT_MOUNT_FLAGS = "";
public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1;
public static final int DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH = -1;
public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
public static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false;
public static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60;
private static final Random RNG = new Random();
@@ -47,14 +47,15 @@ public class VaultSettings {
private final StringProperty displayName = new SimpleStringProperty();
private final StringProperty winDriveLetter = new SimpleStringProperty();
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REAVEAL_AFTER_MOUNT);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REVEAL_AFTER_MOUNT);
private final BooleanProperty useCustomMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH);
private final StringProperty customMountPath = new SimpleStringProperty();
private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE);
private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS);
private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT);
private final IntegerProperty maxCleartextFilenameLength = new SimpleIntegerProperty(DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH);
private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE);
private final IntegerProperty autoLockIdleSeconds = new SimpleIntegerProperty(DEFAULT_AUTOLOCK_IDLE_SECONDS);
private final StringBinding mountName;
public VaultSettings(String id) {
@@ -63,7 +64,7 @@ public class VaultSettings {
}
Observable[] observables() {
return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock};
return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, maxCleartextFilenameLength, actionAfterUnlock, autoLockWhenIdle, autoLockIdleSeconds};
}
public static VaultSettings withRandomId() {
@@ -152,8 +153,8 @@ public class VaultSettings {
return mountFlags;
}
public IntegerProperty filenameLengthLimit() {
return filenameLengthLimit;
public IntegerProperty maxCleartextFilenameLength() {
return maxCleartextFilenameLength;
}
public ObjectProperty<WhenUnlocked> actionAfterUnlock() {
@@ -164,6 +165,14 @@ public class VaultSettings {
return actionAfterUnlock.get();
}
public BooleanProperty autoLockWhenIdle() {
return autoLockWhenIdle;
}
public IntegerProperty autoLockIdleSeconds() {
return autoLockIdleSeconds;
}
/* Hashcode/Equals */
@Override
@@ -173,8 +182,7 @@ public class VaultSettings {
@Override
public boolean equals(Object obj) {
if (obj instanceof VaultSettings && obj.getClass().equals(this.getClass())) {
VaultSettings other = (VaultSettings) obj;
if (obj instanceof VaultSettings other && obj.getClass().equals(this.getClass())) {
return Objects.equals(this.id, other.id);
} else {
return false;

View File

@@ -29,8 +29,10 @@ class VaultSettingsJsonAdapter {
out.name("customMountPath").value(value.customMountPath().get());
out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get());
out.name("mountFlags").value(value.mountFlags().get());
out.name("filenameLengthLimit").value(value.filenameLengthLimit().get());
out.name("maxCleartextFilenameLength").value(value.maxCleartextFilenameLength().get());
out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name());
out.name("autoLockWhenIdle").value(value.autoLockWhenIdle().get());
out.name("autoLockIdleSeconds").value(value.autoLockIdleSeconds().get());
out.endObject();
}
@@ -42,12 +44,14 @@ class VaultSettingsJsonAdapter {
String customMountPath = null;
String winDriveLetter = null;
boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP;
boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT;
boolean revealAfterMount = VaultSettings.DEFAULT_REVEAL_AFTER_MOUNT;
boolean useCustomMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH;
boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE;
String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS;
int filenameLengthLimit = VaultSettings.DEFAULT_FILENAME_LENGTH_LIMIT;
int maxCleartextFilenameLength = VaultSettings.DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH;
WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK;
boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE;
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
in.beginObject();
while (in.hasNext()) {
@@ -64,8 +68,10 @@ class VaultSettingsJsonAdapter {
case "individualMountPath", "customMountPath" -> customMountPath = in.nextString();
case "usesReadOnlyMode" -> usesReadOnlyMode = in.nextBoolean();
case "mountFlags" -> mountFlags = in.nextString();
case "filenameLengthLimit" -> filenameLengthLimit = in.nextInt();
case "maxCleartextFilenameLength" -> maxCleartextFilenameLength = in.nextInt();
case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString());
case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean();
case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt();
default -> {
LOG.warn("Unsupported vault setting found in JSON: " + name);
in.skipValue();
@@ -88,8 +94,10 @@ class VaultSettingsJsonAdapter {
vaultSettings.customMountPath().set(customMountPath);
vaultSettings.usesReadOnlyMode().set(usesReadOnlyMode);
vaultSettings.mountFlags().set(mountFlags);
vaultSettings.filenameLengthLimit().set(filenameLengthLimit);
vaultSettings.maxCleartextFilenameLength().set(maxCleartextFilenameLength);
vaultSettings.actionAfterUnlock().set(actionAfterUnlock);
vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle);
vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds);
return vaultSettings;
}

View File

@@ -0,0 +1,60 @@
package org.cryptomator.common.vaults;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.collections.ObservableList;
import java.time.Instant;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Singleton
public class AutoLocker {
private static final Logger LOG = LoggerFactory.getLogger(AutoLocker.class);
private final ScheduledExecutorService scheduler;
private final ObservableList<Vault> vaultList;
@Inject
public AutoLocker(ScheduledExecutorService scheduler, ObservableList<Vault> vaultList) {
this.scheduler = scheduler;
this.vaultList = vaultList;
}
public void init() {
scheduler.scheduleAtFixedRate(this::tick, 0, 1, TimeUnit.MINUTES);
}
private void tick() {
vaultList.stream() // all vaults
.filter(Vault::isUnlocked) // unlocked vaults
.filter(this::exceedsIdleTime) // idle vaults
.forEach(this::autolock);
}
private void autolock(Vault vault) {
try {
vault.lock(false);
LOG.info("Autolocked {} after idle timeout", vault.getDisplayName());
} catch (Volume.VolumeException | LockNotCompletedException e) {
LOG.error("Autolocking failed.", e);
}
}
private boolean exceedsIdleTime(Vault vault) {
assert vault.isUnlocked();
// TODO: shouldn't we read these properties from within FX Application Thread?
if (vault.getVaultSettings().autoLockWhenIdle().get()) {
int maxIdleSeconds = vault.getVaultSettings().autoLockIdleSeconds().get();
var deadline = vault.getStats().getLastActivity().plusSeconds(maxIdleSeconds);
return deadline.isBefore(Instant.now());
} else {
return false;
}
}
}

View File

@@ -5,15 +5,15 @@ import org.cryptomator.common.mountpoint.MountPointChooser;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.settings.VolumeImpl;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.frontend.dokany.DokanyMountFailedException;
import org.cryptomator.frontend.dokany.Mount;
import org.cryptomator.frontend.dokany.MountFactory;
import org.cryptomator.frontend.dokany.MountFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
public class DokanyVolume extends AbstractVolume {
@@ -22,15 +22,13 @@ public class DokanyVolume extends AbstractVolume {
private static final String FS_TYPE_NAME = "CryptomatorFS";
private final VaultSettings vaultSettings;
private final MountFactory mountFactory;
private Mount mount;
@Inject
public DokanyVolume(VaultSettings vaultSettings, ExecutorService executorService, @Named("orderedMountPointChoosers") Iterable<MountPointChooser> choosers) {
public DokanyVolume(VaultSettings vaultSettings, @Named("orderedMountPointChoosers") Iterable<MountPointChooser> choosers) {
super(choosers);
this.vaultSettings = vaultSettings;
this.mountFactory = new MountFactory(executorService);
}
@Override
@@ -39,11 +37,11 @@ public class DokanyVolume extends AbstractVolume {
}
@Override
public void mount(CryptoFileSystem fs, String mountFlags) throws InvalidMountPointException, VolumeException {
public void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws InvalidMountPointException, VolumeException {
this.mountPoint = determineMountPoint();
try {
this.mount = mountFactory.mount(fs.getPath("/"), mountPoint, vaultSettings.mountName().get(), FS_TYPE_NAME, mountFlags.strip());
} catch (MountFailedException e) {
this.mount = MountFactory.mount(fs.getPath("/"), mountPoint, vaultSettings.mountName().get(), FS_TYPE_NAME, mountFlags.strip(), onExitAction);
} catch (DokanyMountFailedException e) {
if (vaultSettings.getCustomMountPath().isPresent()) {
LOG.warn("Failed to mount vault into {}. Is this directory currently accessed by another process (e.g. Windows Explorer)?", mountPoint);
}

View File

@@ -6,8 +6,8 @@ import org.cryptomator.common.mountpoint.InvalidMountPointException;
import org.cryptomator.common.mountpoint.MountPointChooser;
import org.cryptomator.common.settings.VolumeImpl;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.frontend.fuse.mount.CommandFailedException;
import org.cryptomator.frontend.fuse.mount.EnvironmentVariables;
import org.cryptomator.frontend.fuse.mount.FuseMountException;
import org.cryptomator.frontend.fuse.mount.FuseMountFactory;
import org.cryptomator.frontend.fuse.mount.FuseNotSupportedException;
import org.cryptomator.frontend.fuse.mount.Mount;
@@ -20,6 +20,7 @@ import javax.inject.Named;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Pattern;
public class FuseVolume extends AbstractVolume {
@@ -35,20 +36,21 @@ public class FuseVolume extends AbstractVolume {
}
@Override
public void mount(CryptoFileSystem fs, String mountFlags) throws InvalidMountPointException, VolumeException {
public void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws InvalidMountPointException, VolumeException {
this.mountPoint = determineMountPoint();
mount(fs.getPath("/"), mountFlags);
mount(fs.getPath("/"), mountFlags, onExitAction);
}
private void mount(Path root, String mountFlags) throws VolumeException {
private void mount(Path root, String mountFlags, Consumer<Throwable> onExitAction) throws VolumeException {
try {
Mounter mounter = FuseMountFactory.getMounter();
EnvironmentVariables envVars = EnvironmentVariables.create() //
.withFlags(splitFlags(mountFlags)).withMountPoint(mountPoint) //
.withFlags(splitFlags(mountFlags)) //
.withMountPoint(mountPoint) //
.withFileNameTranscoder(mounter.defaultFileNameTranscoder()) //
.build();
this.mount = mounter.mount(root, envVars);
} catch (CommandFailedException | FuseNotSupportedException e) {
this.mount = mounter.mount(root, envVars, onExitAction);
} catch ( FuseMountException | FuseNotSupportedException e) {
throw new VolumeException("Unable to mount Filesystem", e);
}
}
@@ -89,8 +91,7 @@ public class FuseVolume extends AbstractVolume {
public synchronized void unmountForced() throws VolumeException {
try {
mount.unmountForced();
mount.close();
} catch (CommandFailedException e) {
} catch (FuseMountException e) {
throw new VolumeException(e);
}
cleanupMountPoint();
@@ -100,8 +101,7 @@ public class FuseVolume extends AbstractVolume {
public synchronized void unmount() throws VolumeException {
try {
mount.unmount();
mount.close();
} catch (CommandFailedException e) {
} catch (FuseMountException e) {
throw new VolumeException(e);
}
cleanupMountPoint();

View File

@@ -0,0 +1,12 @@
package org.cryptomator.common.vaults;
public class LockNotCompletedException extends Exception {
public LockNotCompletedException(String reason) {
super(reason);
}
public LockNotCompletedException(Throwable cause) {
super(cause);
}
}

View File

@@ -17,10 +17,12 @@ import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.common.Constants;
import org.cryptomator.cryptofs.VaultConfig;
import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig;
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.cryptolib.api.MasterkeyLoader;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,28 +37,29 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
@PerVault
public class Vault {
private static final Logger LOG = LoggerFactory.getLogger(Vault.class);
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
private static final int UNLIMITED_FILENAME_LENGTH = Integer.MAX_VALUE;
private final VaultSettings vaultSettings;
private final Provider<Volume> volumeProvider;
private final StringBinding defaultMountFlags;
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final ObjectProperty<VaultState> state;
private final VaultState state;
private final ObjectProperty<Exception> lastKnownException;
private final VaultStats stats;
private final StringBinding displayName;
@@ -74,7 +77,7 @@ public class Vault {
private volatile Volume volume;
@Inject
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, ObjectProperty<VaultState> state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
this.vaultSettings = vaultSettings;
this.volumeProvider = volumeProvider;
this.defaultMountFlags = defaultMountFlags;
@@ -99,24 +102,31 @@ public class Vault {
// Commands
// ********************************************************************************/
private CryptoFileSystem createCryptoFileSystem(CharSequence passphrase) throws NoSuchFileException, IOException, InvalidPassphraseException, CryptoException {
private CryptoFileSystem createCryptoFileSystem(MasterkeyLoader keyLoader) throws IOException, MasterkeyLoadingFailedException {
Set<FileSystemFlags> flags = EnumSet.noneOf(FileSystemFlags.class);
if (vaultSettings.usesReadOnlyMode().get()) {
flags.add(FileSystemFlags.READONLY);
} else if(vaultSettings.maxCleartextFilenameLength().get() == -1) {
LOG.debug("Determining cleartext filename length limitations...");
var checker = new FileSystemCapabilityChecker();
int shorteningThreshold = getUnverifiedVaultConfig().allegedShorteningThreshold();
int ciphertextLimit = checker.determineSupportedCiphertextFileNameLength(getPath());
if (ciphertextLimit < shorteningThreshold) {
int cleartextLimit = checker.determineSupportedCleartextFileNameLength(getPath());
vaultSettings.maxCleartextFilenameLength().set(cleartextLimit);
} else {
vaultSettings.maxCleartextFilenameLength().setValue(UNLIMITED_FILENAME_LENGTH);
}
}
if (!flags.contains(FileSystemFlags.READONLY) && vaultSettings.filenameLengthLimit().get() == -1) {
LOG.debug("Determining file name length limitations...");
int limit = new FileSystemCapabilityChecker().determineSupportedFileNameLength(getPath());
vaultSettings.filenameLengthLimit().set(limit);
LOG.info("Storing file name length limit of {}", limit);
if (vaultSettings.maxCleartextFilenameLength().get() < UNLIMITED_FILENAME_LENGTH) {
LOG.warn("Limiting cleartext filename length on this device to {}.", vaultSettings.maxCleartextFilenameLength().get());
}
assert vaultSettings.filenameLengthLimit().get() > 0;
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() //
.withPassphrase(passphrase) //
.withKeyLoader(keyLoader) //
.withFlags(flags) //
.withMasterkeyFilename(MASTERKEY_FILENAME) //
.withMaxPathLength(vaultSettings.filenameLengthLimit().get() + Constants.MAX_ADDITIONAL_PATH_LENGTH) //
.withMaxNameLength(vaultSettings.filenameLengthLimit().get()) //
.withMaxCleartextNameLength(vaultSettings.maxCleartextFilenameLength().get()) //
.build();
return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
}
@@ -133,29 +143,51 @@ public class Vault {
}
}
public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException, VolumeException, InvalidMountPointException {
if (cryptoFileSystem.get() == null) {
CryptoFileSystem fs = createCryptoFileSystem(passphrase);
cryptoFileSystem.set(fs);
try {
volume = volumeProvider.get();
volume.mount(fs, getEffectiveMountFlags());
} catch (Exception e) {
destroyCryptoFileSystem();
throw e;
}
} else {
public synchronized void unlock(MasterkeyLoader keyLoader) throws CryptoException, IOException, VolumeException, InvalidMountPointException {
if (cryptoFileSystem.get() != null) {
throw new IllegalStateException("Already unlocked.");
}
CryptoFileSystem fs = createCryptoFileSystem(keyLoader);
boolean success = false;
try {
cryptoFileSystem.set(fs);
volume = volumeProvider.get();
volume.mount(fs, getEffectiveMountFlags(), this::lockOnVolumeExit);
success = true;
} finally {
if (!success) {
destroyCryptoFileSystem();
}
}
}
public synchronized void lock(boolean forced) throws VolumeException {
private void lockOnVolumeExit(Throwable t) {
LOG.info("Unmounted vault '{}'", getDisplayName());
destroyCryptoFileSystem();
state.set(VaultState.Value.LOCKED);
if (t != null) {
LOG.warn("Unexpected unmount and lock of vault " + getDisplayName(), t);
}
}
public synchronized void lock(boolean forced) throws VolumeException, LockNotCompletedException {
//initiate unmount
if (forced && volume.supportsForcedUnmount()) {
volume.unmountForced();
} else {
volume.unmount();
}
destroyCryptoFileSystem();
//wait for lockOnVolumeExit to be executed
try {
boolean locked = state.awaitState(VaultState.Value.LOCKED, 3000, TimeUnit.MILLISECONDS);
if (!locked) {
throw new LockNotCompletedException("Locking of vault " + this.getDisplayName() + " still in progress.");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new LockNotCompletedException(e);
}
}
public void reveal(Volume.Revealer vaultRevealer) throws VolumeException {
@@ -166,16 +198,12 @@ public class Vault {
// Observable Properties
// *******************************************************************************
public ObjectProperty<VaultState> stateProperty() {
public VaultState stateProperty() {
return state;
}
public VaultState getState() {
return state.get();
}
public void setState(VaultState value) {
state.setValue(value);
public VaultState.Value getState() {
return state.getValue();
}
public ObjectProperty<Exception> lastKnownExceptionProperty() {
@@ -195,7 +223,7 @@ public class Vault {
}
public boolean isLocked() {
return state.get() == VaultState.LOCKED;
return state.get() == VaultState.Value.LOCKED;
}
public BooleanBinding processingProperty() {
@@ -203,7 +231,7 @@ public class Vault {
}
public boolean isProcessing() {
return state.get() == VaultState.PROCESSING;
return state.get() == VaultState.Value.PROCESSING;
}
public BooleanBinding unlockedProperty() {
@@ -211,7 +239,7 @@ public class Vault {
}
public boolean isUnlocked() {
return state.get() == VaultState.UNLOCKED;
return state.get() == VaultState.Value.UNLOCKED;
}
public BooleanBinding missingProperty() {
@@ -219,7 +247,7 @@ public class Vault {
}
public boolean isMissing() {
return state.get() == VaultState.MISSING;
return state.get() == VaultState.Value.MISSING;
}
public BooleanBinding needsMigrationProperty() {
@@ -227,7 +255,7 @@ public class Vault {
}
public boolean isNeedsMigration() {
return state.get() == VaultState.NEEDS_MIGRATION;
return state.get() == VaultState.Value.NEEDS_MIGRATION;
}
public BooleanBinding unknownErrorProperty() {
@@ -235,7 +263,7 @@ public class Vault {
}
public boolean isUnknownError() {
return state.get() == VaultState.ERROR;
return state.get() == VaultState.Value.ERROR;
}
public StringBinding displayNameProperty() {
@@ -251,7 +279,7 @@ public class Vault {
}
public String getAccessPoint() {
if (state.get() == VaultState.UNLOCKED) {
if (state.getValue() == VaultState.Value.UNLOCKED) {
assert volume != null;
return volume.getMountPoint().orElse(Path.of("")).toString();
} else {
@@ -299,6 +327,12 @@ public class Vault {
return stats;
}
public UnverifiedVaultConfig getUnverifiedVaultConfig() throws IOException {
Path configPath = getPath().resolve(org.cryptomator.common.Constants.VAULTCONFIG_FILENAME);
String token = Files.readString(configPath, StandardCharsets.US_ASCII);
return VaultConfig.decode(token);
}
public Observable[] observables() {
return new Observable[]{state};
}
@@ -355,8 +389,7 @@ public class Vault {
@Override
public boolean equals(Object obj) {
if (obj instanceof Vault && obj.getClass().equals(this.getClass())) {
final Vault other = (Vault) obj;
if (obj instanceof Vault other && obj.getClass().equals(this.getClass())) {
return Objects.equals(this.vaultSettings, other.vaultSettings);
} else {
return false;

View File

@@ -26,7 +26,7 @@ public interface VaultComponent {
Builder vaultSettings(VaultSettings vaultSettings);
@BindsInstance
Builder initialVaultState(VaultState vaultState);
Builder initialVaultState(VaultState.Value vaultState);
@BindsInstance
Builder initialErrorCause(@Nullable @Named("lastKnownException") Exception initialErrorCause);

View File

@@ -22,10 +22,10 @@ class VaultListChangeListener implements ListChangeListener<Vault> {
public void onChanged(Change<? extends Vault> c) {
while (c.next()) {
if (c.wasAdded()) {
List<VaultSettings> addedSettings = c.getAddedSubList().stream().map(Vault::getVaultSettings).collect(Collectors.toList());
List<VaultSettings> addedSettings = c.getAddedSubList().stream().map(Vault::getVaultSettings).toList();
vaultSettingsList.addAll(c.getFrom(), addedSettings);
} else if (c.wasRemoved()) {
List<VaultSettings> removedSettings = c.getRemoved().stream().map(Vault::getVaultSettings).collect(Collectors.toList());
List<VaultSettings> removedSettings = c.getRemoved().stream().map(Vault::getVaultSettings).toList();
vaultSettingsList.removeAll(removedSettings);
}
}

View File

@@ -11,6 +11,7 @@ package org.cryptomator.common.vaults;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.cryptofs.migration.Migrators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,51 +21,51 @@ import javax.inject.Singleton;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
@Singleton
public class VaultListManager {
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
private final AutoLocker autoLocker;
private final VaultComponent.Builder vaultComponentBuilder;
private final ObservableList<Vault> vaultList;
private final String defaultVaultName;
@Inject
public VaultListManager(VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) {
public VaultListManager(ObservableList<Vault> vaultList, AutoLocker autoLocker, VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) {
this.vaultList = vaultList;
this.autoLocker = autoLocker;
this.vaultComponentBuilder = vaultComponentBuilder;
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
this.vaultList = FXCollections.observableArrayList(Vault::observables);
addAll(settings.getDirectories());
vaultList.addListener(new VaultListChangeListener(settings.getDirectories()));
autoLocker.init();
}
public ObservableList<Vault> getVaultList() {
return vaultList;
}
public Vault add(Path pathToVault) throws NoSuchFileException {
public Vault add(Path pathToVault) throws IOException {
Path normalizedPathToVault = pathToVault.normalize().toAbsolutePath();
if (!CryptoFileSystemProvider.containsVault(normalizedPathToVault, MASTERKEY_FILENAME)) {
if (CryptoFileSystemProvider.checkDirStructureForVault(normalizedPathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) == DirStructure.UNRELATED) {
throw new NoSuchFileException(normalizedPathToVault.toString(), null, "Not a vault directory");
}
Optional<Vault> alreadyExistingVault = get(normalizedPathToVault);
if (alreadyExistingVault.isPresent()) {
return alreadyExistingVault.get();
} else {
Vault newVault = create(newVaultSettings(normalizedPathToVault));
vaultList.add(newVault);
return newVault;
}
return get(normalizedPathToVault) //
.orElseGet(() -> {
Vault newVault = create(newVaultSettings(normalizedPathToVault));
vaultList.add(newVault);
return newVault;
});
}
private VaultSettings newVaultSettings(Path path) {
@@ -79,7 +80,7 @@ public class VaultListManager {
}
private void addAll(Collection<VaultSettings> vaultSettings) {
Collection<Vault> vaults = vaultSettings.stream().map(this::create).collect(Collectors.toList());
Collection<Vault> vaults = vaultSettings.stream().map(this::create).toList();
vaultList.addAll(vaults);
}
@@ -94,43 +95,45 @@ public class VaultListManager {
private Vault create(VaultSettings vaultSettings) {
VaultComponent.Builder compBuilder = vaultComponentBuilder.vaultSettings(vaultSettings);
try {
VaultState vaultState = determineVaultState(vaultSettings.path().get());
VaultState.Value vaultState = determineVaultState(vaultSettings.path().get());
compBuilder.initialVaultState(vaultState);
} catch (IOException e) {
LOG.warn("Failed to determine vault state for " + vaultSettings.path().get(), e);
compBuilder.initialVaultState(VaultState.ERROR);
compBuilder.initialVaultState(ERROR);
compBuilder.initialErrorCause(e);
}
return compBuilder.build().vault();
}
public static VaultState redetermineVaultState(Vault vault) {
VaultState previousState = vault.getState();
public static VaultState.Value redetermineVaultState(Vault vault) {
VaultState state = vault.stateProperty();
VaultState.Value previousState = state.getValue();
return switch (previousState) {
case LOCKED, NEEDS_MIGRATION, MISSING -> {
try {
VaultState determinedState = determineVaultState(vault.getPath());
vault.setState(determinedState);
var determinedState = determineVaultState(vault.getPath());
state.set(determinedState);
yield determinedState;
} catch (IOException e) {
LOG.warn("Failed to determine vault state for " + vault.getPath(), e);
vault.setState(VaultState.ERROR);
state.set(ERROR);
vault.setLastKnownException(e);
yield VaultState.ERROR;
yield ERROR;
}
}
case ERROR, UNLOCKED, PROCESSING -> previousState;
};
}
private static VaultState determineVaultState(Path pathToVault) throws IOException {
if (!CryptoFileSystemProvider.containsVault(pathToVault, MASTERKEY_FILENAME)) {
return VaultState.MISSING;
} else if (Migrators.get().needsMigration(pathToVault, MASTERKEY_FILENAME)) {
return VaultState.NEEDS_MIGRATION;
} else {
return VaultState.LOCKED;
private static VaultState.Value determineVaultState(Path pathToVault) throws IOException {
if (!Files.exists(pathToVault)) {
return VaultState.Value.MISSING;
}
return switch (CryptoFileSystemProvider.checkDirStructureForVault(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME)) {
case VAULT -> VaultState.Value.LOCKED;
case UNRELATED -> VaultState.Value.MISSING;
case MAYBE_LEGACY -> Migrators.get().needsMigration(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) ? VaultState.Value.NEEDS_MIGRATION : VaultState.Value.MISSING;
};
}
}

View File

@@ -0,0 +1,19 @@
package org.cryptomator.common.vaults;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@Module
public class VaultListModule {
@Provides
@Singleton
public ObservableList<Vault> provideVaultList() {
return FXCollections.observableArrayList(Vault::observables);
}
}

View File

@@ -40,12 +40,6 @@ public class VaultModule {
return new AtomicReference<>();
}
@Provides
@PerVault
public ObjectProperty<VaultState> provideVaultState(VaultState initialState) {
return new SimpleObjectProperty<>(initialState);
}
@Provides
@Named("lastKnownException")
@PerVault
@@ -53,7 +47,6 @@ public class VaultModule {
return new SimpleObjectProperty<>(initialErrorCause);
}
@Provides
public Volume provideVolume(Settings settings, WebDavVolume webDavVolume, FuseVolume fuseVolume, DokanyVolume dokanyVolume) {
VolumeImpl preferredImpl = settings.preferredVolumeImpl().get();
@@ -105,7 +98,6 @@ public class VaultModule {
flags.append(" -oatomic_o_trunc");
flags.append(" -oauto_xattr");
flags.append(" -oauto_cache");
flags.append(" -omodules=iconv,from_code=UTF-8,to_code=UTF-8-MAC"); // show files names in Unicode NFD encoding
flags.append(" -onoappledouble"); // vastly impacts performance for some reason...
flags.append(" -odefault_permissions"); // let the kernel assume permissions based on file attributes etc
@@ -146,7 +138,7 @@ public class VaultModule {
// see https://github.com/billziss-gh/winfsp/blob/5d0b10d0b643652c00ebb4704dc2bb28e7244973/src/dll/fuse/fuse_main.c#L53-L62 for syntax guide
// see https://github.com/billziss-gh/winfsp/blob/5d0b10d0b643652c00ebb4704dc2bb28e7244973/src/dll/fuse/fuse.c#L295-L319 for options (-o <...>)
// see https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions/5ba00e4be4f5e938eaae6ef1500b331de12dee77 (FUSE 4.) on why the given defaults were choosen
// see https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions/5ba00e4be4f5e938eaae6ef1500b331de12dee77 (FUSE 4.) on why the given defaults were chosen
private String getWindowsFuseDefaultMountFlags(StringBinding mountName, ReadOnlyBooleanProperty readOnly) {
assert SystemUtils.IS_OS_WINDOWS;
StringBuilder flags = new StringBuilder();

View File

@@ -0,0 +1,141 @@
package org.cryptomator.common.vaults;
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.beans.value.ObservableObjectValue;
import javafx.beans.value.ObservableValueBase;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@PerVault
public class VaultState extends ObservableValueBase<VaultState.Value> implements ObservableObjectValue<VaultState.Value> {
private static final Logger LOG = LoggerFactory.getLogger(VaultState.class);
public enum Value {
/**
* No vault found at the provided path
*/
MISSING,
/**
* Vault requires migration to a newer vault format
*/
NEEDS_MIGRATION,
/**
* Vault ready to be unlocked
*/
LOCKED,
/**
* Vault in transition between two other states
*/
PROCESSING,
/**
* Vault is unlocked
*/
UNLOCKED,
/**
* Unknown state due to preceding unrecoverable exceptions.
*/
ERROR;
}
private final AtomicReference<Value> value;
private final Lock lock = new ReentrantLock();
private final Condition valueChanged = lock.newCondition();
@Inject
public VaultState(VaultState.Value initialValue) {
this.value = new AtomicReference<>(initialValue);
}
@Override
public Value get() {
return getValue();
}
@Override
public Value getValue() {
return value.get();
}
/**
* Transitions from <code>fromState</code> to <code>toState</code>.
*
* @param fromState Previous state
* @param toState New state
* @return <code>true</code> if successful
*/
public boolean transition(Value fromState, Value toState) {
Preconditions.checkArgument(fromState != toState, "fromState must be different than toState");
boolean success = value.compareAndSet(fromState, toState);
if (success) {
fireValueChangedEvent();
} else {
LOG.debug("Failed transiting into state {}: Expected state was not{}.", fromState, toState);
}
return success;
}
public void set(Value newState) {
var oldState = value.getAndSet(newState);
if (oldState != newState) {
fireValueChangedEvent();
}
}
/**
* Waits for the specified time, until the desired state is reached.
*
* @param desiredState what state to wait for
* @param time the maximum time to wait
* @param unit the time unit of the {@code time} argument
* @return {@code false} if the waiting time detectably elapsed before reaching {@code desiredState}
* @throws InterruptedException if the current thread is interrupted
*/
public boolean awaitState(Value desiredState, long time, TimeUnit unit) throws InterruptedException {
lock.lock();
try {
long remaining = TimeUnit.NANOSECONDS.convert(time, unit);
while (value.get() != desiredState) {
if (remaining <= 0L) {
return false;
}
remaining = valueChanged.awaitNanos(remaining);
}
return true;
} finally {
lock.unlock();
}
}
private void signal() {
lock.lock();
try {
valueChanged.signalAll();
} finally {
lock.unlock();
}
}
@Override
protected void fireValueChangedEvent() {
signal();
if (Platform.isFxApplicationThread()) {
super.fireValueChangedEvent();
} else {
Platform.runLater(super::fireValueChangedEvent);
}
}
}

View File

@@ -13,9 +13,11 @@ import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
@@ -26,22 +28,23 @@ public class VaultStats {
private static final Logger LOG = LoggerFactory.getLogger(VaultStats.class);
private final AtomicReference<CryptoFileSystem> fs;
private final ObjectProperty<VaultState> state;
private final VaultState state;
private final ScheduledService<Optional<CryptoFileSystemStats>> updateService;
private final LongProperty bytesPerSecondRead = new SimpleLongProperty();
private final LongProperty bytesPerSecondWritten = new SimpleLongProperty();
private final LongProperty bytesPerSecondEncrypted = new SimpleLongProperty();
private final LongProperty bytesPerSecondDecrypted = new SimpleLongProperty();
private final DoubleProperty cacheHitRate = new SimpleDoubleProperty();
private final LongProperty toalBytesRead = new SimpleLongProperty();
private final LongProperty toalBytesWritten = new SimpleLongProperty();
private final LongProperty totalBytesRead = new SimpleLongProperty();
private final LongProperty totalBytesWritten = new SimpleLongProperty();
private final LongProperty totalBytesEncrypted = new SimpleLongProperty();
private final LongProperty totalBytesDecrypted = new SimpleLongProperty();
private final LongProperty filesRead = new SimpleLongProperty();
private final LongProperty filesWritten = new SimpleLongProperty();
private final ObjectProperty<Instant> lastActivity = new SimpleObjectProperty<>();
@Inject
VaultStats(AtomicReference<CryptoFileSystem> fs, ObjectProperty<VaultState> state, ExecutorService executor) {
VaultStats(AtomicReference<CryptoFileSystem> fs, VaultState state, ExecutorService executor) {
this.fs = fs;
this.state = state;
this.updateService = new UpdateStatsService();
@@ -52,13 +55,16 @@ public class VaultStats {
}
private void vaultStateChanged(@SuppressWarnings("unused") Observable observable) {
if (VaultState.UNLOCKED.equals(state.get())) {
if (VaultState.Value.UNLOCKED == state.get()) {
assert fs.get() != null;
LOG.debug("start recording stats");
updateService.restart();
Platform.runLater(() -> {
lastActivity.set(Instant.now());
updateService.restart();
});
} else {
LOG.debug("stop recording stats");
updateService.cancel();
Platform.runLater(() -> updateService.cancel());
}
}
@@ -69,13 +75,19 @@ public class VaultStats {
cacheHitRate.set(stats.map(this::getCacheHitRate).orElse(0.0));
bytesPerSecondDecrypted.set(stats.map(CryptoFileSystemStats::pollBytesDecrypted).orElse(0L));
bytesPerSecondEncrypted.set(stats.map(CryptoFileSystemStats::pollBytesEncrypted).orElse(0L));
toalBytesRead.set(stats.map(CryptoFileSystemStats::pollTotalBytesRead).orElse(0L));
toalBytesWritten.set(stats.map(CryptoFileSystemStats::pollTotalBytesWritten).orElse(0L));
totalBytesRead.set(stats.map(CryptoFileSystemStats::pollTotalBytesRead).orElse(0L));
totalBytesWritten.set(stats.map(CryptoFileSystemStats::pollTotalBytesWritten).orElse(0L));
totalBytesEncrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesEncrypted).orElse(0L));
totalBytesDecrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesDecrypted).orElse(0L));
var oldAccessCount = filesRead.get() + filesWritten.get();
filesRead.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesRead).orElse(0L));
filesWritten.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesWritten).orElse(0L));
var newAccessCount = filesRead.get() + filesWritten.get();
// check for any I/O activity
if (newAccessCount > oldAccessCount) {
lastActivity.set(Instant.now());
}
}
private double getCacheHitRate(CryptoFileSystemStats stats) {
@@ -134,7 +146,7 @@ public class VaultStats {
return bytesPerSecondEncrypted;
}
public long getBytesPerSecondEnrypted() {
public long getBytesPerSecondEncrypted() {
return bytesPerSecondEncrypted.get();
}
@@ -152,13 +164,13 @@ public class VaultStats {
return cacheHitRate.get();
}
public LongProperty toalBytesReadProperty() {return toalBytesRead;}
public LongProperty totalBytesReadProperty() {return totalBytesRead;}
public long getTotalBytesRead() { return toalBytesRead.get();}
public long getTotalBytesRead() { return totalBytesRead.get();}
public LongProperty toalBytesWrittenProperty() {return toalBytesWritten;}
public LongProperty totalBytesWrittenProperty() {return totalBytesWritten;}
public long getTotalBytesWritten() { return toalBytesWritten.get();}
public long getTotalBytesWritten() { return totalBytesWritten.get();}
public LongProperty totalBytesEncryptedProperty() {return totalBytesEncrypted;}
@@ -175,4 +187,12 @@ public class VaultStats {
public LongProperty filesWritten() {return filesWritten;}
public long getFilesWritten() {return filesWritten.get();}
public ObjectProperty<Instant> lastActivityProperty() {
return lastActivity;
}
public Instant getLastActivity() {
return lastActivity.get();
}
}

View File

@@ -7,10 +7,12 @@ import org.cryptomator.cryptofs.CryptoFileSystem;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import java.util.stream.Stream;
/**
* Takes a Volume and usess it to mount an unlocked vault
* Takes a Volume and uses it to mount an unlocked vault
*/
public interface Volume {
@@ -22,7 +24,7 @@ public interface Volume {
boolean isSupported();
/**
* Gets the coresponding enum type of the {@link VolumeImpl volume implementation ("VolumeImpl")} that is implemented by this Volume.
* Gets the corresponding enum type of the {@link VolumeImpl volume implementation ("VolumeImpl")} that is implemented by this Volume.
*
* @return the type of implementation as defined by the {@link VolumeImpl VolumeImpl enum}
*/
@@ -32,7 +34,7 @@ public interface Volume {
* @param fs
* @throws IOException
*/
void mount(CryptoFileSystem fs, String mountFlags) throws IOException, VolumeException, InvalidMountPointException;
void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws IOException, VolumeException, InvalidMountPointException;
/**
* Reveals the mounted volume.

View File

@@ -17,6 +17,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class WebDavVolume implements Volume {
@@ -31,6 +32,7 @@ public class WebDavVolume implements Volume {
private WebDavServer server;
private WebDavServletController servlet;
private Mounter.Mount mount;
private Consumer<Throwable> onExitAction;
@Inject
public WebDavVolume(Provider<WebDavServer> serverProvider, VaultSettings vaultSettings, Settings settings, WindowsDriveLetters windowsDriveLetters) {
@@ -41,12 +43,13 @@ public class WebDavVolume implements Volume {
}
@Override
public void mount(CryptoFileSystem fs, String mountFlags) throws VolumeException {
public void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws VolumeException {
startServlet(fs);
mountServlet();
this.onExitAction = onExitAction;
}
private void startServlet(CryptoFileSystem fs){
private void startServlet(CryptoFileSystem fs) {
if (server == null) {
server = serverProvider.get();
}
@@ -64,9 +67,9 @@ public class WebDavVolume implements Volume {
throw new IllegalStateException("Mounting requires unlocked WebDAV servlet.");
}
//on windows, prevent an automatic drive letter selection in the upstream library. Either we choose already a specifc one or there is no free.
//on windows, prevent an automatic drive letter selection in the upstream library. Either we choose already a specific one or there is no free.
Supplier<String> driveLetterSupplier;
if(System.getProperty("os.name").toLowerCase().contains("windows") && vaultSettings.winDriveLetter().isEmpty().get()) {
if (System.getProperty("os.name").toLowerCase().contains("windows") && vaultSettings.winDriveLetter().isEmpty().get()) {
driveLetterSupplier = () -> windowsDriveLetters.getAvailableDriveLetter().orElse(null);
} else {
driveLetterSupplier = () -> vaultSettings.winDriveLetter().get();
@@ -101,6 +104,7 @@ public class WebDavVolume implements Volume {
throw new VolumeException(e);
}
cleanup();
onExitAction.accept(null);
}
@Override
@@ -111,6 +115,7 @@ public class WebDavVolume implements Volume {
throw new VolumeException(e);
}
cleanup();
onExitAction.accept(null);
}
@Override

View File

@@ -41,7 +41,7 @@ class FileOpenRequestHandler {
}
private void openFiles(OpenFilesEvent evt) {
Collection<Path> pathsToOpen = evt.getFiles().stream().map(File::toPath).collect(Collectors.toList());
Collection<Path> pathsToOpen = evt.getFiles().stream().map(File::toPath).toList();
AppLaunchEvent launchEvent = new AppLaunchEvent(AppLaunchEvent.EventType.OPEN_FILE, pathsToOpen);
tryToEnqueueFileOpenRequest(launchEvent);
}
@@ -59,7 +59,7 @@ class FileOpenRequestHandler {
LOG.trace("Argument not a valid path: {}", str);
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}).filter(Objects::nonNull).toList();
if (!pathsToOpen.isEmpty()) {
AppLaunchEvent launchEvent = new AppLaunchEvent(AppLaunchEvent.EventType.OPEN_FILE, pathsToOpen);
tryToEnqueueFileOpenRequest(launchEvent);

View File

@@ -11,12 +11,12 @@ import java.io.File;
*
* @param <E> Event type the policy possibly reacts to
*/
public class LaunchAndSizeBasedTriggerinPolicy<E> extends TriggeringPolicyBase<E> {
public class LaunchAndSizeBasedTriggeringPolicy<E> extends TriggeringPolicyBase<E> {
LaunchBasedTriggeringPolicy<E> launchBasedTriggeringPolicy;
SizeBasedTriggeringPolicy<E> sizeBasedTriggeringPolicy;
public LaunchAndSizeBasedTriggerinPolicy(FileSize threshold) {
public LaunchAndSizeBasedTriggeringPolicy(FileSize threshold) {
this.launchBasedTriggeringPolicy = new LaunchBasedTriggeringPolicy<>();
this.sizeBasedTriggeringPolicy = new SizeBasedTriggeringPolicy<>();
sizeBasedTriggeringPolicy.setMaxFileSize(threshold);

View File

@@ -47,8 +47,8 @@ public class LoggerModule {
@Singleton
static LoggerContext provideLoggerContext() {
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
if (loggerFactory instanceof LoggerContext) {
return (LoggerContext) loggerFactory;
if (loggerFactory instanceof LoggerContext context) {
return context;
} else {
throw new IllegalStateException("SLF4J not bound to Logback.");
}
@@ -85,7 +85,7 @@ public class LoggerModule {
appender.setContext(context);
appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
appender.setEncoder(encoder);
LaunchAndSizeBasedTriggerinPolicy triggeringPolicy = new LaunchAndSizeBasedTriggerinPolicy(FileSize.valueOf(LOG_MAX_SIZE));
LaunchAndSizeBasedTriggeringPolicy triggeringPolicy = new LaunchAndSizeBasedTriggeringPolicy(FileSize.valueOf(LOG_MAX_SIZE));
triggeringPolicy.setContext(context);
triggeringPolicy.start();
appender.setTriggeringPolicy(triggeringPolicy);

View File

@@ -6,10 +6,10 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.NewPasswordController;
import org.cryptomator.ui.common.PasswordStrengthUtil;
@@ -33,13 +33,6 @@ import java.util.ResourceBundle;
@Module
public abstract class AddVaultModule {
@Provides
@AddVaultWizardScoped
@Named("newPassword")
static ObjectProperty<CharSequence> provideNewPasswordProperty() {
return new SimpleObjectProperty<>("");
}
@Provides
@AddVaultWizardWindow
@AddVaultWizardScoped
@@ -167,8 +160,8 @@ public abstract class AddVaultModule {
@Provides
@IntoMap
@FxControllerKey(NewPasswordController.class)
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, @Named("newPassword") ObjectProperty<CharSequence> password) {
return new NewPasswordController(resourceBundle, strengthRater, password);
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
return new NewPasswordController(resourceBundle, strengthRater);
}
@Binds

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