Compare commits

...

569 Commits

Author SHA1 Message Date
Armin Schrenk
311c490377 Merge branch 'hotfix/1.14.2' 2024-11-19 09:59:27 +01:00
Armin Schrenk
39ed00ff6f Use correct version 2024-11-19 09:57:56 +01:00
Armin Schrenk
28338d2dcf use stable version 2024-11-19 09:50:46 +01:00
Armin Schrenk
e4e757606d update dependencies for patch release
Fixes #3574 and #3499. Closes #3569
2024-11-05 11:11:32 +01:00
Cryptobot
6fcb796177 New Crowdin updates (#3559)
New translations strings.properties

Afrikaans; Arabic; Bashkir; Belarusian; Bengali; Bosnian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian; Czech; Danish; Dutch; English; Filipino; Finnish; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Macedonian; Marathi; Norwegian; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Serbian (Cyrillic); Serbian (Latin); Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Urdu (Pakistan); Uyghur; Vietnamese;

[ci skip]

(cherry picked from commit 0fb0bc8e1d)
2024-11-04 17:59:02 +01:00
Cryptobot
4d6b035c29 New Crowdin updates (#3553)
New translations strings.properties

Afrikaans; English; Norwegian; Thai; Uyghur;

[ci skip]

(cherry picked from commit 2939702842)
2024-11-04 17:57:43 +01:00
Armin Schrenk
d6a020994e Merge branch 'hotfix/1.14.1' 2024-09-18 13:17:25 +02:00
Armin Schrenk
518f75be32 fixes #3538 2024-09-18 13:16:45 +02:00
Armin Schrenk
28c7dbad69 prepare 1.14.1 2024-09-18 13:16:16 +02:00
Armin Schrenk
68bf441fdd Merge branch 'release/1.14.0' 2024-09-17 10:03:02 +02:00
Armin Schrenk
a606bcb81e finalize 1.14.0 2024-09-17 09:59:22 +02:00
Armin Schrenk
fe93e51ffa Merge branch 'develop' into release/1.14.0 2024-09-17 09:51:23 +02:00
Cryptobot
f2949aae63 New Crowdin updates (#3520)
New translations strings.properties

Chinese Simplified; Chinese Traditional; Filipino; German; Punjabi; Romanian; Russian; Slovenian; Turkish; Ukrainian; 

[ci skip]
2024-09-17 09:49:55 +02:00
Armin Schrenk
80e101456b adjust keychainManager to new API 2024-09-16 17:40:49 +02:00
Armin Schrenk
2f311c1dfe use final releases 2024-09-16 17:29:24 +02:00
Tobias Hagemann
8aaee3710a Update README.md 2024-09-10 11:57:03 +02:00
Armin Schrenk
414d81dc06 Update mac-dmg.yml
Switch to macOS-12 due to errors
2024-08-20 18:17:08 +02:00
Armin Schrenk
b450ab028d Update mac-dmg.yml
macos-11 is no more
2024-08-20 17:42:32 +02:00
Armin Schrenk
5a51e53603 Merge branch 'develop' into release/1.14.0 2024-08-20 11:18:22 +02:00
Armin Schrenk
d65beb632d Fixes #3519 2024-08-20 11:10:26 +02:00
Armin Schrenk
2b03477d31 prepare 1.14.0 2024-08-19 16:36:31 +02:00
Cryptobot
f25e23da82 New Crowdin updates (#3463)
New translations strings.properties

Arabic; Chinese Simplified; Chinese Traditional; Dutch; Filipino; French; German; Greek; Italian; Japanese; Korean; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Russian; Slovak; Spanish; Swedish; Turkish; Urdu (Pakistan); 

[ci skip]
2024-08-19 16:33:41 +02:00
dependabot[bot]
82368e2632 Bump the java-production-dependencies group across 1 directory with 9 updates (#3516) 2024-08-19 14:29:15 +00:00
dependabot[bot]
9057090b56 Bump the maven-build-plugins group across 1 directory with 3 updates (#3513) 2024-08-19 14:18:32 +00:00
dependabot[bot]
357937e0bf Bump the java-test-dependencies group across 1 directory with 2 updates (#3514) 2024-08-19 14:17:07 +00:00
Armin Schrenk
f84a2396eb ignore integrations-api 2.0.0-alpha1 2024-08-19 10:42:58 +02:00
dependabot[bot]
193dcad6e8 Bump the javafx group with 5 updates (#3498)
* Bump javafx from 22.0.1 to 22.0.2
* update build scripts to updated jfx version

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2024-08-19 10:34:14 +02:00
Armin Schrenk
257f4427b8 catch all methods of adding a vault for #2880 2024-08-19 10:27:13 +02:00
Armin Schrenk
4778ba0770 add autostart for deb artifact 2024-08-16 15:56:58 +02:00
Armin Schrenk
77b908199e Mitigates #2880 (#3512) 2024-08-16 12:59:38 +02:00
Armin Schrenk
d448c42f87 Feature: JDK 22.0.2+9 for release artifacts (#3510)
* update jdks for release artifacts to jdk 22.02+9
2024-08-14 16:40:44 +02:00
Armin Schrenk
b9403222ba add java.compiler module to build scripts
references 93d0fd41a6 and https://github.com/google/dagger/issues/4321
2024-08-13 16:28:09 +02:00
Armin Schrenk
93d0fd41a6 Update cryptofs to 2.7.0-beta1
Closes #2058
2024-08-13 11:59:23 +02:00
Armin Schrenk
067bd4752c prevent leaking of NVD API key into logs 2024-08-09 11:30:16 +02:00
Armin Schrenk
fb4f9fc68f Update integrations-win and -linux for quickAccess service providers 2024-08-09 11:05:02 +02:00
Armin Schrenk
a20667a156 Merge pull request #3494 from cryptomator/feature/quick-access
Feature: Add unlocked vaults to an quick access area
2024-08-07 16:42:53 +02:00
Armin Schrenk
4d47544244 cleanup 2024-08-07 16:32:30 +02:00
Armin Schrenk
d59f149f7c Load quick access service lazy 2024-08-06 15:17:18 +02:00
Armin Schrenk
028f6e7a02 clean up 2024-08-06 15:08:29 +02:00
Armin Schrenk
71e4f98665 hard code default quickaccess service 2024-08-06 12:26:26 +02:00
Tobias Hagemann
d60ced52fe added codesigning jdk files in build.sh for local macos builds to match mac-dmg.yml ci build 2024-07-30 21:14:32 +02:00
Tobias Hagemann
45c7d2b071 added provisioning profile to mac build process with updated entitlements 2024-07-30 18:48:54 +02:00
Ralph Plawetzki
7a789d2eed Fixes #3501 (PR #3502) 2024-07-30 12:27:16 +02:00
Armin Schrenk
cc1e542146 clean up 2024-07-23 16:50:27 +02:00
Armin Schrenk
e4e84d46b6 hide option, if no quick access service is present 2024-07-23 16:50:15 +02:00
Armin Schrenk
61fc53bf9c rename internal method 2024-07-23 16:39:34 +02:00
Tobias Hagemann
f8386a5a99 Update README.md 2024-07-18 15:09:05 +02:00
Armin Schrenk
da7e89fc72 fix windows build script 2024-07-17 16:35:33 +02:00
Armin Schrenk
6b57a0ad9c add translation 2024-07-17 11:34:29 +02:00
Armin Schrenk
f1eb997804 make quickAccessService togglable & selectable in UI 2024-07-16 17:25:47 +02:00
Armin Schrenk
2fe5180721 cleanup 2024-07-16 17:19:52 +02:00
Armin Schrenk
2fa88490bd update to integrations-api 1.4.0-beta2
* differ between using quick access and actual impl
* rename properties
2024-07-16 13:36:37 +02:00
Jan-Peter Klein
5f5b5a5426 set preferences window min width and height 2024-07-09 13:48:45 +02:00
Jan-Peter Klein
cb054bb4f5 fix update available check in preference tab selection 2024-07-09 13:46:41 +02:00
dependabot[bot]
b4f9bc62ca Bump the maven-build-plugins group across 1 directory with 3 updates (#3484) 2024-07-08 07:52:56 +00:00
Tobias Hagemann
34bface2d7 Merge pull request #3481 from purejava/fix-#3480 2024-07-07 16:40:40 +02:00
Ralph Plawetzki
70e52b1a31 Fix typo
Closes #3480
2024-07-07 15:41:28 +02:00
Tobias Hagemann
59a2398c4c Update README.md 2024-07-04 11:49:37 +02:00
Armin Schrenk
e5003c1783 use quick access service in unlock/lock 2024-06-27 17:47:05 +02:00
Armin Schrenk
d6fd012f71 fix av whitelisting step in win-exe workflow 2024-06-26 13:28:37 +02:00
Armin Schrenk
d9d8c84230 adjust formatting of metainfo file 2024-06-26 13:23:38 +02:00
Julian Raufelder
1ad2cc3ee5 Update to JDK 22 2024-06-26 11:57:17 +02:00
Armin Schrenk
2eac09f6be [ci skip] Merge branch 'main' into develop 2024-06-26 10:29:47 +02:00
Armin Schrenk
4114ea6163 Merge branch 'release/1.13.0' 2024-06-26 10:29:15 +02:00
Armin Schrenk
82da9f7a88 finalize release 2024-06-26 10:27:29 +02:00
Armin Schrenk
aa08046c4d Merge branch 'develop' into release/1.13.0 2024-06-21 15:18:39 +02:00
Armin Schrenk
b6d7f63470 [ci skip] also sign binaries from CraC project (dammn zulu jdk) 2024-06-21 15:10:47 +02:00
Armin Schrenk
624d18238c Merge branch 'develop' into release/1.13.0 2024-06-21 14:38:38 +02:00
Armin Schrenk
3bfe2b7a9e fix Windows build 2024-06-21 14:38:17 +02:00
Armin Schrenk
ba79cd0f8c prepare 1.13.0 2024-06-21 11:55:54 +02:00
Armin Schrenk
be63ea1104 Closes #3439 2024-06-21 11:51:49 +02:00
Cryptobot
a3ad2a5677 New Crowdin updates (#3355)
New translations strings.properties

Arabic; Bashkir; Belarusian; Bengali; Bosnian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian; Czech; Danish; Dutch; Filipino; Finnish; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Macedonian; Marathi; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Serbian (Cyrillic); Serbian (Latin); Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Vietnamese; 

[ci skip]
2024-06-21 11:29:09 +02:00
dependabot[bot]
26e5ceea01 Bump the maven-build-plugins group with 2 updates (#3459) 2024-06-21 08:20:05 +00:00
dependabot[bot]
83f1c4ea41 Bump org.mockito:mockito-core in the java-test-dependencies group (#3427) 2024-06-21 08:19:43 +00:00
Armin Schrenk
8d78e1432a Merge pull request #3454 from cryptomator/feature/jfx22
Feature: Update to jfx22
2024-06-20 14:43:15 +02:00
mindmonk
d2ec5a5646 Merge pull request #3457 from cryptomator/feature/dokany-info-dialog
Feature: Migrate volume type Dokany to Default one and Display Info Dialog
2024-06-17 12:20:39 +02:00
Jan-Peter Klein
6bb0328799 removed dialog in naming 2024-06-14 14:20:18 +02:00
Jan-Peter Klein
8a8617b480 renamed method and code refactored 2024-06-14 11:07:21 +02:00
Jan-Peter Klein
7484744038 minor text change 2024-06-13 12:06:38 +02:00
Jan-Peter Klein
0bbc4ecae5 refactored code and new method handleDokanySupportEndAndShowDialog 2024-06-13 12:06:18 +02:00
Jan-Peter Klein
9fcb166047 close dialog by click on 'Open Preferences' 2024-06-13 12:04:34 +02:00
Jan-Peter Klein
1ac017e3ab changed dialog prefix 2024-06-13 11:51:01 +02:00
Jan-Peter Klein
1ba401b8e6 changed wording of button and description
primary color for icon
2024-06-12 12:02:40 +02:00
Armin Schrenk
07303b58f7 Merge branch 'develop' into feature/jfx22 2024-06-12 11:16:41 +02:00
Armin Schrenk
32a463768c Merge pull request #3456 from purejava/fix-#3453
Workaround for malformed javafx POM. Closes #3453.
2024-06-12 11:14:52 +02:00
Armin Schrenk
2307950e3b add javafx.platform property workaround to other build/ci scripts 2024-06-12 10:58:49 +02:00
Ralph Plawetzki
8108128c22 Temporary work around for JavaFX upstream bug
Occurs with Maven 3.9.7, fixed with Gluon JavaFX 23-ea+20, that contains a fixed parent POM
See https://mail.openjdk.org/pipermail/openjfx-dev/2024-May/047279.html
2024-06-11 19:59:18 +02:00
Jan-Peter Klein
58fe6da7a8 Merge branch 'develop' into feature/dokany-info-dialog 2024-06-11 15:25:23 +02:00
Jan-Peter Klein
92bf73297a add dokany info dialog 2024-06-11 14:43:56 +02:00
Armin Schrenk
0bf8fb39dd Update to javafx 22.0.1 2024-06-07 15:39:42 +02:00
Armin Schrenk
0dc9a3a834 align local build scripts 2024-06-07 14:56:54 +02:00
Armin Schrenk
91d6264b9f ignore downloaded artifact 2024-06-06 12:10:03 +02:00
Armin Schrenk
d2599ea525 closes #2656 2024-06-06 12:07:18 +02:00
dependabot[bot]
7180af9bc7 Bump the java-production-dependencies group across 1 directory with 9 updates (#3446) 2024-06-03 10:30:50 +00:00
Armin Schrenk
dc993dc57c fixes #3440 (PR in #3447) 2024-06-03 12:29:54 +02:00
dependabot[bot]
464c74ab6c Bump the maven-build-plugins group across 1 directory with 2 updates (#3431) 2024-06-03 09:39:36 +00:00
Armin Schrenk
8c7dd8c74f Merge pull request #3435 from cryptomator/feature/jdk22
Feature: JDK22
2024-05-21 16:58:57 +02:00
Armin Schrenk
69bcf6fac6 do not forget to update debian files
(dammn you unflexible launchpad!)
2024-05-21 12:51:01 +02:00
Armin Schrenk
7c243dd434 pin cryptolib version due removed jdk.crypto.ec package 2024-05-16 17:51:04 +02:00
Armin Schrenk
357a0b9c31 closes #3376 2024-05-14 17:58:21 +02:00
Armin Schrenk
d69d11b82f update dependencies requiring JDK 22 2024-05-14 17:25:56 +02:00
mindmonk
863e9bbcb3 Merge pull request #3362 from cryptomator/feature/update-checker-refactoring
Feature: Expansion of Preferences Update Tab with UI Elements and Refactoring of UpdateChecker
2024-05-10 16:31:26 +02:00
Jan-Peter Klein
1c47012033 undo getter changes 2024-05-10 15:57:04 +02:00
Jan-Peter Klein
cd99eaa323 updateAvailable ObservableValue to BooleanBinding 2024-05-10 15:51:41 +02:00
Jan-Peter Klein
dda2afda92 refactored ObservableValues to BooleanBindings and code cleanup 2024-05-10 15:45:17 +02:00
Jan-Peter Klein
5519eefcfa cr related changes 2024-05-10 14:55:50 +02:00
Jan-Peter Klein
a81352800d removed twoWeeksAgo var 2024-05-08 11:38:23 +02:00
Jan-Peter Klein
6fec16e498 removed unused ui function 2024-05-08 10:57:42 +02:00
Jan-Peter Klein
42f31204a3 removed lastUpdateReminder setting 2024-05-08 09:41:58 +02:00
Jan-Peter Klein
7ab64cfe46 removed lastUpdateReminder setting 2024-05-08 09:05:26 +02:00
Jan-Peter Klein
1581a10c04 removed unused label id 2024-05-08 08:30:06 +02:00
Jan-Peter Klein
249becc25d removed unused instance var 2024-05-08 08:28:53 +02:00
Jan-Peter Klein
da8e84f39d removed unnecessary HBox 2024-05-07 13:27:52 +02:00
Jan-Peter Klein
9ad2d223c3 changed BooleanBinding updateAvailable to ObservableValue<Boolean> 2024-05-07 13:23:53 +02:00
Jan-Peter Klein
3bf1e659ef changed checkFailed text wording 2024-05-07 12:41:39 +02:00
Jan-Peter Klein
e79257e5ea changed checkFailed property to ObservableValue 2024-05-06 13:46:49 +02:00
Armin Schrenk
dac517a6fb update project ot jdk 22
Note: dependency bumps regarding jdk22 compatiblilty are missing!
2024-05-02 16:59:45 +02:00
mindmonk
1ab808f1b0 Merge pull request #3414 from MSevenR/feature/double-click-unlocked-vault
Double-click on an Unlocked Vault
2024-05-02 09:31:56 +02:00
Jan-Peter Klein
08f81b7df4 registered module in SettingsJsonTest 2024-04-29 11:12:14 +02:00
Jan-Peter Klein
b16f32ca83 introduced new dependency
removed latestVersion from Settings
changed SettingsJson from Date to Instant
new UpdateChecker Property checkFailed
optimized naming
changed wordning
refactoring
2024-04-29 10:34:17 +02:00
MSevenR
d6ed88b544 Double-click on an Unlocked Vault
Double-click on an Unlocked Vault in the List to Reveal It
2024-04-26 01:44:45 -05:00
Jan-Peter Klein
ae697d7b73 refactor isUpdateSuccessfulAndCurrent to instance variable 2024-04-25 10:54:00 +02:00
Jan-Peter Klein
ff3306cc17 removed blank line, unused instance variable, import and Logger
refactored DateTimeFormatter into an instance variable
2024-04-24 15:03:49 +02:00
Armin Schrenk
9ae2f4e0f6 add timezone id to timestamp in settings 2024-04-23 16:12:59 +02:00
Armin Schrenk
4230afcbac refactored timeDiff-message-method to updatePref controller 2024-04-23 16:12:36 +02:00
Armin Schrenk
7fc6ab05a4 use Instant also in UpdateChecker 2024-04-23 15:19:45 +02:00
Armin Schrenk
060f6bfc97 change storage of timestamps in model to Instant 2024-04-23 15:18:37 +02:00
Jan-Peter Klein
919dac6caa refactoring 2024-04-22 16:35:20 +02:00
Jan-Peter Klein
98bcf63b2c remove lastUpdateCheck from Settings; add lastUpdateReminder and lastSuccessfulUpdateCheck
implement updateTimeDifferenceMessage
reorder UI elements
refactor code for clarity and maintainability
2024-04-17 11:40:58 +02:00
Tobias Hagemann
0585262952 Merge pull request #3395 from purejava/flathub-colour-banners
Add coloured banners for app in Flathub store
2024-04-13 16:33:31 +02:00
Ralph Plawetzki
a33dc3980e Use colours from Cryptomator CD manual 2024-04-13 15:36:52 +02:00
Ralph Plawetzki
caa5e77386 Swap the light and dark colors, it's calmer for the eye 2024-04-13 08:48:20 +02:00
Ralph Plawetzki
c037920e79 Add coloured banners for app in Flathub store 2024-04-12 17:45:38 +02:00
Armin Schrenk
3cdd352d39 Update check-jdk-updates.yml
Use latest jdk version for jdk check
2024-04-10 12:27:05 +02:00
dependabot[bot]
8ae80e2932 Bump the maven-build-plugins group with 2 updates (#3391) 2024-04-09 08:34:03 +00:00
dependabot[bot]
2ffa1ee236 Bump the github-actions group with 2 updates (#3387) 2024-04-09 08:16:34 +00:00
Tobias Hagemann
2bf5b57823 Update README.md
[ci skip]
2024-04-05 12:33:38 +02:00
Jan-Peter Klein
853ea69180 updated log error message as suggested by coderabbit 2024-04-04 13:30:47 +02:00
Jan-Peter Klein
43d0dd99ec adjusted code as per PR suggestions 2024-04-04 12:37:56 +02:00
Armin Schrenk
b40e6db701 Merge branch 'main' into develop 2024-03-27 13:02:32 +01:00
Armin Schrenk
387eb420eb Merge branch 'hotfix/1.12.4' 2024-03-27 12:58:36 +01:00
Armin Schrenk
7785bb8820 finalize 1.12.4 2024-03-27 12:57:55 +01:00
Armin Schrenk
de4fa8c7b0 use latest WiX version
fixes CVE-2024-29187 and CVE-2024-29188
2024-03-27 12:55:13 +01:00
Armin Schrenk
17f519e01c prepare 1.12.4 2024-03-27 12:53:49 +01:00
dependabot[bot]
6c50023074 Bump the maven-build-plugins group with 2 updates (#3380) 2024-03-25 09:09:23 +00:00
Sebastian Stenzel
0009940e1e adjusted after dependency update 2024-03-14 12:09:10 +01:00
Armin Schrenk
f2a50b59b5 well, that should be the last reference to dokany 2024-03-12 09:56:30 +01:00
Armin Schrenk
ed03606981 One should also remove the actual dependency 2024-03-12 09:51:11 +01:00
Armin Schrenk
4a1eaf25c7 Closes #3361, Fixes #3351 2024-03-12 09:46:37 +01:00
dependabot[bot]
f5e445a610 Bump the java-production-dependencies group with 3 updates (#3365) 2024-03-12 07:57:00 +00:00
Jan-Peter Klein
6a3a256c0b Merge branch 'develop' into feature/update-checker-refactoring 2024-03-08 10:28:16 +01:00
Jan-Peter Klein
1ed77ebcc0 code cleanup 2024-03-08 10:27:35 +01:00
Jan-Peter Klein
db224e9e5c added latestVersion and lastUpdateCheck to settings and integrated with update checker 2024-03-08 09:58:59 +01:00
dependabot[bot]
c719982ef3 Bump the github-actions group with 1 update (#3354) 2024-03-05 17:24:28 +00:00
dependabot[bot]
f783f5d5ec Bump the java-test-dependencies group with 1 update (#3358) 2024-03-05 17:21:45 +00:00
dependabot[bot]
dd4f87b54c Bump the java-production-dependencies group with 4 updates (#3359) 2024-03-05 17:21:09 +00:00
Jan-Peter Klein
b3789700e1 add upToDateLabel and fix update indicator issue 2024-03-05 12:56:38 +01:00
Jan-Peter Klein
b39834f4eb Merge branch 'develop' into feature/update-checker-refactoring 2024-03-05 10:18:32 +01:00
Jan-Peter Klein
8064d75102 removed state label and reorganized ui elements 2024-03-05 10:15:11 +01:00
Jan-Peter Klein
4064b61cd7 refactored updateChecker by incorporating state management and date tracking 2024-02-29 09:29:26 +01:00
Armin Schrenk
ef3affece3 [ci skip] fix wrong PR description in flathub workflow 2024-02-28 13:42:37 +01:00
Armin Schrenk
414465371b [ci skip] refactor win-exe workflow
* only publish, if msi and exe succeed
* make stable release jobs dependent of publish
2024-02-28 13:19:54 +01:00
Armin Schrenk
feed72a729 [ci skip] fix flathub workflow 2024-02-27 22:52:56 +01:00
Armin Schrenk
bca20a7a66 [ci skip] seperate av whitelisting into own workflow to be able to upload assets on failure 2024-02-27 18:55:14 +01:00
Armin Schrenk
a38377baaa [ci skip] Merge branch 'main' into develop 2024-02-27 12:53:30 +01:00
Armin Schrenk
61a45fc738 Merge branch 'release/1.12.3' 2024-02-27 12:52:00 +01:00
Armin Schrenk
3a65b5551f adjust release check to changed metainfo file
references fcb940e29c
2024-02-27 12:48:36 +01:00
Armin Schrenk
94ed5c18b8 damnn merge from develop to release 2024-02-27 12:41:06 +01:00
Armin Schrenk
a559483d86 finalize 1.12.3 2024-02-27 12:38:52 +01:00
Armin Schrenk
3acdef1dd0 Merge branch 'develop' into release/1.12.3 2024-02-27 12:37:13 +01:00
Armin Schrenk
def6f8ab95 [ci skip] clean up 2024-02-27 12:35:55 +01:00
Armin Schrenk
11ba1f3ddc revert 1ab73be1f4 and 2d968eac8c 2024-02-27 12:32:37 +01:00
Cryptobot
3228f2cf5f New Crowdin updates (#3343)
New translations strings.properties

Chinese Simplified; Dutch; French; Japanese; Portuguese; Russian; Slovak; Swedish; 

[ci skip]
2024-02-27 10:23:56 +01:00
Armin Schrenk
9c4f7ad79d [ci skip] remove unknown env/style combination from appstream metadata 2024-02-26 17:41:18 +01:00
Armin Schrenk
3bd57d162b [ci skip] update appstream metadata 2024-02-26 17:37:04 +01:00
dependabot[bot]
5ea73a5a8d Bump the java-production-dependencies group with 1 update (#3347) 2024-02-26 09:50:42 +00:00
Armin Schrenk
38670838c7 [ci skip] Drop yq usage 2024-02-26 10:15:25 +01:00
Armin Schrenk
3e0b84dbce [ci skip] fix pr body description & reduce log noise 2024-02-23 17:39:38 +01:00
Armin Schrenk
2302db6206 [ci skip] fix create pr command in flathub job 2024-02-23 17:27:48 +01:00
Armin Schrenk
a94bf99660 [ci skip] automatically set up tracking branch on push 2024-02-23 17:13:11 +01:00
Armin Schrenk
0c5ce353b1 [ci skip] use github.actor 2024-02-23 17:05:26 +01:00
Armin Schrenk
b3ce777a42 [ci skip] configure git in flathub job 2024-02-23 16:29:18 +01:00
Armin Schrenk
3085df3397 [ci skip] further fixes:
* remove yq after update
* set token for git
2024-02-23 16:14:21 +01:00
Armin Schrenk
fb740b605f add missing quote char [ci skip] 2024-02-23 15:57:06 +01:00
Armin Schrenk
6a74d9f3b2 use same varaible in get-version job 2024-02-23 15:53:22 +01:00
Armin Schrenk
1c7dffb63f Add ci job to create flathub PR on release [ci skip] 2024-02-23 15:44:48 +01:00
Jan-Peter Klein
a213f073b1 enhance screen selection by adding primary fallback 2024-02-23 10:51:23 +01:00
Armin Schrenk
1ab73be1f4 fixes #3344 2024-02-22 16:11:54 +01:00
Armin Schrenk
8412871090 apply proper formatting and state to error dialog 2024-02-22 12:23:43 +01:00
Armin Schrenk
fa63f3ca67 Reset develop to SNAPSHOT version 2024-02-22 12:21:00 +01:00
Armin Schrenk
dbc0f52481 fix not-uploading artifacts on release 2024-02-21 22:04:35 +01:00
Armin Schrenk
b8cd1caeac also upload asc file as artifact for mac build 2024-02-21 13:09:14 +01:00
Armin Schrenk
43c25b6d97 fix ci
references 84732337ca
2024-02-21 12:53:01 +01:00
Armin Schrenk
e44bc09074 Merge branch 'develop' into release/1.12.3 2024-02-21 12:20:36 +01:00
Cryptobot
7b02f78ef5 New Crowdin updates (#3342)
New translations strings.properties

Arabic; Bashkir; Belarusian; Bengali; Bosnian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian; Czech; Danish; Dutch; Filipino; Finnish; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Macedonian; Marathi; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Serbian (Cyrillic); Serbian (Latin); Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Vietnamese; 

[ci skip]
2024-02-21 12:13:24 +01:00
Armin Schrenk
f7e8a4d1e6 prepare 1.12.3 2024-02-20 18:13:01 +01:00
Armin Schrenk
664375d692 fix wrong method name 2024-02-20 18:06:55 +01:00
Armin Schrenk
2d968eac8c Merge pull request #3336 from cryptomator/feature/3272-vaultid-as-mountpoint
Feature: For FUSE-Ts default mountpoint use vault id as mountpoint
2024-02-20 17:34:09 +01:00
Armin Schrenk
542d2fcfe1 only create winget PR for stable versions [ci skip] 2024-02-19 16:42:42 +01:00
mindmonk
144e929896 Merge pull request #3335 from cryptomator/feature/center-unlock-dialog-on-mainstage
Center Unlock Success Dialog on Main Application Window
2024-02-19 15:05:28 +01:00
Armin Schrenk
803748f78d update code-sign-action [ci skip] 2024-02-19 14:46:58 +01:00
Armin Schrenk
3410e7243a Update minimal required macOS version for dmg
due to javafx update in 7d281e2878
2024-02-19 13:02:05 +01:00
Armin Schrenk
84732337ca removed GTK-2 support
due to javafx update in 7d281e2878
2024-02-19 12:17:11 +01:00
dependabot[bot]
c527808710 Bump the java-production-dependencies group with 4 updates (#3340) 2024-02-19 09:35:25 +00:00
Armin Schrenk
99c89dbf39 fix possible null comparsion 2024-02-19 10:22:22 +01:00
Jan-Peter Klein
829b64cd3d dialog centers on main app screen if mainWindow is hidden 2024-02-19 08:55:16 +01:00
Jan-Peter Klein
f4007267fb simplified the code and removed the function 2024-02-16 17:31:20 +01:00
Armin Schrenk
c82a0bfaf3 cleanup 2024-02-16 17:09:05 +01:00
Armin Schrenk
251ad65344 Merge pull request #3327 from cryptomator/feature/3233-load-presets-background
Feature: Load LocationPresets in background and show indicator in UI
2024-02-16 16:21:01 +01:00
Jan-Peter Klein
155ba4607b introduced functionality to center the unlock screen within the main application window 2024-02-16 15:24:52 +01:00
Armin Schrenk
62f6865d3e cleanup created directories after mount
fails silently
2024-02-14 10:30:51 +01:00
Armin Schrenk
ffb3290248 Merge branch 'develop' into feature/3272-vaultid-as-mountpoint 2024-02-14 10:29:30 +01:00
Armin Schrenk
a013ae3d91 [ci skip] change mountPointDir for macOS-Dev-run profile
aligns production build
2024-02-14 10:29:14 +01:00
Armin Schrenk
19a954e677 use correct mountProvider 2024-02-14 10:05:56 +01:00
Armin Schrenk
f262980acc closes #3272 2024-02-13 16:37:46 +01:00
Armin Schrenk
3b3aa18c92 fixes #3233
this time with gc prevention of a binding
2024-02-13 00:55:07 +01:00
Armin Schrenk
c7b8bc89c2 also don't bother upload to av scan, if not published 2024-02-12 13:18:17 +01:00
Armin Schrenk
5fc981abd3 prevent automatic overwrite of already released files 2024-02-12 13:16:45 +01:00
Armin Schrenk
36ec1a5ebc update windows update url [ci skip] 2024-02-09 18:37:19 +01:00
Armin Schrenk
be4aad4168 set default value for Windows debug flag 2024-02-09 17:03:22 +01:00
Armin Schrenk
fcb940e29c update release section of appstream metainfo file [ci skip] 2024-02-09 14:52:10 +01:00
Armin Schrenk
4f3ca2a6c4 fix appimage build script [ci skip] 2024-02-09 12:56:33 +01:00
Armin Schrenk
27cd34bee0 Merge branch 'main' into develop [ci skip] 2024-02-09 12:53:16 +01:00
Armin Schrenk
c07e51be51 Merge branch 'release/1.12.2' 2024-02-09 12:51:57 +01:00
Armin Schrenk
0421879b39 finalize 1.12.2 2024-02-09 12:51:19 +01:00
Armin Schrenk
2d627717a0 prepare 1.12.2 2024-02-09 10:59:33 +01:00
Armin Schrenk
dc0e88a694 fixes #3319 2024-02-09 10:55:27 +01:00
Armin Schrenk
a5e3630375 also specify version for winget release [ci skip] 2024-02-08 17:47:50 +01:00
Armin Schrenk
17335e8f70 shorten workflow name [ci skip] 2024-02-08 17:39:38 +01:00
Armin Schrenk
42dd2fba48 github cli needs special token in CI env [ci skip] 2024-02-08 17:37:50 +01:00
Armin Schrenk
e1cca6427c Add ci job for releasing to winget 2024-02-08 17:34:02 +01:00
Armin Schrenk
42d3dbaa23 always use latest version of winfsp-uninstaller 2024-02-08 17:10:40 +01:00
Armin Schrenk
185d67c492 Merge branch 'main' into develop [ci skip] 2024-02-07 11:43:59 +01:00
Armin Schrenk
a8af3c8b40 Merge branch 'release/1.12.1' 2024-02-07 11:42:58 +01:00
Armin Schrenk
038a7fac62 finalize 1.12.1 2024-02-07 11:42:37 +01:00
Armin Schrenk
48408fa40d prepare 1.12.1 2024-02-07 11:37:44 +01:00
Armin Schrenk
18a417667e Fixes #3315 2024-02-07 11:33:45 +01:00
JaniruTEC
aab07b13e3 Changed version specifier for dependency-check
See: https://github.com/cryptomator/cryptofs/pull/202#discussion_r1453615249
2024-02-06 22:28:16 +01:00
Armin Schrenk
869e40e351 use latest coffeelibs-jdk release 2024-02-06 15:34:09 +01:00
Armin Schrenk
bf91e3f15c Merge branch 'main' into develop [ci skip] 2024-02-06 14:29:19 +01:00
Armin Schrenk
17544828e4 Merge branch 'release/1.12.0' 2024-02-06 14:28:08 +01:00
Armin Schrenk
cfef3139b1 finalize 1.12.0 2024-02-06 14:20:50 +01:00
Armin Schrenk
b01ba27b06 Partially reverting 24293b316f 2024-02-06 14:16:03 +01:00
Armin Schrenk
5a33e66a7d prepare 1.12.0 2024-02-06 11:31:42 +01:00
Armin Schrenk
3c4e35406e Bump dependencies 2024-02-06 11:27:02 +01:00
Cryptobot
d3275fa4e7 New Crowdin updates (#3256)
New translations strings.properties

Arabic; Bashkir; Belarusian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Czech; Danish; Dutch; Filipino; French; German; Greek; Hebrew; Hungarian; Italian; Japanese; Korean; Latvian; Norwegian Bokmal; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Slovak; Spanish; Swahili, Tanzania; Swedish; Turkish; Vietnamese;

[ci skip]
2024-02-06 11:21:07 +01:00
dependabot[bot]
a30db34c19 Bump the java-production-dependencies group with 6 updates (#3295) 2024-02-06 10:18:33 +00:00
dependabot[bot]
509100e7ae Bump the java-test-dependencies group with 2 updates (#3312) 2024-02-06 10:17:11 +00:00
dependabot[bot]
024c34172b Bump the github-actions group with 5 updates (#3308) 2024-02-06 10:16:24 +00:00
dependabot[bot]
638570562b Bump the maven-build-plugins group with 3 updates (#3300) 2024-02-06 10:15:06 +00:00
Sebastian Stenzel
ee5a5c6563 Merge pull request #3291 from cryptomator/feature/legacy-device-migration
Hub 1.2.x → Hub 1.3.x Legacy Device Migration
2024-02-02 14:59:30 +01:00
Armin Schrenk
85c52c60c5 Revert "update javafx to 21.0.2"
This reverts commit 93184abd3c.
2024-02-02 10:45:34 +01:00
Armin Schrenk
93184abd3c update javafx to 21.0.2 2024-01-30 12:55:33 +01:00
Armin Schrenk
8062392ccd update jdk to 21.0.2+13 2024-01-30 12:17:45 +01:00
Jan-Peter Klein
d49c02c7de optimize share vault fxml 2024-01-29 17:37:55 +01:00
Sebastian Stenzel
d66cfe0e7c adjust to new migration API 2024-01-26 16:48:08 +01:00
mindmonk
fa26fa9dee Merge pull request #3289 from cryptomator/feature/share-vault
Feature: Introduce 'Share Vault' Functionality
2024-01-26 16:08:06 +01:00
Jan-Peter Klein
52fc94ca01 fixed a spelling error 2024-01-26 16:03:51 +01:00
Jan-Peter Klein
e9a412ae16 improved layout and added styleClass for add-box 2024-01-26 15:42:25 +01:00
Jan-Peter Klein
8104c35d76 more specific translation keys and consistent spacing 2024-01-23 19:09:49 +01:00
Jan-Peter Klein
baa2e05e69 improved wording and layout 2024-01-23 14:00:20 +01:00
Armin Schrenk
f50b204cef Merge pull request #3288 from cryptomator/feature/3246-split-device-registration
Feature: Split device registration into "normal" and "legacy" flow
2024-01-22 14:56:45 +01:00
lectrical
ed902bc59f Hello 2024 2024-01-20 16:22:27 +01:00
Sebastian Stenzel
693299a5d7 first draft of legacy device migration
actual migration still missing due to API discussion
2024-01-20 13:28:56 +01:00
Sebastian Stenzel
def64aa2ac added tests 2024-01-20 13:25:57 +01:00
Sebastian Stenzel
c5bb8a131d dedup 2024-01-20 13:15:33 +01:00
Sebastian Stenzel
2e443c72a9 add new API encryptVaultKey(vaultKey, userKey)
and `decodeECPublicKey(byte[])`
2024-01-20 13:12:59 +01:00
Sebastian Stenzel
e9ee17493b refactor API, expose decodeECPrivateKey(byte[]) 2024-01-20 13:01:48 +01:00
Sebastian Stenzel
35eb548d8e replaced Guava's BaseEncoding with Base64 2024-01-20 12:58:44 +01:00
Sebastian Stenzel
dc5d6e734e deduplicate code 2024-01-19 17:55:36 +01:00
Sebastian Stenzel
729f38866f use string templates for URI construction 2024-01-19 17:40:39 +01:00
Jan-Peter Klein
4de8434f1b Merge branch 'develop' into feature/share-vault 2024-01-19 12:31:37 +01:00
Jan-Peter Klein
cd40731b5f implemented open hub feature
optimized fxml files and img
2024-01-19 12:30:56 +01:00
Armin Schrenk
24293b316f Merge pull request #3236 from cryptomator/feature/3233-locationpresets-background
Feature: Load LocationPresets in background and show indicator in UI
2024-01-19 10:51:46 +01:00
Armin Schrenk
062c674ef1 Always hide spinner, as soon as locationPresetLoading is finished 2024-01-19 10:44:06 +01:00
Armin Schrenk
830bb5776f Use naming convention for comparator 2024-01-19 10:04:15 +01:00
Armin Schrenk
bfdb23785e Merge branch 'develop' into feature/3233-locationpresets-background 2024-01-18 15:57:45 +01:00
Armin Schrenk
248d655afb ditch custom in-place sorting and rely on javafx methods 2024-01-18 15:45:45 +01:00
Armin Schrenk
995c0a4b92 remove unnecessary TODO 2024-01-17 23:30:41 +01:00
Armin Schrenk
42425afe56 closes #3246
splitting registerSuccess into two scenes, one for hub 1.3.x and one for legacy
2024-01-17 16:52:35 +01:00
Sebastian Stenzel
a1b712495f switch back to UI thread later
see https://github.com/cryptomator/cryptomator/pull/3287#discussion_r1453196792
2024-01-17 13:35:23 +01:00
Sebastian Stenzel
2225476bf8 reordered methods
[ci skip]
2024-01-17 13:33:38 +01:00
Sebastian Stenzel
325057c548 Merge pull request #3287 from cryptomator/feature/refactored-hub-unlock
Refactored Hub Unlock
2024-01-17 13:32:09 +01:00
JaniruTEC
b1a5eed2aa Merge pull request #3286 from cryptomator/refactoring/centralize-dependency-check
Externalize dependency-check
2024-01-16 19:54:32 +01:00
Jan-Peter Klein
4ca190cfb9 implemented a 'Share Vault' button in vault_detail_locked and added a new window for vault sharing options 2024-01-16 17:21:07 +01:00
GiwrgosTsifoutis
828fd321cc Fixed "Locked Vault Options after unlocking vault #3249" (#3267)
Fixes #3249 

Bound the UIs disabled state to the vault's lock state without the need of a map
2024-01-16 12:32:36 +01:00
Armin Schrenk
2e32f39986 [ci skip] fix missing translation key
(cherry picked from commit daa026b285)
2024-01-16 11:38:54 +01:00
Armin Schrenk
daa026b285 [ci skip] fix missing translation key 2024-01-16 11:38:33 +01:00
Sebastian Stenzel
87084e8c2a TODO now obsolete
as we will now re-attempt unlock when returning from device registration

[ci skip]
2024-01-16 04:14:06 +01:00
Sebastian Stenzel
8e52058373 re-attempt receiving key after registering device 2024-01-16 03:58:30 +01:00
Armin Schrenk
8bf0acf35f build release artifacts with javafx 21.0.1
references 7d281e2878
2024-01-15 16:35:34 +01:00
JaniruTEC
e0d3a3d9c7 Externalized dependency-check 2024-01-15 16:12:27 +01:00
Sebastian Stenzel
b59ce75ecd add step 0: check API level 2024-01-14 15:02:41 +01:00
Sebastian Stenzel
748f895b98 change unlock request order 2024-01-14 15:01:51 +01:00
Sebastian Stenzel
6d974c7fcf fix incorrect vaultId 2024-01-14 14:58:58 +01:00
Sebastian Stenzel
0ed73e8b41 use string templates for building /api/* URIs 2024-01-14 14:02:35 +01:00
Sebastian Stenzel
538b4ecd0b added javadoc 2024-01-14 13:59:23 +01:00
Armin Schrenk
8f32b46b30 set no jlink compression for build artifacts
references 00fc2a9837
2024-01-12 13:18:05 +01:00
Armin Schrenk
4de25afde0 wrap locations in scrollPane 2024-01-11 23:48:26 +01:00
Armin Schrenk
2e6c228f3f Merge branch 'develop' into feature/3233-locationpresets-background 2024-01-11 22:59:41 +01:00
Armin Schrenk
00fc2a9837 remove deprecate compress options and use default ones
see also https://bugs.openjdk.org/browse/JDK-8301124?jql=text%20~%20%22compress%22
2024-01-11 22:59:08 +01:00
Armin Schrenk
22e80e7dac update local appimage buildscript to download jmods 2024-01-11 22:56:41 +01:00
Armin Schrenk
517e05c378 use stable version of winfsp-uninstaller 2024-01-11 22:35:51 +01:00
Sebastian Stenzel
5759b7e596 Merge pull request #3210 from cryptomator/feature/3203-device-already-registered
Feature: Adjust Hub workflow, if device is already registerd
2024-01-11 12:05:25 +01:00
Sebastian Stenzel
bfb26f6171 renamed field 2024-01-11 11:46:06 +01:00
Sebastian Stenzel
f36e2bb4b7 reduced visibility 2024-01-11 11:45:57 +01:00
Sebastian Stenzel
b85e455ff5 renamed field 2024-01-11 11:42:08 +01:00
Sebastian Stenzel
a902400522 get rid of registerException
use separate views, no need to pass state between views
2024-01-11 11:23:54 +01:00
Sebastian Stenzel
a6d6474294 Merge branch 'develop' into feature/3203-device-already-registered 2024-01-11 11:02:45 +01:00
Sebastian Stenzel
06859fe36b remove newline
[ci skip]
2024-01-11 10:27:42 +01:00
Sebastian Stenzel
7d7b7c1dc9 Merge pull request #3260 from cryptomator/feature/annihilate-FUPFMS
annihilate FUPFMS
2024-01-11 10:25:21 +01:00
Sebastian Stenzel
706d2b51be remove added newline
[ci skip]
2024-01-11 10:24:28 +01:00
Armin Schrenk
92bf136a8b Merge pull request #3278 from mooons/issue-3277
Bump README's build dependency JDK version from 19 to 21
2024-01-09 12:03:21 +01:00
mooons
f00f028d8b Bump README's build dependency JDK version from 19 to 21. Fix #3277 2024-01-09 01:57:59 -08:00
dependabot[bot]
325092efb0 Bump the java-test-dependencies group with 1 update (#3238) 2023-12-26 04:32:24 +00:00
dependabot[bot]
aaf8036713 Bump the maven-build-plugins group with 3 updates (#3264) 2023-12-25 19:40:21 +00:00
Sebastian Stenzel
c86ee679a9 renamed fuse-specific exception to be more generic 2023-12-21 10:05:22 +01:00
Sebastian Stenzel
a0fcb63a1a replaced FUPFMS
with more generic set of used mount services
2023-12-21 09:40:43 +01:00
Armin Schrenk
55ba255651 Update dependency-check.yml
to not run into 403 due to rate limit
2023-12-18 10:49:47 +01:00
dependabot[bot]
47df4213c3 Bump the java-production-dependencies group with 5 updates (#3255) 2023-12-18 09:40:34 +00:00
Armin Schrenk
6929760979 adjust dependency check plugin 2023-12-13 16:47:30 +01:00
Armin Schrenk
720fbd0e6b use separate cache for dependency-cache data 2023-12-13 16:47:08 +01:00
mindmonk
923af4bc83 Merge pull request #3199 from cryptomator/feature/vault-volume-type
Feature: Customizable Volume Type Options for Each Vault
2023-12-13 16:16:08 +01:00
Jan-Peter Klein
e9c464ba8f sonar cloud issues solved 2023-12-13 15:56:39 +01:00
Jan-Peter Klein
7b0f616747 Merge branch 'develop' into feature/vault-volume-type 2023-12-13 15:50:55 +01:00
Jan-Peter Klein
65788f3c1f pr mentioned changes 2023-12-13 15:50:37 +01:00
Jan-Peter Klein
f55fbf0f64 code cleanup and optimized a description text 2023-12-13 09:25:50 +01:00
Armin Schrenk
851838e3a2 remove run of dependency-chec workflow for release branches (already done in check release workflow) 2023-12-12 14:58:48 +01:00
Armin Schrenk
e194f9b205 update dependency check and refactor to own workflow 2023-12-12 14:56:48 +01:00
Jan-Peter Klein
2f8df88ad5 Merge branch 'develop' into feature/vault-volume-type
# Conflicts:
#	src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java
2023-12-12 12:48:59 +01:00
Jan-Peter Klein
55247d9f8a moved provideDefaultMountService to MountModule and renamed problematicFuseMountServices to CONFLICTING_MOUNT_SERVICES 2023-12-12 12:38:33 +01:00
dependabot[bot]
48f273b755 Bump ch.qos.logback:logback-core from 1.4.13 to 1.4.14 (#3251) 2023-12-12 08:48:54 +00:00
Jan-Peter Klein
4fc31cb13f refactored 'loopbackPortSupported' from 'BooleanExpression' to 'ObservableValue<Boolean>' in VolumePreferencesController and MountOptionsController 2023-12-11 15:16:41 +01:00
Jan-Peter Klein
a795b82a42 vault options ui change 2023-12-11 14:49:54 +01:00
Jan-Peter Klein
1e28a04a7b renamed string properties 2023-12-11 10:16:26 +01:00
Jan-Peter Klein
b88eef4591 renamed string property 2023-12-08 12:03:08 +01:00
Jan-Peter Klein
eef5edf775 code cleanup 2023-12-08 11:14:54 +01:00
Armin Schrenk
bdb1d605eb Add cloud vendor to example of involved software 2023-12-07 18:43:10 +01:00
Armin Schrenk
dfe4b74f3d clean code:
* remove unused methods
* combine or move methods
2023-12-07 17:48:58 +01:00
Jan-Peter Klein
985a3c30de changed string properties for volume type labels 2023-12-07 13:56:04 +01:00
Jan-Peter Klein
1b5125dfed refactored code, global default volume type settings 2023-12-07 10:48:33 +01:00
Jan-Peter Klein
da240ce8b9 optimized error message 2023-12-07 08:40:39 +01:00
Jan-Peter Klein
52affb891e refactored mount method 2023-12-06 16:41:36 +01:00
Jan-Peter Klein
fac72ca24a undo remove settings port 2023-12-06 09:44:05 +01:00
Jan-Peter Klein
5cbed502ed undo VaultListManager changes 2023-12-06 08:49:21 +01:00
Jan-Peter Klein
dce4c60881 removed pr unrelated changes and code cleanup 2023-12-06 08:40:43 +01:00
Jan-Peter Klein
63bf0315c7 created global mountService 2023-12-05 16:21:12 +01:00
Armin Schrenk
8b543c48ee [ci skip] Merge branch 'main' into develop 2023-12-05 11:11:31 +01:00
Armin Schrenk
087a5326df Merge branch 'release/1.11.1' 2023-12-05 11:09:36 +01:00
Armin Schrenk
a4545352d8 finalize 1.11.1 2023-12-05 11:09:09 +01:00
dependabot[bot]
a07dea7ca8 Bump the github-actions group with 2 updates (#3235) 2023-12-05 08:39:49 +00:00
Jan-Peter Klein
c369487e8e Merge branch 'develop' into feature/vault-volume-type 2023-12-01 09:13:38 +01:00
Jan-Peter Klein
98590ecec5 refactoring 2023-12-01 09:11:43 +01:00
Armin Schrenk
316f3975ed add missing import 2023-11-30 18:24:52 +01:00
Armin Schrenk
71bf7e0913 Simplify handling of window hiding events 2023-11-30 18:22:07 +01:00
dependabot[bot]
c7839e2c46 Bump the java-production-dependencies group with 2 updates (#3234) 2023-11-30 14:26:07 +00:00
Armin Schrenk
89b8bc4148 adjust ui and add localization 2023-11-30 11:44:41 +01:00
Armin Schrenk
43ad1c05c0 cancel background task, if window is closed 2023-11-30 11:18:33 +01:00
Armin Schrenk
1343099be6 [ci skip] correct dependabot config 2023-11-30 10:03:29 +01:00
Armin Schrenk
b895ac69fb fixes #3233 2023-11-29 18:45:52 +01:00
dependabot[bot]
7d281e2878 Bump the javafx group with 5 updates (#3229) 2023-11-29 15:08:31 +00:00
Armin Schrenk
688450bf5a prepare 1.11.1 2023-11-28 13:38:05 +01:00
Cryptobot
e994133177 New Crowdin updates (#3191)
New translations strings.properties

Bulgarian; Chinese Simplified; Chinese Traditional; Dutch; Filipino; French; Greek; Hungarian; Norwegian Bokmal; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Spanish; Swedish; Turkish; 

[ci skip]
2023-11-28 13:32:08 +01:00
dependabot[bot]
68713ef9a7 Merge pull request #3228 from cryptomator/dependabot/maven/maven-build-plugins-907533b1a4 2023-11-28 12:28:35 +00:00
Armin Schrenk
dbacbc8874 do not exectue dependency-check on CI (due to missing NVD API key) 2023-11-28 13:25:47 +01:00
dependabot[bot]
8382299a05 Bump the maven-build-plugins group with 4 updates
Bumps the maven-build-plugins group with 4 updates: [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin), [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire), [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) and [org.owasp:dependency-check-maven](https://github.com/jeremylong/DependencyCheck).


Updates `org.apache.maven.plugins:maven-dependency-plugin` from 3.6.0 to 3.6.1
- [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.0...maven-dependency-plugin-3.6.1)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.1.2 to 3.2.2
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.2)

Updates `org.codehaus.mojo:license-maven-plugin` from 2.2.0 to 2.3.0
- [Release notes](https://github.com/mojohaus/license-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/license-maven-plugin/compare/2.2.0...2.3.0)

Updates `org.owasp:dependency-check-maven` from 8.4.0 to 9.0.1
- [Release notes](https://github.com/jeremylong/DependencyCheck/releases)
- [Changelog](https://github.com/jeremylong/DependencyCheck/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jeremylong/DependencyCheck/compare/v8.4.0...v9.0.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-dependency-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven-build-plugins
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.codehaus.mojo:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.owasp:dependency-check-maven
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: maven-build-plugins
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-28 12:20:39 +00:00
dependabot[bot]
93b09cf449 Bump the java-production-dependencies group with 6 updates (#3230) 2023-11-28 12:19:58 +00:00
dependabot[bot]
dac3311b81 Bump the java-test-dependencies group with 2 updates (#3227) 2023-11-28 12:05:42 +00:00
Armin Schrenk
5b1ca7a533 update dependabot config 2023-11-28 12:59:39 +01:00
Armin Schrenk
e940c29110 Closes #3226 2023-11-28 12:44:42 +01:00
Jan-Peter Klein
6a704ca0ad Merge branch 'develop' into feature/vault-volume-type 2023-11-27 16:24:35 +01:00
Jan-Peter Klein
38c102a64b refactored code by removing unnecessary observables 2023-11-27 12:46:29 +01:00
Armin Schrenk
b632c84bb6 more renaming 2023-11-24 11:23:22 +01:00
Armin Schrenk
6bb5ed1d73 fixes #3207 2023-11-24 11:19:44 +01:00
Jan-Peter Klein
1052e4c3d2 fix gui issues in vault mount settings 2023-11-23 10:55:17 +01:00
Armin Schrenk
44f776050f Apply suggestions from code review
Co-authored-by: Tobias Hagemann <tobias.hagemann@skymatic.de>
2023-11-22 21:36:15 +01:00
Armin Schrenk
baa29dbd73 remove unused translation key 2023-11-17 16:33:53 +01:00
Armin Schrenk
1caf391936 use correct word for button label 2023-11-17 16:24:23 +01:00
Armin Schrenk
82caf76e12 clean up 2023-11-17 15:51:20 +01:00
Armin Schrenk
de27bbf96e always cancle unlock result when closing the unlock window 2023-11-17 15:50:39 +01:00
Armin Schrenk
1199ef40dd on 409 repsonse of registerDevice-request, show setupFailed with adjusted message 2023-11-17 15:47:08 +01:00
Jan-Peter Klein
e7e88f13e3 improved code quality 2023-11-17 14:51:13 +01:00
Armin Schrenk
41c22b7840 Rename leftovers 2023-11-17 13:30:40 +01:00
Armin Schrenk
19cc4e8a37 Merge pull request #3194 from AntoineJT/feature/3155-toggle-vault-status-on-double-click
Feature: Double click on a vault in the list to unlock it
2023-11-15 16:51:44 +01:00
Jan-Peter Klein
7bc1d52bf8 set deprecated since of settingsjson port to 1.12.0, changed button text and added tooltip to 'show vault options' button 2023-11-12 13:49:47 +01:00
Antoine James Tournepiche
fd84ff09e1 No longer lock vault on double click
See https://github.com/cryptomator/cryptomator/pull/3194#issuecomment-1806106843
2023-11-10 22:05:58 +01:00
Antoine James Tournepiche
3dce175f94 Improve naming, avoid shadowing 2023-11-10 17:42:19 +01:00
Antoine James Tournepiche
0aaa3263cf Improve feature #3155 implementation 2023-11-09 23:50:34 +01:00
Antoine James Tournepiche
c4dcbd8c44 Implement requested feature #3155
Toggle selected vault lock status on double click on a vault item
in the vault list on the main window
2023-11-09 23:42:22 +01:00
Jan-Peter Klein
ef9cdd8e92 Merge branch 'develop' into feature/vault-volume-type
# Conflicts:
#	src/main/resources/i18n/strings.properties
2023-11-08 11:45:03 +01:00
Armin Schrenk
09ced50590 [ci skip] reset to snapshot version 2023-11-08 11:28:21 +01:00
Armin Schrenk
b2ab1a30a5 Merge branch 'main' into develop 2023-11-08 11:26:49 +01:00
Armin Schrenk
9eff3916b3 Merge branch 'release/1.11.0' 2023-11-08 11:26:13 +01:00
Armin Schrenk
98472d1952 use correct release date 2023-11-08 11:25:45 +01:00
Armin Schrenk
1ceafb69a5 finalize 1.11.0 2023-11-08 11:22:27 +01:00
Armin Schrenk
f3f4b6576c Merge branch 'develop' into release/1.11.0
# Conflicts:
#	src/main/resources/i18n/strings.properties
2023-11-08 10:52:30 +01:00
Cryptobot
e699d7dafc New Crowdin updates (#3189)
* New translations strings.properties
German, Spanish, Turkish
[ci skip]
2023-11-08 10:51:07 +01:00
Cryptobot
5eb6d186c0 New Crowdin updates (#3188)
New translations strings.properties

Arabic; Belarusian; Bengali; Bosnian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian; Czech; Danish; Dutch; Filipino; Finnish; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Macedonian; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Serbian (Cyrillic); Serbian (Latin); Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Vietnamese; 

[ci skip]
2023-11-08 10:41:05 +01:00
Armin Schrenk
edc9409e56 pin wording 2023-11-08 10:19:12 +01:00
JaniruTEC
d015719fae Removed outdated translations 2023-11-07 18:52:48 +01:00
JaniruTEC
afc69e447e Renamed "setup code" to "Account Key" in localization files 2023-11-07 18:20:10 +01:00
JaniruTEC
54fbbd734f Renamed "setup code" to "Account Key" in UI 2023-11-07 18:19:12 +01:00
Jan-Peter Klein
2f657c7c14 migrate port to vault settings 2023-11-07 12:42:07 +01:00
Sebastian Stenzel
d29872e69e add "Action Required" prompt
when encountering http status 449 during vault unlock. fixes #3181

Co-authored-by: SailReal <julian.raufelder@skymatic.de>
(cherry picked from commit f2e7d0fae2)
2023-11-07 12:20:27 +01:00
Jan-Peter Klein
ab9278a9fc Merge branch 'develop' into feature/vault-volume-type 2023-11-03 10:48:00 +01:00
Jan-Peter Klein
49769f986a remove port from settings 2023-11-03 10:47:43 +01:00
Jan-Peter Klein
b68b895bba removed tcp port from volume preferences controller 2023-11-02 16:53:29 +01:00
Tobias Hagemann
99fb9972f9 updated sponsors
[ci skip]
2023-11-02 15:37:19 +01:00
Sebastian Stenzel
f2e7d0fae2 add "Action Required" prompt
when encountering http status 449 during vault unlock. fixes #3181

Co-authored-by: SailReal <julian.raufelder@skymatic.de>
2023-11-02 14:41:58 +01:00
Jan-Peter Klein
77f9e6c411 some ui and wording changes 2023-11-02 13:47:58 +01:00
Jan-Peter Klein
31fcf294e9 fix misbehaivour 2023-11-01 14:59:25 +01:00
Jan-Peter Klein
a03f00ee9a set up default mount service as pre fallbackProvider 2023-10-31 20:29:54 +01:00
Jan-Peter Klein
80af32bd82 introduced FuseRestartRequiredException and UnlockFuseRestartRequired window 2023-10-30 17:05:09 +01:00
Jan-Peter Klein
b7e4c0fe31 set default mount service and port while adding a vault 2023-10-30 15:27:11 +01:00
Jan-Peter Klein
76d499596f Merge branch 'develop' into feature/vault-volume-type 2023-10-30 14:33:32 +01:00
Jan-Peter Klein
1818344c49 different labeling for volume type option in general volume preferences and vault options 2023-10-30 14:33:01 +01:00
Armin Schrenk
7ff2e22f17 Merge branch 'develop' into release/1.11.0 2023-10-30 10:41:11 +01:00
Cryptobot
4eee66b0ef New Crowdin updates (#3128)
New translations strings.properties

Arabic; Belarusian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Czech; Danish; Dutch; Filipino; Finnish; French; German; Greek; Hebrew; Hungarian; Italian; Japanese; Korean; Norwegian Bokmal; Polish; Portuguese; Portuguese, Brazilian; Romanian; Russian; Slovak; Spanish; Swahili, Tanzania; Swedish; Turkish; Ukrainian; Vietnamese; 

[ci skip]
2023-10-30 10:39:04 +01:00
Sebastian Stenzel
19fe7ba6bf updated to tiny-oauth2-client 0.8.0 2023-10-27 19:54:58 +02:00
Armin Schrenk
7b522582fb Merge pull request #3163 from cryptomator/feature/3075-fix-ci-jdk-version
Feature: Use fixed JDK version for releases
2023-10-27 12:51:49 +02:00
Jan-Peter Klein
e79c975d7b prevent mounting via MountFailedException when fuseRestartRequired 2023-10-27 12:39:25 +02:00
Armin Schrenk
7594e51e2b Update debian.yml
Remove architecture in apt install dependency
2023-10-27 12:30:37 +02:00
Armin Schrenk
b3f0ff3662 use coffeelibs JDK for release builds 2023-10-27 12:10:37 +02:00
Armin Schrenk
8ce304a0c3 Add link to how-to-jdk-update in notification 2023-10-26 16:21:22 +02:00
Jan-Peter Klein
c85823fe04 code cleanup 2023-10-26 12:18:40 +02:00
Jan-Peter Klein
8f46aec851 created MountServiceConverter class 2023-10-26 10:35:16 +02:00
Jan-Peter Klein
cd6d1eeab3 moved fupfms to VaultModule 2023-10-26 10:25:11 +02:00
Jan-Peter Klein
52b74a74fe display specific mount options according to selected volume type in vault mounting options 2023-10-25 14:02:29 +02:00
Jan-Peter Klein
368f0630c1 some sonar cloud fixes 2023-10-25 12:44:22 +02:00
Jan-Peter Klein
040bc4c5df fix sonar cloud issues 2023-10-24 14:26:06 +02:00
Jan-Peter Klein
07906fbea5 modified mounter to utilize the mount service settings specified in the vault settings 2023-10-24 14:04:53 +02:00
Armin Schrenk
f893b2b5be Merge pull request #3026 from cryptomator/feature/uninstall-old-winfsp
Feature: Update to WinFsp 2.x and uninstall old winfsp in Windows EXE installer
2023-10-23 12:26:28 +02:00
Armin Schrenk
db868c6df7 move worklfow to correct directory 2023-10-20 16:22:45 +02:00
Jan-Peter Klein
44f67b7c89 Merge branch 'develop' into feature/vault-volume-type 2023-10-20 15:58:52 +02:00
Sebastian Stenzel
6225d8d1f0 Merge branch 'develop' into release/1.11.0 2023-10-20 14:00:42 +02:00
Sebastian Stenzel
ed975b459e bump dependencies 2023-10-20 14:00:08 +02:00
Armin Schrenk
652a6f5c4d use environment variables and update current jdk 2023-10-20 13:42:00 +02:00
Armin Schrenk
a7a94099a8 Closes #3075 2023-10-20 13:35:03 +02:00
Armin Schrenk
71a3cbc334 add workflow to check for jdk updates 2023-10-20 13:29:43 +02:00
Armin Schrenk
800b2440b3 Merge pull request #3157 from cryptomator/feature/3113-network-timeout
Time restrict network requests
2023-10-20 12:58:08 +02:00
Sebastian Stenzel
f50a49e7a3 prepare 1.11.0 2023-10-20 12:11:06 +02:00
Sebastian Stenzel
92ece4dfb6 increased request timeout to 10s 2023-10-20 12:06:10 +02:00
Sebastian Stenzel
174225c60e add timeout to OAuth2 requests 2023-10-20 12:03:07 +02:00
Sebastian Stenzel
3071410a22 Merge branch 'develop' into feature/3113-network-timeout 2023-10-20 12:00:16 +02:00
Sebastian Stenzel
5c5777ffc5 Merge pull request #3091 from cryptomator/feature/simplify-out-of-bounds
simplify out-of-bounds check
2023-10-20 11:56:36 +02:00
Sebastian Stenzel
8dd8b93656 Merge pull request #3041 from cryptomator/feature/new-hub-keyloading
Adjusted to Hub 1.3.x API
2023-10-20 11:55:28 +02:00
Armin Schrenk
3b2d455b4a Update dependencies 2023-10-19 17:31:52 +02:00
Sebastian Stenzel
b0dfa22903 removed unused class 2023-10-19 12:49:19 +02:00
Sebastian Stenzel
88b1c28d88 Merge branch 'develop' into feature/new-hub-keyloading 2023-10-19 11:33:13 +02:00
Sebastian Stenzel
5b85d7859a bump webdav-nio-adapter version 2023-10-19 11:28:54 +02:00
Sebastian Stenzel
468eed58d5 cleanup 2023-10-19 10:00:14 +02:00
Sebastian Stenzel
34c17be474 add request timeouts 2023-10-19 10:00:03 +02:00
Sebastian Stenzel
5dedd6b1c1 renamed class again 2023-10-18 11:30:22 +02:00
Sebastian Stenzel
25e8e81686 support apiBaseUrl in hub config 2023-10-18 11:08:42 +02:00
Sebastian Stenzel
1f7ab03bbb undo JEP 443 changes due to bug in javac
leads to invalid class files when built via Maven due to specific combination of javac arguments
2023-10-18 11:01:26 +02:00
Sebastian Stenzel
86f3cb7288 applied suggestions from code review 2023-10-18 09:40:34 +02:00
Sebastian Stenzel
a1b8bf23b4 Merge branch 'develop' into feature/new-hub-keyloading 2023-10-18 09:40:03 +02:00
Sebastian Stenzel
1f21d5ea4c Merge pull request #3129 from cryptomator/feature/jdk21
JDK 21
2023-10-18 09:39:12 +02:00
Sebastian Stenzel
f8ff7201d7 Merge branch 'develop' into feature/new-hub-keyloading 2023-10-18 08:50:34 +02:00
Armin Schrenk
3567c036c3 remove unused imports 2023-10-17 17:25:38 +02:00
Armin Schrenk
0cf1f087ad Closes #3113 2023-10-17 11:36:50 +02:00
Armin Schrenk
209f60727e fix f4ad7aa43d 2023-10-16 16:38:12 +02:00
Armin Schrenk
56624fc079 Replace URL files by hardcoded links in build scripts 2023-10-16 16:35:17 +02:00
Armin Schrenk
218c5243e3 Merge branch 'develop' into feature/uninstall-old-winfsp 2023-10-16 16:29:57 +02:00
Armin Schrenk
560a979e0e Merge pull request #3131 from cryptomator/feature/sign-all-dlls
Feature: Sign all dlls to pass Microsoft Windows Smart App control
2023-10-16 16:21:08 +02:00
Sebastian Stenzel
1debe4c7c8 explicitly set Logback ConfiguratorRank 2023-10-16 16:20:03 +02:00
Sebastian Stenzel
2e2aa77727 update dependencies 2023-10-16 16:19:11 +02:00
Sebastian Stenzel
162ebf6545 Merge branch 'develop' into feature/jdk21 2023-10-16 16:12:10 +02:00
Armin Schrenk
cf09eff640 Use new version of uninstaller:
* logging
* correct reboot
2023-10-13 17:49:48 +02:00
Armin Schrenk
2d503a0edb Merge pull request #3148 from cryptomator/feature/propagate-deleted-discussions
Propagate deleted discussions to the error database
2023-10-13 17:01:45 +02:00
Julian Raufelder
7f7f0a099a Propagate deleted discussions to the error database 2023-10-12 14:11:54 +02:00
Julian Raufelder
109f5d1faa Update the error-db when a discussion is deleted 2023-10-12 10:56:14 +02:00
Armin Schrenk
38a5d40b64 Merge branch 'develop' into feature/uninstall-old-winfsp 2023-10-11 16:14:26 +02:00
Armin Schrenk
9b55f6fc56 Refactor extraction and singing in seperate steps 2023-10-11 12:55:05 +02:00
Sebastian Stenzel
83879f5cfe revert 8e9d54b & 6c5ee14 due to bug in JDK 21
see https://bugs.openjdk.org/browse/JDK-8313323
2023-10-09 16:19:56 +02:00
Armin Schrenk
083ac5a7e0 Merge pull request #3133 from purejava/build-arch
Improve AppImage build script
2023-10-09 13:10:05 +02:00
dependabot[bot]
a7eba377ba Bump org.mockito:mockito-core from 5.5.0 to 5.6.0 (#3142) 2023-10-09 09:58:47 +00:00
dependabot[bot]
4ee1e6d9f1 Bump the github-actions group with 1 update (#3135) 2023-10-04 20:24:43 +00:00
Ralph Plawetzki
24a63c10d0 Build for aarch64 too 2023-09-30 14:54:15 +02:00
Armin Schrenk
0d805b2d43 clean up 2023-09-28 18:34:38 +02:00
Armin Schrenk
7bc47fe6d7 Really fixes #3130 2023-09-28 18:33:26 +02:00
Armin Schrenk
ae50846257 Revert ce466e7715 2023-09-28 18:33:01 +02:00
Armin Schrenk
ce466e7715 fixes #3130 2023-09-28 13:47:51 +02:00
Armin Schrenk
15885545b5 supress some output 2023-09-27 11:13:52 +02:00
Armin Schrenk
29fedcd390 integrate code from test script into github workflow 2023-09-27 10:24:59 +02:00
Armin Schrenk
fadd6b761f add cert import 2023-09-26 17:30:18 +02:00
Armin Schrenk
d857335901 update test script:
* use variables
* use signtool
* find newest signtool version
2023-09-26 16:43:00 +02:00
Armin Schrenk
93b4cbfb2c add test script 2023-09-26 13:42:18 +02:00
Armin Schrenk
625334c6c8 fix windows build script 2023-09-25 16:02:31 +02:00
Sebastian Stenzel
943374856e build using JDK 21 GA 2023-09-25 12:18:01 +02:00
Sebastian Stenzel
e1d7fd92ad Merge branch 'develop' into feature/jdk21
# Conflicts:
#	pom.xml
2023-09-25 12:15:14 +02:00
Sebastian Stenzel
c10dc74818 update integrations-linux to 1.4.0-beta1 2023-09-25 12:12:28 +02:00
Tobias Hagemann
92d9f2c18d try to fix mac build script to be compatible with create-dmg 1.2.0 2023-09-20 15:27:17 +02:00
Armin Schrenk
d7488b6984 fix wrong pom version 2023-09-20 15:16:18 +02:00
Tobias Hagemann
88ad3cd724 Merge branch 'develop' into feature/new-hub-keyloading 2023-09-20 14:38:13 +02:00
Armin Schrenk
ba9e0b0c12 Merge branch 'main' into develop 2023-09-20 11:34:37 +02:00
Armin Schrenk
bbe7255901 Merge branch 'release/1.10.1' 2023-09-20 11:33:39 +02:00
Armin Schrenk
51e55d3e3b finalize 1.10.1 2023-09-20 11:09:37 +02:00
Armin Schrenk
f704dc0de9 prepare 1.10.1 2023-09-20 11:07:50 +02:00
Cryptobot
e858280f30 New Crowdin updates (#3110)
New Crowdin updates (#3110)

New translations strings.properties

Bulgarian; Chinese Traditional; 

[ci skip]
2023-09-20 11:05:33 +02:00
Armin Schrenk
f9b170204a Merge pull request #3118 from cryptomator/feature/3117-disable-update-check
Disable Update Check
2023-09-20 11:02:14 +02:00
Armin Schrenk
0ed7415a0d Merge pull request #3109 from cryptomator/feature/error-dialog-request-with-errorcode
Enhance user agent string when downloading error code database
2023-09-20 11:02:01 +02:00
Armin Schrenk
7a0d50ecca removed unnecessary import 2023-09-20 10:48:26 +02:00
Armin Schrenk
19e035aa33 Merge pull request #3123 from cryptomator/feature/context-menu-focus
Fix addVaultButton misbehavior
2023-09-19 20:56:56 +02:00
Jan-Peter Klein
830970cb75 improved format and naming 2023-09-19 16:29:12 +02:00
Jan-Peter Klein
9b2987d0a2 improved function naming 2023-09-19 16:26:55 +02:00
Armin Schrenk
76a4062f8b update org.cryptomator.integrations:integrations-win from 1.2.2 to 1.2.3 2023-09-19 15:12:45 +02:00
Jan-Peter Klein
113717f955 addVaultButton context menu event filter removed 2023-09-19 15:12:40 +02:00
Jan-Peter Klein
c40ad58028 detached context menu from button to fix misbehavior 2023-09-19 15:03:22 +02:00
Jan-Peter Klein
d6a7efcb7f added OS_NAME, OS_VERSION and OS_ARCH to user-agent 2023-09-19 14:00:45 +02:00
Jan-Peter Klein
910b89d6ce Merge branch 'develop' into feature/error-dialog-request-with-errorcode 2023-09-19 13:19:40 +02:00
Tobias Hagemann
5554dfdd89 fixes #3121 2023-09-19 12:22:24 +02:00
Tobias Hagemann
1657cd50fc fixes #3112 2023-09-19 12:12:27 +02:00
Sebastian Stenzel
57bf5e11b5 Merge branch 'develop' into feature/simplify-out-of-bounds 2023-09-18 19:33:25 +02:00
Sebastian Stenzel
594ca47c85 Merge branch 'develop' into feature/jdk21
# Conflicts:
#	.github/workflows/appimage.yml
#	.github/workflows/mac-dmg.yml
2023-09-18 19:33:06 +02:00
Sebastian Stenzel
6c5ee14c73 rename unused var 2023-09-18 19:29:35 +02:00
Sebastian Stenzel
8e9d54b44b rename unused var 2023-09-18 19:27:28 +02:00
Sebastian Stenzel
70805665bf use features of Java 21 with --enable-preview 2023-09-18 19:21:56 +02:00
Sebastian Stenzel
ac243a706e improve readability 2023-09-18 19:13:03 +02:00
Sebastian Stenzel
aa382ce80d update coffeelibs jdk to 21 2023-09-18 19:10:54 +02:00
Sebastian Stenzel
b7da508ccc Update src/main/java/org/cryptomator/ui/mainwindow/ResizeController.java
Co-authored-by: Bas Ruigrok <Rexbas@proton.me>
2023-09-18 13:19:58 +02:00
Sebastian Stenzel
47bd0ca647 disable update check for PPA builds 2023-09-18 13:10:19 +02:00
Sebastian Stenzel
c5d6c0ce98 add cryptomator.disableUpdateCheck property 2023-09-18 13:03:09 +02:00
Sebastian Stenzel
6017d6b7a9 bump webdav-nio-adapter
containing fixes for CVE-2023-40167, CVE-2023-2976, CVE-2023-37895
2023-09-18 12:34:49 +02:00
Sebastian Stenzel
e31e06b288 added @VisibleForTesting 2023-09-18 10:13:51 +02:00
Sebastian Stenzel
84ac803a7d reordered properties
[ci skip]
2023-09-18 10:10:50 +02:00
Armin Schrenk
bcb970afb1 Update bug.yml
Add missing FUSE option in volume type selection
2023-09-13 13:59:50 +02:00
Jan-Peter Klein
9d640b57ce added build number to user-agent header 2023-09-13 12:31:53 +02:00
Jan-Peter Klein
4c83617847 fixed build error 2023-09-12 18:07:30 +02:00
Jan-Peter Klein
5d7906972b added user-agent header with <product> / <product-version> to HttpRequest 2023-09-12 17:59:08 +02:00
Jan-Peter Klein
666cd4a4f0 enhanced request URI with URLEncoder for errorCode 2023-09-12 17:14:45 +02:00
Jan-Peter Klein
eb4d39e8b4 introduce 'errorCode' parameter in request 2023-09-12 13:34:55 +02:00
Jan-Peter Klein
44ec19122a added port and mountService to vaultSettings 2023-09-12 02:19:08 +02:00
Jan-Peter Klein
8ba2540b35 implemented volume type selection in 'vault options mount' 2023-09-11 14:23:31 +02:00
Armin Schrenk
a1ad89a2e2 Merge branch 'main' into develop [ci skip] 2023-09-11 09:56:35 +02:00
Sebastian Stenzel
4043e3f71f build using JDK 21 2023-09-06 16:22:41 +02:00
Tobias Hagemann
08887f1147 Merge branch 'develop' into feature/new-hub-keyloading 2023-09-06 14:18:11 +02:00
Armin Schrenk
06f288ef76 only execute winfsp-uninstaller on install or repair 2023-08-29 17:51:05 +02:00
Armin Schrenk
ffcad9f1ec reformat 2023-08-29 17:32:49 +02:00
Armin Schrenk
031dc8a31a bump exe uninstaller to new version and skip uninstaller on bundle uninstall 2023-08-29 17:25:43 +02:00
Sebastian Stenzel
cfd433b328 revert to simple of of bounds check
as suggested in https://github.com/cryptomator/cryptomator/pull/3017#discussion_r1264527894 with minor adjustments
2023-08-29 07:26:46 +02:00
Armin Schrenk
422efcc89f [ci skip] use new version of winfsp-uninstaller 2023-08-23 15:43:57 +02:00
Armin Schrenk
c1c0c2e82f [ci skip] use new version of winfsp-uninstaller 2023-08-22 10:47:18 +02:00
Armin Schrenk
c6790fec70 [ci skip] use new version of winfsp-uninstaller 2023-08-17 12:01:58 +02:00
Armin Schrenk
e9ef122e7f Merge branch 'develop' into feature/uninstall-old-winfsp 2023-08-14 15:13:11 +02:00
Sebastian Stenzel
f48963a6d0 Merge branch 'develop' into feature/new-hub-keyloading
# Conflicts:
#	src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
2023-08-09 15:26:03 +02:00
Armin Schrenk
40611b4ebe improve wording 2023-08-01 10:48:42 +02:00
Sebastian Stenzel
6ce34efb52 Merge branch 'develop' into feature/new-hub-keyloading 2023-07-28 15:23:00 +02:00
Armin Schrenk
0800c53aac update to uninstaller-beta4 2023-07-24 10:36:23 +02:00
Armin Schrenk
c6ab05979c cleanup [ci skip] 2023-07-19 16:33:40 +02:00
Armin Schrenk
2c8d5d3d5d update ci script 2023-07-19 16:30:08 +02:00
Armin Schrenk
b76a311ddc Replace winfsp-uninstaller by downloadlink 2023-07-19 16:24:44 +02:00
Armin Schrenk
315bf0d51f Format confirmation dialog 2023-07-14 16:00:49 +02:00
Armin Schrenk
4cdbe50eb6 adjust to new winfsp-uninstaller exe 2023-07-13 17:29:50 +02:00
Armin Schrenk
ead0f0fae1 add exe for winfsp uninstallation and include in burn bundle 2023-07-11 09:41:54 +02:00
Sebastian Stenzel
cd10d38990 adjusted to latest API-changes 2023-07-06 18:57:10 +02:00
Sebastian Stenzel
8cb21c97e3 add mark for future improvement 2023-07-04 16:58:37 +02:00
Sebastian Stenzel
0ad8ce77ef handle "invalid setup code" error properly 2023-07-04 16:55:42 +02:00
Sebastian Stenzel
e358ffd666 added tests 2023-07-04 16:47:54 +02:00
Sebastian Stenzel
496f9a9cd5 docs
[ci skip]
2023-07-04 15:05:22 +02:00
Sebastian Stenzel
61025de0d6 renamed var
[ci skip]
2023-07-04 14:43:56 +02:00
Sebastian Stenzel
f08049b960 fix "register device" on legacy hub instances 2023-07-04 14:34:36 +02:00
Sebastian Stenzel
746c8f54eb Merge branch 'develop' into feature/new-hub-keyloading
# Conflicts:
#	src/main/java/org/cryptomator/ui/keyloading/hub/CreateDeviceDto.java
#	src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java
2023-06-30 16:20:59 +02:00
Sebastian Stenzel
9fc1efa005 adjust labels 2023-06-29 10:38:31 +02:00
Sebastian Stenzel
448eac8ff5 cleanup 2023-06-23 12:06:06 +02:00
Sebastian Stenzel
5a18d086e0 register device using a setup code 2023-06-22 17:16:00 +02:00
Sebastian Stenzel
918ace2eb6 Merge branch 'develop' into feature/new-hub-keyloading 2023-06-14 10:31:58 +02:00
Sebastian Stenzel
fe733967dc send device type in device registration request 2023-06-01 15:06:21 +02:00
Sebastian Stenzel
59f5c0cb12 started new unlock workflow using user-specific private key 2023-05-09 17:09:49 +02:00
217 changed files with 9927 additions and 2069 deletions

View File

@@ -26,6 +26,7 @@ body:
Examples:
- Operating System: Windows 10
- Cryptomator: 1.5.16
- OneDrive: 23.226
- LibreOffice: 7.1.4
value: |
- Operating System:
@@ -43,6 +44,7 @@ body:
- WinFsp (Local Drive)
- FUSE-T
- macFUSE
- FUSE
- WebDAV (Windows Explorer)
- WebDAV (AppleScript)
- WebDAV (gio)
@@ -95,4 +97,4 @@ body:
id: further-info
attributes:
label: Anything else?
description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue?
description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue?

View File

@@ -6,11 +6,41 @@ updates:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "UTC"
timezone: "Etc/UTC"
ignore:
- dependency-name: "org.cryptomator:integrations-api"
versions: ["2.0.0-alpha1"]
groups:
maven-dependencies:
java-test-dependencies:
patterns:
- "org.junit.jupiter:*"
- "org.mockito:*"
- "org.hamcrest:*"
- "com.google.jimfs:jimfs"
maven-build-plugins:
patterns:
- "org.apache.maven.plugins:*"
- "org.jacoco:jacoco-maven-plugin"
- "org.owasp:dependency-check-maven"
- "me.fabriciorby:maven-surefire-junit5-tree-reporter"
- "org.codehaus.mojo:license-maven-plugin"
javafx:
patterns:
- "org.openjfx:*"
java-production-dependencies:
patterns:
- "*"
exclude-patterns:
- "org.openjfx:*"
- "org.apache.maven.plugins:*"
- "org.jacoco:jacoco-maven-plugin"
- "org.owasp:dependency-check-maven"
- "me.fabriciorby:maven-surefire-junit5-tree-reporter"
- "org.codehaus.mojo:license-maven-plugin"
- "org.junit.jupiter:*"
- "org.mockito:*"
- "org.hamcrest:*"
- "com.google.jimfs:jimfs"
- package-ecosystem: "github-actions"
directory: "/" # even for `.github/workflows`

View File

@@ -10,8 +10,8 @@ on:
required: false
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
JAVA_DIST: 'zulu'
JAVA_VERSION: '22.0.2+9'
jobs:
get-version:
@@ -29,16 +29,16 @@ jobs:
include:
- os: ubuntu-latest
appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: 'f522ac2ae4bdd61f0219b7b8d2058ff72a22f36a44378453bcfdcd82f8f5e08c'
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: 'd44bff3b94d5668fdee18a938d7b1269026d663d44765f02d29a9bdfd3fa1eb0'
- os: [self-hosted, Linux, ARM64]
appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: 'c0d80ebbe0aab404ef9ad8b46c05bf533a1e40b39b2720eebd9238d81f6326ca'
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: '3d5457136690c4f5bb9522d38b45218e045bdac13c24aa4c808c7c8d17d039c7'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -68,28 +68,24 @@ jobs:
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B clean package -Pdependency-check,linux -DskipTests
run: mvn -B clean package -Plinux -DskipTests -Djavafx.platform=linux
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink
#Remark: no compression is applied for improved build compression later (here appimage)
run: >
${JAVA_HOME}/bin/jlink
--verbose
--output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
--strip-debug
--compress=1
- name: Prepare additional launcher
run: envsubst '${SEMVER_STR} ${REVISION_NUM}' < dist/linux/launcher-gtk2.properties > launcher-gtk2.properties
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
REVISION_NUM: ${{ needs.get-version.outputs.revNum }}
--compress zip-0
- name: Run jpackage
run: >
${JAVA_HOME}/bin/jpackage
@@ -102,7 +98,7 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator"
@@ -163,7 +159,7 @@ jobs:
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: appimage-${{ matrix.appimage-suffix }}
path: |
@@ -172,8 +168,8 @@ jobs:
cryptomator-*.asc
if-no-files-found: error
- name: Publish AppImage on GitHub Releases
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}

40
.github/workflows/av-whitelist.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: AntiVirus Whitelisting
on:
workflow_call:
inputs:
url:
description: "Url to the file to upload"
required: true
type: string
workflow_dispatch:
inputs:
url:
description: "Url to the file to upload"
required: true
type: string
jobs:
allowlist:
name: Anti Virus Allowlisting
runs-on: ubuntu-latest
steps:
- name: Download file
run: |
curl --remote-name ${{ inputs.url }} -L
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
port: 990
username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
- name: Upload to Avast
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
protocol: ftp
server: whitelisting.avast.com
port: 21
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}

View File

@@ -6,8 +6,8 @@ on:
types: [labeled]
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
JAVA_DIST: 'zulu'
JAVA_VERSION: 22
defaults:
run:
@@ -18,14 +18,14 @@ jobs:
name: Compile and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Cache SonarCloud packages
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
@@ -33,10 +33,10 @@ jobs:
- name: Build and Test
run: >
xvfb-run
mvn -B verify
mvn -B verify -Djavafx.platform=linux
jacoco:report
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
-Pcoverage,dependency-check
-Pcoverage
-Dsonar.projectKey=cryptomator_cryptomator
-Dsonar.organization=cryptomator
-Dsonar.host.url=https://sonarcloud.io
@@ -45,7 +45,7 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Draft a release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
draft: true
discussion_category_name: releases

64
.github/workflows/check-jdk-updates.yml vendored Normal file
View File

@@ -0,0 +1,64 @@
name: Checks JDK version for minor updates
on:
schedule:
- cron: '0 0 1 * *' # run once a month at the first day of month
env:
JDK_VERSION: '22.0.1+8'
JDK_VENDOR: zulu
jobs:
jdk-current:
name: Check out current version
runs-on: ubuntu-latest
outputs:
jdk-date: ${{ steps.get-data.outputs.jdk-date}}
steps:
- uses: actions/setup-java@v4
with:
java-version: ${{ env.JDK_VERSION }}
distribution: ${{ env.JDK_VENDOR }}
check-latest: false
- name: Read JAVA_VERSION_DATE and store in env variable
id: get-data
run: |
date=$(cat ${JAVA_HOME}/release | grep "JAVA_VERSION_DATE=\"" | awk -F'=' '{print $2}' | tr -d '"')
echo "jdk-date=${date}" >> "$GITHUB_OUTPUT"
jdk-latest:
name: Checkout latest jdk version
runs-on: ubuntu-latest
outputs:
jdk-date: ${{ steps.get-data.outputs.jdk-date}}
jdk-version: ${{ steps.get-data.outputs.jdk-version}}
steps:
- uses: actions/setup-java@v4
with:
java-version: 21
distribution: ${{ env.JDK_VENDOR }}
check-latest: true
- name: Read JAVA_VERSION_DATE and store in env variable
id: get-data
run: |
date=$(cat ${JAVA_HOME}/release | grep "JAVA_VERSION_DATE=\"" | awk -F'=' '{print $2}' | tr -d '"')
echo "jdk-date=${date}" >> "$GITHUB_OUTPUT"
version=$(cat ${JAVA_HOME}/release | grep "JAVA_RUNTIME_VERSION=\"" | awk -F'=' '{print $2}' | tr -d '"')
echo "jdk-version=${version}" >> "$GITHUB_OUTPUT"
notify:
name: Notifies for jdk update
runs-on: ubuntu-latest
needs: [jdk-current, jdk-latest]
if: ${{ needs.jdk-latest.outputs.jdk-date }} > ${{ needs.jdk-current.outputs.jdk-date }}
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "JDK update available"
SLACK_MESSAGE: "Cryptomator-CI JDK can be upgraded to ${{ needs.jdk-latest.outputs.jdk-version }}. See https://github.com/cryptomator/cryptomator/wiki/How-to-update-the-build-JDK for instructions."
SLACK_FOOTER: false
MSG_MINIMAL: true

View File

@@ -16,19 +16,21 @@ on:
type: boolean
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'f522ac2ae4bdd61f0219b7b8d2058ff72a22f36a44378453bcfdcd82f8f5e08c'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: 'c0d80ebbe0aab404ef9ad8b46c05bf533a1e40b39b2720eebd9238d81f6326ca'
JAVA_DIST: 'zulu'
JAVA_VERSION: '22.0.2+9'
COFFEELIBS_JDK: 22
COFFEELIBS_JDK_VERSION: '22.0.2+9-0ppa1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'd44bff3b94d5668fdee18a938d7b1269026d663d44765f02d29a9bdfd3fa1eb0'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '3d5457136690c4f5bb9522d38b45218e045bdac13c24aa4c808c7c8d17d039c7'
jobs:
build:
name: Build Debian Package
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- id: versions
name: Get version information
run: |
@@ -42,16 +44,16 @@ jobs:
run: |
sudo add-apt-repository ppa:coffeelibs/openjdk
sudo apt-get update
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.JAVA_VERSION }} libgtk2.0-0
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.COFFEELIBS_JDK }}=${{ env.COFFEELIBS_JDK_VERSION }}
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: true
cache: 'maven'
- name: Run maven
run: mvn -B clean package -Pdependency-check,linux -DskipTests
run: mvn -B clean package -Plinux -Djavafx.platform=linux -DskipTests
- name: Download OpenJFX jmods
id: download-jmods
run: |
@@ -97,7 +99,8 @@ jobs:
run: |
cp -r dist/linux/debian/ pkgdir
export RFC2822_TIMESTAMP=`date --rfc-2822`
envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM}' < dist/linux/debian/rules > pkgdir/debian/rules
export DISABLE_UPDATE_CHECK=${{ inputs.dput }}
envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM} ${DISABLE_UPDATE_CHECK}' < dist/linux/debian/rules > pkgdir/debian/rules
envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog
find . -name "*.jar" >> pkgdir/debian/source/include-binaries
mv pkgdir cryptomator_${{ inputs.ppaver }}
@@ -125,7 +128,7 @@ jobs:
run: |
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: linux-deb-package
path: |
@@ -139,12 +142,11 @@ jobs:
- name: Publish on PPA
if: inputs.dput
run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes
# If ref is a tag, also upload to GitHub Releases:
- name: Publish Debian package on GitHub Releases
if: startsWith(github.ref, 'refs/tags/')
if: startsWith(github.ref, 'refs/tags/') && inputs.dput
env:
GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
run: |
artifacts=$(ls | grep cryptomator*.deb)
gh release upload ${{ github.ref_name }} $artifacts
gh release upload ${{ github.ref_name }} $artifacts

18
.github/workflows/dependency-check.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: OWASP Maven Dependency Check
on:
schedule:
- cron: '0 8 * * 0'
workflow_dispatch:
jobs:
check-dependencies:
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@v1
with:
runner-os: 'ubuntu-latest'
java-distribution: 'temurin'
java-version: 22
check-command: 'mvn -B validate -Pdependency-check -Djavafx.platform=linux'
secrets:
nvd-api-key: ${{ secrets.NVD_API_KEY }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- name: Get download count of latest releases
id: get-stats
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
const query = `query($owner:String!, $name:String!) {

View File

@@ -2,7 +2,7 @@ name: Update Error Database
on:
discussion:
types: [created, edited, category_changed, answered, unanswered]
types: [created, edited, deleted, category_changed, answered, unanswered]
discussion_comment:
types: [created, edited, deleted]
@@ -12,8 +12,9 @@ jobs:
if: github.event.discussion.category.name == 'Errors'
steps:
- name: Query Discussion Data
if: github.event_name == 'discussion_comment' || github.event_name == 'discussion' && github.event.action != 'deleted'
id: query-data
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
const query = `query ($owner: String!, $name: String!, $discussionNumber: Int!) {
@@ -47,8 +48,13 @@ jobs:
- name: Merge Error Code Data
run: |
jq -c '.' ${{ steps.get-gist.outputs.file }} > original.json
echo $DISCUSSION | jq -c '.repository.discussion | .comments = .comments.totalCount | {(.id|tostring) : .}' > new.json
jq -s '.[0] * .[1]' original.json new.json > merged.json
if [ ! -z "$DISCUSSION" ]
then
echo $DISCUSSION | jq -c '.repository.discussion | .comments = .comments.totalCount | {(.id|tostring) : .}' > new.json
jq -s '.[0] * .[1]' original.json new.json > merged.json
else
cat original.json | jq 'del(.[] | select(.url=="https://github.com/cryptomator/cryptomator/discussions/${{ github.event.discussion.number }}"))' > merged.json
fi
env:
DISCUSSION: ${{ steps.query-data.outputs.result }}
- name: Patch Gist

88
.github/workflows/flathub.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: Create PR for flathub
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag'
required: true
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.tag }}
tarball:
name: Determines tarball url and compute checksum
runs-on: ubuntu-latest
needs: [get-version]
if: github.event_name == 'workflow_dispatch' || needs.get-version.outputs.versionType == 'stable'
outputs:
url: ${{ steps.url.outputs.url}}
sha512: ${{ steps.sha512.outputs.sha512}}
steps:
- name: Determine tarball url
id: url
run: |
URL="";
if [[ -n "${{ inputs.tag }}" ]]; then
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ inputs.tag }}.tar.gz"
else
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz"
fi
echo "url=${URL}" >> "$GITHUB_OUTPUT"
- name: Download source tarball and compute checksum
id: sha512
run: |
curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
echo "sha512=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
flathub:
name: Create PR for flathub
runs-on: ubuntu-latest
needs: [tarball, get-version]
env:
FLATHUB_PR_URL: tbd
steps:
- uses: actions/checkout@v4
with:
repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
- name: Update build file
run: |
sed -i -e 's/VERSION: [0-9]\+\.[0-9]\+\.[0-9]\+.*/VERSION: ${{ needs.get-version.outputs.semVerStr }}/g' org.cryptomator.Cryptomator.yaml
sed -i -e 's/sha512: [0-9A-Za-z_\+-]\{128\} #CRYPTOMATOR/sha512: ${{ needs.tarball.outputs.sha512 }} #CRYPTOMATOR/g' org.cryptomator.Cryptomator.yaml
sed -i -e 's;url: https://github.com/cryptomator/cryptomator/archive/refs/tags/[^[:blank:]]\+;url: ${{ needs.tarball.outputs.url }};g' org.cryptomator.Cryptomator.yaml
- name: Commit and push
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
git config push.autoSetupRemote true
git stage .
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
git push
- name: Create pull request
run: |
printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update maven dependencies\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
if: github.event_name == 'release'
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "Flathub release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
SLACK_MESSAGE: "See <${{ env.FLATHUB_PR_URL }}|PR> on how to proceed.>."
SLACK_FOOTER: false
MSG_MINIMAL: true

View File

@@ -22,8 +22,8 @@ on:
value: ${{ jobs.determine-version.outputs.type }}
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
JAVA_DIST: 'zulu'
JAVA_VERSION: 22
jobs:
determine-version:
@@ -35,11 +35,11 @@ jobs:
revNum: ${{ steps.versions.outputs.revNum }}
type: ${{ steps.versions.outputs.type}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -50,7 +50,7 @@ jobs:
if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
SEM_VER_STR=${GITHUB_REF##*/}
elif [[ "${{ inputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+.* ]]; then
SEM_VER_STR="${{ github.event.inputs.version }}"
SEM_VER_STR="${{ inputs.version }}"
else
SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
fi
@@ -71,6 +71,6 @@ jobs:
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
echo "type=${TYPE}" >> $GITHUB_OUTPUT
- name: Validate Version
uses: skymatic/semver-validation-action@v2
uses: skymatic/semver-validation-action@v3
with:
version: ${{ steps.versions.outputs.semVerStr }}
version: ${{ steps.versions.outputs.semVerStr }}

View File

@@ -15,8 +15,8 @@ on:
type: boolean
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
JAVA_DIST: 'zulu'
JAVA_VERSION: '22.0.2+9'
jobs:
get-version:
@@ -32,24 +32,24 @@ jobs:
fail-fast: false
matrix:
include:
- os: macos-11
- os: macos-12
architecture: x64
output-suffix: x64
xcode-path: '/Applications/Xcode_13.2.1.app'
fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '55b8ff7453d59c89ae129f6c9c5ad7b09a5d359568811b376ac1766c14d6a17c'
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '115cb08bb59d880cfff6e51e0bf0dcc45785ed9d456b8b8425597b04da6ab3d4'
- os: [self-hosted, macOS, ARM64]
architecture: aarch64
output-suffix: arm64
xcode-path: '/Applications/Xcode_13.2.1.app'
fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: 'c60f5f19aa847e0e620e0b011e5de68f2c6755641c2141cec27a0b89f612beaf'
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: '813c6748f7c99cb7a579d48b48a087b4682b1fad1fc1a4fe5f9b21cf872b15a7'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -62,7 +62,7 @@ jobs:
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods/
unzip -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
- name: Ensure major jfx version in pom and in jmods is the same
run: |
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
@@ -72,30 +72,31 @@ jobs:
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
if [ "${POM_JFX_VERSION}" -ne "${JMOD_VERSION}" ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != jmod version (${JMOD_VERSION})"
exit 1
fi
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B clean package -Pdependency-check,mac -DskipTests
run: mvn -B -Djavafx.platform=mac clean package -Pmac -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink
#Remark: no compression is applied for improved build compression later (here dmg)
run: >
${JAVA_HOME}/bin/jlink
--verbose
--output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
--strip-debug
--compress=1
--compress zip-0
- name: Run jpackage
run: >
${JAVA_HOME}/bin/jpackage
@@ -108,7 +109,7 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac"
@@ -136,12 +137,14 @@ jobs:
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Generate license for dmg
run: >
mvn -B license:add-third-party
mvn -B -Djavafx.platform=mac license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
@@ -174,7 +177,7 @@ jobs:
run: |
echo "Codesigning jdk files..."
find Cryptomator.app/Contents/runtime/Contents/Home/lib/ -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
find Cryptomator.app/Contents/runtime/Contents/Home/lib/ -name 'jspawnhelper' -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
find Cryptomator.app/Contents/runtime/Contents/Home/lib/ \( -name 'jspawnhelper' -o -name 'pauseengine' -o -name 'simengine' \) -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
echo "Codesigning jar contents..."
find Cryptomator.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
for JAR_PATH in `find Cryptomator.app -name "*.jar"`; do
@@ -193,9 +196,12 @@ jobs:
fi
done
echo "Codesigning Cryptomator.app..."
sed -i '' "s|###APP_IDENTIFIER_PREFIX###|${TEAM_IDENTIFIER}.|g" dist/mac/Cryptomator.entitlements
sed -i '' "s|###TEAM_IDENTIFIER###|${TEAM_IDENTIFIER}|g" dist/mac/Cryptomator.entitlements
codesign --force --deep --entitlements dist/mac/Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app
env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
TEAM_IDENTIFIER: ${{ secrets.MACOS_TEAM_IDENTIFIER }}
- name: Prepare .dmg contents
run: |
mkdir dmg
@@ -222,7 +228,6 @@ jobs:
--app-drop-link 512 245
--eula "dist/mac/dmg/resources/license.rtf"
--icon ".background" 128 758
--icon ".fseventsd" 320 758
--icon ".VolumeIcon.icns" 512 758
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env:
@@ -250,14 +255,16 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: dmg-${{ matrix.output-suffix }}
path: Cryptomator-*.dmg
path: |
Cryptomator-*.dmg
Cryptomator-*.asc
if-no-files-found: error
- name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}

View File

@@ -12,7 +12,7 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
days-before-stale: 14
days-before-close: 0

View File

@@ -19,7 +19,7 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Publish asc on GitHub Releases
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}

View File

@@ -4,8 +4,8 @@ on:
pull_request:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
JAVA_DIST: 'zulu'
JAVA_VERSION: 22
defaults:
run:
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Build and Test
run: xvfb-run mvn -B clean install jacoco:report -Pcoverage,dependency-check
run: xvfb-run mvn -B clean install jacoco:report -Pcoverage -Djavafx.platform=linux

View File

@@ -10,12 +10,22 @@ defaults:
run:
shell: bash
env:
JAVA_DIST: 'zulu'
JAVA_VERSION: 22
jobs:
release-check-precondition:
check-preconditions:
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- id: validate-pom-version
name: Validate POM version
run: |
@@ -34,7 +44,22 @@ jobs:
fi
- name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file
run: |
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\"/>" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\">" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml"
exit 1
fi
fi
- name: Cache NVD DB
uses: actions/cache@v4
with:
path: ~/.m2/repository/org/owasp/dependency-check-data/
key: dependency-check-${{ github.run_id }}
restore-keys: |
dependency-check
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5
- name: Run org.owasp:dependency-check plugin
id: dependency-check
continue-on-error: true
run: mvn -B verify -Pdependency-check -DskipTests -Djavafx.platform=linux
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}

View File

@@ -12,7 +12,7 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
days-before-stale: 365
days-before-close: 90

View File

@@ -11,13 +11,16 @@ on:
isDebug:
description: 'Build debug version with console output'
type: boolean
default: false
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 20
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '18625bbc13c57dbf802486564247a8d8cab72ec558c240a401bf6440384ebd77'
JAVA_DIST: 'zulu'
JAVA_VERSION: '22.0.2+9'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'f9376d200f5c5b85327d575c1ec1482e6455f19916577f7e2fc9be2f48bb29b6'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
defaults:
run:
@@ -37,9 +40,12 @@ jobs:
LOOPBACK_ALIAS: 'cryptomator-vault'
WIN_CONSOLE_FLAG: ''
steps:
- uses: actions/checkout@v3
- name: Upgrade WIX to latest version
run: choco install wixtoolset --version 3.14.1
shell: pwsh
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -71,23 +77,24 @@ jobs:
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B clean package -Pdependency-check,win -DskipTests
run: mvn -B clean package -Pwin -DskipTests -Djavafx.platform=win
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink
#Remark: no compression is applied for improved build compression later (here msi)
run: >
${JAVA_HOME}/bin/jlink
--verbose
--output runtime
--module-path "jfxjmods;${JAVA_HOME}/jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
--strip-debug
--compress=1
--compress zip-0
- name: Change win-console flag if debug is active
if: ${{ inputs.isDebug }}
run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV
@@ -103,10 +110,10 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.win"
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
@@ -143,26 +150,56 @@ jobs:
- name: Fix permissions
run: attrib -r appdir/Cryptomator/Cryptomator.exe
shell: pwsh
- name: Extract integrations DLL for code signing
- name: Extract jars with DLLs for Codesigning
shell: pwsh
run: gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --extract integrations.dll }
run: |
Add-Type -AssemblyName "System.io.compression.filesystem"
$jarFolder = Resolve-Path ".\appdir\Cryptomator\app\mods"
$jarExtractDir = New-Item -Path ".\appdir\jar-extract" -ItemType Directory
#for all jars inspect
Get-ChildItem -Path $jarFolder -Filter "*.jar" | ForEach-Object {
$jar = [Io.compression.zipfile]::OpenRead($_.FullName)
if (@($jar.Entries | Where-Object {$_.Name.ToString().EndsWith(".dll")} | Select-Object -First 1).Count -gt 0) {
#jars containing dlls extract
Set-Location $jarExtractDir
Expand-Archive -Path $_.FullName
}
$jar.Dispose()
}
- name: Extract wixhelper.dll for Codesigning #see https://github.com/cryptomator/cryptomator/issues/3130
shell: pwsh
run: |
New-Item -Path appdir/jpackage-jmod -ItemType Directory
& $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
- name: Codesign
uses: skymatic/code-sign-action@v2
uses: skymatic/code-sign-action@v3
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
description: Cryptomator
timestampUrl: 'http://timestamp.digicert.com'
folder: appdir/Cryptomator
folder: appdir
recursive: true
- name: Repack signed DLL into jar
- name: Replace DLLs inside jars with signed ones
shell: pwsh
run: |
gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --update integrations.dll; Remove-Item integrations.dll}
$jarExtractDir = Resolve-Path ".\appdir\jar-extract"
$jarFolder = Resolve-Path ".\appdir\Cryptomator\app\mods"
Get-ChildItem -Path $jarExtractDir | ForEach-Object {
$jarName = $_.Name
$jarFile = "${jarFolder}\${jarName}.jar"
Set-Location $_
Get-ChildItem -Path $_ -Recurse -File "*.dll" | ForEach-Object {
# update jar with signed dll
jar --file="$jarFile" --update $(Resolve-Path -Relative -Path $_)
}
}
- name: Generate license for MSI
run: >
mvn -B license:add-third-party
mvn -B license:add-third-party "-Djavafx.platform=win"
"-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.outputDirectory=dist/win/resources"
"-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
@@ -181,20 +218,21 @@ jobs:
--dest installer
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
--win-menu
--win-dir-chooser
--win-shortcut-prompt
--win-update-url "https:\\cryptomator.org"
--win-update-url "https:\\cryptomator.org\downloads"
--win-menu-group Cryptomator
--resource-dir dist/win/resources
--license-file dist/win/resources/license.rtf
--file-associations dist/win/resources/FAvaultFile.properties
env:
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
- name: Codesign MSI
uses: skymatic/code-sign-action@v2
uses: skymatic/code-sign-action@v3
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
@@ -212,37 +250,28 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: msi
path: |
Cryptomator-*.msi
Cryptomator-*.asc
if-no-files-found: error
- name: Publish .msi on GitHub Releases
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
*.msi
*.asc
build-exe:
name: Build .exe installer
runs-on: windows-latest
needs: [get-version, build-msi]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Download .msi
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: msi
path: dist/win/bundle/resources
- name: Strip version info from msi file name
run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -250,7 +279,7 @@ jobs:
cache: 'maven'
- name: Generate license for exe
run: >
mvn -B license:add-third-party
mvn -B license:add-third-party "-Djavafx.platform=win"
"-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
"-Dlicense.outputDirectory=dist/win/bundle/resources"
@@ -261,8 +290,11 @@ jobs:
shell: pwsh
- name: Download WinFsp
run: |
$winfspUrl = (Select-String -Path ".\dist\win\bundle\resources\winFspMetaData.wxi" -Pattern '<\?define BundledWinFspDownloadLink="(.+)".*?>').Matches.Groups[1].Value
curl --output dist/win/bundle/resources/winfsp.msi -L $winfspUrl
curl --output dist/win/bundle/resources/winfsp.msi -L ${{ env.WINFSP_MSI }}
shell: pwsh
- name: Download Legacy-WinFsp uninstaller
run: |
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
shell: pwsh
- name: Compile to wixObj file
run: >
@@ -272,7 +304,7 @@ jobs:
-out dist/win/bundle/
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
-dBundleVendor="Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2024 Skymatic GmbH"
-dAboutUrl="https://cryptomator.org"
-dHelpUrl="https://cryptomator.org/contact"
-dUpdateUrl="https://cryptomator.org/downloads/"
@@ -288,7 +320,7 @@ jobs:
-ib installer/unsigned/Cryptomator-Installer.exe
-o tmp/engine.exe
- name: Codesign burn engine
uses: skymatic/code-sign-action@v2
uses: skymatic/code-sign-action@v3
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
@@ -302,7 +334,7 @@ jobs:
-ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe
-o installer/Cryptomator-Installer.exe
- name: Codesign EXE
uses: skymatic/code-sign-action@v2
uses: skymatic/code-sign-action@v3
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
@@ -320,59 +352,68 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: exe
path: |
Cryptomator-*.exe
Cryptomator-*.asc
if-no-files-found: error
publish:
name: Publish installers to the github release
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
runs-on: ubuntu-latest
needs: [build-msi, build-exe]
outputs:
download-url-msi: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-exe: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }}
steps:
- name: Download installers
uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Publish .msi on GitHub Releases
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
id: publish
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
# do not change ordering of filelist, required for correct job output
files: |
Cryptomator-*.exe
Cryptomator-*.asc
*.msi
*.exe
*.asc
allowlist:
name: Anti Virus Allowlisting
if: startsWith(github.ref, 'refs/tags/')
allowlist-msi:
uses: ./.github/workflows/av-whitelist.yml
needs: [publish]
with:
url: ${{ needs.publish.outputs.download-url-msi }}
secrets: inherit
allowlist-exe:
uses: ./.github/workflows/av-whitelist.yml
needs: [publish]
with:
url: ${{ needs.publish.outputs.download-url-exe }}
secrets: inherit
notify-winget:
name: Notify for winget-release
if: needs.get-version.outputs.versionType == 'stable'
needs: [publish, get-version]
runs-on: ubuntu-latest
needs: [build-msi, build-exe]
steps:
- name: Download .msi
uses: actions/download-artifact@v3
with:
name: msi
path: msi
- name: Download .exe
uses: actions/download-artifact@v3
with:
name: exe
path: exe
- name: Collect files
run: |
mkdir files
cp msi/*.msi files
cp exe/*.exe files
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
port: 990
username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
local-dir: files/
- name: Upload to Avast
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
with:
protocol: ftp
server: whitelisting.avast.com
port: 21
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
local-dir: files/
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "MSI of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published."
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml| release to winget>."
SLACK_FOOTER: false
MSG_MINIMAL: true

27
.github/workflows/winget.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Publish MSI to winget-pkgs
on:
workflow_dispatch:
inputs:
tag:
description: 'Release tag'
required: true
jobs:
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Sync winget-pkgs fork
run: |
gh repo sync cryptomator/winget-pkgs -b master --force
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
- name: Submit package
uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: Cryptomator.Cryptomator
version: ${{ inputs.tag }}
release-tag: ${{ inputs.tag }}
installers-regex: '\.msi$'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}

27
.idea/compiler.xml generated
View File

@@ -14,32 +14,29 @@
<option name="dagger.fastInit" value="enabled" />
<option name="dagger.formatGeneratedSource" value="enabled" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.45/dagger-compiler-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.45/dagger-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.49/dagger-compiler-2.49.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.49/dagger-2.49.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-producers/2.45/dagger-producers-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.49/dagger-spi-2.49.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/1.9.20-1.0.14/symbol-processing-api-1.9.20-1.0.14.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.0/kotlin-stdlib-jdk8-1.9.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.20/kotlin-stdlib-1.9.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.0/kotlin-stdlib-jdk7-1.9.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.7.1/error_prone_annotations-2.7.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.45/dagger-spi-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/1.7.0-1.0.6/symbol-processing-api-1.7.0-1.0.6.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.7.0/kotlin-stdlib-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.0/kotlin-stdlib-common-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.0/kotlin-stdlib-jdk8-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.0/kotlin-stdlib-jdk7-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-metadata-jvm/0.5.0/kotlinx-metadata-jvm-0.5.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" />
</processorPath>
<module name="cryptomator" />
</profile>

2
.idea/misc.xml generated
View File

@@ -8,7 +8,7 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_20_PREVIEW" project-jdk-name="20" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" project-jdk-name="22" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" />
<method v="2">
<option name="Make" enabled="true" />
</method>

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" />
<method v="2">
<option name="Make" enabled="true" />
</method>

View File

@@ -5,7 +5,7 @@
</envs>
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" />
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" />
<method v="2">
<option name="Make" enabled="true" />
</method>

View File

@@ -30,9 +30,8 @@ Cryptomator is provided free of charge as an open-source project despite the hig
<table>
<tbody>
<tr>
<td><a href="https://mowcapital.com/"><img src="https://cryptomator.org/img/sponsors/mowcapital.svg" alt="Mow Capital" height="40"></a></td>
<td><a href="https://www.easeus.com/"><img src="https://cryptomator.org/img/sponsors/easeus.png" alt="EaseUS" height="40"></a></td>
<td><a href="https://www.hassmann-it-forensik.de/"><img src="https://cryptomator.org/img/sponsors/hassmannitforensik.png" alt="Hassmann IT-Forensik" height="40"></a></td>
<td><a href="https://mowcapital.com/"><img src="https://cryptomator.org/img/sponsors/mowcapital.svg" alt="Mow Capital" height="28"></a></td>
<td><a href="https://www.route4me.com/"><img src="https://cryptomator.org/img/sponsors/route4me.svg" alt="Route4Me" height="56"></a></td>
</tr>
</tbody>
</table>
@@ -85,7 +84,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies
* JDK 19 (e.g. temurin)
* JDK 22 (e.g. temurin, zulu)
* Maven 3
### Run Maven

View File

@@ -1,4 +1,6 @@
# created during build
# downloaded/created during build
openjfx-jmods.zip
*.jmod
Cryptomator.AppDir
*.AppImage
*.AppImage.zsync

View File

@@ -1,4 +1,5 @@
#!/bin/bash
set -e
cd $(dirname $0)
REVISION_NO=`git rev-list --count HEAD`
@@ -7,31 +8,62 @@ REVISION_NO=`git rev-list --count HEAD`
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found."; exit 1; }
command -v curl >/dev/null 2>&1 || { echo >&2 "curl not found."; exit 1; }
command -v unzip >/dev/null 2>&1 || { echo >&2 "unzip not found."; exit 1; }
VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
SEMVER_STR=${VERSION}
CPU_ARCH=$(uname -p)
if [[ ! "${CPU_ARCH}" =~ x86_64|aarch64 ]]; then echo "Platform ${CPU_ARCH} not supported"; exit 1; fi
mvn -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR}
# compile
mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests -Djavafx.platform=linux
cp ../../../LICENSE.txt ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods
JAVAFX_VERSION=22.0.2
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='d44bff3b94d5668fdee18a938d7b1269026d663d44765f02d29a9bdfd3fa1eb0'
if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='3d5457136690c4f5bb9522d38b45218e045bdac13c24aa4c808c7c8d17d039c7'
fi
# download javaFX jmods
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_linux-${JAVAFX_ARCH}_bin-jmods.zip"
curl -L ${JAVAFX_JMODS_URL} -o openjfx-jmods.zip
echo "${JAVAFX_JMODS_SHA256} openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods
unzip -o -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
JMOD_VERSION=$(jmod describe ./openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout -B -f ../../../pom.xml)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})"
exit 1
fi
# add runtime
${JAVA_HOME}/bin/jlink \
--verbose \
--output runtime \
--module-path "${JAVA_HOME}/jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net \
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
--strip-debug \
--compress=1
--compress zip-0
# create app dir
envsubst '${SEMVER_STR} ${REVISION_NUM}' < ../launcher-gtk2.properties > launcher-gtk2.properties
${JAVA_HOME}/bin/jpackage \
--verbose \
--type app-image \
@@ -44,7 +76,7 @@ ${JAVA_HOME}/bin/jpackage \
--vendor "Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2023 Skymatic GmbH" \
--copyright "(C) 2016 - 2024 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--app-version "${VERSION}.${REVISION_NO}" \
@@ -59,7 +91,6 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.showTrayIcon=true" \
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\"" \
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
--add-launcher cryptomator-gtk2=launcher-gtk2.properties \
--resource-dir ../resources
# transform AppDir
@@ -83,17 +114,17 @@ ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.App
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
# load AppImageTool
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o /tmp/appimagetool.AppImage
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-${CPU_ARCH}.AppImage -o /tmp/appimagetool.AppImage
chmod +x /tmp/appimagetool.AppImage
# create AppImage
/tmp/appimagetool.AppImage \
Cryptomator.AppDir \
cryptomator-${SEMVER_STR}-x86_64.AppImage \
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage \
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${CPU_ARCH}.AppImage.zsync'
echo ""
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-x86_64.AppImage"
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage"
echo ""
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir runtime squashfs-root openjfx-jmods; rm /tmp/appimagetool.AppImage openjfx-jmods.zip"
echo ""
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir jni runtime squashfs-root; rm launcher-gtk2.properties /tmp/appimagetool.AppImage"
echo ""

View File

@@ -5,26 +5,27 @@
<metadata_license>FSFAP</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<name>Cryptomator</name>
<summary>Multi-platform client-side encryption tool optimized for cloud storages</summary>
<summary>Encryption made easy and optimized for the cloud</summary>
<description>
<p>
Cryptomator provides transparent, client-side encryption for your cloud. Protect your documents from unauthorized
access. Cryptomator is free and open source software, so you can rest assured there are no backdoors.
Cryptomator provides easy-to-use, transparent, client-side encryption for your cloud.
It protects your documents from unauthorized access and prying eyes, while you will still be able to view and edit your documents locally.
By not requiring any registration or account and performing all encryption locally, it gives you back control over your data and ensures your privacy.
Cryptomator is offered for all major platforms (including Android and iOS).
</p>
<p>
Cryptomator encrypts file contents and names using AES. Your passphrase is protected against bruteforcing attempts
using scrypt. Directory structures get obfuscated. The only thing which cannot be encrypted without breaking your
cloud synchronization is the modification date of your files.
Cryptomator encrypts file contents and names using the widespread industry standard AES.
Your passphrase is protected against brute forcing attempts using scrypt.
Additionally, directory structures get obfuscated.
For more info about the Cryptomator encryption scheme, check out the online documentation.
</p>
<p>
Cryptomator is a free and open source software licensed under the GPLv3. This allows anyone to check our code. It
is impossible to introduce backdoors for third parties. Also we cannot hide vulnerabilities. And the best thing
is: There is no need to trust us, as you can control us!
</p>
<p>
Vendor lock-ins are impossible. Even if we decided to stop development: The source code is already cloned by
hundreds of other developers. As you don't need an account, you will never stand in front of locked doors.
Cryptomator is a free and open-source software licensed under the GPLv3.
This allows anyone to check our code.
Thus, it is impossible to introduce backdoors for third parties or to hide vulnerabilities, so you do not need to trust Cryptomator.
Also, vendor lock-ins are impossible.
Even if we decided to stop development: The source code is already cloned by hundreds of other developers and development can be picked up by others.
</p>
</description>
@@ -42,7 +43,7 @@
</provides>
<screenshots>
<screenshot>
<screenshot type="default">
<caption>Light theme</caption>
<image>https://user-images.githubusercontent.com/11858409/156986109-6e58f59c-8b8c-4501-b33b-bb1e33007cea.png</image>
</screenshot>
@@ -52,42 +53,128 @@
</screenshot>
</screenshots>
<branding>
<color type="primary" scheme_preference="light">#EBF5EB</color>
<color type="primary" scheme_preference="dark">#2F4858</color>
</branding>
<url type="homepage">https://cryptomator.org/</url>
<url type="bugtracker">https://github.com/cryptomator/cryptomator/issues/</url>
<url type="donation">https://cryptomator.org/donate</url>
<url type="faq">https://community.cryptomator.org/c/kb/faq</url>
<url type="help">https://community.cryptomator.org/</url>
<url type="help">https://docs.cryptomator.org/</url>
<url type="translate">https://translate.cryptomator.org</url>
<developer_name>Skymatic GmbH</developer_name>
<developer id="de.skymatic">
<name>Skymatic GmbH</name>
</developer>
<content_rating type="oars-1.1">
<content_attribute id="social-info">mild</content_attribute> <!-- update checker connects to https://api.cryptomator.org/updates/latestVersion.json -->
</content_rating>
<releases>
<release date="2023-09-11" version="1.10.0"/>
<release date="2023-08-11" version="1.9.4"/>
<release date="2023-08-07" version="1.9.3"/>
<release date="2023-07-24" version="1.9.2"/>
<release date="2023-06-07" version="1.9.1"/>
<release date="2023-05-30" version="1.9.0"/>
<release date="2023-04-25" version="1.8.0"/>
<release date="2023-04-07" version="1.7.5"/>
<release date="2023-04-05" version="1.7.4"/>
<release date="2023-03-15" version="1.7.3"/>
<release date="2023-03-07" version="1.7.2"/>
<release date="2023-03-03" version="1.7.1"/>
<release date="2023-03-01" version="1.7.0"/>
<release date="2022-12-14" version="1.6.17"/>
<release date="2022-12-06" version="1.6.16"/>
<release date="2022-10-06" version="1.6.15"/>
<release date="2022-08-31" version="1.6.14"/>
<release date="2022-07-27" version="1.6.12"/>
<release date="2022-07-26" version="1.6.11"/>
<release date="2022-05-03" version="1.6.10"/>
<release date="2022-04-27" version="1.6.9"/>
<release date="2022-03-30" version="1.6.8"/>
<release date="2021-12-16" version="1.6.5"/>
<release date="2024-11-19" version="1.14.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.14.2</url>
</release>
<release date="2024-09-17" version="1.14.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.14.0</url>
</release>
<release date="2024-06-26" version="1.13.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.13.0</url>
</release>
<release date="2024-03-27" version="1.12.4">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.4</url>
</release>
<release date="2024-02-27" version="1.12.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.3</url>
</release>
<release date="2024-02-09" version="1.12.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.2</url>
</release>
<release date="2024-02-07" version="1.12.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.1</url>
</release>
<release date="2024-02-06" version="1.12.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.0</url>
</release>
<release date="2023-12-05" version="1.11.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.11.1</url>
</release>
<release date="2023-11-08" version="1.11.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.11.0</url>
</release>
<release date="2023-09-20" version="1.10.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.10.1</url>
</release>
<release date="2023-09-11" version="1.10.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.10.0</url>
</release>
<release date="2023-08-11" version="1.9.4">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.4</url>
</release>
<release date="2023-08-07" version="1.9.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.3</url>
</release>
<release date="2023-07-24" version="1.9.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.2</url>
</release>
<release date="2023-06-07" version="1.9.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.1</url>
</release>
<release date="2023-05-30" version="1.9.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.0</url>
</release>
<release date="2023-04-25" version="1.8.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.8.0</url>
</release>
<release date="2023-04-07" version="1.7.5">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.5</url>
</release>
<release date="2023-04-05" version="1.7.4">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.4</url>
</release>
<release date="2023-03-15" version="1.7.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.3</url>
</release>
<release date="2023-03-07" version="1.7.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.2</url>
</release>
<release date="2023-03-03" version="1.7.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.1</url>
</release>
<release date="2023-03-01" version="1.7.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.0</url>
</release>
<release date="2022-12-14" version="1.6.17">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.17</url>
</release>
<release date="2022-12-06" version="1.6.16">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.16</url>
</release>
<release date="2022-10-06" version="1.6.15">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.15</url>
</release>
<release date="2022-08-31" version="1.6.14">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.14</url>
</release>
<release date="2022-07-27" version="1.6.12">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.12</url>
</release>
<release date="2022-07-26" version="1.6.11">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.11</url>
</release>
<release date="2022-05-03" version="1.6.10">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.10</url>
</release>
<release date="2022-04-27" version="1.6.9">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.9</url>
</release>
<release date="2022-03-30" version="1.6.8">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.8</url>
</release>
<release date="2021-12-16" version="1.6.5">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.5</url>
</release>
</releases>
</component>

View File

@@ -2,7 +2,7 @@ Source: cryptomator
Maintainer: Cryptobot <releases@cryptomator.org>
Section: utils
Priority: optional
Build-Depends: debhelper (>=10), coffeelibs-jdk-20, libgtk2.0-0, libgtk-3-0, libxxf86vm1, libgl1
Build-Depends: debhelper (>=10), coffeelibs-jdk-22 (>= 22.0.1+8-0ppa1), libgtk-3-0, libxxf86vm1, libgl1
Standards-Version: 4.5.0
Homepage: https://cryptomator.org
Vcs-Git: https://github.com/cryptomator/cryptomator.git

View File

@@ -4,11 +4,11 @@ Upstream-Contact: Cryptomator <info@cryptomator.org>
Source: https://cryptomator.org
Files: *
Copyright: 2016-2023 Skymatic GmbH
Copyright: 2016-2024 Skymatic GmbH
License: GPL-3+
Files: debian/org.cryptomator.Cryptomator.appdata.xml
Copyright: 2016-2023 Skymatic GmbH
Copyright: 2016-2024 Skymatic GmbH
License: FSFAP
License: GPL-3+

View File

@@ -4,7 +4,7 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
JAVA_HOME = /usr/lib/jvm/java-20-coffeelibs
JAVA_HOME = /usr/lib/jvm/java-22-coffeelibs
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
ifeq ($(DEB_BUILD_ARCH),amd64)
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
@@ -24,15 +24,16 @@ override_dh_auto_clean:
override_dh_auto_build:
mkdir resources
ln -s ../common/org.cryptomator.Cryptomator512.png resources/cryptomator.png
# Remark: no compression is applied for improved build compression later (here deb)
$(JAVA_HOME)/bin/jlink \
--output runtime \
--module-path "${JMODS_PATH}" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
--strip-debug \
--compress=2
--compress zip-0
$(JAVA_HOME)/bin/jpackage \
--type app-image \
--runtime-image runtime \
@@ -44,7 +45,7 @@ override_dh_auto_build:
--vendor "Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2023 Skymatic GmbH" \
--copyright "(C) 2016 - 2024 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \
@@ -59,6 +60,8 @@ override_dh_auto_build:
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"/usr/share/icons/hicolor/symbolic/apps\"" \
--java-options "-Dcryptomator.buildNumber=\"deb-${REVISION_NUM}\"" \
--java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\"" \
--java-options "-Dcryptomator.disableUpdateCheck=\"${DISABLE_UPDATE_CHECK}\"" \
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
--app-version "${VERSION_NUM}.${REVISION_NUM}" \
--resource-dir resources \
--verbose

View File

@@ -1,14 +0,0 @@
java-options=-Xss5m \
-Xmx256m \
--enable-preview \
--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64 \
-Dfile.encoding=\"utf-8\" \
-Dcryptomator.appVersion=\"${SEMVER_STR}\" \
-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\" \
-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\" \
-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\" \
-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\" \
-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\" \
-Dcryptomator.showTrayIcon=false \
-Dcryptomator.buildNumber=\"appimage-${REVISION_NUM}\" \
-Djdk.gtk.version=2

1
dist/mac/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
embedded.provisionprofile

View File

@@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>###APP_IDENTIFIER_PREFIX###org.cryptomator</string>
<key>com.apple.developer.team-identifier</key>
<string>###TEAM_IDENTIFIER###</string>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
@@ -10,5 +14,9 @@
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>###APP_IDENTIFIER_PREFIX###org.cryptomator</string>
</array>
</dict>
</plist>

View File

@@ -1,6 +1,9 @@
# created during build
# downloaded/created during build
Cryptomator.app/
runtime/
dmg/
*.dmg
license.rtf
license.rtf
openjfx-jmods.zip
*.jmod
Cryptomator.entitlements

56
dist/mac/dmg/build.sh vendored
View File

@@ -1,12 +1,15 @@
#!/bin/bash
# parse options
usage() { echo "Usage: $0 [-s <codesign-identity>]" 1>&2; exit 1; }
while getopts ":s:" o; do
usage() { echo "Usage: $0 [-s <codesign-identity>] [-t <team-identifier>]" 1>&2; exit 1; }
while getopts ":s:t:" o; do
case "${o}" in
s)
CODESIGN_IDENTITY=${OPTARG}
;;
t)
TEAM_IDENTIFIER=${OPTARG}
;;
*)
usage
;;
@@ -21,7 +24,7 @@ rm -rf runtime dmg *.app *.dmg
# set variables
APP_NAME="Cryptomator"
VENDOR="Skymatic GmbH"
COPYRIGHT_YEARS="2016 - 2023"
COPYRIGHT_YEARS="2016 - 2024"
PACKAGE_IDENTIFIER="org.cryptomator"
MAIN_JAR_GLOB="cryptomator-*.jar"
MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
@@ -29,13 +32,17 @@ REVISION_NO=`git rev-list --count HEAD`
VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
FUSE_LIB="FUSE-T"
ARCH="undefined"
JAVAFX_VERSION=22.0.2
JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then
ARCH="aarch64"
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="813c6748f7c99cb7a579d48b48a087b4682b1fad1fc1a4fe5f9b21cf872b15a7"
else
ARCH="x64"
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="115cb08bb59d880cfff6e51e0bf0dcc45785ed9d456b8b8425597b04da6ab3d4"
fi
OPENJFX_JMODS="https://download2.gluonhq.com/openjfx/20.0.2/openjfx-20.0.2_osx-${ARCH}_bin-jmods.zip"
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
# check preconditions
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
@@ -47,35 +54,37 @@ if [ -n "${CODESIGN_IDENTITY}" ]; then
fi
# download and check jmods
curl -L ${OPENJFX_JMODS} -o openjfx-jmods.zip
curl -L ${JAVAFX_JMODS_URL} -o openjfx-jmods.zip
echo "${JAVAFX_JMODS_SHA256} openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods/
unzip -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods/
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(mvn -f../../../pom.xml help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != jmod version (${JMOD_VERSION})"
exit 1
if [ "${POM_JFX_VERSION}" -ne "${JMOD_VERSION}" ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != jmod version (${JMOD_VERSION})"
exit 1
fi
# compile
mvn -B -f../../../pom.xml clean package -DskipTests -Pmac
mvn -B -Djavafx.platform=mac -f../../../pom.xml clean package -DskipTests -Pmac
cp ../../../LICENSE.txt ../../../target
cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
# add runtime
${JAVA_HOME}/bin/jlink \
--output runtime \
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
--strip-debug \
--compress=1
--compress zip-0
# create app dir
${JAVA_HOME}/bin/jpackage \
@@ -115,9 +124,10 @@ ${JAVA_HOME}/bin/jpackage \
cp ../resources/${APP_NAME}-Vault.icns ${APP_NAME}.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
# generate license
mvn -B -f../../../pom.xml license:add-third-party \
mvn -B -Djavafx.platform=mac -f../../../pom.xml license:add-third-party \
-Dlicense.thirdPartyFilename=license.rtf \
-Dlicense.outputDirectory=dist/mac/dmg/resources \
-Dlicense.fileTemplate=resources/licenseTemplate.ftl \
@@ -127,7 +137,11 @@ mvn -B -f../../../pom.xml license:add-third-party \
-Dlicense.licenseMergesUrl=file://$(pwd)/../../../license/merges
# codesign
if [ -n "${CODESIGN_IDENTITY}" ]; then
if [ -n "${CODESIGN_IDENTITY}" ] && [ -n "${TEAM_IDENTIFIER}" ]; then
echo "Codesigning jdk files..."
find ${APP_NAME}.app/Contents/runtime/Contents/Home/lib/ -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
find ${APP_NAME}.app/Contents/runtime/Contents/Home/lib/ -name 'jspawnhelper' -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
echo "Codesigning jar contents..."
find ${APP_NAME}.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
for JAR_PATH in `find ${APP_NAME}.app -name "*.jar"`; do
if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
@@ -145,7 +159,10 @@ if [ -n "${CODESIGN_IDENTITY}" ]; then
fi
done
echo "Codesigning ${APP_NAME}.app..."
codesign --force --deep --entitlements ../${APP_NAME}.entitlements -o runtime -s ${CODESIGN_IDENTITY} ${APP_NAME}.app
cp ../${APP_NAME}.entitlements .
sed -i '' "s|###APP_IDENTIFIER_PREFIX###|${TEAM_IDENTIFIER}.|g" ${APP_NAME}.entitlements
sed -i '' "s|###TEAM_IDENTIFIER###|${TEAM_IDENTIFIER}|g" ${APP_NAME}.entitlements
codesign --force --deep --entitlements ${APP_NAME}.entitlements -o runtime -s ${CODESIGN_IDENTITY} ${APP_NAME}.app
fi
# prepare dmg contents
@@ -168,6 +185,5 @@ create-dmg \
--app-drop-link 512 245 \
--eula "resources/license.rtf" \
--icon ".background" 128 758 \
--icon ".fseventsd" 320 758 \
--icon ".VolumeIcon.icns" 512 758 \
${APP_NAME}-${VERSION_NO}.dmg dmg

View File

@@ -17,7 +17,7 @@
\f1\b0 \
\
\f0\b \'a9 2016 \'96 2023 Skymatic GmbH
\f0\b \'a9 2016 \'96 2024 Skymatic GmbH
\f1\b0 \
\
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\

View File

@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>LSMinimumSystemVersion</key>
<string>10.13.0</string>
<string>11</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleAllowMixedLocalizations</key>

3
dist/win/.gitignore vendored
View File

@@ -4,4 +4,7 @@ installer
*.wixobj
*.pdb
*.msi
*.exe
*.jmod
resources/jfxJmods.zip
license.rtf

48
dist/win/build.ps1 vendored
View File

@@ -41,7 +41,7 @@ Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
$copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor"
# compile
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin "-Djavafx.platform=win"
Copy-Item "$buildDir\..\..\target\$MainJarGlob.jar" -Destination "$buildDir\..\..\target\mods"
# add runtime
@@ -51,34 +51,36 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
}
## download jfx jmods
$jmodsVersion='20.0.2'
$jmodsUrl = "https://download2.gluonhq.com/openjfx/${jmodsVersion}/openjfx-${jmodsVersion}_windows-x64_bin-jmods.zip"
$jfxJmodsChecksum = '18625bbc13c57dbf802486564247a8d8cab72ec558c240a401bf6440384ebd77'
$jfxJmodsZip = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $jfxJmodsZip) ) {
Write-Output "Downloading ${jmodsUrl}..."
Invoke-WebRequest $jmodsUrl -OutFile $jfxJmodsZip # redirects are followed by default
$javaFxVersion='22.0.2'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'f9376d200f5c5b85327d575c1ec1482e6455f19916577f7e2fc9be2f48bb29b6'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
Write-Output "Downloading ${javaFxJmodsUrl}..."
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
}
$jmodsChecksumActual = $(Get-FileHash -Path $jfxJmodsZip -Algorithm SHA256).Hash
if( $jmodsChecksumActual -ne $jfxJmodsChecksum ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $jfxJmodsChecksum, actual: $jmodsChecksumActual"
exit 1;
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256
, actual: $jmodsChecksumActual"
exit 1;
}
Expand-Archive -Path $jfxJmodsZip -DestinationPath ".\resources\"
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods"
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
## create custom runtime
& "$Env:JAVA_HOME\bin\jlink" `
--verbose `
--output runtime `
--module-path "$Env:JAVA_HOME/jmods;$buildDir/resources/javafx-jmods" `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--strip-native-commands `
--no-header-files `
--no-man-pages `
--strip-debug `
--compress=1
--compress "zip-0" #do not compress to have improved msi compression
$appPath = ".\$AppName"
if ($clean -and (Test-Path -Path $appPath)) {
@@ -98,7 +100,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
--vendor $Vendor `
--copyright $copyright `
--java-options "--enable-preview" `
--java-options "--enable-native-access=org.cryptomator.jfuse.win" `
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" `
--java-options "-Xss5m" `
--java-options "-Xmx256m" `
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
@@ -120,7 +122,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
--icon resources/$AppName.ico
#Create RTF license for msi
&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" `
"-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\resources\" `
@@ -143,6 +145,7 @@ try {
# create .msi
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
$Env:JP_WIXHELPER_DIR = "."
& "$Env:JAVA_HOME\bin\jpackage" `
--verbose `
--type msi `
@@ -164,7 +167,7 @@ $Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
--file-associations resources/FAvaultFile.properties
#Create RTF license for bundle
&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" `
"-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\bundle\resources\" `
@@ -174,10 +177,15 @@ $Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges"
# download Winfsp
$winfspMsiUrl= (Select-String -Path ".\bundle\resources\winFspMetaData.wxi" -Pattern '<\?define BundledWinFspDownloadLink="(.+)".*?>').Matches.Groups[1].Value
$winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi'
Write-Output "Downloading ${winfspMsiUrl}..."
Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default
# download legacy-winfsp uninstaller
$winfspUninstaller= 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
Write-Output "Downloading ${winfspUninstaller}..."
Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninstaller.exe" # redirects are followed by default
# copy MSI to bundle resources
Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi"

View File

@@ -1,5 +1,6 @@
<?xml version="1.0"?>
<!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html-->
<!-- Attributes explicitly not used:
@@ -10,21 +11,10 @@
AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico">
<!-- detect outdated WinFsp installations -->
<?include "resources\winFspMetaData.wxi" ?>
<util:ProductSearch
Variable="InstalledWinFspVersion"
Variable="InstalledLegacyWinFspVersion"
Result="version"
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"
/>
<!-- Note: The bundle engine takes the Message format literaly -->
<bal:Condition Message=
"The WinFsp driver used by Cryptomator is outdated and must be removed before the installation.
1. Open the view of installed apps
2. Search for &quot;WinFsp&quot;
3. Uninstall the listed application
4. Reboot your device
5. Restart this installer">(InstalledWinFspVersion = v0.0.0.0) OR ($(var.BundledWinFspVersion) &lt;= InstalledWinFspVersion)</bal:Condition>
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"/>
<!-- for definition of the standard themes, see https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/-->
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
@@ -36,26 +26,41 @@
SuppressOptionsUI="yes"
ThemeFile="bundle\customBootstrapperTheme.xml"
LocalizationFile="bundle\customBootstrapperTheme.wxl"
LogoFile="bundle\resources\logo.png"
/>
LogoFile="bundle\resources\logo.png"/>
<Payload SourceFile="bundle\resources\logoSide.png" />
</BootstrapperApplicationRef>
<Chain>
<ExePackage Cache="yes" PerMachine="yes" Permanent="no"
SourceFile="resources\winfsp-uninstaller.exe"
DisplayName="Removing outdated WinFsp Driver"
Description="Executable to remove old winfsp"
DetectCondition="false"
InstallCondition="(InstalledLegacyWinFspVersion &lt;&gt; v0.0.0.0) AND ((WixBundleAction = 7) OR (WixBundleAction = 5))">
<CommandLine Condition="WixBundleUILevel &lt;= 3" InstallArgument="-q -l &quot;[WixBundleLog].winfsp-uninstaller.log&quot;" RepairArgument="-q" UninstallArgument="-s" />
<!-- XML allows line breaks in attributes, hence keep the line breaks here -->
<CommandLine Condition="WixBundleUILevel &gt; 3" InstallArgument="-l &quot;[WixBundleLog].winfsp-uninstaller.log&quot; -t &quot;Cryptomator Installer&quot; -m &quot;Cryptomator requires a newer version of the WinFsp driver. The installer will now uninstall WinFsp, possibly reboot, and afterwards proceed with the installation.
Do you want to continue?&quot;" RepairArgument="-q" UninstallArgument="-s" />
<ExitCode Behavior="success" Value="0"/>
<ExitCode Behavior="success" Value="1"/>
<ExitCode Behavior="error" Value="2"/>
<ExitCode Behavior="error" Value="3"/>
<ExitCode Behavior="forceReboot" Value="4"/>
<ExitCode Behavior="success" Value="5"/>
</ExePackage>
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/msipackage.html-->
<MsiPackage
SourceFile="resources\Cryptomator.msi"
CacheId="cryptomator-bundle-cryptomator"
DisplayInternalUI="no"
Visible="no"
/>
Visible="no"/>
<MsiPackage
SourceFile="resources\winfsp.msi"
CacheId="cryptomator-bundle-winfsp"
Visible="yes"
DisplayInternalUI="no"
Vital="no"
Permanent="yes"
/>
Permanent="yes"/>
</Chain>
</Bundle>
</Wix>

View File

@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0
\pard\tx283\tx567\tx850\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
\par
\b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\b\'a9 2016 \'96 2024 Skymatic GmbH \b0\par
\par
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
\par

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- A version number MUST be prefixed with letter "v", otherwise it is considered a normal string -->
<?define BundledWinFspVersion="v1.12.22339" ?>
<?define BundledWinFspDownloadLink="https://github.com/winfsp/winfsp/releases/download/v1.12.22339/winfsp-1.12.22339.msi" ?> <!-- Only used by external build scripts -->
</Include>

View File

@@ -1,5 +0,0 @@
@echo off
:: see comments in file ./version170-migrate-settings.ps1
cd %~dp0
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command .\version170-migrate-settings.ps1

View File

@@ -1,35 +0,0 @@
# This script migrates Cryptomator settings for all local users on Windows in case the users uses custom directories as mountpoint
# See also https://github.com/cryptomator/cryptomator/pull/2654.
#
# TODO: This script should be evaluated in a yearly interval if it is still needed and if not, should be removed
#
#Requires -RunAsAdministrator
#Get all active, local user profiles
$profileList = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
Get-ChildItem $profileList | ForEach-Object {
$profilePath = $_.GetValue("ProfileImagePath")
$settingsPath = "$profilePath\AppData\Roaming\Cryptomator\settings.json"
if(!(Test-Path -Path $settingsPath -PathType Leaf)) {
#No settings file, nothing to do.
return;
}
$settings = Get-Content -Path $settingsPath | ConvertFrom-Json
if($settings.preferredVolumeImpl -ne "FUSE") {
#Fuse not used, nothing to do
return;
}
#check if customMountPoints are used
$atLeastOneCustomPath = $false;
foreach ($vault in $settings.directories){
$atLeastOneCustomPath = $atLeastOneCustomPath -or ($vault.useCustomMountPath -eq "True")
}
#if so, use WinFsp Local Drive
if( $atLeastOneCustomPath ) {
Add-Member -Force -InputObject $settings -Name "mountService" -Value "org.cryptomator.frontend.fuse.mount.WinFspMountProvider" -MemberType NoteProperty
$newSettings = $settings | Select-Object * -ExcludeProperty "preferredVolumeImpl"
ConvertTo-Json $newSettings | Set-Content -Path $settingsPath
}
}

View File

@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0
\pard\tx283\tx567\tx850\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
\par
\b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\b\'a9 2016 \'96 2024 Skymatic GmbH \b0\par
\par
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
\par

View File

@@ -70,7 +70,7 @@
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
<?endif?>
<Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
<Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll"/>
<CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" />
<?ifndef SkipCryptomatorLegacyCheck ?>
@@ -139,11 +139,6 @@
Sequence="execute" Before="PatchWebDAV" />
<CustomAction Id="PatchWebDAV" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- Special Settings migration for 1.7.0,. Should be removed eventually, for more info, see ../contrib/version170-migrate-settings.ps1-->
<SetProperty Id="V170MigrateSettings" Value="&quot;[INSTALLDIR]version170-migrate-settings.bat&quot;"
Sequence="execute" Before="V170MigrateSettings" />
<CustomAction Id="V170MigrateSettings" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- Running App detection and exit -->
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<util:CloseApplication
@@ -195,7 +190,6 @@
<RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications -->
<Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
</InstallExecuteSequence>
<InstallUISequence>

84
pom.xml
View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId>
<version>1.10.0</version>
<version>1.14.2</version>
<name>Cryptomator Desktop App</name>
<organization>
@@ -26,56 +26,60 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>20</project.jdk.version>
<project.jdk.version>22</project.jdk.version>
<!-- Group IDs of jars that need to stay on the class path for now -->
<!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) -->
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.6.7</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.3.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.2.2</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.2.1</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.3.0-beta6</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>3.0.0</cryptomator.fuse.version>
<cryptomator.dokany.version>2.0.0</cryptomator.dokany.version>
<cryptomator.webdav.version>2.0.3</cryptomator.webdav.version>
<cryptomator.cryptofs.version>2.7.1</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.4.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.3.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.2.4</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.5.1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.0.2</cryptomator.fuse.version>
<cryptomator.webdav.version>2.0.7</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<commons-lang3.version>3.13.0</commons-lang3.version>
<dagger.version>2.48</dagger.version>
<commons-lang3.version>3.16.0</commons-lang3.version>
<dagger.version>2.51.1</dagger.version>
<easybind.version>2.2</easybind.version>
<guava.version>32.1.2-jre</guava.version>
<jackson.version>2.15.2</jackson.version>
<javafx.version>20.0.2</javafx.version>
<guava.version>33.3.0-jre</guava.version>
<jackson.version>2.17.2</jackson.version>
<javafx.version>22.0.2</javafx.version>
<jwt.version>4.4.0</jwt.version>
<nimbus-jose.version>9.31</nimbus-jose.version>
<logback.version>1.4.11</logback.version>
<slf4j.version>2.0.9</slf4j.version>
<tinyoauth2.version>0.6.0</tinyoauth2.version>
<zxcvbn.version>1.8.2</zxcvbn.version>
<nimbus-jose.version>9.37.3</nimbus-jose.version>
<logback.version>1.5.7</logback.version>
<slf4j.version>2.0.16</slf4j.version>
<tinyoauth2.version>0.8.0</tinyoauth2.version>
<zxcvbn.version>1.9.0</zxcvbn.version>
<!-- test dependencies -->
<junit.jupiter.version>5.10.0</junit.jupiter.version>
<mockito.version>5.5.0</mockito.version>
<hamcrest.version>2.2</hamcrest.version>
<junit.jupiter.version>5.11.0</junit.jupiter.version>
<mockito.version>5.12.0</mockito.version>
<hamcrest.version>3.0</hamcrest.version>
<!-- build-time dependencies -->
<jetbrains.annotations.version>24.0.1</jetbrains.annotations.version>
<dependency-check.version>8.4.0</dependency-check.version>
<jacoco.version>0.8.10</jacoco.version>
<license-generator.version>2.2.0</license-generator.version>
<junit-tree-reporter.version>1.2.1</junit-tree-reporter.version>
<mvn-compiler.version>3.11.0</mvn-compiler.version>
<jetbrains.annotations.version>24.1.0</jetbrains.annotations.version>
<dependency-check.version>10.0.3</dependency-check.version>
<jacoco.version>0.8.12</jacoco.version>
<license-generator.version>2.4.0</license-generator.version>
<junit-tree-reporter.version>1.3.0</junit-tree-reporter.version>
<mvn-compiler.version>3.13.0</mvn-compiler.version>
<mvn-resources.version>3.3.1</mvn-resources.version>
<mvn-dependency.version>3.6.0</mvn-dependency.version>
<mvn-surefire.version>3.1.2</mvn-surefire.version>
<mvn-jar.version>3.3.0</mvn-jar.version>
<mvn-dependency.version>3.7.1</mvn-dependency.version>
<mvn-surefire.version>3.4.0</mvn-surefire.version>
<mvn-jar.version>3.4.2</mvn-jar.version>
</properties>
<dependencies>
<!-- Cryptomator Libs -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
@@ -86,11 +90,6 @@
<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>
@@ -164,11 +163,18 @@
<artifactId>nimbus-jose-jwt</artifactId>
<version>${nimbus-jose.version}</version>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- EasyBind -->
<dependency>
@@ -460,17 +466,19 @@
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<configuration>
<cveValidForHours>24</cveValidForHours>
<nvdValidForHours>24</nvdValidForHours>
<failBuildOnCVSS>0</failBuildOnCVSS>
<skipTestScope>true</skipTestScope>
<detail>true</detail>
<suppressionFile>suppression.xml</suppressionFile>
<nvdApiKeyEnvironmentVariable>NVD_API_KEY</nvdApiKeyEnvironmentVariable>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>validate</phase>
</execution>
</executions>
</plugin>

View File

@@ -21,7 +21,6 @@ open module org.cryptomator.desktop {
requires org.cryptomator.cryptolib;
requires org.cryptomator.cryptofs;
requires org.cryptomator.frontend.dokany;
requires org.cryptomator.frontend.fuse;
requires org.cryptomator.frontend.webdav;
requires org.cryptomator.integrations.api;
@@ -32,17 +31,18 @@ open module org.cryptomator.desktop {
requires javafx.graphics;
requires javafx.controls;
requires javafx.fxml;
requires jdk.crypto.ec;
// 3rd party:
requires ch.qos.logback.classic;
requires ch.qos.logback.core;
requires com.auth0.jwt;
requires com.google.common;
requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.datatype.jsr310;
requires com.nimbusds.jose.jwt;
requires com.nulabinc.zxcvbn;
requires com.tobiasdiez.easybind;
requires dagger;
requires java.compiler;
requires io.github.coffeelibs.tinyoauth2client;
requires org.slf4j;
requires org.apache.commons.lang3;

View File

@@ -5,10 +5,8 @@
*******************************************************************************/
package org.cryptomator.common;
import com.tobiasdiez.easybind.EasyBind;
import dagger.Module;
import dagger.Provides;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.keychain.KeychainModule;
import org.cryptomator.common.mount.MountModule;
import org.cryptomator.common.settings.Settings;
@@ -22,8 +20,6 @@ import org.slf4j.LoggerFactory;
import javax.inject.Named;
import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Comparator;
@@ -136,13 +132,4 @@ public abstract class CommonsModule {
LOG.error("Uncaught exception in " + thread.getName(), throwable);
}
@Provides
@Singleton
static ObservableValue<InetSocketAddress> provideServerSocketAddressBinding(Settings settings) {
return settings.port.map(port -> {
String host = SystemUtils.IS_OS_WINDOWS ? "127.0.0.1" : "localhost";
return InetSocketAddress.createUnresolved(host, settings.port.intValue());
});
}
}

View File

@@ -2,6 +2,7 @@ package org.cryptomator.common;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,6 +32,7 @@ public class Environment {
private static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
private static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
private Environment() {}
@@ -43,15 +45,16 @@ public class Environment {
logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
logCryptomatorSystemProperty(LOG_DIR_PROP_NAME);
logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME);
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
logCryptomatorSystemProperty(MOUNTPOINT_DIR_PROP_NAME);
logCryptomatorSystemProperty(MIN_PW_LENGTH_PROP_NAME);
logCryptomatorSystemProperty(APP_VERSION_PROP_NAME);
logCryptomatorSystemProperty(BUILD_NUMBER_PROP_NAME);
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
logCryptomatorSystemProperty(DISABLE_UPDATE_CHECK_PROP_NAME);
}
public static Environment getInstance() {
@@ -74,10 +77,6 @@ public class Environment {
return getPaths(SETTINGS_PATH_PROP_NAME);
}
public Stream<Path> getP12Path() {
return getPaths(P12_PATH_PROP_NAME);
}
public Stream<Path> getIpcSocketPath() {
return getPaths(IPC_SOCKET_PATH_PROP_NAME);
}
@@ -86,6 +85,10 @@ public class Environment {
return getPaths(KEYCHAIN_PATHS_PROP_NAME);
}
public Stream<Path> getP12Path() {
return getPaths(P12_PATH_PROP_NAME);
}
public Optional<Path> getLogDir() {
return getPath(LOG_DIR_PROP_NAME);
}
@@ -94,14 +97,14 @@ public class Environment {
return Optional.ofNullable(System.getProperty(LOOPBACK_ALIAS_PROP_NAME));
}
public Optional<Path> getPluginDir() {
return getPath(PLUGIN_DIR_PROP_NAME);
}
public Optional<Path> getMountPointsDir() {
return getPath(MOUNTPOINT_DIR_PROP_NAME);
}
public int getMinPwLength() {
return Integer.getInteger(MIN_PW_LENGTH_PROP_NAME, DEFAULT_MIN_PW_LENGTH);
}
/**
* Returns the app version defined in the {@value APP_VERSION_PROP_NAME} property or returns "SNAPSHOT".
*
@@ -115,20 +118,24 @@ public class Environment {
return Optional.ofNullable(System.getProperty(BUILD_NUMBER_PROP_NAME));
}
public int getMinPwLength() {
return Integer.getInteger(MIN_PW_LENGTH_PROP_NAME, DEFAULT_MIN_PW_LENGTH);
public Optional<Path> getPluginDir() {
return getPath(PLUGIN_DIR_PROP_NAME);
}
public boolean showTrayIcon() {
return Boolean.getBoolean(TRAY_ICON_PROP_NAME);
}
public boolean disableUpdateCheck() {
return Boolean.getBoolean(DISABLE_UPDATE_CHECK_PROP_NAME);
}
private Optional<Path> getPath(String propertyName) {
String value = System.getProperty(propertyName);
return Optional.ofNullable(value).map(Paths::get);
}
// visible for testing
@VisibleForTesting
Stream<Path> getPaths(String propertyName) {
Stream<String> rawSettingsPaths = getRawList(propertyName, System.getProperty("path.separator").charAt(0));
return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Path::of);

View File

@@ -3,6 +3,7 @@ package org.cryptomator.common;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import org.jetbrains.annotations.VisibleForTesting;
import java.util.Locale;
import java.util.Objects;
@@ -114,7 +115,7 @@ public class ErrorCode {
* @param bottomFrames Other stack frames, potentially forming the bottom of the stack of <code>allFrames</code>
* @return The number of additional frames in <code>allFrames</code>. In most cases this should be equal to the difference in size.
*/
// visible for testing
@VisibleForTesting
static int countTopmostFrames(StackTraceElement[] allFrames, StackTraceElement[] bottomFrames) {
if (allFrames.length < bottomFrames.length) {
// if frames had been stacked on top of bottomFrames, allFrames would be larger
@@ -124,7 +125,7 @@ public class ErrorCode {
}
}
// visible for testing
@VisibleForTesting
static <T> int commonSuffixLength(T[] set, T[] subset) {
Preconditions.checkArgument(set.length >= subset.length);
// iterate items backwards as long as they are identical

View File

@@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SubstitutingProperties extends PropertiesDecorator {
@@ -58,7 +59,7 @@ public class SubstitutingProperties extends PropertiesDecorator {
LoggerFactory.getLogger(SubstitutingProperties.class).warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src);
return "";
} else {
return val.replace("\\", "\\\\");
return Matcher.quoteReplacement(val);
}
}

View File

@@ -44,7 +44,7 @@ public class KeychainManager implements KeychainAccessProvider {
}
@Override
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean ignored) throws KeychainAccessException {
getKeychainOrFail().storePassphrase(key, displayName, passphrase);
setPassphraseStored(key, true);
}

View File

@@ -62,7 +62,7 @@ public final class OneDriveWindowsLocationPresetsProvider implements LocationPre
ProcessBuilder command = new ProcessBuilder(args);
Process p = command.start();
waitForSuccess(p, 3, "`reg query`");
return p.inputReader(StandardCharsets.UTF_8).lines().filter(outputFilter);
return p.inputReader(StandardCharsets.ISO_8859_1).lines().filter(outputFilter);
}

View File

@@ -1,6 +0,0 @@
package org.cryptomator.common.mount;
import org.cryptomator.integrations.mount.MountService;
public record ActualMountService(MountService service, boolean isDesired) {
}

View File

@@ -0,0 +1,14 @@
package org.cryptomator.common.mount;
import org.cryptomator.integrations.mount.MountFailedException;
/**
* Thrown by {@link Mounter} to indicate that the selected mount service can not be used
* due to incompatibilities with a different mount service that is already in use.
*/
public class ConflictingMountServiceException extends MountFailedException {
public ConflictingMountServiceException(String msg) {
super(msg);
}
}

View File

@@ -4,21 +4,18 @@ import dagger.Module;
import dagger.Provides;
import org.cryptomator.common.ObservableUtil;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.Mount;
import org.cryptomator.integrations.mount.MountService;
import javax.inject.Named;
import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Module
public class MountModule {
private static final AtomicReference<MountService> formerSelectedMountService = new AtomicReference<>(null);
private static final List<String> problematicFuseMountServices = List.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", "org.cryptomator.frontend.fuse.mount.FuseTMountProvider");
@Provides
@Singleton
static List<MountService> provideSupportedMountServices() {
@@ -27,46 +24,18 @@ public class MountModule {
@Provides
@Singleton
@Named("FUPFMS")
static AtomicReference<MountService> provideFirstUsedProblematicFuseMountService() {
return new AtomicReference<>(null);
static ObservableValue<MountService> provideDefaultMountService(List<MountService> mountProviders, Settings settings) {
var fallbackProvider = mountProviders.stream().findFirst().get(); //there should always be a mount provider, at least webDAV
return ObservableUtil.mapWithDefault(settings.mountService, //
serviceName -> mountProviders.stream().filter(s -> s.getClass().getName().equals(serviceName)).findFirst().orElse(fallbackProvider), //
fallbackProvider);
}
@Provides
@Singleton
static ObservableValue<ActualMountService> provideMountService(Settings settings, List<MountService> serviceImpls, @Named("FUPFMS") AtomicReference<MountService> fupfms) {
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
var observableMountService = ObservableUtil.mapWithDefault(settings.mountService, //
desiredServiceImpl -> { //
var serviceFromSettings = serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny(); //
var targetedService = serviceFromSettings.orElse(fallbackProvider);
return applyWorkaroundForProblematicFuse(targetedService, serviceFromSettings.isPresent(), fupfms);
}, //
() -> { //
return applyWorkaroundForProblematicFuse(fallbackProvider, true, fupfms);
});
return observableMountService;
@Named("usedMountServices")
static Set<MountService> provideSetOfUsedMountServices() {
return ConcurrentHashMap.newKeySet();
}
//see https://github.com/cryptomator/cryptomator/issues/2786
private synchronized static ActualMountService applyWorkaroundForProblematicFuse(MountService targetedService, boolean isDesired, AtomicReference<MountService> firstUsedProblematicFuseMountService) {
//set the first used problematic fuse service if applicable
var targetIsProblematicFuse = isProblematicFuseService(targetedService);
if (targetIsProblematicFuse && firstUsedProblematicFuseMountService.get() == null) {
firstUsedProblematicFuseMountService.set(targetedService);
}
//do not use the targeted mount service and fallback to former one, if the service is problematic _and_ not the first problematic one used.
if (targetIsProblematicFuse && !firstUsedProblematicFuseMountService.get().equals(targetedService)) {
return new ActualMountService(formerSelectedMountService.get(), false);
} else {
formerSelectedMountService.set(targetedService);
return new ActualMountService(targetedService, isDesired);
}
}
public static boolean isProblematicFuseService(MountService service) {
return problematicFuseMountServices.contains(service.getClass().getName());
}
}
}

View File

@@ -1,6 +1,7 @@
package org.cryptomator.common.mount;
import org.apache.commons.lang3.SystemUtils;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,7 +67,7 @@ public final class MountWithinParentUtil {
}
}
//visible for testing
@VisibleForTesting
static MountPointState getMountPointState(Path path) throws IOException, IllegalMountPointException {
if (Files.notExists(path, LinkOption.NOFOLLOW_LINKS)) {
return MountPointState.NOT_EXISTING;
@@ -82,7 +83,7 @@ public final class MountWithinParentUtil {
return MountPointState.BROKEN_JUNCTION;
}
//visible for testing
@VisibleForTesting
enum MountPointState {
NOT_EXISTING,
@@ -93,7 +94,7 @@ public final class MountWithinParentUtil {
}
//visible for testing
@VisibleForTesting
static void removeResidualHideaway(Path mountPoint, Path hideaway) throws IOException {
checkIsHideawayDirectory(mountPoint, hideaway);
Files.delete(hideaway); //Fails if not empty
@@ -155,7 +156,7 @@ public final class MountWithinParentUtil {
}
}
//visible for testing
@VisibleForTesting
static Path getHideaway(Path mountPoint) {
return mountPoint.resolveSibling(HIDEAWAY_PREFIX + mountPoint.getFileName().toString() + HIDEAWAY_SUFFIX);
}

View File

@@ -7,13 +7,19 @@ import org.cryptomator.integrations.mount.Mount;
import org.cryptomator.integrations.mount.MountBuilder;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.MountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR;
@@ -24,24 +30,41 @@ import static org.cryptomator.integrations.mount.MountCapability.UNMOUNT_FORCED;
@Singleton
public class Mounter {
private final Settings settings;
private static final Logger LOG = LoggerFactory.getLogger(Mounter.class);
// mount providers (key) can not be used if any of the conflicting mount providers (values) are already in use
private static final Map<String, Set<String>> CONFLICTING_MOUNT_SERVICES = Map.of(
"org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", Set.of("org.cryptomator.frontend.fuse.mount.FuseTMountProvider"),
"org.cryptomator.frontend.fuse.mount.FuseTMountProvider", Set.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider")
);
private final Environment env;
private final Settings settings;
private final WindowsDriveLetters driveLetters;
private final ObservableValue<ActualMountService> mountServiceObservable;
private final List<MountService> mountProviders;
private final Set<MountService> usedMountServices;
private final ObservableValue<MountService> defaultMountService;
@Inject
public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue<ActualMountService> mountServiceObservable) {
this.settings = settings;
public Mounter(Environment env, //
Settings settings, //
WindowsDriveLetters driveLetters, //
List<MountService> mountProviders, //
@Named("usedMountServices") Set<MountService> usedMountServices, //
ObservableValue<MountService> defaultMountService) {
this.env = env;
this.settings = settings;
this.driveLetters = driveLetters;
this.mountServiceObservable = mountServiceObservable;
this.mountProviders = mountProviders;
this.usedMountServices = usedMountServices;
this.defaultMountService = defaultMountService;
}
private class SettledMounter {
private MountService service;
private MountBuilder builder;
private VaultSettings vaultSettings;
private final MountService service;
private final MountBuilder builder;
private final VaultSettings vaultSettings;
public SettledMounter(MountService service, MountBuilder builder, VaultSettings vaultSettings) {
this.service = service;
@@ -53,8 +76,13 @@ public class Mounter {
for (var capability : service.capabilities()) {
switch (capability) {
case FILE_SYSTEM_NAME -> builder.setFileSystemName("cryptoFs");
case LOOPBACK_PORT ->
builder.setLoopbackPort(settings.port.get()); //TODO: move port from settings to vaultsettings (see https://github.com/cryptomator/cryptomator/tree/feature/mount-setting-per-vault)
case LOOPBACK_PORT -> {
if (vaultSettings.mountService.getValue() == null) {
builder.setLoopbackPort(settings.port.get());
} else {
builder.setLoopbackPort(vaultSettings.port.get());
}
}
case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName);
case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode.get());
case MOUNT_FLAGS -> {
@@ -103,9 +131,7 @@ public class Mounter {
}
} else if (canMountToParent && !canMountToDir) {
MountWithinParentUtil.prepareParentNoMountPoint(userChosenMountPoint);
cleanup = () -> {
MountWithinParentUtil.cleanup(userChosenMountPoint);
};
cleanup = () -> MountWithinParentUtil.cleanup(userChosenMountPoint);
}
try {
builder.setMountpoint(userChosenMountPoint);
@@ -131,13 +157,26 @@ public class Mounter {
}
public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException {
var mountService = this.mountServiceObservable.getValue().service();
var mountService = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defaultMountService.getValue());
if (isConflictingMountService(mountService)) {
var msg = STR."\{mountService.getClass()} unavailable due to conflict with either of \{CONFLICTING_MOUNT_SERVICES.get(mountService.getClass().getName())}";
throw new ConflictingMountServiceException(msg);
}
usedMountServices.add(mountService);
var builder = mountService.forFileSystem(cryptoFsRoot);
var internal = new SettledMounter(mountService, builder, vaultSettings);
var internal = new SettledMounter(mountService, builder, vaultSettings); // FIXME: no need for an inner class
var cleanup = internal.prepare();
return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup);
}
public boolean isConflictingMountService(MountService service) {
var conflictingServices = CONFLICTING_MOUNT_SERVICES.getOrDefault(service.getClass().getName(), Set.of());
return usedMountServices.stream().map(MountService::getClass).map(Class::getName).anyMatch(conflictingServices::contains);
}
public record MountHandle(Mount mountObj, boolean supportsUnmountForced, Runnable specialCleanup) {
}

View File

@@ -25,6 +25,7 @@ import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.NodeOrientation;
import java.time.Instant;
import java.util.function.Consumer;
public class Settings {
@@ -36,16 +37,21 @@ public class Settings {
static final boolean DEFAULT_START_HIDDEN = false;
static final boolean DEFAULT_AUTO_CLOSE_VAULTS = false;
static final boolean DEFAULT_USE_KEYCHAIN = true;
static final boolean DEFAULT_USE_QUICKACCESS = true;
static final int DEFAULT_PORT = 42427;
static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
static final boolean DEFAULT_DEBUG_MODE = false;
static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
@Deprecated // to be changed to "whatever is available" eventually
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";
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";
static final String DEFAULT_QUICKACCESS_SERVICE = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.quickaccess.ExplorerQuickAccessService" : //
SystemUtils.IS_OS_LINUX ? "org.cryptomator.linux.quickaccess.NautilusBookmarks" : null;
static final String DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT.name();
static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
static final String DEFAULT_LAST_UPDATE_CHECK = "2000-01-01";
public static final Instant DEFAULT_TIMESTAMP = Instant.parse("2000-01-01T00:00:00Z");
public final ObservableList<VaultSettings> directories;
public final BooleanProperty askedForUpdateCheck;
public final BooleanProperty checkForUpdates;
@@ -57,6 +63,8 @@ public class Settings {
public final BooleanProperty debugMode;
public final ObjectProperty<UiTheme> theme;
public final StringProperty keychainProvider;
public final BooleanProperty useQuickAccess;
public final StringProperty quickAccessService;
public final ObjectProperty<NodeOrientation> userInterfaceOrientation;
public final StringProperty licenseKey;
public final BooleanProperty showMinimizeButton;
@@ -67,7 +75,7 @@ public class Settings {
public final IntegerProperty windowHeight;
public final StringProperty language;
public final StringProperty mountService;
public final StringProperty lastUpdateCheck;
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
private Consumer<Settings> saveCmd;
@@ -89,6 +97,7 @@ public class Settings {
this.startHidden = new SimpleBooleanProperty(this, "startHidden", json.startHidden);
this.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults);
this.useKeychain = new SimpleBooleanProperty(this, "useKeychain", json.useKeychain);
this.useQuickAccess = new SimpleBooleanProperty(this, "addToQuickAccess", json.useQuickAccess);
this.port = new SimpleIntegerProperty(this, "webDavPort", json.port);
this.numTrayNotifications = new SimpleIntegerProperty(this, "numTrayNotifications", json.numTrayNotifications);
this.debugMode = new SimpleBooleanProperty(this, "debugMode", json.debugMode);
@@ -104,7 +113,8 @@ public class Settings {
this.windowHeight = new SimpleIntegerProperty(this, "windowHeight", json.windowHeight);
this.language = new SimpleStringProperty(this, "language", json.language);
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
this.lastUpdateCheck = new SimpleStringProperty(this, "lastUpdateCheck", json.lastUpdateCheck);
this.quickAccessService = new SimpleStringProperty(this, "quickAccessService", json.quickAccessService);
this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
@@ -116,6 +126,7 @@ public class Settings {
startHidden.addListener(this::somethingChanged);
autoCloseVaults.addListener(this::somethingChanged);
useKeychain.addListener(this::somethingChanged);
useQuickAccess.addListener(this::somethingChanged);
port.addListener(this::somethingChanged);
numTrayNotifications.addListener(this::somethingChanged);
debugMode.addListener(this::somethingChanged);
@@ -131,7 +142,8 @@ public class Settings {
windowHeight.addListener(this::somethingChanged);
language.addListener(this::somethingChanged);
mountService.addListener(this::somethingChanged);
lastUpdateCheck.addListener(this::somethingChanged);
quickAccessService.addListener(this::somethingChanged);
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
}
@SuppressWarnings("deprecation")
@@ -170,6 +182,7 @@ public class Settings {
json.startHidden = startHidden.get();
json.autoCloseVaults = autoCloseVaults.get();
json.useKeychain = useKeychain.get();
json.useQuickAccess = useQuickAccess.get();
json.port = port.get();
json.numTrayNotifications = numTrayNotifications.get();
json.debugMode = debugMode.get();
@@ -185,7 +198,8 @@ public class Settings {
json.windowHeight = windowHeight.get();
json.language = language.get();
json.mountService = mountService.get();
json.lastUpdateCheck = lastUpdateCheck.get();
json.quickAccessService = quickAccessService.get();
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
return json;
}

View File

@@ -1,9 +1,11 @@
package org.cryptomator.common.settings;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -80,7 +82,13 @@ class SettingsJson {
@JsonProperty(value = "preferredVolumeImpl", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233
String preferredVolumeImpl;
@JsonProperty("lastUpdateCheck")
String lastUpdateCheck = Settings.DEFAULT_LAST_UPDATE_CHECK;
@JsonProperty("lastSuccessfulUpdateCheck")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
Instant lastSuccessfulUpdateCheck = Settings.DEFAULT_TIMESTAMP;
@JsonProperty("useQuickAccess")
boolean useQuickAccess = Settings.DEFAULT_USE_QUICKACCESS;
@JsonProperty("quickAccessService")
String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE;
}

View File

@@ -10,6 +10,7 @@ package org.cryptomator.common.settings;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.common.base.Suppliers;
import org.cryptomator.common.Environment;
import org.slf4j.Logger;
@@ -36,7 +37,7 @@ import java.util.stream.Stream;
@Singleton
public class SettingsProvider implements Supplier<Settings> {
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true);
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true).registerModule(new JavaTimeModule());
private static final Logger LOG = LoggerFactory.getLogger(SettingsProvider.class);
private static final long SAVE_DELAY_MS = 1000;
@@ -57,7 +58,10 @@ public class SettingsProvider implements Supplier<Settings> {
}
private Settings load() {
Settings settings = env.getSettingsPath().flatMap(this::tryLoad).findFirst().orElseGet(() -> Settings.create(env));
Settings settings = env.getSettingsPath() //
.flatMap(this::tryLoad) //
.findFirst() //
.orElseGet(() -> Settings.create(env));
settings.setSaveCmd(this::scheduleSave);
return settings;
}

View File

@@ -8,7 +8,7 @@ package org.cryptomator.common.settings;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.io.BaseEncoding;
import org.apache.commons.lang3.SystemUtils;
import org.jetbrains.annotations.VisibleForTesting;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
@@ -39,6 +39,7 @@ public class VaultSettings {
static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false;
static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60;
static final int DEFAULT_PORT = 42427;
private static final Random RNG = new Random();
@@ -55,6 +56,8 @@ public class VaultSettings {
public final IntegerProperty autoLockIdleSeconds;
public final ObjectProperty<Path> mountPoint;
public final StringExpression mountName;
public final StringProperty mountService;
public final IntegerProperty port;
VaultSettings(VaultSettingsJson json) {
this.id = json.id;
@@ -69,6 +72,8 @@ public class VaultSettings {
this.autoLockWhenIdle = new SimpleBooleanProperty(this, "autoLockWhenIdle", json.autoLockWhenIdle);
this.autoLockIdleSeconds = new SimpleIntegerProperty(this, "autoLockIdleSeconds", json.autoLockIdleSeconds);
this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint));
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
this.port = new SimpleIntegerProperty(this, "port", json.port);
// mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318
this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> {
final String name;
@@ -94,7 +99,7 @@ public class VaultSettings {
}
Observable[] observables() {
return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode};
return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService};
}
public static VaultSettings withRandomId() {
@@ -123,10 +128,12 @@ public class VaultSettings {
json.autoLockWhenIdle = autoLockWhenIdle.get();
json.autoLockIdleSeconds = autoLockIdleSeconds.get();
json.mountPoint = mountPoint.map(Path::toString).getValue();
json.mountService = mountService.get();
json.port = port.get();
return json;
}
//visible for testing
@VisibleForTesting
static String normalizeDisplayName(String original) {
if (original.isBlank() || ".".equals(original) || "..".equals(original)) {
return "_";

View File

@@ -45,6 +45,12 @@ class VaultSettingsJson {
@JsonProperty("autoLockIdleSeconds")
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
@JsonProperty("mountService")
String mountService;
@JsonProperty("port")
int port = VaultSettings.DEFAULT_PORT;
@Deprecated(since = "1.7.0")
@JsonProperty(value = "winDriveLetter", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233
String winDriveLetter;

View File

@@ -11,7 +11,7 @@ package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
import org.cryptomator.common.mount.Mounter;
import org.cryptomator.common.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
@@ -24,6 +24,9 @@ import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException;
import org.cryptomator.integrations.quickaccess.QuickAccessService;
import org.cryptomator.integrations.quickaccess.QuickAccessServiceException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,6 +58,7 @@ public class Vault {
private final VaultSettings vaultSettings;
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final AtomicReference<QuickAccessService.QuickAccessEntry> quickAccessEntry;
private final VaultState state;
private final ObjectProperty<Exception> lastKnownException;
private final VaultConfigCache configCache;
@@ -68,12 +72,19 @@ public class Vault {
private final BooleanBinding unknownError;
private final ObjectBinding<Mountpoint> mountPoint;
private final Mounter mounter;
private final Settings settings;
private final BooleanProperty showingStats;
private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@Inject
Vault(VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats, WindowsDriveLetters windowsDriveLetters, Mounter mounter) {
Vault(VaultSettings vaultSettings, //
VaultConfigCache configCache, //
AtomicReference<CryptoFileSystem> cryptoFileSystem, //
VaultState state, //
@Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
VaultStats stats, //
Mounter mounter, Settings settings) {
this.vaultSettings = vaultSettings;
this.configCache = configCache;
this.cryptoFileSystem = cryptoFileSystem;
@@ -89,7 +100,9 @@ public class Vault {
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
this.mounter = mounter;
this.settings = settings;
this.showingStats = new SimpleBooleanProperty(false);
this.quickAccessEntry = new AtomicReference<>(null);
}
// ******************************************************************************
@@ -149,6 +162,9 @@ public class Vault {
var rootPath = fs.getRootDirectories().iterator().next();
var mountHandle = mounter.mount(vaultSettings, rootPath);
success = this.mountHandle.compareAndSet(null, mountHandle);
if (settings.useQuickAccess.getValue()) {
addToQuickAccess();
}
} finally {
if (!success) {
destroyCryptoFileSystem();
@@ -173,6 +189,7 @@ public class Vault {
mountHandle.mountObj().close();
mountHandle.specialCleanup().run();
} finally {
removeFromQuickAccess();
destroyCryptoFileSystem();
}
@@ -180,6 +197,52 @@ public class Vault {
LOG.info("Locked vault '{}'", getDisplayName());
}
private synchronized void addToQuickAccess() {
if (quickAccessEntry.get() != null) {
//we don't throw an exception since we don't wanna block unlocking
LOG.warn("Vault already added to quick access area. Will be removed on next lock operation.");
return;
}
QuickAccessService.get() //
.filter(s -> s.getClass().getName().equals(settings.quickAccessService.getValue())) //
.findFirst() //
.ifPresentOrElse( //
this::addToQuickAccessInternal, //
() -> LOG.warn("Unable to add Vault to quick access area: Desired implementation not available.") //
);
}
private void addToQuickAccessInternal(@NotNull QuickAccessService s) {
if (getMountPoint() instanceof Mountpoint.WithPath mp) {
try {
var entry = s.add(mp.path(), getDisplayName());
quickAccessEntry.set(entry);
} catch (QuickAccessServiceException e) {
LOG.error("Adding vault to quick access area failed", e);
}
} else {
LOG.warn("Unable to add vault to quick access area: Vault is not mounted to local system path.");
}
}
private synchronized void removeFromQuickAccess() {
if (quickAccessEntry.get() == null) {
LOG.debug("Removing vault from quick access area: Entry not found, nothing to do.");
return;
}
removeFromQuickAccessInternal();
}
private void removeFromQuickAccessInternal() {
try {
quickAccessEntry.get().remove();
quickAccessEntry.set(null);
} catch (QuickAccessServiceException e) {
LOG.error("Removing vault from quick access area failed", e);
}
}
// ******************************************************************************
// Observable Properties
// *******************************************************************************

View File

@@ -8,11 +8,13 @@
*******************************************************************************/
package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils;
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.cryptomator.integrations.mount.MountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,6 +26,7 @@ import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
@@ -38,14 +41,21 @@ public class VaultListManager {
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
private final AutoLocker autoLocker;
private final List<MountService> mountServices;
private final VaultComponent.Factory vaultComponentFactory;
private final ObservableList<Vault> vaultList;
private final String defaultVaultName;
@Inject
public VaultListManager(ObservableList<Vault> vaultList, AutoLocker autoLocker, VaultComponent.Factory vaultComponentFactory, ResourceBundle resourceBundle, Settings settings) {
public VaultListManager(ObservableList<Vault> vaultList, //
AutoLocker autoLocker, //
List<MountService> mountServices,
VaultComponent.Factory vaultComponentFactory,
ResourceBundle resourceBundle,
Settings settings) {
this.vaultList = vaultList;
this.autoLocker = autoLocker;
this.mountServices = mountServices;
this.vaultComponentFactory = vaultComponentFactory;
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
@@ -76,6 +86,15 @@ public class VaultListManager {
} else {
vaultSettings.displayName.set(defaultVaultName);
}
//due to https://github.com/cryptomator/cryptomator/issues/2880#issuecomment-1680313498
var nameOfWinfspLocalMounter = "org.cryptomator.frontend.fuse.mount.WinFspMountProvider";
if (SystemUtils.IS_OS_WINDOWS //
&& vaultSettings.path.get().toString().contains("Dropbox") //
&& mountServices.stream().anyMatch(s -> s.getClass().getName().equals(nameOfWinfspLocalMounter))) {
vaultSettings.mountService.setValue(nameOfWinfspLocalMounter);
}
return vaultSettings;
}

View File

@@ -6,6 +6,7 @@
*******************************************************************************/
package org.cryptomator.launcher;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,7 +49,7 @@ class FileOpenRequestHandler {
handleLaunchArgs(FileSystems.getDefault(), args);
}
// visible for testing
@VisibleForTesting
void handleLaunchArgs(FileSystem fs, List<String> args) {
Collection<Path> pathsToOpen = args.stream().map(str -> {
try {

View File

@@ -5,6 +5,7 @@ import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.Configurator;
import ch.qos.logback.classic.spi.ConfiguratorRank;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.ConsoleAppender;
@@ -19,6 +20,7 @@ import org.cryptomator.common.Environment;
import java.nio.file.Path;
import java.util.Map;
@ConfiguratorRank(ConfiguratorRank.CUSTOM_NORMAL_PRIORITY)
public class LogbackConfigurator extends ContextAwareBase implements Configurator {
private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";

View File

@@ -13,31 +13,37 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutorService;
@AddVaultWizardScoped
public class CreateNewVaultLocationController implements FxController {
@@ -49,19 +55,23 @@ public class CreateNewVaultLocationController implements FxController {
private final Stage window;
private final Lazy<Scene> chooseNameScene;
private final Lazy<Scene> chooseExpertSettingsScene;
private final List<RadioButton> locationPresetBtns;
private final ObjectProperty<Path> vaultPath;
private final StringProperty vaultName;
private final ExecutorService backgroundExecutor;
private final ResourceBundle resourceBundle;
private final ObservableValue<VaultPathStatus> vaultPathStatus;
private final ObservableValue<Boolean> validVaultPath;
private final BooleanProperty usePresetPath;
private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false);
private final ObservableList<Node> radioButtons;
private final ObservableList<Node> sortedRadioButtons;
private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
//FXML
public ToggleGroup locationPresetsToggler;
public VBox radioButtonVBox;
public HBox customLocationRadioBtn;
public RadioButton customRadioButton;
public Label locationStatusLabel;
public FontAwesome5IconView goodLocation;
@@ -73,25 +83,20 @@ public class CreateNewVaultLocationController implements FxController {
@FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, //
ObjectProperty<Path> vaultPath, //
@Named("vaultName") StringProperty vaultName, //
ResourceBundle resourceBundle) {
ExecutorService backgroundExecutor, ResourceBundle resourceBundle) {
this.window = window;
this.chooseNameScene = chooseNameScene;
this.chooseExpertSettingsScene = chooseExpertSettingsScene;
this.vaultPath = vaultPath;
this.vaultName = vaultName;
this.backgroundExecutor = backgroundExecutor;
this.resourceBundle = resourceBundle;
this.vaultPathStatus = ObservableUtil.mapWithDefault(vaultPath, this::validatePath, new VaultPathStatus(false, "error.message"));
this.validVaultPath = ObservableUtil.mapWithDefault(vaultPathStatus, VaultPathStatus::valid, false);
this.vaultPathStatus.addListener(this::updateStatusLabel);
this.usePresetPath = new SimpleBooleanProperty();
this.locationPresetBtns = LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
.flatMap(LocationPresetsProvider::getLocations) //
.sorted(Comparator.comparing(LocationPreset::name)) //
.map(preset -> { //
var btn = new RadioButton(preset.name());
btn.setUserData(preset.path());
return btn;
}).toList();
this.radioButtons = FXCollections.observableArrayList();
this.sortedRadioButtons = radioButtons.sorted(this::compareLocationPresets);
}
private VaultPathStatus validatePath(Path p) throws NullPointerException {
@@ -137,12 +142,45 @@ public class CreateNewVaultLocationController implements FxController {
@FXML
public void initialize() {
radioButtonVBox.getChildren().addAll(1, locationPresetBtns); //first item is the list header
locationPresetsToggler.getToggles().addAll(locationPresetBtns);
var task = backgroundExecutor.submit(this::loadLocationPresets);
window.addEventHandler(WindowEvent.WINDOW_HIDING, _ -> task.cancel(true));
locationPresetsToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation);
usePresetPath.bind(locationPresetsToggler.selectedToggleProperty().isNotEqualTo(customRadioButton));
radioButtons.add(customLocationRadioBtn);
Bindings.bindContent(radioButtonVBox.getChildren(), sortedRadioButtons); //to prevent garbage collection of the binding, we bind explicitly to the sorted list
}
private void loadLocationPresets() {
Platform.runLater(() -> loadingPresetLocations.set(true));
try {
LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
.flatMap(LocationPresetsProvider::getLocations) //we do not use sorted(), because it evaluates the stream elements, blocking until all elements are gathered
.forEach(this::createRadioButtonFor);
} finally {
Platform.runLater(() -> loadingPresetLocations.set(false));
}
}
private void createRadioButtonFor(LocationPreset preset) {
Platform.runLater(() -> {
var btn = new RadioButton(preset.name());
btn.setUserData(preset.path());
radioButtons.add(btn);
locationPresetsToggler.getToggles().add(btn);
});
}
private int compareLocationPresets(Node left, Node right) {
if (customLocationRadioBtn.getId().equals(left.getId())) {
return 1;
} else if (customLocationRadioBtn.getId().equals(right.getId())) {
return -1;
} else {
return ((RadioButton) left).getText().compareToIgnoreCase(((RadioButton) right).getText());
}
}
private void togglePredefinedLocation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
var storagePath = Optional.ofNullable((Path) newValue.getUserData()).orElse(customVaultPath);
vaultPath.set(storagePath.resolve(vaultName.get()));
@@ -197,7 +235,15 @@ public class CreateNewVaultLocationController implements FxController {
}
public boolean isValidVaultPath() {
return validVaultPath.getValue();
return Boolean.TRUE.equals(validVaultPath.getValue());
}
public boolean isLoadingPresetLocations() {
return loadingPresetLocations.getValue();
}
public BooleanProperty loadingPresetLocationsProperty() {
return loadingPresetLocations;
}
public BooleanProperty usePresetPathProperty() {

View File

@@ -1,5 +1,7 @@
package org.cryptomator.ui.addvaultwizard;
import org.jetbrains.annotations.VisibleForTesting;
import javax.inject.Inject;
import java.util.List;
import java.util.ResourceBundle;
@@ -51,7 +53,7 @@ public class ReadmeGenerator {
resourceBundle.getString("addvault.new.readme.accessLocation.4")));
}
// visible for testing
@VisibleForTesting
String createDocument(Iterable<String> paragraphs) {
StringBuilder sb = new StringBuilder(RTF_HEADER);
for (String p : paragraphs) {
@@ -63,7 +65,7 @@ public class ReadmeGenerator {
return sb.toString();
}
// visible for testing
@VisibleForTesting
String escapeNonAsciiChars(CharSequence input) {
StringBuilder sb = new StringBuilder();
appendEscaped(sb, input);

View File

@@ -12,6 +12,7 @@ public enum FxmlFile {
CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_SUCCESS("/fxml/convertvault_hubtopassword_success.fxml"), //
DOKANY_SUPPORT_END("/fxml/dokany_support_end.fxml"), //
ERROR("/fxml/error.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
HEALTH_START("/fxml/health_start.fxml"), //
@@ -20,10 +21,14 @@ public enum FxmlFile {
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
HUB_LEGACY_REGISTER_DEVICE("/fxml/hub_legacy_register_device.fxml"), //
HUB_LEGACY_REGISTER_SUCCESS("/fxml/hub_legacy_register_success.fxml"), //
HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), //
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"),
HUB_REGISTER_DEVICE_ALREADY_EXISTS("/fxml/hub_register_device_already_exists.fxml"), //
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"), //
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), //
HUB_REQUIRE_ACCOUNT_INIT("/fxml/hub_require_account_init.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), //
MAIN_WINDOW("/fxml/main_window.fxml"), //
@@ -41,8 +46,10 @@ public enum FxmlFile {
RECOVERYKEY_RESET_PASSWORD_SUCCESS("/fxml/recoverykey_reset_password_success.fxml"), //
RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), //
REMOVE_VAULT("/fxml/remove_vault.fxml"), //
SHARE_VAULT("/fxml/share_vault.fxml"), //
UPDATE_REMINDER("/fxml/update_reminder.fxml"), //
UNLOCK_ENTER_PASSWORD("/fxml/unlock_enter_password.fxml"),
UNLOCK_REQUIRES_RESTART("/fxml/unlock_requires_restart.fxml"), //
UNLOCK_INVALID_MOUNT_POINT("/fxml/unlock_invalid_mount_point.fxml"), //
UNLOCK_SELECT_MASTERKEYFILE("/fxml/unlock_select_masterkeyfile.fxml"), //
UNLOCK_SUCCESS("/fxml/unlock_success.fxml"), //

View File

@@ -47,12 +47,14 @@ public enum FontAwesome5Icon {
QUESTION_CIRCLE("\uf059"), //
REDO("\uF01E"), //
SEARCH("\uF002"), //
SHARE("\uF064"), //
SPINNER("\uF110"), //
STETHOSCOPE("\uF0f1"), //
SYNC("\uF021"), //
TIMES("\uF00D"), //
TRASH("\uF1F8"), //
UNLINK("\uf127"), //
USER_COG("\uf4fe"), //
WRENCH("\uF0AD"), //
WINDOW_MINIMIZE("\uF2D1"), //
;

View File

@@ -16,6 +16,7 @@ import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.recoverykey.RecoveryKeyFactory;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -116,7 +117,7 @@ public class HubToPasswordConvertController implements FxController {
}, Platform::runLater); //
}
//visible for testing
@VisibleForTesting
void convertInternal() throws CompletionException, IllegalArgumentException {
var passphrase = newPasswordController.getNewPassword();
var vaultPath = vault.getPath();
@@ -141,7 +142,7 @@ public class HubToPasswordConvertController implements FxController {
}
}
//visible for testing
@VisibleForTesting
void backupHubConfig(Path hubConfigPath) throws IOException {
byte[] hubConfigBytes = Files.readAllBytes(hubConfigPath);
Path backupPath = hubConfigPath.resolveSibling(VAULTCONFIG_FILENAME + BackupHelper.generateFileIdSuffix(hubConfigBytes) + MASTERKEY_BACKUP_SUFFIX);
@@ -149,7 +150,7 @@ public class HubToPasswordConvertController implements FxController {
LOG.debug("Successfully created hub config backup {}", backupPath.getFileName());
}
//visible for testing
@VisibleForTesting
Path createPasswordConfig(Path passwordConfigPath, Path masterkeyFile, Passphrase passphrase) throws IOException, MasterkeyLoadingFailedException {
var unverifiedVaultConfig = vault.getVaultConfigCache().get();
try (var masterkey = masterkeyFileAccess.load(masterkeyFile, passphrase)) {

View File

@@ -0,0 +1,34 @@
package org.cryptomator.ui.dokanysupportend;
import dagger.Lazy;
import dagger.Subcomponent;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javafx.scene.Scene;
import javafx.stage.Stage;
@DokanySupportEndScoped
@Subcomponent(modules = {DokanySupportEndModule.class})
public interface DokanySupportEndComponent {
@DokanySupportEndWindow
Stage window();
@FxmlScene(FxmlFile.DOKANY_SUPPORT_END)
Lazy<Scene> dokanySupportEndScene();
default void showDokanySupportEndWindow() {
Stage stage = window();
stage.setScene(dokanySupportEndScene().get());
stage.sizeToScene();
stage.show();
}
@Subcomponent.Factory
interface Factory {
DokanySupportEndComponent create();
}
}

View File

@@ -0,0 +1,34 @@
package org.cryptomator.ui.dokanysupportend;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
@DokanySupportEndScoped
public class DokanySupportEndController implements FxController {
private final Stage window;
private final FxApplicationWindows applicationWindows;
@Inject
DokanySupportEndController(@DokanySupportEndWindow Stage window, FxApplicationWindows applicationWindows) {
this.window = window;
this.applicationWindows = applicationWindows;
}
@FXML
public void close() {
window.close();
}
public void openVolumePreferences() {
applicationWindows.showPreferencesWindow(SelectedPreferencesTab.VOLUME);
window.close();
}
}

View File

@@ -0,0 +1,57 @@
package org.cryptomator.ui.dokanysupportend;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
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.StageFactory;
import javax.inject.Provider;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.Map;
import java.util.ResourceBundle;
@Module
abstract class DokanySupportEndModule {
@Provides
@DokanySupportEndWindow
@DokanySupportEndScoped
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@DokanySupportEndWindow
@DokanySupportEndScoped
static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle) {
Stage stage = factory.create();
stage.setTitle(resourceBundle.getString("dokanySupportEnd.title"));
stage.setMinWidth(500);
stage.setMinHeight(100);
stage.initModality(Modality.APPLICATION_MODAL);
return stage;
}
@Provides
@FxmlScene(FxmlFile.DOKANY_SUPPORT_END)
@DokanySupportEndScoped
static Scene provideDokanySupportEndScene(@DokanySupportEndWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.DOKANY_SUPPORT_END);
}
@Binds
@IntoMap
@FxControllerKey(DokanySupportEndController.class)
abstract FxController bindDokanySupportEndController(DokanySupportEndController controller);
}

View File

@@ -0,0 +1,13 @@
package org.cryptomator.ui.dokanysupportend;
import javax.inject.Scope;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface DokanySupportEndScoped {
}

View File

@@ -0,0 +1,14 @@
package org.cryptomator.ui.dokanysupportend;
import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
@interface DokanySupportEndWindow {
}

View File

@@ -31,6 +31,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
@@ -42,7 +43,8 @@ public class ErrorController implements FxController {
private static final ObjectMapper JSON = new ObjectMapper();
private static final Logger LOG = LoggerFactory.getLogger(ErrorController.class);
private static final String ERROR_CODES_URL = "https://api.cryptomator.org/desktop/error-codes.json";
private static final String USER_AGENT_FORMAT = "Cryptomator/%s (Build %s) (%s %s %s)";
private static final String ERROR_CODES_URL_FORMAT = "https://api.cryptomator.org/desktop/error-codes.json?error-code=%s";
private static final String SEARCH_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/categories/errors?discussions_q=category:Errors+%s";
private static final String REPORT_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/new?category=Errors&title=Error+%s&body=%s";
private static final String SEARCH_ERRORCODE_DELIM = " OR ";
@@ -73,6 +75,7 @@ public class ErrorController implements FxController {
private final BooleanExpression errorSolutionFound = matchingErrorDiscussion.isNotNull();
private final BooleanProperty isLoadingHttpResponse = new SimpleBooleanProperty();
private final BooleanProperty askedForLookupDatabasePermission = new SimpleBooleanProperty();
private final boolean formerSceneWasResizable;
@Inject
ErrorController(Application application, @Named("stackTrace") String stackTrace, ErrorCode errorCode, @Nullable Scene previousScene, Stage window, Environment environment, ExecutorService executorService) {
@@ -83,12 +86,14 @@ public class ErrorController implements FxController {
this.window = window;
this.environment = environment;
this.executorService = executorService;
this.formerSceneWasResizable = window.isResizable();
}
@FXML
public void back() {
if (previousScene != null) {
window.setScene(previousScene);
window.setResizable(formerSceneWasResizable);
}
}
@@ -142,11 +147,19 @@ public class ErrorController implements FxController {
@FXML
public void lookUpSolution() {
String userAgent = USER_AGENT_FORMAT.formatted( //
environment.getAppVersion(), //
environment.getBuildNumber().orElse("undefined"), //
System.getProperty("os.name"), //
System.getProperty("os.version"), //
System.getProperty("os.arch"));
isLoadingHttpResponse.set(true);
askedForLookupDatabasePermission.set(true);
HttpClient httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
HttpRequest httpRequest = HttpRequest.newBuilder()//
.uri(URI.create(ERROR_CODES_URL))//
.header("User-Agent", userAgent)
.timeout(Duration.ofSeconds(10))
.uri(URI.create(ERROR_CODES_URL_FORMAT.formatted(URLEncoder.encode(errorCode.toString(),StandardCharsets.UTF_8))))//
.build();
httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofInputStream())//
.thenAcceptAsync(this::loadHttpResponse, executorService)//

View File

@@ -1,7 +1,9 @@
package org.cryptomator.ui.fxapp;
import dagger.Lazy;
import org.cryptomator.common.Environment;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,6 +19,7 @@ public class FxApplication {
private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class);
private final long startupTime;
private final Environment environment;
private final Settings settings;
private final AppLaunchEventHandler launchEventHandler;
private final Lazy<TrayMenuComponent> trayMenu;
@@ -26,8 +29,9 @@ public class FxApplication {
private final AutoUnlocker autoUnlocker;
@Inject
FxApplication(@Named("startupTime") long startupTime, Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker) {
FxApplication(@Named("startupTime") long startupTime, Environment environment, Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker) {
this.startupTime = startupTime;
this.environment = environment;
this.settings = settings;
this.launchEventHandler = launchEventHandler;
this.trayMenu = trayMenu;
@@ -68,9 +72,31 @@ public class FxApplication {
return null;
});
appWindows.checkAndShowUpdateReminderWindow();
if (!environment.disableUpdateCheck()) {
appWindows.checkAndShowUpdateReminderWindow();
}
migrateAndInformDokanyRemoval();
launchEventHandler.startHandlingLaunchEvents();
autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES);
}
private void migrateAndInformDokanyRemoval() {
var dokanyProviderId = "org.cryptomator.frontend.dokany.mount.DokanyMountProvider";
boolean dokanyFound = false;
if (settings.mountService.getValueSafe().equals(dokanyProviderId)) {
dokanyFound = true;
settings.mountService.set(null);
}
for (VaultSettings vaultSettings : settings.directories) {
if (vaultSettings.mountService.getValueSafe().equals(dokanyProviderId)) {
dokanyFound = true;
vaultSettings.mountService.set(null);
}
}
if (dokanyFound) {
appWindows.showDokanySupportEndWindow();
}
}
}

View File

@@ -7,12 +7,14 @@ package org.cryptomator.ui.fxapp;
import dagger.Module;
import dagger.Provides;
import org.cryptomator.ui.dokanysupportend.DokanySupportEndComponent;
import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.health.HealthCheckComponent;
import org.cryptomator.ui.lock.LockComponent;
import org.cryptomator.ui.mainwindow.MainWindowComponent;
import org.cryptomator.ui.preferences.PreferencesComponent;
import org.cryptomator.ui.quit.QuitComponent;
import org.cryptomator.ui.sharevault.ShareVaultComponent;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
@@ -22,7 +24,18 @@ import javafx.scene.image.Image;
import java.io.IOException;
import java.io.InputStream;
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, VaultOptionsComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class, HealthCheckComponent.class, UpdateReminderComponent.class})
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, //
MainWindowComponent.class, //
PreferencesComponent.class, //
VaultOptionsComponent.class, //
UnlockComponent.class, //
LockComponent.class, //
QuitComponent.class, //
ErrorComponent.class, //
HealthCheckComponent.class, //
UpdateReminderComponent.class, //
DokanySupportEndComponent.class, //
ShareVaultComponent.class})
abstract class FxApplicationModule {
private static Image createImageFromResource(String resourceName) throws IOException {

View File

@@ -5,12 +5,14 @@ import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
import org.cryptomator.ui.dokanysupportend.DokanySupportEndComponent;
import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.lock.LockComponent;
import org.cryptomator.ui.mainwindow.MainWindowComponent;
import org.cryptomator.ui.preferences.PreferencesComponent;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import org.cryptomator.ui.quit.QuitComponent;
import org.cryptomator.ui.sharevault.ShareVaultComponent;
import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.unlock.UnlockWorkflow;
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
@@ -47,23 +49,27 @@ public class FxApplicationWindows {
private final QuitComponent.Builder quitWindowBuilder;
private final UnlockComponent.Factory unlockWorkflowFactory;
private final UpdateReminderComponent.Factory updateReminderWindowBuilder;
private final DokanySupportEndComponent.Factory dokanySupportEndWindowBuilder;
private final LockComponent.Factory lockWorkflowFactory;
private final ErrorComponent.Factory errorWindowFactory;
private final ExecutorService executor;
private final VaultOptionsComponent.Factory vaultOptionsWindow;
private final ShareVaultComponent.Factory shareVaultWindow;
private final FilteredList<Window> visibleWindows;
@Inject
public FxApplicationWindows(@PrimaryStage Stage primaryStage,
public FxApplicationWindows(@PrimaryStage Stage primaryStage, //
Optional<TrayIntegrationProvider> trayIntegration, //
Lazy<MainWindowComponent> mainWindow, //
Lazy<PreferencesComponent> preferencesWindow, //
QuitComponent.Builder quitWindowBuilder, //
UnlockComponent.Factory unlockWorkflowFactory, //
UpdateReminderComponent.Factory updateReminderWindowBuilder, //
DokanySupportEndComponent.Factory dokanySupportEndWindowBuilder, //
LockComponent.Factory lockWorkflowFactory, //
ErrorComponent.Factory errorWindowFactory, //
VaultOptionsComponent.Factory vaultOptionsWindow, //
ShareVaultComponent.Factory shareVaultWindow, //
ExecutorService executor) {
this.primaryStage = primaryStage;
this.trayIntegration = trayIntegration;
@@ -72,10 +78,12 @@ public class FxApplicationWindows {
this.quitWindowBuilder = quitWindowBuilder;
this.unlockWorkflowFactory = unlockWorkflowFactory;
this.updateReminderWindowBuilder = updateReminderWindowBuilder;
this.dokanySupportEndWindowBuilder = dokanySupportEndWindowBuilder;
this.lockWorkflowFactory = lockWorkflowFactory;
this.errorWindowFactory = errorWindowFactory;
this.executor = executor;
this.vaultOptionsWindow = vaultOptionsWindow;
this.shareVaultWindow = shareVaultWindow;
this.visibleWindows = Window.getWindows().filtered(Window::isShowing);
}
@@ -122,6 +130,10 @@ public class FxApplicationWindows {
return CompletableFuture.supplyAsync(() -> preferencesWindow.get().showPreferencesWindow(selectedTab), Platform::runLater).whenComplete(this::reportErrors);
}
public void showShareVaultWindow(Vault vault) {
CompletableFuture.runAsync(() -> shareVaultWindow.create(vault).showShareVaultWindow(), Platform::runLater);
}
public CompletionStage<Stage> showVaultOptionsWindow(Vault vault, SelectedVaultOptionsTab tab) {
return showMainWindow().thenApplyAsync((window) -> vaultOptionsWindow.create(vault).showVaultOptionsWindow(tab), Platform::runLater).whenComplete(this::reportErrors);
}
@@ -134,6 +146,11 @@ public class FxApplicationWindows {
CompletableFuture.runAsync(() -> updateReminderWindowBuilder.create().checkAndShowUpdateReminderWindow(), Platform::runLater);
}
public void showDokanySupportEndWindow() {
CompletableFuture.runAsync(() -> dokanySupportEndWindowBuilder.create().showDokanySupportEndWindow(), Platform::runLater);
}
public CompletionStage<Void> startUnlockWorkflow(Vault vault, @Nullable Stage owner) {
return CompletableFuture.supplyAsync(() -> {
Preconditions.checkState(vault.stateProperty().transition(VaultState.Value.LOCKED, VaultState.Value.PROCESSING), "Vault not locked.");

View File

@@ -1,45 +1,57 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.common.Environment;
import org.cryptomator.common.SemVerComparator;
import org.cryptomator.common.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Worker;
import javafx.concurrent.WorkerStateEvent;
import javafx.util.Duration;
import java.time.Instant;
import java.util.Comparator;
@FxApplicationScoped
public class UpdateChecker {
private static final Logger LOG = LoggerFactory.getLogger(UpdateChecker.class);
private static final Duration AUTOCHECK_DELAY = Duration.seconds(5);
private static final Duration AUTO_CHECK_DELAY = Duration.seconds(5);
private final Environment env;
private final Settings settings;
private final String currentVersion;
private final StringProperty latestVersionProperty;
private final Comparator<String> semVerComparator;
private final StringProperty latestVersion = new SimpleStringProperty();
private final ScheduledService<String> updateCheckerService;
private final ObjectProperty<UpdateCheckState> state = new SimpleObjectProperty<>(UpdateCheckState.NOT_CHECKED);
private final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
private final Comparator<String> versionComparator = new SemVerComparator();
private final BooleanBinding updateAvailable;
private final BooleanBinding checkFailed;
@Inject
UpdateChecker(Settings settings, Environment env, @Named("latestVersion") StringProperty latestVersionProperty, @Named("SemVer") Comparator<String> semVerComparator, ScheduledService<String> updateCheckerService) {
UpdateChecker(Settings settings, //
Environment env, //
ScheduledService<String> updateCheckerService) {
this.env = env;
this.settings = settings;
this.latestVersionProperty = latestVersionProperty;
this.semVerComparator = semVerComparator;
this.updateCheckerService = updateCheckerService;
this.currentVersion = env.getAppVersion();
this.lastSuccessfulUpdateCheck = settings.lastSuccessfulUpdateCheck;
this.updateAvailable = Bindings.createBooleanBinding(this::isUpdateAvailable, latestVersion);
this.checkFailed = Bindings.equal(UpdateCheckState.CHECK_FAILED, state);
}
public void automaticallyCheckForUpdatesIfEnabled() {
if (settings.checkForUpdates.get()) {
startCheckingForUpdates(AUTOCHECK_DELAY);
if (!env.disableUpdateCheck() && settings.checkForUpdates.get()) {
startCheckingForUpdates(AUTO_CHECK_DELAY);
}
}
@@ -59,36 +71,65 @@ public class UpdateChecker {
private void checkStarted(WorkerStateEvent event) {
LOG.debug("Checking for updates...");
state.set(UpdateCheckState.IS_CHECKING);
}
private void checkSucceeded(WorkerStateEvent event) {
String latestVersion = updateCheckerService.getValue();
LOG.info("Current version: {}, lastest version: {}", currentVersion, latestVersion);
if (semVerComparator.compare(currentVersion, latestVersion) < 0) {
// update is available
latestVersionProperty.set(latestVersion);
} else {
latestVersionProperty.set(null);
}
var latestVersionString = updateCheckerService.getValue();
LOG.info("Current version: {}, latest version: {}", getCurrentVersion(), latestVersionString);
lastSuccessfulUpdateCheck.set(Instant.now());
latestVersion.set(latestVersionString);
state.set(UpdateCheckState.CHECK_SUCCESSFUL);
}
private void checkFailed(WorkerStateEvent event) {
LOG.warn("Error checking for updates", event.getSource().getException());
state.set(UpdateCheckState.CHECK_FAILED);
}
public enum UpdateCheckState {
NOT_CHECKED,
IS_CHECKING,
CHECK_SUCCESSFUL,
CHECK_FAILED;
}
/* Observable Properties */
public BooleanBinding checkingForUpdatesProperty() {
return updateCheckerService.stateProperty().isEqualTo(Worker.State.RUNNING);
}
public ReadOnlyStringProperty latestVersionProperty() {
return latestVersionProperty;
return latestVersion;
}
public BooleanBinding updateAvailableProperty() {
return updateAvailable;
}
public BooleanBinding checkFailedProperty() {
return checkFailed;
}
public boolean isUpdateAvailable() {
String currentVersion = getCurrentVersion();
String latestVersionString = latestVersion.get();
if (currentVersion == null || latestVersionString == null) {
return false;
} else {
return versionComparator.compare(currentVersion, latestVersionString) < 0;
}
}
public ObjectProperty<Instant> lastSuccessfulUpdateCheckProperty() {
return lastSuccessfulUpdateCheck;
}
public ObjectProperty<UpdateCheckState> updateCheckStateProperty() {
return state;
}
public String getCurrentVersion() {
return currentVersion;
return env.getAppVersion();
}
}

View File

@@ -11,8 +11,6 @@ import org.slf4j.LoggerFactory;
import javax.inject.Named;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;
@@ -32,13 +30,6 @@ public abstract class UpdateCheckerModule {
private static final Duration UPDATE_CHECK_INTERVAL = Duration.hours(3);
private static final Duration DISABLED_UPDATE_CHECK_INTERVAL = Duration.hours(100000); // Duration.INDEFINITE leads to overflows...
@Provides
@Named("latestVersion")
@FxApplicationScoped
static StringProperty provideLatestVersion() {
return new SimpleStringProperty();
}
@Provides
@FxApplicationScoped
static Optional<HttpClient> provideHttpClient() {
@@ -63,6 +54,7 @@ public abstract class UpdateCheckerModule {
return HttpRequest.newBuilder() //
.uri(LATEST_VERSION_URI) //
.header("User-Agent", userAgent) //
.timeout(java.time.Duration.ofSeconds(10))
.build();
}

View File

@@ -101,16 +101,16 @@ public class StartController implements FxController {
}
}
private void loadingKeyFailed(Throwable e) {
switch (e) {
case UnlockCancelledException uce -> {} //ok
case VaultKeyInvalidException vkie -> {
LOG.error("Invalid key"); //TODO: specific error screen
private void loadingKeyFailed(Throwable t) {
switch (t) {
case UnlockCancelledException e -> {} // ok // TODO: rename to _ with JEP 443
case VaultKeyInvalidException e -> { // TODO: rename to _ with JEP 443
LOG.error("Invalid key"); // TODO: specific error screen
appWindows.showErrorWindow(e, window, null);
}
default -> {
LOG.error("Failed to load key.", e);
appWindows.showErrorWindow(e, window, null);
LOG.error("Failed to load key.", t);
appWindows.showErrorWindow(t, window, null);
}
}
}

View File

@@ -35,13 +35,13 @@ public class AuthFlowController implements FxController {
private final String deviceId;
private final HubConfig hubConfig;
private final AtomicReference<String> tokenRef;
private final CompletableFuture<JWEObject> result;
private final CompletableFuture<ReceivedKey> result;
private final Lazy<Scene> receiveKeyScene;
private final ObjectProperty<URI> authUri;
private AuthFlowTask task;
@Inject
public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, @Named("deviceId") String deviceId, HubConfig hubConfig, @Named("bearerToken") AtomicReference<String> tokenRef, CompletableFuture<JWEObject> result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy<Scene> receiveKeyScene) {
public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, @Named("deviceId") String deviceId, HubConfig hubConfig, @Named("bearerToken") AtomicReference<String> tokenRef, CompletableFuture<ReceivedKey> result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy<Scene> receiveKeyScene) {
this.application = application;
this.window = window;
this.executor = executor;

View File

@@ -1,13 +1,14 @@
package org.cryptomator.ui.keyloading.hub;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.coffeelibs.tinyoauth2client.AuthFlow;
import io.github.coffeelibs.tinyoauth2client.TinyOAuth2;
import io.github.coffeelibs.tinyoauth2client.http.response.Response;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.time.Duration;
import java.util.function.Consumer;
class AuthFlowTask extends Task<String> {
@@ -21,7 +22,7 @@ class AuthFlowTask extends Task<String> {
/**
* Spawns a server and waits for the redirectUri to be called.
*
* @param hubConfig Configuration object holding parameters required by {@link AuthFlow}
* @param hubConfig Configuration object holding parameters required by {@link io.github.coffeelibs.tinyoauth2client.AuthorizationCodeGrant}
* @param redirectUriConsumer A callback invoked with the redirectUri, as soon as the server has started
*/
public AuthFlowTask(HubConfig hubConfig, AuthFlowContext authFlowContext, Consumer<URI> redirectUriConsumer) {
@@ -34,10 +35,11 @@ class AuthFlowTask extends Task<String> {
protected String call() throws IOException, InterruptedException {
var response = TinyOAuth2.client(hubConfig.clientId) //
.withTokenEndpoint(URI.create(hubConfig.tokenEndpoint)) //
.authFlow(URI.create(hubConfig.authEndpoint)) //
.withRequestTimeout(Duration.ofSeconds(10)) //
.authorizationCodeGrant(URI.create(hubConfig.authEndpoint)) //
.setSuccessResponse(Response.redirect(URI.create(hubConfig.authSuccessUrl + "&device=" + authFlowContext.deviceId()))) //
.setErrorResponse(Response.redirect(URI.create(hubConfig.authErrorUrl + "&device=" + authFlowContext.deviceId()))) //
.authorize(redirectUriConsumer);
.authorize(HttpClient.newHttpClient(), redirectUriConsumer);
if (response.statusCode() != 200) {
throw new NotOkResponseException("Authorization returned status code " + response.statusCode());
}

View File

@@ -1,5 +0,0 @@
package org.cryptomator.ui.keyloading.hub;
record CreateDeviceDto(String id, String name, String publicKey) {
}

View File

@@ -0,0 +1,12 @@
package org.cryptomator.ui.keyloading.hub;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
/**
* Thrown, when Hub registerDevice-Request returns with 409
*/
class DeviceAlreadyExistsException extends MasterkeyLoadingFailedException {
public DeviceAlreadyExistsException() {
super("Device already registered on this Hub instance");
}
}

View File

@@ -1,19 +0,0 @@
package org.cryptomator.ui.keyloading.hub;
import com.google.common.io.CharStreams;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
class HttpHelper {
public static String readBody(HttpResponse<InputStream> response) throws IOException {
try (var in = response.body(); var reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
return CharStreams.toString(reader);
}
}
}

View File

@@ -1,6 +1,10 @@
package org.cryptomator.ui.keyloading.hub;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.jetbrains.annotations.Nullable;
import java.net.URI;
// needs to be accessible by JSON decoder
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -9,8 +13,50 @@ public class HubConfig {
public String clientId;
public String authEndpoint;
public String tokenEndpoint;
public String devicesResourceUrl;
public String authSuccessUrl;
public String authErrorUrl;
public @Nullable String apiBaseUrl;
@Deprecated // use apiBaseUrl + "/devices/"
public String devicesResourceUrl;
/**
* A collection of String template processors to construct URIs related to this Hub instance.
*/
@JsonIgnore
public final URIProcessors URIs = new URIProcessors();
/**
* Get the URI pointing to the <code>/api/</code> base resource.
*
* @return <code>/api/</code> URI
* @apiNote URI is guaranteed to end on <code>/</code>
* @see #URIs
*/
public URI getApiBaseUrl() {
if (apiBaseUrl != null) {
// make sure to end on "/":
return URI.create(apiBaseUrl + "/").normalize();
} else { // legacy approach
assert devicesResourceUrl != null;
// make sure to end on "/":
return URI.create(devicesResourceUrl + "/..").normalize();
}
}
public URI getWebappBaseUrl() {
return getApiBaseUrl().resolve("../app/");
}
public class URIProcessors {
/**
* Resolves paths relative to the <code>/api/</code> endpoint of this Hub instance.
*/
public final StringTemplate.Processor<URI, RuntimeException> API = template -> {
var path = template.interpolate();
var relPath = path.startsWith("/") ? path.substring(1) : path;
return getApiBaseUrl().resolve(relPath);
};
}
}

View File

@@ -1,7 +1,6 @@
package org.cryptomator.ui.keyloading.hub;
import com.google.common.io.BaseEncoding;
import com.nimbusds.jose.JWEObject;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -69,7 +68,7 @@ public abstract class HubKeyLoadingModule {
@Provides
@KeyLoadingScoped
static CompletableFuture<JWEObject> provideResult() {
static CompletableFuture<ReceivedKey> provideResult() {
return new CompletableFuture<>();
}
@@ -114,10 +113,17 @@ public abstract class HubKeyLoadingModule {
}
@Provides
@FxmlScene(FxmlFile.HUB_REGISTER_DEVICE)
@FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE)
@KeyLoadingScoped
static Scene provideHubRegisterDeviceScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE);
static Scene provideHubLegacyRegisterDeviceScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE);
}
@Provides
@FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_SUCCESS)
@KeyLoadingScoped
static Scene provideHubLegacyRegisterSuccessScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_LEGACY_REGISTER_SUCCESS);
}
@Provides
@@ -134,6 +140,20 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_FAILED);
}
@Provides
@FxmlScene(FxmlFile.HUB_REGISTER_DEVICE)
@KeyLoadingScoped
static Scene provideHubRegisterDeviceScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE);
}
@Provides
@FxmlScene(FxmlFile.HUB_REGISTER_DEVICE_ALREADY_EXISTS)
@KeyLoadingScoped
static Scene provideHubRegisterDeviceAlreadyExistsScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE_ALREADY_EXISTS);
}
@Provides
@FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE)
@KeyLoadingScoped
@@ -141,6 +161,13 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
}
@Provides
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT)
@KeyLoadingScoped
static Scene provideRequireAccountInitScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT);
}
@Binds
@IntoMap
@FxControllerKey(NoKeychainController.class)
@@ -166,6 +193,16 @@ public abstract class HubKeyLoadingModule {
@FxControllerKey(RegisterDeviceController.class)
abstract FxController bindRegisterDeviceController(RegisterDeviceController controller);
@Binds
@IntoMap
@FxControllerKey(LegacyRegisterDeviceController.class)
abstract FxController bindLegacyRegisterDeviceController(LegacyRegisterDeviceController controller);
@Binds
@IntoMap
@FxControllerKey(LegacyRegisterSuccessController.class)
abstract FxController bindLegacyRegisterSuccessController(LegacyRegisterSuccessController controller);
@Binds
@IntoMap
@FxControllerKey(RegisterSuccessController.class)
@@ -180,4 +217,9 @@ public abstract class HubKeyLoadingModule {
@IntoMap
@FxControllerKey(UnauthorizedDeviceController.class)
abstract FxController bindUnauthorizedDeviceController(UnauthorizedDeviceController controller);
@Binds
@IntoMap
@FxControllerKey(RequireAccountInitController.class)
abstract FxController bindRequireAccountInitController(RequireAccountInitController controller);
}

View File

@@ -1,7 +1,6 @@
package org.cryptomator.ui.keyloading.hub;
import com.google.common.base.Preconditions;
import com.nimbusds.jose.JWEObject;
import dagger.Lazy;
import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.keychain.NoKeychainAccessProviderException;
@@ -36,14 +35,15 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
private final KeychainManager keychainManager;
private final Lazy<Scene> authFlowScene;
private final Lazy<Scene> noKeychainScene;
private final CompletableFuture<JWEObject> result;
private final CompletableFuture<ReceivedKey> result;
private final DeviceKey deviceKey;
@Inject
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy<Scene> noKeychainScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle) {
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy<Scene> noKeychainScene, CompletableFuture<ReceivedKey> result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle) {
this.window = window;
this.keychainManager = keychainManager;
window.setTitle(windowTitle);
window.setOnCloseRequest(_ -> result.cancel(true));
this.authFlowScene = authFlowScene;
this.noKeychainScene = noKeychainScene;
this.result = result;
@@ -60,7 +60,7 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
var keypair = deviceKey.get();
showWindow(authFlowScene);
var jwe = result.get();
return JWEHelper.decrypt(jwe, keypair.getPrivate());
return jwe.decryptMasterkey(keypair.getPrivate());
} catch (NoKeychainAccessProviderException e) {
showWindow(noKeychainScene);
throw new UnlockCancelledException("Unlock canceled due to missing prerequisites", e);

View File

@@ -1,36 +1,141 @@
package org.cryptomator.ui.keyloading.hub;
import com.google.common.base.Preconditions;
import com.google.common.io.BaseEncoding;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.ECDHDecrypter;
import com.nimbusds.jose.crypto.ECDHEncrypter;
import com.nimbusds.jose.crypto.PasswordBasedDecrypter;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Map;
import java.util.function.Function;
class JWEHelper {
private static final Logger LOG = LoggerFactory.getLogger(JWEHelper.class);
private static final String JWE_PAYLOAD_MASTERKEY_FIELD = "key";
private static final String JWE_PAYLOAD_KEY_FIELD = "key";
private static final String EC_ALG = "EC";
private JWEHelper(){}
private JWEHelper() {}
public static Masterkey decrypt(JWEObject jwe, ECPrivateKey privateKey) throws MasterkeyLoadingFailedException {
public static JWEObject encryptUserKey(ECPrivateKey userKey, ECPublicKey deviceKey) {
return encryptKey(userKey, deviceKey);
}
public static ECPrivateKey decryptUserKey(JWEObject jwe, String setupCode) throws InvalidJweKeyException {
try {
jwe.decrypt(new ECDHDecrypter(privateKey));
return readKey(jwe);
jwe.decrypt(new PasswordBasedDecrypter(setupCode));
return readKey(jwe, JWE_PAYLOAD_KEY_FIELD, JWEHelper::decodeECPrivateKey);
} catch (JOSEException e) {
LOG.warn("Failed to decrypt JWE: {}", jwe);
throw new MasterkeyLoadingFailedException("Failed to decrypt JWE", e);
throw new InvalidJweKeyException(e);
}
}
private static Masterkey readKey(JWEObject jwe) throws MasterkeyLoadingFailedException {
public static ECPrivateKey decryptUserKey(JWEObject jwe, ECPrivateKey deviceKey) throws InvalidJweKeyException {
try {
jwe.decrypt(new ECDHDecrypter(deviceKey));
return readKey(jwe, JWE_PAYLOAD_KEY_FIELD, JWEHelper::decodeECPrivateKey);
} catch (JOSEException e) {
throw new InvalidJweKeyException(e);
}
}
/**
* Attempts to decode a DER-encoded EC private key.
*
* @param encoded DER-encoded EC private key
* @return the decoded key
* @throws KeyDecodeFailedException On malformed input
*/
public static ECPrivateKey decodeECPrivateKey(byte[] encoded) throws KeyDecodeFailedException {
try {
KeyFactory factory = KeyFactory.getInstance(EC_ALG);
var privateKey = factory.generatePrivate(new PKCS8EncodedKeySpec(encoded));
if (privateKey instanceof ECPrivateKey ecPrivateKey) {
return ecPrivateKey;
} else {
throw new IllegalStateException(EC_ALG + " key factory not generating ECPrivateKeys");
}
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(EC_ALG + " not supported");
} catch (InvalidKeySpecException e) {
throw new KeyDecodeFailedException(e);
}
}
/**
* Attempts to decode a DER-encoded EC public key.
*
* @param encoded DER-encoded EC public key
* @return the decoded key
* @throws KeyDecodeFailedException On malformed input
*/
public static ECPublicKey decodeECPublicKey(byte[] encoded) throws KeyDecodeFailedException {
try {
KeyFactory factory = KeyFactory.getInstance(EC_ALG);
var publicKey = factory.generatePublic(new X509EncodedKeySpec(encoded));
if (publicKey instanceof ECPublicKey ecPublicKey) {
return ecPublicKey;
} else {
throw new IllegalStateException(EC_ALG + " key factory not generating ECPublicKeys");
}
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(EC_ALG + " not supported");
} catch (InvalidKeySpecException e) {
throw new KeyDecodeFailedException(e);
}
}
public static JWEObject encryptVaultKey(Masterkey vaultKey, ECPublicKey userKey) {
return encryptKey(vaultKey, userKey);
}
private static JWEObject encryptKey(Key key, ECPublicKey userKey) {
try {
var encodedVaultKey = Base64.getEncoder().encodeToString(key.getEncoded());
var keyGen = new ECKeyGenerator(Curve.P_384);
var ephemeralKeyPair = keyGen.generate();
var header = new JWEHeader.Builder(JWEAlgorithm.ECDH_ES, EncryptionMethod.A256GCM).ephemeralPublicKey(ephemeralKeyPair.toPublicJWK()).build();
var payload = new Payload(Map.of(JWE_PAYLOAD_KEY_FIELD, encodedVaultKey));
var jwe = new JWEObject(header, payload);
jwe.encrypt(new ECDHEncrypter(userKey));
return jwe;
} catch (JOSEException e) {
throw new RuntimeException(e);
}
}
public static Masterkey decryptVaultKey(JWEObject jwe, ECPrivateKey privateKey) throws InvalidJweKeyException {
try {
jwe.decrypt(new ECDHDecrypter(privateKey));
return readKey(jwe, JWE_PAYLOAD_KEY_FIELD, Masterkey::new);
} catch (JOSEException e) {
throw new InvalidJweKeyException(e);
}
}
private static <T> T readKey(JWEObject jwe, String keyField, Function<byte[], T> rawKeyFactory) throws MasterkeyLoadingFailedException {
Preconditions.checkArgument(jwe.getState() == JWEObject.State.DECRYPTED);
var fields = jwe.getPayload().toJSONObject();
if (fields == null) {
@@ -39,17 +144,31 @@ class JWEHelper {
}
var keyBytes = new byte[0];
try {
if (fields.get(JWE_PAYLOAD_MASTERKEY_FIELD) instanceof String key) {
keyBytes = BaseEncoding.base64().decode(key);
return new Masterkey(keyBytes);
if (fields.get(keyField) instanceof String key) {
keyBytes = Base64.getDecoder().decode(key);
return rawKeyFactory.apply(keyBytes);
} else {
throw new IllegalArgumentException("JWE payload doesn't contain field " + JWE_PAYLOAD_MASTERKEY_FIELD);
throw new IllegalArgumentException("JWE payload doesn't contain field " + keyField);
}
} catch (IllegalArgumentException e) {
} catch (IllegalArgumentException | KeyDecodeFailedException e) {
LOG.error("Unexpected JWE payload: {}", jwe.getPayload());
throw new MasterkeyLoadingFailedException("Unexpected JWE payload", e);
} finally {
Arrays.fill(keyBytes, (byte) 0x00);
}
}
public static class InvalidJweKeyException extends MasterkeyLoadingFailedException {
public InvalidJweKeyException(Throwable cause) {
super("Invalid key", cause);
}
}
public static class KeyDecodeFailedException extends CryptoException {
public KeyDecodeFailedException(Throwable cause) {
super("Malformed key", cause);
}
}
}

View File

@@ -0,0 +1,191 @@
package org.cryptomator.ui.keyloading.hub;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.ObjectMapper;
import dagger.Lazy;
import org.cryptomator.common.settings.DeviceKey;
import org.cryptomator.cryptolib.common.P384KeyPair;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
@KeyLoadingScoped
public class LegacyRegisterDeviceController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(LegacyRegisterDeviceController.class);
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true);
private static final List<Integer> EXPECTED_RESPONSE_CODES = List.of(201, 409);
private final Stage window;
private final HubConfig hubConfig;
private final String bearerToken;
private final Lazy<Scene> registerSuccessScene;
private final Lazy<Scene> registerFailedScene;
private final String deviceId;
private final P384KeyPair keyPair;
private final CompletableFuture<ReceivedKey> result;
private final DecodedJWT jwt;
private final HttpClient httpClient;
private final BooleanProperty deviceNameAlreadyExists = new SimpleBooleanProperty(false);
public TextField deviceNameField;
public Button registerBtn;
@Inject
public LegacyRegisterDeviceController(@KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("deviceId") String deviceId, DeviceKey deviceKey, CompletableFuture<ReceivedKey> result, @Named("bearerToken") AtomicReference<String> bearerToken, @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_SUCCESS) Lazy<Scene> registerSuccessScene, @FxmlScene(FxmlFile.HUB_REGISTER_FAILED) Lazy<Scene> registerFailedScene) {
this.window = window;
this.hubConfig = hubConfig;
this.deviceId = deviceId;
this.keyPair = Objects.requireNonNull(deviceKey.get());
this.result = result;
this.bearerToken = Objects.requireNonNull(bearerToken.get());
this.registerSuccessScene = registerSuccessScene;
this.registerFailedScene = registerFailedScene;
this.jwt = JWT.decode(this.bearerToken);
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build();
}
public void initialize() {
deviceNameField.setText(determineHostname());
deviceNameField.textProperty().addListener(observable -> deviceNameAlreadyExists.set(false));
}
private String determineHostname() {
try {
var hostName = InetAddress.getLocalHost().getHostName();
return Objects.requireNonNullElse(hostName, "");
} catch (IOException e) {
return "";
}
}
@FXML
public void register() {
deviceNameAlreadyExists.set(false);
registerBtn.setContentDisplay(ContentDisplay.LEFT);
registerBtn.setDisable(true);
var deviceUri = URI.create(hubConfig.devicesResourceUrl + deviceId);
var deviceKey = keyPair.getPublic().getEncoded();
var dto = new CreateDeviceDto();
dto.id = deviceId;
dto.name = deviceNameField.getText();
dto.publicKey = Base64.getUrlEncoder().withoutPadding().encodeToString(deviceKey);
var json = toJson(dto);
var request = HttpRequest.newBuilder(deviceUri) //
.PUT(HttpRequest.BodyPublishers.ofString(json, StandardCharsets.UTF_8)) //
.header("Authorization", "Bearer " + bearerToken) //
.header("Content-Type", "application/json") //
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.discarding()) //
.thenApply(response -> {
if (EXPECTED_RESPONSE_CODES.contains(response.statusCode())) {
return response;
} else {
throw new RuntimeException("Server answered with unexpected status code " + response.statusCode());
}
}).handleAsync((response, throwable) -> {
if (response != null) {
this.handleResponse(response);
} else {
this.registrationFailed(throwable);
}
return null;
}, Platform::runLater);
}
private String toJson(CreateDeviceDto dto) {
try {
return JSON.writer().writeValueAsString(dto);
} catch (JacksonException e) {
throw new IllegalStateException("Failed to serialize DTO", e);
}
}
private void handleResponse(HttpResponse<Void> voidHttpResponse) {
assert EXPECTED_RESPONSE_CODES.contains(voidHttpResponse.statusCode());
if (voidHttpResponse.statusCode() == 409) {
deviceNameAlreadyExists.set(true);
registerBtn.setContentDisplay(ContentDisplay.TEXT_ONLY);
registerBtn.setDisable(false);
} else {
LOG.debug("Device registration for hub instance {} successful.", hubConfig.authSuccessUrl);
window.setScene(registerSuccessScene.get());
}
}
private void registrationFailed(Throwable cause) {
LOG.warn("Device registration failed.", cause);
window.setScene(registerFailedScene.get());
result.completeExceptionally(cause);
}
@FXML
public void close() {
window.close();
}
private void windowClosed(WindowEvent windowEvent) {
result.cancel(true);
}
/* Getter */
public String getUserName() {
return jwt.getClaim("email").asString();
}
//--- Getters & Setters
public BooleanProperty deviceNameAlreadyExistsProperty() {
return deviceNameAlreadyExists;
}
public boolean getDeviceNameAlreadyExists() {
return deviceNameAlreadyExists.get();
}
private static class CreateDeviceDto {
public String id;
public String name;
public final String type = "DESKTOP";
public String publicKey;
}
}

View File

@@ -0,0 +1,24 @@
package org.cryptomator.ui.keyloading.hub;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
@KeyLoadingScoped
public class LegacyRegisterSuccessController implements FxController {
private final Stage window;
@Inject
public LegacyRegisterSuccessController(@KeyLoading Stage window) {
this.window = window;
}
@FXML
public void close() {
window.close();
}
}

View File

@@ -1,5 +1,9 @@
package org.cryptomator.ui.keyloading.hub;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import com.nimbusds.jose.JWEObject;
import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
@@ -8,6 +12,8 @@ import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
@@ -17,14 +23,15 @@ import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -33,27 +40,36 @@ import java.util.concurrent.atomic.AtomicReference;
@KeyLoadingScoped
public class ReceiveKeyController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(ReceiveKeyController.class);
private static final String SCHEME_PREFIX = "hub+";
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true);
private static final Duration REQ_TIMEOUT = Duration.ofSeconds(10);
private final Stage window;
private final HubConfig hubConfig;
private final String vaultId;
private final String deviceId;
private final String bearerToken;
private final CompletableFuture<JWEObject> result;
private final CompletableFuture<ReceivedKey> result;
private final Lazy<Scene> registerDeviceScene;
private final Lazy<Scene> legacyRegisterDeviceScene;
private final Lazy<Scene> unauthorizedScene;
private final URI vaultBaseUri;
private final Lazy<Scene> accountInitializationScene;
private final Lazy<Scene> invalidLicenseScene;
private final HttpClient httpClient;
@Inject
public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference<String> tokenRef, CompletableFuture<JWEObject> result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene) {
public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, HubConfig hubConfig, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference<String> tokenRef, CompletableFuture<ReceivedKey> result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene, @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene, @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene) {
this.window = window;
this.hubConfig = hubConfig;
this.vaultId = extractVaultId(vault.getVaultConfigCache().getUnchecked().getKeyId()); // TODO: access vault config's JTI directly (requires changes in cryptofs)
this.deviceId = deviceId;
this.bearerToken = Objects.requireNonNull(tokenRef.get());
this.result = result;
this.registerDeviceScene = registerDeviceScene;
this.legacyRegisterDeviceScene = legacyRegisterDeviceScene;
this.unauthorizedScene = unauthorizedScene;
this.vaultBaseUri = getVaultBaseUri(vault);
this.accountInitializationScene = accountInitializationScene;
this.invalidLicenseScene = invalidLicenseScene;
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build();
@@ -61,23 +77,158 @@ public class ReceiveKeyController implements FxController {
@FXML
public void initialize() {
var keyUri = appendPath(vaultBaseUri, "/keys/" + deviceId);
var request = HttpRequest.newBuilder(keyUri) //
.header("Authorization", "Bearer " + bearerToken) //
receiveKey();
}
public void receiveKey() {
requestApiConfig();
}
/**
* STEP 0 (Request): GET /api/config
*/
private void requestApiConfig() {
var configUri = hubConfig.URIs.API."config";
var request = HttpRequest.newBuilder(configUri) //
.GET() //
.timeout(REQ_TIMEOUT) //
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()) //
.thenAcceptAsync(this::loadedExistingKey, Platform::runLater) //
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.US_ASCII)) //
.thenAcceptAsync(this::receivedApiConfig, Platform::runLater) //
.exceptionally(this::retrievalFailed);
}
private void loadedExistingKey(HttpResponse<InputStream> response) {
/**
* STEP 0 (Response): GET /api/config
*
* @param response Response
*/
private void receivedApiConfig(HttpResponse<String> response) {
LOG.debug("GET {} -> Status Code {}", response.request().uri(), response.statusCode());
Preconditions.checkState(response.statusCode() == 200, "Unexpected response " + response.statusCode());
try {
var config = JSON.reader().readValue(response.body(), ConfigDto.class);
if (config.apiLevel >= 1) {
requestDeviceData();
} else {
requestLegacyAccessToken();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* STEP 1 (Request): GET user key for this device
*/
private void requestDeviceData() {
var deviceUri = hubConfig.URIs.API."devices/\{deviceId}";
var request = HttpRequest.newBuilder(deviceUri) //
.header("Authorization", "Bearer " + bearerToken) //
.GET() //
.timeout(REQ_TIMEOUT) //
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)) //
.thenAcceptAsync(this::receivedDeviceData) //
.exceptionally(this::retrievalFailed);
}
/**
* STEP 1 (Response): GET user key for this device
*
* @param response Response
*/
private void receivedDeviceData(HttpResponse<String> response) {
LOG.debug("GET {} -> Status Code {}", response.request().uri(), response.statusCode());
try {
switch (response.statusCode()) {
case 200 -> retrievalSucceeded(response);
case 200 -> {
var device = JSON.reader().readValue(response.body(), DeviceDto.class);
requestVaultMasterkey(device.userPrivateKey);
}
case 404 -> Platform.runLater(this::needsDeviceRegistration);
default -> throw new IllegalStateException("Unexpected response " + response.statusCode());
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private void needsDeviceRegistration() {
window.setScene(registerDeviceScene.get());
}
/**
* STEP 2 (Request): GET vault key for this user
*/
private void requestVaultMasterkey(String encryptedUserKey) {
var vaultKeyUri = hubConfig.URIs.API."vaults/\{vaultId}/access-token";
var request = HttpRequest.newBuilder(vaultKeyUri) //
.header("Authorization", "Bearer " + bearerToken) //
.GET() //
.timeout(REQ_TIMEOUT) //
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.US_ASCII)) //
.thenAcceptAsync(response -> receivedVaultMasterkey(encryptedUserKey, response), Platform::runLater) //
.exceptionally(this::retrievalFailed);
}
/**
* STEP 2 (Response): GET vault key for this user
*
* @param response Response
*/
private void receivedVaultMasterkey(String encryptedUserKey, HttpResponse<String> response) {
LOG.debug("GET {} -> Status Code {}", response.request().uri(), response.statusCode());
switch (response.statusCode()) {
case 200 -> receivedBothEncryptedKeys(response.body(), encryptedUserKey);
case 402 -> licenseExceeded();
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access - TODO: add specific dialog?
case 449 -> accountInitializationRequired();
default -> throw new IllegalStateException("Unexpected response " + response.statusCode());
}
}
private void receivedBothEncryptedKeys(String encryptedVaultKey, String encryptedUserKey) {
try {
var vaultKeyJwe = JWEObject.parse(encryptedVaultKey);
var userKeyJwe = JWEObject.parse(encryptedUserKey);
result.complete(ReceivedKey.vaultKeyAndUserKey(vaultKeyJwe, userKeyJwe));
window.close();
} catch (ParseException e) {
retrievalFailed(e);
}
}
/**
* LEGACY FALLBACK (Request): GET the legacy access token from Hub 1.x
*/
@Deprecated
private void requestLegacyAccessToken() {
var legacyAccessTokenUri = hubConfig.URIs.API."vaults/\{vaultId}/keys/\{deviceId}";
var request = HttpRequest.newBuilder(legacyAccessTokenUri) //
.header("Authorization", "Bearer " + bearerToken) //
.GET() //
.timeout(REQ_TIMEOUT) //
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.US_ASCII)) //
.thenAcceptAsync(this::receivedLegacyAccessTokenResponse, Platform::runLater) //
.exceptionally(this::retrievalFailed);
}
/**
* LEGACY FALLBACK (Response)
*
* @param response Response
*/
@Deprecated
private void receivedLegacyAccessTokenResponse(HttpResponse<String> response) {
try {
switch (response.statusCode()) {
case 200 -> receivedLegacyAccessTokenSuccess(response.body());
case 402 -> licenseExceeded();
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access
case 404 -> needsDeviceRegistration();
case 404 -> needsLegacyDeviceRegistration();
default -> throw new IOException("Unexpected response " + response.statusCode());
}
} catch (IOException e) {
@@ -85,10 +236,11 @@ public class ReceiveKeyController implements FxController {
}
}
private void retrievalSucceeded(HttpResponse<InputStream> response) throws IOException {
@Deprecated
private void receivedLegacyAccessTokenSuccess(String rawToken) throws IOException {
try {
var string = HttpHelper.readBody(response);
result.complete(JWEObject.parse(string));
var token = JWEObject.parse(rawToken);
result.complete(ReceivedKey.legacyDeviceKey(token));
window.close();
} catch (ParseException e) {
throw new IOException("Failed to parse JWE", e);
@@ -99,14 +251,19 @@ public class ReceiveKeyController implements FxController {
window.setScene(invalidLicenseScene.get());
}
private void needsDeviceRegistration() {
window.setScene(registerDeviceScene.get());
@Deprecated
private void needsLegacyDeviceRegistration() {
window.setScene(legacyRegisterDeviceScene.get());
}
private void accessNotGranted() {
window.setScene(unauthorizedScene.get());
}
private void accountInitializationRequired() {
window.setScene(accountInitializationScene.get());
}
private Void retrievalFailed(Throwable cause) {
result.completeExceptionally(cause);
return null;
@@ -130,16 +287,15 @@ public class ReceiveKeyController implements FxController {
}
}
private static URI getVaultBaseUri(Vault vault) {
try {
var kid = vault.getVaultConfigCache().get().getKeyId();
assert kid.getScheme().startsWith(SCHEME_PREFIX);
var hubUriScheme = kid.getScheme().substring(SCHEME_PREFIX.length());
return new URI(hubUriScheme, kid.getSchemeSpecificPart(), kid.getFragment());
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (URISyntaxException e) {
throw new IllegalStateException("URI constructed from params known to be valid", e);
}
private static String extractVaultId(URI vaultKeyUri) {
assert vaultKeyUri.getScheme().startsWith(SCHEME_PREFIX);
var path = vaultKeyUri.getPath();
return path.substring(path.lastIndexOf('/') + 1);
}
@JsonIgnoreProperties(ignoreUnknown = true)
private record DeviceDto(@JsonProperty(value = "userPrivateKey", required = true) String userPrivateKey) {}
@JsonIgnoreProperties(ignoreUnknown = true)
private record ConfigDto(@JsonProperty(value = "apiLevel") int apiLevel) {}
}

View File

@@ -0,0 +1,45 @@
package org.cryptomator.ui.keyloading.hub;
import com.nimbusds.jose.JWEObject;
import org.cryptomator.cryptolib.api.Masterkey;
import java.security.interfaces.ECPrivateKey;
@FunctionalInterface
interface ReceivedKey {
/**
* Decrypts the vault key.
*
* @param deviceKey This device's private key.
* @return The decrypted vault key
*/
Masterkey decryptMasterkey(ECPrivateKey deviceKey);
/**
* Creates an unlock response object from the user key + vault key.
*
* @param vaultKeyJwe a JWE containing the symmetric vault key, encrypted for this device's user.
* @param userKeyJwe a JWE containing the user's private key, encrypted for this device.
* @return Ciphertext received by Hub, which can be decrypted using this device's private key.
*/
static ReceivedKey vaultKeyAndUserKey(JWEObject vaultKeyJwe, JWEObject userKeyJwe) {
return deviceKey -> {
var userKey = JWEHelper.decryptUserKey(userKeyJwe, deviceKey);
return JWEHelper.decryptVaultKey(vaultKeyJwe, userKey);
};
}
/**
* Creates an unlock response object from the received legacy "access token" JWE.
*
* @param vaultKeyJwe a JWE containing the symmetric vault key, encrypted for this device.
* @return Ciphertext received by Hub, which can be decrypted using this device's private key.
* @deprecated Only for compatibility with Hub 1.0 - 1.2
*/
@Deprecated
static ReceivedKey legacyDeviceKey(JWEObject vaultKeyJwe) {
return deviceKey -> JWEHelper.decryptVaultKey(vaultKeyJwe, deviceKey);
}
}

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