Compare commits

...

229 Commits

Author SHA1 Message Date
Armin Schrenk
c59554f7bb Merge branch 'release/1.18.0' 2025-11-12 10:43:22 +01:00
Armin Schrenk
11c66e8df7 Use correct SHA256 value for openjfx linux arm64 2025-11-11 16:23:33 +01:00
Armin Schrenk
c49bf0f146 finalize 1.18.0 2025-11-11 16:08:00 +01:00
Armin Schrenk
e74bd91879 Merge branch 'develop' into release/1.18.0 2025-11-11 15:58:03 +01:00
Cryptobot
89d9249a08 New Crowdin updates (#4016)
New translations strings.properties

Afrikaans; 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; 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]
2025-11-11 15:57:18 +01:00
Armin Schrenk
013fff1223 Feature: Sign files with Azure trusted signing (#4038) 2025-11-11 14:24:20 +01:00
Armin Schrenk
fd9d27215e adjust wording 2025-11-11 13:20:02 +01:00
Sebastian Stenzel
7315b59a6d simplify + allow IDE to find used i18n strings 2025-11-06 15:36:08 +01:00
Jerry Pan
884c6f6bdd Fix : Shortcut doesn’t close SimpleDialogs (#4026) 2025-10-31 13:40:19 +01:00
Tobias Hagemann
c5367db971 Fix Hub vault URL to preserve path component 2025-10-29 15:22:24 +01:00
Armin Schrenk
8bb451261e Merge branch 'develop' into release/1.18.0 2025-10-16 16:43:01 +02:00
Armin Schrenk
de4c7d47e5 Merge pull request #3821 from cryptomator/feature/restore-vaultconfig
Feature: Vault Recovery Enhancements
2025-10-16 16:36:58 +02:00
Jan-Peter Klein
b4fe63c966 Merge branch 'feature/restore-vaultconfig' of https://github.com/cryptomator/cryptomator into feature/restore-vaultconfig 2025-10-16 15:38:16 +02:00
Jan-Peter Klein
ed45182b6c add IllegalStateException to the catch clause 2025-10-16 15:37:47 +02:00
Armin Schrenk
afd2d74c90 Merge branch 'develop' into feature/restore-vaultconfig 2025-10-16 15:25:27 +02:00
Jan-Peter Klein
4bcf01270a fix owner 2025-10-16 15:12:22 +02:00
Armin Schrenk
64466df6b8 [skip ci] revert powershell build early stop (was intended for testing purpose only) 2025-10-16 10:40:35 +02:00
Armin Schrenk
db9bd49dd9 add jdk modules jdk.crypto.ec and jdk.crypto.cryptoki requrired by nimbus-jose-jwt dependency
references e50c949b62
2025-10-16 10:38:01 +02:00
Cryptobot
4ed4a3e3e5 New Crowdin updates (#4009)
New translations strings.properties

Arabic; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Czech; Danish; Dutch; Filipino; Finnish; French; German; Greek; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Norwegian Bokmal; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Slovak; Slovenian; Spanish; Swedish; Thai; Turkish; Ukrainian; Uyghur; Vietnamese; 

[ci skip]
2025-10-16 10:19:44 +02:00
Armin Schrenk
ad73b2f31d Merge pull request #4015 from cryptomator/feature/pin-gh-actions-version
Feature: Pin CI actions version
2025-10-15 16:07:09 +02:00
Jan-Peter Klein
227b322b8a revert cleanup that introduced a bug 2025-10-15 15:55:29 +02:00
Armin Schrenk
ccf2e60390 add version info in a comment 2025-10-15 14:55:39 +02:00
Jan-Peter Klein
1104c1067a wording changes 2025-10-15 14:06:00 +02:00
Armin Schrenk
83d2c39080 also pin official github actions 2025-10-15 12:48:49 +02:00
Armin Schrenk
446caff901 Pin exact version of external ci actions 2025-10-15 12:31:38 +02:00
Jan-Peter Klein
90537caee7 change wording 2025-10-15 07:34:17 +02:00
Jan-Peter Klein
25dea8ebe6 infeo suggested wordings 2025-10-14 14:51:12 +02:00
Jan-Peter Klein
4a7d2907c8 use ellipsis 2025-10-14 14:28:53 +02:00
Jan-Peter Klein
7f3af0c7f6 add defaults to switches to solve sonar cloud issues 2025-10-14 13:41:15 +02:00
dependabot[bot]
e6e04078fa Bump the java-production-dependencies group across 1 directory with 5 updates (#4007) 2025-10-14 11:16:41 +00:00
Armin Schrenk
e3f6b5f812 Feature: JFX 25 (#4013)
Closes #3902. References https://github.com/cryptomator/cryptomator/issues/3453 and references https://github.com/cryptomator/cryptomator/pull/3825
2025-10-14 13:15:49 +02:00
Armin Schrenk
f3461f7da4 fix failing CI 2025-10-14 13:06:52 +02:00
Jan-Peter Klein
94518ede99 set the messageLabel directly 2025-10-14 10:04:14 +02:00
Jan-Peter Klein
0fa041da85 remove the unconditional constructor title 2025-10-14 08:15:37 +02:00
Jan-Peter Klein
daa4f3a568 recheck directory structure after restoring backup 2025-10-14 08:02:17 +02:00
Jan-Peter Klein
fc6f7d184c skip unsafe states and check config file before reload 2025-10-14 07:42:24 +02:00
Armin Schrenk
e50c949b62 Bump com.nimbusds:nimbus-jose-jwt from version 9.37.3 to version 10.5
Addresses shaded vulnerability in CVE-2025-53864 (OSSINDEX)
2025-10-13 11:50:54 +02:00
Armin Schrenk
349349e057 Add share option in context menu (#4008) 2025-10-10 11:04:37 +02:00
Armin Schrenk
4b36a1219f [skip ci] bump dependency-check-workflow to version 3 2025-10-08 14:11:57 +02:00
Armin Schrenk
6533ba7367 use more env context in CI 2025-10-08 10:36:29 +02:00
Tobias Hagemann
7f9c9a7df6 Reinstate original macOS icon shape in macOS 26 Tahoe (#3990)
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2025-10-08 09:57:10 +02:00
Armin Schrenk
afda8a4981 only create AUR PR if it is a stable release 2025-09-26 15:39:05 +02:00
Armin Schrenk
153f9b485c prepare 1.18.0 2025-09-26 13:38:53 +02:00
Armin Schrenk
b9e91115b4 fix windows installer build 2025-09-26 13:38:02 +02:00
dependabot[bot]
2d29b1a76f Bump the java-production-dependencies group across 1 directory with 5 updates (#3988)
Closes #3883, closes #3932, closes #3982

Bumps the java-production-dependencies group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [org.cryptomator:fuse-nio-adapter](https://github.com/cryptomator/fuse-nio-adapter) | `5.0.5` | `5.1.0` |
| [org.cryptomator:integrations-api](https://github.com/cryptomator/integrations-api) | `1.6.0` | `1.7.0` |
| [org.cryptomator:integrations-mac](https://github.com/cryptomator/integrations-mac) | `1.4.0` | `1.4.1` |
| [org.cryptomator:integrations-linux](https://github.com/cryptomator/integrations-linux) | `1.6.0` | `1.6.1` |
| [org.cryptomator:integrations-win](https://github.com/cryptomator/integrations-win) | `1.5.0` | `1.5.1` |



Updates `org.cryptomator:fuse-nio-adapter` from 5.0.5 to 5.1.0
- [Release notes](https://github.com/cryptomator/fuse-nio-adapter/releases)
- [Changelog](https://github.com/cryptomator/fuse-nio-adapter/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/fuse-nio-adapter/compare/5.0.5...5.1.0)

Updates `org.cryptomator:integrations-api` from 1.6.0 to 1.7.0
- [Release notes](https://github.com/cryptomator/integrations-api/releases)
- [Changelog](https://github.com/cryptomator/integrations-api/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/integrations-api/compare/1.6.0...1.7.0)

Updates `org.cryptomator:integrations-mac` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/cryptomator/integrations-mac/releases)
- [Changelog](https://github.com/cryptomator/integrations-mac/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/integrations-mac/compare/1.4.0...1.4.1)

Updates `org.cryptomator:integrations-linux` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/cryptomator/integrations-linux/releases)
- [Changelog](https://github.com/cryptomator/integrations-linux/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/integrations-linux/compare/1.6.0...1.6.1)

Updates `org.cryptomator:integrations-win` from 1.5.0 to 1.5.1
- [Release notes](https://github.com/cryptomator/integrations-win/releases)
- [Changelog](https://github.com/cryptomator/integrations-win/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/integrations-win/compare/1.5.0...1.5.1)

---
updated-dependencies:
- dependency-name: org.cryptomator:fuse-nio-adapter
  dependency-version: 5.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-api
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-mac
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-linux
  dependency-version: 1.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-win
  dependency-version: 1.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-22 15:47:26 +02:00
Cryptobot
f62a5ed74b New Crowdin updates (#3931)
New translations strings.properties

Chinese Traditional; Danish; French; Greek; Korean; Polish; Swedish; Ukrainian; Vietnamese; 

[ci skip]
2025-09-22 15:23:45 +02:00
dependabot[bot]
7fe7e1f5bf Bump org.mockito:mockito-core in the java-test-dependencies group (#3985) 2025-09-22 13:20:37 +00:00
dependabot[bot]
a4d9703cf4 Bump the maven-build-plugins group with 3 updates (#3984) 2025-09-22 13:12:52 +00:00
dependabot[bot]
c9a3a775cc Bump the java-production-dependencies group across 1 directory with 9 updates (#3978) 2025-09-16 15:08:10 +00:00
dependabot[bot]
e7cac42d5d Bump the maven-build-plugins group across 1 directory with 2 updates (#3977) 2025-09-16 14:27:31 +00:00
dependabot[bot]
983e7d973b Bump the github-actions group across 1 directory with 6 updates (#3970) 2025-09-16 14:19:24 +00:00
dependabot[bot]
a84ac94701 Bump the java-test-dependencies group across 1 directory with 3 updates (#3956) 2025-09-16 14:18:18 +00:00
Dhruv Bajpai
4761c58265 specify JVM crash log path (#3951)
Add jvm option `-XX:+ErrorFile=...` with a clear, but with high possibility not-existing path to use fallback path.
2025-09-16 14:19:59 +02:00
pxwanglu
682e762a5a chore: fix some typos in comments (#3960)
Signed-off-by: pxwanglu <pxwanglu@icloud.com>
2025-09-08 18:43:50 +02:00
Armin Schrenk
c3ada43abb Feature: Refactoring for Windows installer build (#3968)
* decouple patchUpdateCheck script from app name
* simplify patchWebdav script and align it with patchUpdate
2025-09-05 13:17:35 +02:00
Tobias Hagemann
9a71782fff Add Windows MSI installer option to disable update checks via DISABLEUPDATECHECK property (#3961)
Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-09-04 14:39:20 +02:00
Jan-Peter Klein
2f4c12a89e remove no more used injections 2025-09-04 08:45:04 +02:00
Jan-Peter Klein
2b79c58577 renaming and reordering 2025-09-04 08:44:18 +02:00
Jan-Peter Klein
1d3c62e2c7 revert cleanup that introduced a bug 2025-09-03 14:58:25 +02:00
Jan-Peter Klein
17166c45ac show correct message 2025-09-03 14:42:20 +02:00
Jan-Peter Klein
f758388063 fix closeOrReturn button 2025-09-03 14:28:16 +02:00
Jan-Peter Klein
8767564977 revert cleanup that introduced a bug 2025-09-03 13:39:08 +02:00
Jan-Peter Klein
59f47116f0 change wording 2025-09-03 12:42:24 +02:00
Jan-Peter Klein
8fac541024 use defaults.vault.vaultName as fallback displayName 2025-09-02 07:40:02 +02:00
Jan-Peter Klein
1ba21b531a declare NoSuchElementException in method head 2025-09-02 07:27:02 +02:00
Jan-Peter Klein
daad48d5af clarify NoSuchElementException log message 2025-09-01 09:33:03 +02:00
Jan-Peter Klein
8eedc62fbe Check vault path before preparing new vault in recovery flow and refactor chooseValidVaultDirectory() to return Path instead of File 2025-09-01 09:14:21 +02:00
Jan-Peter Klein
d65442f042 add explicit VAULT_CONFIG_MISSING case and move legacy comment from LOCKED to NEEDS_MIGRATION 2025-09-01 08:21:28 +02:00
Jan-Peter Klein
216513405a removed unused strings 2025-08-27 10:35:11 +02:00
Jan-Peter Klein
f4c0bc29ed handle NoSuchElementException during recovery key validation 2025-08-27 09:43:28 +02:00
Jan-Peter Klein
d1ce0362b4 extract vault directory selection into new method chooseValidVaultDirectory using Optional 2025-08-27 09:34:04 +02:00
Jan-Peter Klein
4497fb160e new class VaultPreparator in recovery package 2025-08-27 09:22:26 +02:00
Jan-Peter Klein
5bffa28cdb remove unused method 2025-08-27 08:52:51 +02:00
Jan-Peter Klein
14c5693594 check dir structure first in determineVaultState 2025-08-27 08:37:04 +02:00
Jan-Peter Klein
53c6045cca extend initializeLastKnownKeyLoaderIfPossible and deduplicate in create 2025-08-27 07:26:37 +02:00
Jan-Peter Klein
16d441ec44 cleanup 2025-08-21 12:26:16 +02:00
Jan-Peter Klein
fa053ac3df undo no longer needed changes 2025-08-20 10:00:08 +02:00
Jan-Peter Klein
e78a064af6 dialogs with icons and some other ui improvements 2025-08-13 11:40:10 +02:00
Jan-Peter Klein
644e38f49e Merge branch 'develop' into feature/restore-vaultconfig 2025-08-06 13:53:04 +02:00
Jan-Peter Klein
3b38049d71 remove Objects.requireNonNull 2025-08-06 08:18:32 +02:00
Jan-Peter Klein
c199d1cb3b remove optional 2025-08-01 12:51:27 +02:00
Jan-Peter Klein
164a4de6de fix filter 2025-08-01 09:52:03 +02:00
Armin Schrenk
f64455d8fb dedup code
references  #3943
2025-07-29 13:02:01 +02:00
Armin Schrenk
8b1d2101db Feature: Switch to different windows signer (#3943)
Replace usage of signtool with Actalis code signer.
2025-07-28 15:13:15 +02:00
Armin Schrenk
22a37699ea Fixes commit 44f92cfb26. 2025-07-22 13:04:33 +02:00
Armin Schrenk
44f92cfb26 replace null parameter 2025-07-17 12:37:57 +02:00
Armin Schrenk
27c10080d6 fixes #3925
Stop listening for ipc messages when to many failed requests in a row
2025-07-14 12:20:49 +02:00
Jan-Peter Klein
2067c5a33b optimize exception handling
exclude only dir.c9r
2025-07-10 18:45:58 +02:00
Jan-Peter Klein
fc5ed9ecc0 remove unused property 2025-07-10 17:26:45 +02:00
Jan-Peter Klein
5e956c50c2 handle unexpected recovery action type 2025-07-10 11:54:00 +02:00
Jan-Peter Klein
5110b35690 hard coded UI strings replaced
showThirdText property binding
2025-07-10 10:15:11 +02:00
Jan-Peter Klein
499960b3ec replace while with do-while and use Constants.DATA_DIR_NAME 2025-07-10 09:42:00 +02:00
Jan-Peter Klein
f6479ddf24 optimize dialogs 2025-07-10 08:30:46 +02:00
Jan-Peter Klein
5d8b016e5f refactoring 2025-07-10 08:29:51 +02:00
Jan-Peter Klein
2bf2f2b616 exclude dirid.c9r 2025-07-09 19:27:51 +02:00
Jan-Peter Klein
1089e90ebf remove unused imports 2025-07-09 18:39:28 +02:00
Jan-Peter Klein
9fee4afd2a remove duplicate unicode value 2025-07-09 18:37:38 +02:00
Armin Schrenk
7ad9b10138 Feature: Windows debug launcher (#2666)
Add additonal launcher to windows release to debug javafx problems.
2025-07-08 17:43:08 +02:00
Armin Schrenk
fb6e4f0c15 [skip ci] Merge branch 'main' into develop 2025-07-08 14:08:37 +02:00
Armin Schrenk
6c5f3cb72c Merge branch 'release/1.17.1' 2025-07-08 14:06:54 +02:00
Armin Schrenk
581b16e354 finalize 1.17.1 2025-07-08 13:42:43 +02:00
Armin Schrenk
d74248ff63 prepare 1.17.1 2025-07-08 13:41:04 +02:00
Cryptobot
698ac639e9 New Crowdin updates (#3913)
New translations strings.properties

Arabic; Portuguese;

[ci skip]
2025-07-08 13:40:09 +02:00
Armin Schrenk
5a086f52b5 Revert "exclude early access javafx versions in dependency updates"
This reverts commit 54b7f3c842.
2025-07-08 13:35:43 +02:00
Armin Schrenk
54b7f3c842 exclude early access javafx versions in dependency updates 2025-07-07 16:13:17 +02:00
mindmonk
94b9813c50 Merge pull request #3918 from cryptomator/feature/fix-password-tab-on-migrated-legacy-vaults
Fix: Show Change Password tab after vault migration by improving KeyLoader scheme handling
2025-07-07 15:15:06 +02:00
Jan-Peter Klein
b00ee4740a legacy vaults supported now 2025-07-07 14:58:19 +02:00
Jan-Peter Klein
78cffe2f60 fix password tab on migrated legacy vaults 2025-07-07 11:32:19 +02:00
Jan-Peter Klein
9d15a7664d fix docs links 2025-07-07 11:14:19 +02:00
Jan-Peter Klein
f5ecf846f2 resolve SonarCloud issue by safely accessing Optional value 2025-07-05 14:15:59 +02:00
Jan-Peter Klein
a9444182bb clean up 2025-07-04 22:17:27 +02:00
Jan-Peter Klein
191d9473c0 small enhancements 2025-07-04 19:17:24 +02:00
Jan-Peter Klein
8089bcd0d0 cleanup 2025-07-04 17:16:32 +02:00
Mateo
5d8457cbdd Feature: Default to previously used vault directory when creating a vault (#3903) 2025-07-04 11:08:22 +02:00
Jan-Peter Klein
f623b1ee7e better naming, void instead of unused boolean and LOGs 2025-07-03 15:48:21 +02:00
Armin Schrenk
c546f3363b reduce object creation and conversion 2025-07-03 12:08:41 +02:00
Jan-Peter Klein
8a1ec1d073 read file header instead of allBytes to determine Scheme 2025-07-02 11:29:01 +02:00
Jan-Peter Klein
81307b6d75 remove PosixFilePermissions 2025-07-02 11:26:05 +02:00
Jan-Peter Klein
50fa8e0608 tmpDir renamed to cryptomator 2025-07-01 10:44:11 +02:00
Jan-Peter Klein
626a692d63 optimized LOGs 2025-07-01 10:43:10 +02:00
Jan-Peter Klein
c9b9eee564 remove unused methods 2025-07-01 10:42:36 +02:00
Jan-Peter Klein
edc308ccd1 recover button now in VaultListController 2025-06-30 17:36:30 +02:00
Jan-Peter Klein
ad214691f9 fix sonar cloud quality gate fail 2025-06-30 14:04:13 +02:00
Jan-Peter Klein
acf11da202 cleanup
removed MASTERKEY_MISSING
new recoveryActionType RESTORE_ALL
2025-06-30 09:26:30 +02:00
Armin Schrenk
94eb1e365b replace token for PR creation 2025-06-26 15:40:06 +02:00
Armin Schrenk
414ccad8fb Feature: Automate AUR release (#3910)
Extend/add workflows to automatically create PRs for aur and aur-bin repos for a release.
2025-06-26 15:35:59 +02:00
Armin Schrenk
e57e5358c4 Add workflow to automatically create AUR PR on release 2025-06-25 16:15:46 +02:00
Armin Schrenk
e24719ed19 [skip ci] Merge branch 'main' into develop 2025-06-24 16:28:03 +02:00
Armin Schrenk
e21525ce2e Merge branch 'release/1.17.0' 2025-06-24 16:26:28 +02:00
Armin Schrenk
9a14cfc674 finalize 1.17.0 2025-06-24 16:11:44 +02:00
Armin Schrenk
9af9362a7b Merge branch 'develop' into release/1.17.0 2025-06-24 16:07:29 +02:00
Armin Schrenk
4d4a93746d disable confusing message of kwallet library 2025-06-23 16:34:31 +02:00
Jan-Peter Klein
4280112eab remove Optional and improve prepareVault() 2025-06-23 13:19:35 +02:00
Jan-Peter Klein
638e1e562d Merge branch 'develop' into feature/restore-vaultconfig 2025-06-23 10:17:43 +02:00
Jan-Peter Klein
321bd2ff8c deduplicate generic.button.close by define a constant 2025-06-23 10:00:38 +02:00
Jan-Peter Klein
323a884718 fix sonar cloud security hotspot 2025-06-23 09:47:07 +02:00
Jan-Peter Klein
5bdfffd151 directoryChooser cancelable 2025-06-23 09:20:25 +02:00
Cryptobot
cb6b77318d New translations strings.properties (Finnish) (#3897)
[ci skip]
2025-06-17 15:09:57 +02:00
Jan-Peter Klein
6fcec26eea removed additional redetermineVaultState 2025-06-17 14:39:10 +02:00
dependabot[bot]
feb9fb689e Bump the java-production-dependencies group with 2 updates (#3901) 2025-06-17 11:58:45 +00:00
Armin Schrenk
0178ca4080 fix wrong keychain migration 2025-06-16 18:06:04 +02:00
Jan-Peter Klein
4ddb6b73bd optimised structure and new function initializeLastKnownKeyLoaderIfPossible 2025-06-16 15:22:27 +02:00
Jan-Peter Klein
da845c6941 combined into a single if 2025-06-16 14:38:37 +02:00
Jan-Peter Klein
c30a28aae0 Files.createTempDirectory instead of Files.createDirectory 2025-06-16 14:37:17 +02:00
Jan-Peter Klein
5305c5a631 optimised imports 2025-06-16 14:28:18 +02:00
Jan-Peter Klein
b0d2dcbff3 use constants 2025-06-16 14:18:54 +02:00
Jan-Peter Klein
5c1364792e unwrap ObjectProperty<RecoveryAction> 2025-06-16 14:03:59 +02:00
Jan-Peter Klein
abf8392baa use !Files.exists instead of Files.notExists 2025-06-16 13:49:59 +02:00
Jan-Peter Klein
034a70d473 throw illegalArgumentException directly 2025-06-16 13:40:57 +02:00
Armin Schrenk
79f2863f24 suppress warning message caused by javafx (see JDK-8345121) 2025-06-16 11:23:25 +02:00
Tobias Hagemann
f1ef506e2b Fix missing characters after Unicode in RTF files (#3898) 2025-06-16 10:36:19 +02:00
Jan-Peter Klein
8c9d75fe57 filter excluded filenames 2025-06-12 14:46:15 +02:00
Jan-Peter Klein
d00d77b747 optimised imports and some pr mentioned changes 2025-06-11 13:49:12 +02:00
Armin Schrenk
fbeeaa4c93 prepare 1.17.0 2025-06-11 12:38:38 +02:00
dependabot[bot]
00f5d433da Bump wlixcc/SFTP-Deploy-Action in the github-actions group (#3840) 2025-06-11 10:32:58 +00:00
dependabot[bot]
115a4216ee Bump org.owasp:dependency-check-maven in the maven-build-plugins group (#3896) 2025-06-11 10:31:11 +00:00
dependabot[bot]
403d469dff Bump the java-production-dependencies group across 1 directory with 5 updates (#3891) 2025-06-11 10:30:44 +00:00
Cryptobot
ddf112bdfa New Crowdin updates (#3858)
New translations strings.properties

Arabic; Finnish; German; Korean; Macedonian; Vietnamese;

[ci skip]
2025-06-11 12:28:56 +02:00
Armin Schrenk
2ade07da75 remove ci label from dependabot config 2025-06-11 12:27:24 +02:00
dependabot[bot]
e6a0339878 Bump org.owasp:dependency-check-maven in the maven-build-plugins group (#3890) 2025-06-11 10:25:43 +00:00
dependabot[bot]
2b0c2cf90a Bump the java-test-dependencies group across 1 directory with 2 updates (#3875) 2025-06-11 10:25:08 +00:00
Ralph Plawetzki
2afd8d0988 Build installers for Windows ARM64 (#3825)
---------

Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-06-11 12:17:04 +02:00
Armin Schrenk
f2bda6b5f9 Feature: Update WinFSP to version 2.1 (#3893)
Closes #3887, fixes #3771
2025-06-10 18:43:51 +02:00
Ralph Plawetzki
0bb1bf81ec build.sh improvements (#3889) 2025-06-10 16:18:02 +02:00
Sebastian Stenzel
bf8d5ed09f codesign .dmg (#3886)
fixes #3885
2025-06-10 13:39:34 +02:00
Tobias Hagemann
e9f6854df8 added unlock flow when opening vault via app launch event (#3888) 2025-06-10 13:31:41 +02:00
Jan-Peter Klein
6d47f28634 changed shorteningThreshold to int
optimize imports
2025-06-05 13:15:54 +02:00
Jan-Peter Klein
225332bd4f pr mentioned changes 2025-06-05 13:01:47 +02:00
Ralph Plawetzki
354225bf1e Switch on Windows Hello (#3808)
---------

Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-06-04 11:25:45 +02:00
Jan-Peter Klein
8c84720e24 solve some todos 2025-06-04 10:47:56 +02:00
Armin Schrenk
0d4f373311 enable native access for javafx.graphics during tests
references #3882
2025-06-03 16:52:31 +02:00
Armin Schrenk
1da535e89c don't trigger distribution builds for dependabot 2025-06-03 16:25:13 +02:00
Armin Schrenk
941b4e3652 Feature: JavaFX 24 (#3882) 2025-06-03 15:51:37 +02:00
Armin Schrenk
dd1af8cd78 add migration for renamed SecretServiceKeychainAccess
references #3877
2025-06-03 15:49:40 +02:00
Armin Schrenk
27ea29ab9d fix IllegalArguemntException
do not try to convert a path which is already an OS path
2025-06-03 13:57:08 +02:00
Armin Schrenk
a699a794a9 CI: Trigger the appropiate build workflows based on changed files (#3880) 2025-06-02 16:57:30 +02:00
Armin Schrenk
cd6b1cf129 Update README.md
bump JDK build dependency to 24
2025-06-02 12:08:24 +02:00
Armin Schrenk
7d2c4992af update pom and adjust classes to new keychain api. (#3877) 2025-06-02 10:28:52 +02:00
Jan-Peter Klein
968e8f51e4 new onboarding dialog
remove is hub vault dialog
2025-05-30 15:30:38 +02:00
Armin Schrenk
6a21d24687 Merge pull request #3863 from cryptomator/feature/jdk-24
Feature: JDK 24
2025-05-22 15:41:53 +02:00
Armin Schrenk
cba6ed9875 Merge branch 'develop' into feature/jdk-24 2025-05-21 16:08:38 +02:00
Armin Schrenk
72fdc8f536 [skip ci] allow manual trigger for building macOS x64 dmg 2025-05-21 14:41:48 +02:00
Armin Schrenk
41336cca13 bump to JDK 24 in all java workflows 2025-05-21 13:08:55 +02:00
Armin Schrenk
322907bbcd bump minimal ubuntu version Cryptomator is build on 2025-05-21 13:05:59 +02:00
Armin Schrenk
1f8df6fead fix comparsion to undefined variable 2025-05-21 13:01:54 +02:00
Armin Schrenk
6e085b783d use correct bash syntax to check exit code 2025-05-21 13:01:33 +02:00
Armin Schrenk
59dddd3f4c [skip ci] increase the required build version for coffeelibs to ppa3 build 2025-05-21 12:04:50 +02:00
Armin Schrenk
d6bbcfbbc1 Revert "[skip ci] coffeelibs jdk is built with JEP 493"
This reverts commit 0a0dde3f47.
2025-05-21 11:50:55 +02:00
Jan-Peter Klein
4de6b83e2f remove RecoverUtil 2025-05-19 14:37:39 +02:00
Jan-Peter Klein
90cbb0c5f6 new recovery package in common 2025-05-19 14:27:05 +02:00
Armin Schrenk
7260d7f9f8 fixes #3847 2025-05-19 12:20:04 +02:00
Armin Schrenk
c39c4be1cd Merge branch 'main' into develop
# Conflicts:
#	pom.xml
2025-05-15 08:59:15 +02:00
Armin Schrenk
6f9b3e31e7 [skip ci] prevent gpg from pruning the key cache 2025-05-15 00:27:30 +02:00
Armin Schrenk
0a0dde3f47 [skip ci] coffeelibs jdk is built with JEP 493 2025-05-13 15:22:39 +02:00
Armin Schrenk
e27e303c01 [skip ci] use JDK 24 also for deb build 2025-05-13 14:12:07 +02:00
Armin Schrenk
ef54b685f6 [skip ci] fix wrong logic to determine linkable runtime image in local build scripts 2025-05-08 16:51:04 +02:00
Jan-Peter Klein
0370fd5848 fix minWidth and minHeight 2025-05-08 11:14:10 +02:00
Armin Schrenk
119d18d699 [skip ci] cleanup 2025-05-08 11:08:02 +02:00
Armin Schrenk
8322633b14 apply workaround for wix burn bug 2025-05-08 11:04:59 +02:00
Armin Schrenk
2f32fc5c16 [skip ci] use different working directory for building the exe 2025-05-07 17:23:52 +02:00
Armin Schrenk
7c44c4f194 fix wrong logic in build scripts 2025-05-07 16:59:36 +02:00
Armin Schrenk
bbb663f9d2 update windows ci workflow to wix 6 2025-05-07 12:47:48 +02:00
Armin Schrenk
fdb4a2fb5c remove wix version pinning 2025-05-07 12:17:43 +02:00
Armin Schrenk
0a4684133d update ci to JDK 24 2025-05-07 12:17:27 +02:00
Armin Schrenk
0d5e518af3 adjust jlink to JEP 493 2025-05-07 12:16:52 +02:00
Armin Schrenk
d47ab43fcf add launch feature to exe installer 2025-05-06 17:01:13 +02:00
Armin Schrenk
19a711d12b migrate wix burn bundle to wix 6 2025-05-06 17:00:17 +02:00
Armin Schrenk
bf2db55d00 switch to ubuntu 22.04 (jammy) when deploying to launchpad 2025-05-02 13:49:41 +02:00
Armin Schrenk
885975e099 [skip ci] Merge branch 'main' into develop 2025-04-30 14:05:40 +02:00
Armin Schrenk
79b3274074 migrate to wix6
* drop custom dialogs in installer
2025-04-24 15:56:02 +02:00
Armin Schrenk
7c86e5e39a update pom to use JDK 24 2025-04-24 15:53:17 +02:00
Jan-Peter Klein
e1cc61037e cleanup 2025-03-23 11:15:36 +01:00
Jan-Peter Klein
1ae951126a refactored key validation 2025-03-21 11:03:24 +01:00
Jan-Peter Klein
6bb8c0d4e7 removed unused fxml and controller
dialog fix
2025-03-19 10:09:55 +01:00
Jan-Peter Klein
087b6162ed recoverType fix and more use of dialogs 2025-03-18 14:25:44 +01:00
Jan-Peter Klein
f9e8031acb Merge branch 'develop' into feature/restore-vaultconfig 2025-03-18 11:53:06 +01:00
Jan-Peter Klein
ebd767595b get cipherCombo while key validation 2025-03-17 18:39:17 +01:00
Jan-Peter Klein
6231c5b8b3 restore checkbox and other small ui rearrangements 2025-03-17 16:10:16 +01:00
Jan-Peter Klein
a3b8297e23 recoverykey validate 2025-03-14 13:51:25 +01:00
Jan-Peter Klein
6715ff9f5f introduce RecoverUtil.Types 2025-03-06 09:17:16 +01:00
Jan-Peter Klein
8c5325511c created more static methods in RecoverUtil, added first flow for choose dir and restore 2025-02-28 13:06:35 +01:00
Jan-Peter Klein
895614353e improve RecoverUtil and determineVaultState 2025-02-21 23:24:34 +01:00
Jan-Peter Klein
676c507a50 add RecoverUtil and some ui changes 2025-02-21 19:43:09 +01:00
Jan-Peter Klein
5f4fd92b1d Merge branch 'develop' into feature/restore-vaultconfig 2025-02-19 19:49:35 +01:00
Jan-Peter Klein
8191a7dae6 add isHubVault dialog 2025-01-15 21:05:27 +01:00
Jan-Peter Klein
756672258d add Hub Vault check for MASTERKEY_MISSING state 2025-01-14 15:29:49 +01:00
Jan-Peter Klein
fb6f7072d4 new vault states implemented in selectVaultRemovable 2025-01-14 15:12:21 +01:00
Jan-Peter Klein
aa95ad40c0 added vault config success scene 2025-01-13 15:31:55 +01:00
Jan-Peter Klein
ba3667ab51 restore config by recoverykey
auto restore when bkup exists
added new VaultStates
2024-12-11 16:30:56 +01:00
185 changed files with 5956 additions and 1515 deletions

View File

@@ -0,0 +1,76 @@
name: 'Windows Code Signing'
description: 'Sign files on Windows with the Azure Trusted Signing'
inputs:
base-dir:
description: 'Absolute path to the base directory to search for files'
required: true
recursive:
description: 'Whether to search recursively in subdirectories'
required: false
default: 'false'
file-extensions:
description: 'List of file extensions to sign, separated by comma'
required: true
default: 'exe,dll,ps1'
description:
description: 'Signature description'
required: true
default: 'Cryptomator'
url:
description: 'Signature URL'
required: false
default: 'https://cryptomator.org'
append-signature:
description: 'Whether to append the signature to existing signatures'
required: false
default: 'false'
tenant-id:
description: 'Azure Tenant ID'
required: true
client-id:
description: 'Azure Client ID'
required: true
client-secret:
description: 'Azure Client Secret'
required: true
runs:
using: 'composite'
steps:
- name: Generate, mask, and output the input secrets
id: set-secrets
run: |
echo "::add-mask::${{ inputs.tenant-id }}"
echo "::add-mask::${{ inputs.client-id }}"
echo "::add-mask::${{ inputs.client-secret }}"
echo "tenant-id=${{ inputs.tenant-id }}" >> "$GITHUB_OUTPUT"
echo "client-id=${{ inputs.client-id }}" >> "$GITHUB_OUTPUT"
echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT"
shell: bash
- name: Sign DLLs with Azure Trusted Signing
uses: azure/trusted-signing-action@fc390cf8ed0f14e248a542af1d838388a47c7a7c # v0.5.10
with:
files-folder: ${{ inputs.base-dir }}
files-folder-filter: ${{ inputs.file-extensions }}
files-folder-recurse: ${{ inputs.recursive }}
append-signature: ${{ inputs.append-signature }}
description: ${{ inputs.description }}
description-url: ${{ inputs.url }}
azure-tenant-id: ${{ steps.set-secrets.outputs.tenant-id }}
azure-client-id: ${{ steps.set-secrets.outputs.client-id }}
azure-client-secret: ${{ steps.set-secrets.outputs.client-secret }}
trusted-signing-account-name: cryptomatorSigning
certificate-profile-name: production
endpoint: https://weu.codesigning.azure.net/
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
exclude-environment-credential: false
exclude-workload-identity-credential: true
exclude-managed-identity-credential: true
exclude-shared-token-cache-credential: true
exclude-visual-studio-credential: true
exclude-visual-studio-code-credential: true
exclude-azure-cli-credential: true
exclude-azure-powershell-credential: true
exclude-azure-developer-cli-credential: true
exclude-interactive-browser-credential: true

View File

@@ -53,6 +53,4 @@ updates:
groups:
github-actions:
patterns:
- "*"
labels:
- "misc:ci"
- "*"

View File

@@ -8,16 +8,24 @@ on:
version:
description: 'Version'
required: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/appimage.yml'
- 'dist/linux/appimage/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.2'
JAVA_VERSION: '24.0.1+9'
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }}
version: ${{ inputs.version }} #okay if not defined
build:
name: Build AppImage
@@ -29,22 +37,21 @@ jobs:
include:
- os: ubuntu-latest
appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.2/openjfx-23.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: '063baebc6922e4a89c94b9dfb7a4f53e59e8d6fec400d4e670b31bc2ab324dec'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip'
openjfx-sha: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
- os: ubuntu-24.04-arm
appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.2/openjfx-23.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: '9bbedaeae1590b69e2b22237bda310936df33e344dbc243bea2e86acaab3a0d8'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip'
openjfx-sha: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: true
cache: 'maven'
- name: Download OpenJFX jmods
id: download-jmods
run: |
@@ -61,26 +68,34 @@ jobs:
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION_AMD64 ]; then
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
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B clean package -Plinux -DskipTests -Djavafx.platform=linux
run: mvn -B clean package -Plinux -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- 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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler
--module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.crypto.cryptoki,jdk.crypto.ec,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
@@ -101,7 +116,7 @@ jobs:
--copyright "(C) 2016 - 2025 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"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
@@ -117,6 +132,7 @@ jobs:
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
--java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
--resource-dir dist/linux/resources
- name: Patch Cryptomator.AppDir
run: |
@@ -152,14 +168,14 @@ jobs:
- name: Build AppImage
run: >
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.appimage-suffix }}.AppImage
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.appimage-suffix }}.AppImage.zsync'
-u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.appimage-suffix }}.AppImage.zsync"
--sign --sign-key=615D449FE6E6A235
- name: Create detached GPG signatures
run: |
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@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: appimage-${{ matrix.appimage-suffix }}
path: |
@@ -169,7 +185,7 @@ jobs:
if-no-files-found: error
- name: Publish AppImage on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
@@ -177,3 +193,68 @@ jobs:
cryptomator-*.AppImage
cryptomator-*.zsync
cryptomator-*.asc
create-aur-bin-pr:
name: Create PR for aur-bin repo
needs: [build, get-version]
runs-on: ubuntu-latest
if: github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
steps:
- name: Download AppImages
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: downloads/
merge-multiple: true
- name: Compute sha256 hash of AppImages
id: checksums
run: |
X64_SHA256=$(sha256sum downloads/cryptomator-*-x86_64.AppImage | cut -d ' ' -f1)
echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT"
AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1)
echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: 'cryptomator/aur-bin'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install makepkg pacman-package-manager
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
- name: Update build file
run: |
sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
sed -i -e "s|^sha256sums_x86_64=.*$|sha256sums_x86_64=('${{ steps.checksums.outputs.x64-sha256sum }}'|" PKGBUILD
sed -i -e "s|^sha256sums_aarch64=.*$|sha256sums_aarch64=('${{ steps.checksums.outputs.aarch64-sha256sum}}'|" PKGBUILD
makepkg --printsrcinfo > .SRCINFO
- 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
id: create-pr
run: |
printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update build instructions\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
echo "PR_URL=$URL" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.PR_URL }}|PR> on how to proceed."
SLACK_FOOTER: false
MSG_MINIMAL: true

95
.github/workflows/aur.yml vendored Normal file
View File

@@ -0,0 +1,95 @@
name: Create PR for AUR
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'
env:
INPUT_TAG: ${{ inputs.tag }}
outputs:
url: ${{ steps.url.outputs.url}}
sha256: ${{ steps.sha256.outputs.sha256}}
steps:
- name: Determine tarball url
id: url
run: |
URL="";
if [[ -n "${INPUT_TAG}" ]]; then
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${INPUT_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: sha256
run: |
curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
TARBALL_SHA256=$(sha256sum cryptomator.tar.gz | cut -d ' ' -f1)
echo "sha256=${TARBALL_SHA256}" >> "$GITHUB_OUTPUT"
aur:
name: Create PR for AUR
runs-on: ubuntu-latest
needs: [tarball, get-version]
env:
AUR_PR_URL: tbd
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: 'cryptomator/aur'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install makepkg pacman-package-manager
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
- name: Update build file
run: |
sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
sed -i -e "s|^sha256sums=.*$|sha256sums=('${{ needs.tarball.outputs.sha256 }}'|" PKGBUILD
makepkg --printsrcinfo > .SRCINFO
- 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 build instructions\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 "AUR_PR_URL=$PR_URL" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
if: github.event_name == 'release'
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "AUR release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
SLACK_MESSAGE: "See <${{ env.AUR_PR_URL }}|PR> on how to proceed."
SLACK_FOOTER: false
MSG_MINIMAL: true

View File

@@ -30,16 +30,18 @@ jobs:
runs-on: ubuntu-latest
outputs:
fileName: ${{ steps.extractName.outputs.fileName}}
env:
INPUT_URL: ${{ inputs.url }}
steps:
- name: Extract file name
id: extractName
run: |
url="${{ inputs.url }}"
url="${INPUT_URL}"
echo "fileName=${url##*/}" >> $GITHUB_OUTPUT
- name: Download file
run: curl --remote-name ${{ inputs.url }} -L -o ${{steps.extractName.outputs.fileName}}
run: curl --remote-name ${INPUT_URL} -L -o ${{steps.extractName.outputs.fileName}}
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ steps.extractName.outputs.fileName }}
path: ${{ steps.extractName.outputs.fileName }}
@@ -51,12 +53,12 @@ jobs:
if: github.event_name == 'workflow_call' || inputs.kaspersky
steps:
- name: Download artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
uses: SamKirkland/FTP-Deploy-Action@a51268f67f6605236975928ae28b0f7e9971d50a # v4.6.3
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
@@ -71,12 +73,12 @@ jobs:
if: github.event_name == 'workflow_call' || inputs.avast
steps:
- name: Download artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Avast
uses: wlixcc/SFTP-Deploy-Action@v1.2.5
- name: Upload to Avast
uses: wlixcc/SFTP-Deploy-Action@a5ccb9c6211a94cc59404f0fdb2a9936a6dfee64 # v1.2.6
with:
server: whitelisting.avast.com
port: 22

View File

@@ -2,12 +2,16 @@ name: Build
on:
push:
paths:
- '.github/workflows/build.yml'
- 'pom.xml'
- 'src/**'
pull_request_target:
types: [labeled]
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 23
JAVA_VERSION: 24
defaults:
run:
@@ -18,14 +22,14 @@ jobs:
name: Compile and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Cache SonarCloud packages
uses: actions/cache@v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
@@ -33,7 +37,7 @@ jobs:
- name: Build and Test
run: >
xvfb-run
mvn -B verify -Djavafx.platform=linux
mvn -B verify
jacoco:report
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
-Pcoverage
@@ -45,7 +49,7 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Draft a release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
with:
draft: true
discussion_category_name: releases

View File

@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
JDK_VERSION: '23.0.1+11'
JDK_VERSION: '24.0.1+9'
JDK_VENDOR: temurin
RUNTIME_VERSION_HELPER: >
public class Test {
@@ -26,7 +26,7 @@ jobs:
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,20) >> "$env:GITHUB_ENV"
shell: pwsh
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
java-version: ${{ env.JDK_MAJOR_VERSION}}
distribution: ${{ env.JDK_VENDOR }}
@@ -70,7 +70,7 @@ jobs:
}
- name: Notify
if: steps.determine.outputs.UPDATE_AVAILABLE == 'true'
uses: rtCamp/action-slack-notify@v2
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'

View File

@@ -5,55 +5,68 @@ on:
inputs:
semver:
description: 'SemVer String (e.g. 1.7.0-beta1)'
required: true
ppaver:
description: 'Base PPA Version String (e.g. 1.6.16+1.7.0~beta1) without -0ppa1'
required: true
dput:
description: 'Upload to PPA'
required: true
default: false
type: boolean
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/debian.yml'
- 'dist/linux/debian/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.2+7'
COFFEELIBS_JDK: 23
COFFEELIBS_JDK_VERSION: '23.0.2+7-0ppa1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/23.0.2/openjfx-23.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '063baebc6922e4a89c94b9dfb7a4f53e59e8d6fec400d4e670b31bc2ab324dec'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/23.0.2/openjfx-23.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '9bbedaeae1590b69e2b22237bda310936df33e344dbc243bea2e86acaab3a0d8'
JAVA_VERSION: '24.0.1+9'
COFFEELIBS_JDK: 24
COFFEELIBS_JDK_VERSION: '24.0.1+9-0ppa3'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4'
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.semver }} #okay if not defined
build:
name: Build Debian Package
runs-on: ubuntu-22.04
needs: [get-version]
env:
INPUT_PPAVER: ${{ inputs.ppaver }}
steps:
- uses: actions/checkout@v4
- id: versions
name: Get version information
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- id: deb-version
name: Determine deb-version
run: |
SEM_VER_STR="${{ inputs.semver }}"
SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
REVCOUNT=`git rev-list --count HEAD`
echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT
echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
if [ -n "${INPUT_PPAVER}" ]; then
echo "debVersion=${INPUT_PPAVER}" >> "$GITHUB_OUTPUT"
else
echo "debVersion=${{needs.get-version.outputs.semVerStr}}" >> "$GITHUB_OUTPUT"
fi
- name: Install build tools
run: |
sudo add-apt-repository ppa:coffeelibs/openjdk
sudo apt-get update
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.COFFEELIBS_JDK }}=${{ env.COFFEELIBS_JDK_VERSION }}
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: true
cache: 'maven'
- name: Run maven
run: mvn -B clean package -Plinux -Djavafx.platform=linux -DskipTests
run: mvn -B clean package -Plinux -DskipTests
- name: Download OpenJFX jmods
id: download-jmods
run: |
@@ -94,7 +107,7 @@ jobs:
cp -r jmods pkgdir
cp -r dist/linux/common/ pkgdir
cp target/cryptomator-*.jar pkgdir/mods
tar -cJf cryptomator_${{ inputs.ppaver }}.orig.tar.xz -C pkgdir .
tar -cJf cryptomator_${{ steps.deb-version.outputs.debVersion }}.orig.tar.xz -C pkgdir .
- name: Patch and rename pkgdir
run: |
cp -r dist/linux/debian/ pkgdir
@@ -103,12 +116,12 @@ jobs:
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 }}
mv pkgdir cryptomator_${{ steps.deb-version.outputs.debVersion }}
env:
SEMVER_STR: ${{ steps.versions.outputs.semVerStr }}
VERSION_NUM: ${{ steps.versions.outputs.semVerNum }}
REVISION_NUM: ${{ steps.versions.outputs.revNum }}
PPA_VERSION: ${{ inputs.ppaver }}-0ppa1
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
VERSION_NUM: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NUM: ${{ needs.get-version.outputs.revNum }}
PPA_VERSION: ${{ steps.deb-version.outputs.debVersion }}-0ppa1
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -118,17 +131,18 @@ jobs:
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: debuild
run: |
(sleep 8m; gpg --batch --quiet --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign README.md) &
debuild -S -sa -d
debuild -b -sa -d
env:
DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback
DEBSIGN_KEYID: 615D449FE6E6A235
working-directory: cryptomator_${{ inputs.ppaver }}
working-directory: cryptomator_${{ steps.deb-version.outputs.debVersion }}
- name: Create detached GPG signatures
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@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: linux-deb-package
path: |
@@ -140,7 +154,7 @@ jobs:
cryptomator_*_amd64.deb
cryptomator_*.asc
- name: Publish on PPA
if: inputs.dput
if: inputs.dput && inputs.ppaver != ''
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

View File

@@ -7,12 +7,13 @@ on:
jobs:
check-dependencies:
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@v1
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@1074588008ae3326a2221ea451783280518f0366 # v3.0.1
with:
runner-os: 'ubuntu-latest'
java-distribution: 'temurin'
java-version: 23
check-command: 'mvn -B validate -Pdependency-check -Djavafx.platform=linux'
java-version: 24
secrets:
nvd-api-key: ${{ secrets.NVD_API_KEY }}
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
ossindex-token: ${{ secrets.OSSINDEX_API_TOKEN }}
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@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
const query = `query($owner:String!, $name:String!) {
@@ -53,7 +53,7 @@ jobs:
INTERVAL: 900
JSON_DATA: ${{ steps.get-stats.outputs.result }}
- name: Upload Results
uses: fjogeleit/http-request-action@v1
uses: fjogeleit/http-request-action@1297c6fc63a79b147d1676540a3fd9d2e37817c5 # v1.16.5
with:
url: 'https://graphite-us-central1.grafana.net/metrics'
method: 'POST'

View File

@@ -14,7 +14,7 @@ jobs:
- 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@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
const query = `query ($owner: String!, $name: String!, $discussionNumber: Int!) {
@@ -42,7 +42,7 @@ jobs:
return await github.graphql(query, variables)
- name: Get Gist
id: get-gist
uses: andymckay/get-gist-action@master
uses: andymckay/get-gist-action@cf3bc8164af24126f7e5979eb6d3dc0c12309bd1 # not_tagged
with:
gistURL: https://gist.github.com/cryptobot/accba9fb9555e7192271b85606f97230
- name: Merge Error Code Data
@@ -58,7 +58,7 @@ jobs:
env:
DISCUSSION: ${{ steps.query-data.outputs.result }}
- name: Patch Gist
uses: exuanbo/actions-deploy-gist@v1
uses: exuanbo/actions-deploy-gist@47697fceaeea2006a90594ee24eb9cd0a1121ef8 # v1.1.4
with:
token: ${{ secrets.CRYPTOBOT_GIST_TOKEN }}
gist_id: accba9fb9555e7192271b85606f97230

View File

@@ -26,13 +26,10 @@ jobs:
- 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
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz"
echo "url=${URL}" >> "$GITHUB_OUTPUT"
env:
TAG: ${{ inputs.tag || github.event.release.tag_name}}
- name: Download source tarball and compute checksum
id: sha512
run: |
@@ -46,10 +43,10 @@ jobs:
env:
FLATHUB_PR_URL: tbd
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
@@ -72,9 +69,9 @@ jobs:
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 }}
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
if: github.event_name == 'release'
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}

View File

@@ -23,7 +23,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 23
JAVA_VERSION: 24
jobs:
determine-version:
@@ -35,11 +35,11 @@ jobs:
revNum: ${{ steps.versions.outputs.revNum }}
type: ${{ steps.versions.outputs.type}}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -49,8 +49,8 @@ jobs:
run: |
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="${{ inputs.version }}"
elif [[ "${VERSION_STRING}" =~ [0-9]+\.[0-9]+\.[0-9]+.* ]]; then
SEM_VER_STR="${VERSION_STRING}"
else
SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
fi
@@ -70,7 +70,9 @@ jobs:
echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
echo "type=${TYPE}" >> $GITHUB_OUTPUT
env:
VERSION_STRING: ${{ inputs.version }}
- name: Validate Version
uses: skymatic/semver-validation-action@v3
uses: skymatic/semver-validation-action@7a6ae1c9e121540d11c9c7e4e667c83d583aa153 # v3.0.0
with:
version: ${{ steps.versions.outputs.semVerStr }}

View File

@@ -2,20 +2,29 @@ name: Build macOS .dmg for x64
#######################################
# STOP! DO NOT EDIT THIS FILE!
#
#
# It is a copy of mac-dmg.yml with tiny adjustements (mainly lines 42 to 47)
# It was made necessary, since Github does not offer free macos intel runners for macos 15 and above.
# This workflow can only be triggered by a release.
#
#
#######################################
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version'
required: false
notarize:
description: 'Notarize'
required: true
default: false
type: boolean
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.2+7'
JAVA_VERSION: '24.0.1+9'
jobs:
get-version:
@@ -35,12 +44,12 @@ jobs:
architecture: x64
output-suffix: x64
fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.2/openjfx-23.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '5e6c65c065eea22430c0eab36f37a5985eb8ad99e19e8772262021740d338f68'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_osx-x64_bin-jmods.zip'
openjfx-sha: '0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -70,19 +79,27 @@ jobs:
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B -Djavafx.platform=mac clean package -Pmac -DskipTests
run: mvn -B clean package -Pmac -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- 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.accessibility,jdk.management.jfr,java.compiler
--module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.crypto.cryptoki,jdk.crypto.ec,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
@@ -103,7 +120,7 @@ jobs:
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\""
@@ -133,9 +150,23 @@ jobs:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Build and install DockTilePlugin
env:
DERIVED_DATA_PATH: dist/mac/DockTilePlugin/build
run: |
xcodebuild -project dist/mac/DockTilePlugin/DockTilePlugin.xcodeproj \
-scheme DockTilePlugin \
-configuration Release \
-destination "platform=macOS,arch=x86_64" \
-derivedDataPath ${DERIVED_DATA_PATH} \
-quiet \
clean build
mkdir -p Cryptomator.app/Contents/PlugIns
cp -R ${DERIVED_DATA_PATH}/Build/Products/Release/Cryptomator.docktileplugin Cryptomator.app/Contents/PlugIns/
rm -rf ${DERIVED_DATA_PATH}
- name: Generate license for dmg
run: >
mvn -B -Djavafx.platform=mac license:add-third-party
mvn -B license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
@@ -223,9 +254,14 @@ jobs:
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
- name: Codesign .dmg
run: |
codesign -s ${CODESIGN_IDENTITY} --timestamp Cryptomator-*.dmg
env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
- name: Notarize .dmg
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
uses: cocoalibs/xcode-notarization-action@v1
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
with:
app-path: 'Cryptomator-*.dmg'
apple-id: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
@@ -246,7 +282,7 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dmg-${{ matrix.output-suffix }}
path: |
@@ -255,7 +291,7 @@ jobs:
if-no-files-found: error
- name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}

View File

@@ -13,10 +13,16 @@ on:
required: true
default: false
type: boolean
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/mac-dmg.yml'
- 'dist/mac/**'
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.2+7'
JAVA_VERSION: '24.0.1+9'
jobs:
get-version:
@@ -36,12 +42,12 @@ jobs:
architecture: aarch64
output-suffix: arm64
fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.2/openjfx-23.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: 'c690cc642a3924cf56622951f478ba57aec9ce09063761f800c3319331bed3fc'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_osx-aarch64_bin-jmods.zip'
openjfx-sha: '13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -71,19 +77,27 @@ jobs:
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B -Djavafx.platform=mac clean package -Pmac -DskipTests
run: mvn -B clean package -Pmac -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- 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.accessibility,jdk.management.jfr,java.compiler
--module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.crypto.cryptoki,jdk.crypto.ec,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
@@ -104,7 +118,7 @@ jobs:
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\""
@@ -121,6 +135,7 @@ jobs:
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
--mac-package-identifier org.cryptomator
--resource-dir dist/mac/resources
- name: Patch Cryptomator.app
@@ -134,9 +149,23 @@ jobs:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Build and install DockTilePlugin
env:
DERIVED_DATA_PATH: dist/mac/DockTilePlugin/build
run: |
xcodebuild -project dist/mac/DockTilePlugin/DockTilePlugin.xcodeproj \
-scheme DockTilePlugin \
-configuration Release \
-destination "platform=macOS,arch=arm64" \
-derivedDataPath ${DERIVED_DATA_PATH} \
-quiet \
clean build
mkdir -p Cryptomator.app/Contents/PlugIns
cp -R ${DERIVED_DATA_PATH}/Build/Products/Release/Cryptomator.docktileplugin Cryptomator.app/Contents/PlugIns/
rm -rf ${DERIVED_DATA_PATH}
- name: Generate license for dmg
run: >
mvn -B -Djavafx.platform=mac license:add-third-party
mvn -B license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
@@ -224,9 +253,14 @@ jobs:
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
- name: Codesign .dmg
run: |
codesign -s ${CODESIGN_IDENTITY} --timestamp Cryptomator-*.dmg
env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
- name: Notarize .dmg
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
uses: cocoalibs/xcode-notarization-action@v1
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
with:
app-path: 'Cryptomator-*.dmg'
apple-id: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
@@ -247,7 +281,7 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dmg-${{ matrix.output-suffix }}
path: |
@@ -256,7 +290,7 @@ jobs:
if-no-files-found: error
- name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
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@v9
- uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
with:
days-before-stale: 14
days-before-close: 0

View File

@@ -19,14 +19,14 @@ 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@v2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
cryptomator-*.tar.gz.asc
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'

View File

@@ -5,7 +5,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 23
JAVA_VERSION: 24
defaults:
run:
@@ -15,13 +15,12 @@ jobs:
test:
name: Compile and Test
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@v4
- uses: actions/setup-java@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
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 -Djavafx.platform=linux
run: xvfb-run mvn -B clean install jacoco:report -Pcoverage

View File

@@ -19,9 +19,9 @@ jobs:
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -49,7 +49,7 @@ jobs:
exit 1
fi
- name: Cache NVD DB
uses: actions/cache@v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.m2/repository/org/owasp/dependency-check-data/
key: dependency-check-${{ github.run_id }}
@@ -60,6 +60,6 @@ jobs:
- name: Run org.owasp:dependency-check plugin
id: dependency-check
continue-on-error: true
run: mvn -B verify -Pdependency-check -DskipTests -Djavafx.platform=linux
run: mvn -B verify -Pdependency-check -DskipTests
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}

View File

@@ -12,7 +12,7 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
with:
days-before-stale: 365
days-before-close: 90

View File

@@ -8,18 +8,24 @@ on:
version:
description: 'Version'
required: false
isDebug:
description: 'Build debug version with console output'
sign:
description: 'Sign binaries'
required: false
type: boolean
default: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/win-exe.yml'
- 'dist/win/**'
env:
JAVA_DIST: 'zulu'
JAVA_VERSION: '23.0.2+7'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'ee176dcee3bd78bde7910735bd67f67c792882f5b89626796ae06f7a1c0119d3'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
WINFSP_MSI_HASH: '073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
defaults:
@@ -34,33 +40,46 @@ jobs:
build-msi:
name: Build .msi Installer
runs-on: windows-latest
needs: [get-version]
env:
LOOPBACK_ALIAS: 'cryptomator-vault'
WIN_CONSOLE_FLAG: ''
runs-on: ${{ matrix.os }}
needs: [ get-version ]
strategy:
matrix:
include:
- arch: x64
os: windows-latest
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }}
java-package: ${{ matrix.java-package }}
check-latest: true
cache: 'maven'
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version 6.0.0
wix.exe extension add WixToolset.UI.wixext/6.0.0 --global
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
- name: Download and extract JavaFX jmods from Gluon
if: matrix.arch == 'x64'
#In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip
run: |
curl --output jfxjmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}"
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) {
curl --output openjfx-jmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}"
if(!(Get-FileHash -Path openjfx-jmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) {
throw "Wrong checksum of JMOD archive downloaded from ${{ env.OPENJFX_JMODS_AMD64 }}.";
}
Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
Expand-Archive -Path openjfx-jmods.zip -DestinationPath openjfx-jmods
Get-ChildItem -Path openjfx-jmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
shell: pwsh
- name: Ensure major jfx version in pom and in jmods is the same
if: matrix.arch == 'x64'
run: |
JMOD_VERSION_AMD64=$(jmod describe jfxjmods/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@}
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
@@ -72,29 +91,34 @@ jobs:
exit 1
fi
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
run: mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B clean package -Pwin -DskipTests -Djavafx.platform=win
run: mvn -B clean package -Pwin -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! $(${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"); then
JMOD_PATHS="${JAVA_HOME}/jmods;${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- name: Run jlink
#Remark: no compression is applied for improved build compression later (here msi)
# 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.crypto.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.crypto.cryptoki,jdk.crypto.ec,jdk.crypto.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
--strip-debug
--compress zip-0
- name: Change win-console flag if debug is active
if: ${{ inputs.isDebug }}
run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV
- name: Run jpackage
run: >
${JAVA_HOME}/bin/jpackage
@@ -110,7 +134,7 @@ jobs:
--copyright "(C) 2016 - 2025 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,org.cryptomator.integrations.win"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
@@ -122,30 +146,24 @@ jobs:
--java-options "-Dcryptomator.p12Path=\"@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{localappdata}/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Cryptomator\""
--java-options "-Dcryptomator.loopbackAlias=\"${{ env.LOOPBACK_ALIAS }}\""
--java-options "-Dcryptomator.loopbackAlias=\"cryptomator-vault\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\""
--java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\""
--java-options "-Djavafx.verbose=${{ inputs.isDebug }}"
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
--java-options "-Dcryptomator.disableUpdateCheck=false"
--java-options "-XX:ErrorFile=C:/cryptomator/cryptomator_crash.log"
--resource-dir dist/win/resources
--icon dist/win/resources/Cryptomator.ico
${WIN_CONSOLE_FLAG}
--add-launcher "Cryptomator (Debug)=dist/win/debug-launcher.properties"
- name: Patch Application Directory
run: |
cp dist/win/contrib/* appdir/Cryptomator
- name: Set LOOPBACK_ALIAS in patchWebDAV.bat
shell: pwsh
run: |
$patchScript = "appdir\Cryptomator\patchWebDAV.bat"
try {
(Get-Content $patchScript ) -replace '::REPLACE ME', "SET LOOPBACK_ALIAS=`"${{ env.LOOPBACK_ALIAS}}`"" | Set-Content $patchScript
} catch {
Write-Host "Failed to set LOOPBACK_ALIAS for patchWebDAV.bat"
exit 1
}
- name: Fix permissions
run: attrib -r appdir/Cryptomator/Cryptomator.exe
run: |
attrib -r appdir/Cryptomator/Cryptomator.exe
attrib -r "appdir/Cryptomator/Cryptomator (Debug).exe"
shell: pwsh
- name: Extract jars with DLLs for Codesigning
shell: pwsh
@@ -170,16 +188,27 @@ jobs:
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@v3
- name: Sign DLLs with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
uses: ./.github/actions/win-sign-action
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
description: Cryptomator
timestampUrl: 'http://timestamp.digicert.com'
folder: appdir
base-dir: ${{ github.workspace }}\appdir
recursive: true
append-signature: true
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign DLLs with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
with:
base-dir: 'appdir'
file-extensions: 'dll,exe,ps1'
recursive: true
sign-description: 'Cryptomator'
sign-url: 'https://cryptomator.org'
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
password: ${{ secrets.WIN_CODESIGN_PW }}
- name: Replace DLLs inside jars with signed ones
shell: pwsh
run: |
@@ -196,7 +225,7 @@ jobs:
}
- name: Generate license for MSI
run: >
mvn -B license:add-third-party "-Djavafx.platform=win"
mvn -B license:add-third-party
"-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.outputDirectory=dist/win/resources"
"-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
@@ -228,17 +257,18 @@ jobs:
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@v3
- name: Sign MSI with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
uses: ./.github/actions/win-sign-action
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
description: Cryptomator Installer
timestampUrl: 'http://timestamp.digicert.com'
folder: installer
- name: Add possible alpha/beta tags to installer name
run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.msi
base-dir: ${{ github.workspace }}\installer
file-extensions: msi
description: 'Cryptomator Installer'
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Add possible alpha/beta tags and architecture to installer name
run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -247,9 +277,9 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: msi
name: msi-${{ matrix.arch }}
path: |
Cryptomator-*.msi
Cryptomator-*.asc
@@ -257,26 +287,42 @@ jobs:
build-exe:
name: Build .exe installer
runs-on: windows-latest
needs: [get-version, build-msi]
runs-on: ${{ matrix.os }}
needs: [ get-version, build-msi ]
strategy:
matrix:
include:
- arch: x64
os: windows-latest
executable-suffix: x64
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version 6.0.0
wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
- name: Download .msi
uses: actions/download-artifact@v4
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: msi
name: msi-${{ matrix.arch }}
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@v4
- name: Setup Java
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }}
java-package: ${{ matrix.java-package }}
check-latest: true
cache: 'maven'
- name: Generate license for exe
run: >
mvn -B license:add-third-party "-Djavafx.platform=win"
mvn -B license:add-third-party
"-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
"-Dlicense.outputDirectory=dist/win/bundle/resources"
@@ -287,60 +333,83 @@ jobs:
shell: pwsh
- name: Download WinFsp
run: |
curl --output dist/win/bundle/resources/winfsp.msi -L ${{ env.WINFSP_MSI }}
curl --output $env:WINFSP_PATH -L ${{ env.WINFSP_MSI }}
$computedHash = (Get-FileHash -Path $env:WINFSP_PATH -Algorithm SHA256).Hash.ToLower()
if ($computedHash -ne "${{ env.WINFSP_MSI_HASH }}") {
throw "Checksum mismatch for $env:WINFSP_PATH (expected ${{ env.WINFSP_MSI_HASH }}, got $computedHash)."
}
env:
WINFSP_PATH: 'dist/win/bundle/resources/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
- name: Create Wix Burn bundle
working-directory: dist/win
run: >
"${WIX}/bin/candle.exe" dist/win/bundle/bundleWithWinfsp.wxs
-ext WixBalExtension
-ext WixUtilExtension
-out dist/win/bundle/
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
-dBundleVendor="Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2025 Skymatic GmbH"
-dAboutUrl="https://cryptomator.org"
-dHelpUrl="https://cryptomator.org/contact"
-dUpdateUrl="https://cryptomator.org/downloads/"
- name: Create executable with linker
run: >
"${WIX}/bin/light.exe" -b dist/win/ dist/win/bundle/bundleWithWinfsp.wixobj
-ext WixBalExtension
-ext WixUtilExtension
-out installer/unsigned/Cryptomator-Installer.exe
wix build
-define BundleName="Cryptomator"
-define BundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
-define BundleVendor="Skymatic GmbH"
-define BundleCopyright="(C) 2016 - 2025 Skymatic GmbH"
-define AboutUrl="https://cryptomator.org"
-define HelpUrl="https://cryptomator.org/contact"
-define UpdateUrl="https://cryptomator.org/downloads/"
-ext "WixToolset.Util.wixext"
-ext "WixToolset.BootstrapperApplications.wixext"
./bundle/bundleWithWinfsp.wxs
-out "../../installer/unsigned/Cryptomator-Installer.exe"
- name: Detach burn engine in preparation to sign
run: >
"${WIX}/bin/insignia.exe"
-ib installer/unsigned/Cryptomator-Installer.exe
-o tmp/engine.exe
- name: Codesign burn engine
uses: skymatic/code-sign-action@v3
wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
- name: Sign WiX burn engine with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
uses: ./.github/actions/win-sign-action
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
description: Cryptomator Installer
timestampUrl: 'http://timestamp.digicert.com'
folder: tmp
base-dir: ${{ github.workspace }}\tmp
file-extensions: exe
append-signature: true
description: 'Cryptomator Bundle Installer'
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign burn engine with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
with:
base-dir: 'tmp'
file-extensions: 'exe'
sign-description: 'Cryptomator Bundle Installer'
sign-url: 'https://cryptomator.org'
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
password: ${{ secrets.WIN_CODESIGN_PW }}
- name: Reattach signed burn engine to installer
run : >
"${WIX}/bin/insignia.exe"
-ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe
-o installer/Cryptomator-Installer.exe
- name: Codesign EXE
uses: skymatic/code-sign-action@v3
run: >
wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
- name: Sign EXE installer with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
uses: ./.github/actions/win-sign-action
with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
description: Cryptomator Installer
timestampUrl: 'http://timestamp.digicert.com'
folder: installer
base-dir: ${{ github.workspace }}\installer
file-extensions: exe
append-signature: true
description: 'Cryptomator Bundle Installer'
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign installer with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
with:
base-dir: 'installer'
file-extensions: 'exe'
sign-description: 'Cryptomator Bundle Installer'
sign-url: 'https://cryptomator.org'
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
password: ${{ secrets.WIN_CODESIGN_PW }}
- name: Add possible alpha/beta tags to installer name
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.exe
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -349,9 +418,9 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: exe
name: exe-${{ matrix.executable-suffix }}
path: |
Cryptomator-*.exe
Cryptomator-*.asc
@@ -361,39 +430,39 @@ jobs:
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]
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 }}
download-url-msi-x64: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
steps:
- name: Download installers
uses: actions/download-artifact@v4
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
merge-multiple: true
- name: Publish .msi on GitHub Releases
- name: Publish installers on GitHub Releases
id: publish
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
# do not change ordering of filelist, required for correct job output
files: |
*.msi
*.exe
*x64.msi
*x64.exe
*.asc
allowlist-msi:
allowlist-msi-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [publish]
needs: [ publish ]
with:
url: ${{ needs.publish.outputs.download-url-msi }}
url: ${{ needs.publish.outputs.download-url-msi-x64 }}
secrets: inherit
allowlist-exe:
allowlist-exe-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [publish, allowlist-msi]
needs: [ publish, allowlist-msi-x64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe }}
url: ${{ needs.publish.outputs.download-url-exe-x64 }}
secrets: inherit
notify-winget:
@@ -403,14 +472,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
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_TITLE: "MSI packages 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 them to winget>."
SLACK_FOOTER: false
MSG_MINIMAL: true
MSG_MINIMAL: true

View File

@@ -16,12 +16,12 @@ jobs:
run: |
gh repo sync cryptomator/winget-pkgs -b master --force
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Submit package
uses: vedantmgoyal2009/winget-releaser@main
uses: vedantmgoyal2009/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f # no_specific_version
with:
identifier: Cryptomator.Cryptomator
version: ${{ inputs.tag }}
release-tag: ${{ inputs.tag }}
installers-regex: '\.msi$'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
installers-regex: '-x64\.msi$'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}

2
.idea/misc.xml generated
View File

@@ -8,7 +8,7 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" project-jdk-name="23" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="25" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Linux" 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;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
<method v="2">
<option name="Make" enabled="true" />
</method>

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Linux 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;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
<method v="2">
<option name="Make" enabled="true" />
</method>

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,org.cryptomator.integrations.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.integrationsWin.windowsHelloKeychainPaths=&quot;@{appdata}/Cryptomator/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator/windowsHelloKeychain.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,javafx.graphics" />
<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,org.cryptomator.integrations.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.integrationsWin.windowsHelloKeychainPaths=&quot;@{appdata}/Cryptomator-Dev/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/windowsHelloKeychain.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,javafx.graphics" />
<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/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator/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/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator/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,javafx.graphics" />
<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}/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" />
<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,javafx.graphics" />
<method v="2">
<option name="Make" enabled="true" />
</method>

View File

@@ -78,7 +78,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies
* JDK 23 (e.g. temurin, zulu)
* JDK 24 (e.g. temurin, zulu)
* Maven 3
### Run Maven

View File

@@ -12,23 +12,23 @@ 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)
CPU_ARCH=$(uname -m)
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 -Djavafx.platform=linux
mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
cp ../../../LICENSE.txt ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods
JAVAFX_VERSION=23.0.2
JAVAFX_VERSION=25
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='063baebc6922e4a89c94b9dfb7a4f53e59e8d6fec400d4e670b31bc2ab324dec'
JAVAFX_JMODS_SHA256='96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='9bbedaeae1590b69e2b22237bda310936df33e344dbc243bea2e86acaab3a0d8'
JAVAFX_JMODS_SHA256='951c52481af0ec5885b06f1ebaa8a10da7e8ea23c5e1ef3e2f6f11fa1b3a7ce1'
fi
# download javaFX jmods
@@ -51,12 +51,18 @@ if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
fi
# add runtime
# create runtime
## check for JEP 493
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
## create runtime image
${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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--module-path "${JMOD_PATHS}" \
--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.crypto.cryptoki,jdk.crypto.ec,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
@@ -75,7 +81,7 @@ ${JAVA_HOME}/bin/jpackage \
--name Cryptomator \
--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" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
@@ -92,6 +98,7 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\"" \
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
--resource-dir ../resources
# transform AppDir
@@ -122,7 +129,7 @@ chmod +x /tmp/appimagetool.AppImage
/tmp/appimagetool.AppImage \
Cryptomator.AppDir \
cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage \
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${CPU_ARCH}.AppImage.zsync'
-u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${CPU_ARCH}.AppImage.zsync"
echo ""
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage"

View File

@@ -83,6 +83,15 @@
</content_rating>
<releases>
<release date="2025-11-12" version="1.18.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.18.0</url>
</release>
<release date="2025-07-08" version="1.17.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.1</url>
</release>
<release date="2025-06-24" version="1.17.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.0</url>
</release>
<release date="2025-05-15" version="1.16.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.2</url>
</release>

View File

@@ -1,4 +1,4 @@
cryptomator (${PPA_VERSION}) focal; urgency=low
cryptomator (${PPA_VERSION}) jammy; urgency=low
* Full changelog can be found on https://github.com/cryptomator/cryptomator/releases

View File

@@ -2,7 +2,7 @@ Source: cryptomator
Maintainer: Cryptobot <releases@cryptomator.org>
Section: utils
Priority: optional
Build-Depends: debhelper (>=10), coffeelibs-jdk-23 (>= 23.0.2+7-0ppa1), libgtk-3-0, libxxf86vm1, libgl1
Build-Depends: debhelper (>=10), coffeelibs-jdk-24 (>= 24.0.1+9-0ppa3), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1
Standards-Version: 4.5.0
Homepage: https://cryptomator.org
Vcs-Git: https://github.com/cryptomator/cryptomator.git
@@ -12,7 +12,7 @@ Package: cryptomator
Architecture: any
Section: utils
Priority: optional
Depends: ${shlibs:Depends}, ${misc:Depends}, fuse3
Depends: ${shlibs:Depends}, ${misc:Depends}, fuse3, libgtk-3-0 (>= 3.20.0)
Recommends: gvfs-backends, gvfs-fuse, gnome-keyring
XB-AppName: Cryptomator
XB-Category: Utility;Security;FileTools;

View File

@@ -4,7 +4,7 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
JAVA_HOME = /usr/lib/jvm/java-23-coffeelibs
JAVA_HOME = /usr/lib/jvm/java-24-coffeelibs
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
ifeq ($(DEB_BUILD_ARCH),amd64)
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
@@ -28,7 +28,7 @@ override_dh_auto_build:
$(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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--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.crypto.cryptoki,jdk.crypto.ec,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
@@ -44,7 +44,7 @@ override_dh_auto_build:
--name cryptomator \
--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" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \

1
dist/mac/.gitignore vendored
View File

@@ -1 +1,2 @@
embedded.provisionprofile
xcuserdata/

View File

@@ -0,0 +1,19 @@
//
// CryptomatorDockTilePlugin.swift
// Integrations
//
// Created by Tobias Hagemann on 22.09.25.
// Copyright © 2025 Cryptomator. All rights reserved.
//
import AppKit
class CryptomatorDockTilePlugin: NSObject, NSDockTilePlugIn {
func setDockTile(_ dockTile: NSDockTile?) {
guard let dockTile = dockTile, let image = Bundle(for: Self.self).image(forResource: "Cryptomator") else {
return
}
dockTile.contentView = NSImageView(image: image)
dockTile.display()
}
}

View File

@@ -0,0 +1,314 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 77;
objects = {
/* Begin PBXBuildFile section */
74E08DE12E8584DE007E665C /* CryptomatorDockTilePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74E08DE02E85847E007E665C /* CryptomatorDockTilePlugin.swift */; };
74E08DED2E858532007E665C /* Cryptomator.icns in Resources */ = {isa = PBXBuildFile; fileRef = 74E08DEC2E858532007E665C /* Cryptomator.icns */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
74E08DD92E858467007E665C /* Cryptomator.docktileplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cryptomator.docktileplugin; sourceTree = BUILT_PRODUCTS_DIR; };
74E08DE02E85847E007E665C /* CryptomatorDockTilePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptomatorDockTilePlugin.swift; sourceTree = "<group>"; };
74E08DEC2E858532007E665C /* Cryptomator.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Cryptomator.icns; path = ../resources/Cryptomator.icns; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
74E08DD62E858467007E665C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
74E08DD02E858467007E665C = {
isa = PBXGroup;
children = (
74E08DE02E85847E007E665C /* CryptomatorDockTilePlugin.swift */,
74E08DEC2E858532007E665C /* Cryptomator.icns */,
74E08DDA2E858467007E665C /* Products */,
);
sourceTree = "<group>";
};
74E08DDA2E858467007E665C /* Products */ = {
isa = PBXGroup;
children = (
74E08DD92E858467007E665C /* Cryptomator.docktileplugin */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
74E08DD82E858467007E665C /* DockTilePlugin */ = {
isa = PBXNativeTarget;
buildConfigurationList = 74E08DDD2E858467007E665C /* Build configuration list for PBXNativeTarget "DockTilePlugin" */;
buildPhases = (
74E08DD52E858467007E665C /* Sources */,
74E08DD62E858467007E665C /* Frameworks */,
74E08DD72E858467007E665C /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = DockTilePlugin;
packageProductDependencies = (
);
productName = DockTilePlugin;
productReference = 74E08DD92E858467007E665C /* Cryptomator.docktileplugin */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
74E08DD12E858467007E665C /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastUpgradeCheck = 2600;
ORGANIZATIONNAME = Cryptomator;
TargetAttributes = {
74E08DD82E858467007E665C = {
CreatedOnToolsVersion = 26.0.1;
};
};
};
buildConfigurationList = 74E08DD42E858467007E665C /* Build configuration list for PBXProject "DockTilePlugin" */;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 74E08DD02E858467007E665C;
minimizedProjectReferenceProxies = 1;
preferredProjectObjectVersion = 77;
productRefGroup = 74E08DDA2E858467007E665C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
74E08DD82E858467007E665C /* DockTilePlugin */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
74E08DD72E858467007E665C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74E08DED2E858532007E665C /* Cryptomator.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
74E08DD52E858467007E665C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74E08DE12E8584DE007E665C /* CryptomatorDockTilePlugin.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
74E08DDB2E858467007E665C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = YZQJQUHA3L;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
74E08DDC2E858467007E665C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = YZQJQUHA3L;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_VERSION = 5.0;
};
name = Release;
};
74E08DDE2E858467007E665C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Cryptomator. All rights reserved.";
INFOPLIST_KEY_NSPrincipalClass = CryptomatorDockTilePlugin;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = org.cryptomator.DockTilePlugin;
PRODUCT_NAME = Cryptomator;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
WRAPPER_EXTENSION = docktileplugin;
};
name = Debug;
};
74E08DDF2E858467007E665C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Cryptomator. All rights reserved.";
INFOPLIST_KEY_NSPrincipalClass = CryptomatorDockTilePlugin;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = org.cryptomator.DockTilePlugin;
PRODUCT_NAME = Cryptomator;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
WRAPPER_EXTENSION = docktileplugin;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
74E08DD42E858467007E665C /* Build configuration list for PBXProject "DockTilePlugin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
74E08DDB2E858467007E665C /* Debug */,
74E08DDC2E858467007E665C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
74E08DDD2E858467007E665C /* Build configuration list for PBXNativeTarget "DockTilePlugin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
74E08DDE2E858467007E665C /* Debug */,
74E08DDF2E858467007E665C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 74E08DD12E858467007E665C /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "74E08DD82E858467007E665C"
BuildableName = "Cryptomator.docktileplugin"
BlueprintName = "DockTilePlugin"
ReferencedContainer = "container:DockTilePlugin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "74E08DD82E858467007E665C"
BuildableName = "Cryptomator.docktileplugin"
BlueprintName = "DockTilePlugin"
ReferencedContainer = "container:DockTilePlugin.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

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

@@ -32,15 +32,15 @@ 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"
JAVAFX_VERSION=23.0.2
JAVAFX_VERSION=25
JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="c690cc642a3924cf56622951f478ba57aec9ce09063761f800c3319331bed3fc"
JAVAFX_JMODS_SHA256="13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba"
else
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="5e6c65c065eea22430c0eab36f37a5985eb8ad99e19e8772262021740d338f68"
JAVAFX_JMODS_SHA256="0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52"
fi
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
@@ -71,15 +71,21 @@ if [ "${POM_JFX_VERSION}" -ne "${JMOD_VERSION}" ]; then
fi
# compile
mvn -B -Djavafx.platform=mac -f../../../pom.xml clean package -DskipTests -Pmac
mvn -B -f../../../pom.xml clean package -DskipTests -Pmac
cp ../../../LICENSE.txt ../../../target
cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
# add runtime
# create runtime
## check for JEP 493
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
## create custom 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.security.auth,jdk.accessibility,jdk.management.jfr,java.compiler \
--module-path "${JMOD_PATHS}" \
--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.crypto.cryptoki,jdk.crypto.ec,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
@@ -100,7 +106,7 @@ ${JAVA_HOME}/bin/jpackage \
--copyright "(C) ${COPYRIGHT_YEARS} ${VENDOR}" \
--app-version "${VERSION_NO}" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.mac" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \
@@ -109,6 +115,7 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dsun.java2d.metal=true" \
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/${APP_NAME}\"" \
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/${APP_NAME}/Plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/${APP_NAME}/settings.json\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/${APP_NAME}/ipc.socket\"" \
@@ -126,8 +133,21 @@ sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
# build and install dock tile plugin
echo "Building and installing Cryptomator.docktileplugin..."
DERIVED_DATA_PATH=../DockTilePlugin/build
xcodebuild -project ../DockTilePlugin/DockTilePlugin.xcodeproj \
-scheme DockTilePlugin \
-configuration Release \
-derivedDataPath ${DERIVED_DATA_PATH} \
-quiet \
clean build
mkdir -p ${APP_NAME}.app/Contents/PlugIns
cp -R ${DERIVED_DATA_PATH}/Build/Products/Release/Cryptomator.docktileplugin ${APP_NAME}.app/Contents/PlugIns/
rm -rf ${DERIVED_DATA_PATH}
# generate license
mvn -B -Djavafx.platform=mac -f../../../pom.xml license:add-third-party \
mvn -B -f../../../pom.xml license:add-third-party \
-Dlicense.thirdPartyFilename=license.rtf \
-Dlicense.outputDirectory=dist/mac/dmg/resources \
-Dlicense.fileTemplate=resources/licenseTemplate.ftl \

View File

@@ -116,5 +116,8 @@
<!-- allow utilization of integrated GPU, see https://developer.apple.com/library/mac/qa/qa1734/_index.html -->
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<!-- register dock tile plugin -->
<key>NSDockTilePlugIn</key>
<string>Cryptomator.docktileplugin</string>
</dict>
</plist>

3
dist/win/.gitignore vendored
View File

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

6
dist/win/build.bat vendored
View File

@@ -11,6 +11,10 @@ SET HELP_URL="https://cryptomator.org/contact/"
SET MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
SET LOOPBACK_ALIAS="cryptomator-vault"
:: read clean parameter from command line
SET CLEAN=0
IF "%~1"=="clean" SET CLEAN=1
pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^
-AppName %APPNAME%^
-MainJarGlob "%MAIN_JAR_GLOB%"^
@@ -22,4 +26,4 @@ pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^
-HelpUrl "%HELP_URL%"^
-UpdateUrl "%UPDATE_URL%"^
-LoopbackAlias "%LOOPBACK_ALIAS%"^
-Clean 1
-Clean %CLEAN%

238
dist/win/build.ps1 vendored
View File

@@ -9,39 +9,63 @@ Param(
[Parameter(Mandatory, HelpMessage="Please provide an update url")][string] $UpdateUrl,
[Parameter(Mandatory, HelpMessage="Please provide an about url")][string] $AboutUrl,
[Parameter(Mandatory, HelpMessage="Please provide an alias for localhost")][string] $LoopbackAlias,
[bool] $clean
[bool] $clean = $false # if true, cleans up previous build artifacts
)
# ============================
# Function Definitions Section
# ============================
function Main {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ProgressPreference = 'SilentlyContinue' # disables Invoke-WebRequest's progress bar, which slows down downloads to a few bytes/s
# check preconditions
if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host "Unable to find git.exe in your PATH (try: choco install git)"
Write-Error "Unable to find git.exe in your PATH (try: choco install git)"
exit 1
}
if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host "Unable to find mvn.cmd in your PATH (try: choco install maven)"
Write-Error "Unable to find mvn.cmd in your PATH (try: choco install maven)"
exit 1
}
if ((Get-Command 'wix' -ErrorAction SilentlyContinue) -eq $null)
{
Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.0)'
exit 1
}
$wixExtensions = & wix.exe extension list --global | Out-String
if ($wixExtensions -notmatch 'WixToolset.UI.wixext') {
Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.0 --global)'
exit 1
}
if ($wixExtensions -notmatch 'WixToolset.Util.wixext') {
Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.0 --global)'
exit 1
}
if ($wixExtensions -notmatch 'WixToolset.BootstrapperApplications.wixext') {
Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global)'
exit 1
}
$buildDir = Split-Path -Parent $PSCommandPath
$version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout)
$semVerNo = $version -replace '(\d+\.\d+\.\d+).*','$1'
$revisionNo = $(git rev-list --count HEAD)
Write-Output "`$version=$version"
Write-Output "`$semVerNo=$semVerNo"
Write-Output "`$revisionNo=$revisionNo"
Write-Output "`$buildDir=$buildDir"
Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
Write-Host "`$version=$version"
Write-Host "`$semVerNo=$semVerNo"
Write-Host "`$revisionNo=$revisionNo"
Write-Host "`$buildDir=$buildDir"
Write-Host "`$Env:JAVA_HOME=$Env:JAVA_HOME"
$copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor"
# compile
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin "-Djavafx.platform=win"
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin
Copy-Item "$buildDir\..\..\target\$MainJarGlob.jar" -Destination "$buildDir\..\..\target\mods"
# add runtime
@@ -50,43 +74,102 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
Remove-Item -Path $runtimeImagePath -Force -Recurse
}
## download jfx jmods
$javaFxVersion='23.0.2'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'ee176dcee3bd78bde7910735bd67f67c792882f5b89626796ae06f7a1c0119d3'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
Write-Output "Downloading ${javaFxJmodsUrl}..."
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
## download jfx jmods for X64, while they are part of the Arm64 JDK
$archCode = (Get-CimInstance Win32_Processor).Architecture
$archName = switch ($archCode) {
9 { "x64" }
12 { "ARM64" }
default { "WMI Win32_Processor.Architecture code ($archCode)" }
}
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash.ToLower()
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256
, actual: $jmodsChecksumActual"
exit 1;
switch ($archName) {
'ARM64' {
$javafxBaseJmod = Join-Path $Env:JAVA_HOME "jmods\javafx.base.jmod"
if (!(Test-Path $javafxBaseJmod)) {
Write-Error "JavaFX module not found in JDK. Please ensure a JDK with JavaFX (including jmods) is installed."
exit 1
}
$jmodPaths = "$Env:JAVA_HOME/jmods"
}
'x64' {
$javaFxVersion='25'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
Write-Host "Downloading ${javaFxJmodsUrl}..."
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
}
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash.ToLower()
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256
, actual: $jmodsChecksumActual"
exit 1;
}
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods" -ErrorAction Ignore
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
$jmodPaths="$buildDir/resources/javafx-jmods";
}
default {
Write-Error "Unsupported architecture: $arch"
exit 1
}
}
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods" -ErrorAction Ignore
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
## create custom runtime
### check for JEP 493
if ((& "$Env:JAVA_HOME\bin\jlink" --help | Select-String -Pattern "Linking from run-time image enabled" -SimpleMatch | Measure-Object).Count -eq 0 ) {
$jmodPaths="$Env:JAVA_HOME/jmods;" + $jmodPaths;
}
### create 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.accessibility,jdk.management.jfr,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--module-path $jmodPaths `
--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,jdk.crypto.cryptoki,jdk.crypto.ec,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--strip-native-commands `
--no-header-files `
--no-man-pages `
--strip-debug `
--compress "zip-0" #do not compress to have improved msi compression
--compress "zip-0" #do not compress and use msi compression
$appPath = ".\$AppName"
if ($clean -and (Test-Path -Path $appPath)) {
Remove-Item -Path $appPath -Force -Recurse
}
$javaOptions = @(
"--java-options", "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
"--java-options", "-Xss5m"
"--java-options", "-Xmx256m"
"--java-options", "-Dcryptomator.appVersion=`"$semVerNo`""
"--java-options", "-Dfile.encoding=`"utf-8`""
"--java-options", "-Djava.net.useSystemProxies=true"
"--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`""
"--java-options", "-XX:ErrorFile=`"C:/cryptomator/cryptomator_crash.log`""
"--java-options", "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`""
"--java-options", "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`""
"--java-options", "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`""
"--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`""
"--java-options", "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`""
"--java-options", "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`""
"--java-options", "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`""
"--java-options", "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`""
"--java-options", "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`""
"--java-options", "-Dcryptomator.showTrayIcon=true"
"--java-options", "-Dcryptomator.buildNumber=`"msi-$revisionNo`""
"--java-options", "-Dcryptomator.disableUpdateCheck=false"
)
# create app dir
& "$Env:JAVA_HOME\bin\jpackage" `
--verbose `
@@ -99,30 +182,19 @@ if ($clean -and (Test-Path -Path $appPath)) {
--name $AppName `
--vendor $Vendor `
--copyright $copyright `
--java-options "--enable-preview" `
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" `
--java-options "-Xss5m" `
--java-options "-Xmx256m" `
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
--app-version "$semVerNo.$revisionNo" `
--java-options "-Dfile.encoding=`"utf-8`"" `
--java-options "-Djava.net.useSystemProxies=true" `
--java-options "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" `
--java-options "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" `
--java-options "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`"" `
--java-options "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`"" `
--java-options "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`"" `
--java-options "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`"" `
--java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" `
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" `
--java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" `
--java-options "-Dcryptomator.showTrayIcon=true" `
--java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" `
--resource-dir resources `
--icon resources/$AppName.ico
--icon resources/$AppName.ico `
--add-launcher "${AppName} (Debug)=$buildDir\debug-launcher.properties" `
@javaOptions
if ($LASTEXITCODE -ne 0) {
Write-Error "jpackage Appimage failed with exit code $LASTEXITCODE"
return 1;
}
#Create RTF license for msi
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" `
&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
"-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\resources\" `
@@ -134,14 +206,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
# patch app dir
Copy-Item "contrib\*" -Destination "$AppName"
attrib -r "$AppName\$AppName.exe"
# patch batch script to set hostfile
$webDAVPatcher = "$AppName\patchWebDAV.bat"
try {
(Get-Content $webDAVPatcher ) -replace '::REPLACE ME', "SET LOOPBACK_ALIAS=`"$LoopbackAlias`"" | Set-Content $webDAVPatcher
} catch {
Write-Host "Failed to set LOOPBACK_ALIAS for patchWebDAV.bat"
exit 1
}
attrib -r "$AppName\${AppName} (Debug).exe"
# create .msi
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
@@ -166,8 +231,13 @@ $Env:JP_WIXHELPER_DIR = "."
--about-url $AboutUrl `
--file-associations resources/FAvaultFile.properties
if ($LASTEXITCODE -ne 0) {
Write-Error "jpackage MSI failed with exit code $LASTEXITCODE"
return 1;
}
#Create RTF license for bundle
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" `
&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
"-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\bundle\resources\" `
@@ -177,24 +247,54 @@ $Env:JP_WIXHELPER_DIR = "."
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges"
# download Winfsp
$winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi'
Write-Output "Downloading ${winfspMsiUrl}..."
$winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
$winfspMsiHash = '073A70E00F77423E34BED98B86E600DEF93393BA5822204FAC57A29324DB9F7A'
Write-Host "Downloading ${winfspMsiUrl}..."
Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default
$computedHash = $(Get-FileHash -Path '.\bundle\resources\winfsp.msi' -Algorithm SHA256).Hash
if (! $computedHash.Equals($winfspMsiHash)) {
Write-Error -Category InvalidData -CategoryActivity "Data integrity check failed" -Message @"
Downloaded Winfsp Installer does not match stored SHA256 checksum.
Expected: $winfspMsiHash
Actual: $computedHash
"@
exit 1
}
# download legacy-winfsp uninstaller
$winfspUninstaller= 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
Write-Output "Downloading ${winfspUninstaller}..."
Write-Host "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"
Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi" -Force
# create bundle including winfsp
& "$env:WIX\bin\candle.exe" .\bundle\bundleWithWinfsp.wxs -ext WixBalExtension -ext WixUtilextension -out bundle\ `
-dBundleVersion="$semVerNo.$revisionNo" `
-dBundleVendor="$Vendor" `
-dBundleCopyright="$copyright" `
-dAboutUrl="$AboutUrl" `
-dHelpUrl="$HelpUrl" `
-dUpdateUrl="$UpdateUrl"
& "$env:WIX\bin\light.exe" -b . .\bundle\BundlewithWinfsp.wixobj -ext WixBalExtension -ext WixUtilextension -out installer\$AppName-Installer.exe
& wix build `
-define BundleName="$AppName" `
-define BundleVersion="$semVerNo.$revisionNo" `
-define BundleVendor="$Vendor" `
-define BundleCopyright="$copyright" `
-define AboutUrl="$AboutUrl" `
-define HelpUrl="$HelpUrl" `
-define UpdateUrl="$UpdateUrl" `
-ext "WixToolset.Util.wixext" `
-ext "WixToolset.BootstrapperApplications.wixext" `
.\bundle\bundleWithWinfsp.wxs `
-out "installer\$AppName-Installer.exe"
Write-Host "Created EXE installer .\installer\$AppName-Installer.exe"
return 0;
}
# ============================
# Script Execution Starts Here
# ============================
if ($clean) {
Write-Host "Cleaning up previous build artifacts..."
Remove-Item -Path ".\runtime" -Force -Recurse -ErrorAction Ignore -ProgressAction SilentlyContinue
Remove-Item -Path ".\$AppName" -Force -Recurse -ErrorAction Ignore -ProgressAction SilentlyContinue
Remove-Item -Path ".\installer" -Force -Recurse -ErrorAction Ignore -ProgressAction SilentlyContinue
}
return Main

View File

@@ -1,66 +1,52 @@
<?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:
Condition - the single msi files have their own install conditions, no need to copy them here
-->
<Bundle Name="Cryptomator" UpgradeCode="29eea626-2e5b-4449-b5f8-4602925ddf7b" Version="$(var.BundleVersion)" Manufacturer="$(var.BundleVendor)"
AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico">
<!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/-->
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<ns0:Bundle Name="$(var.BundleName)"
UpgradeCode="29eea626-2e5b-4449-b5f8-4602925ddf7b"
Version="$(var.BundleVersion)"
Manufacturer="$(var.BundleVendor)"
AboutUrl="$(var.AboutUrl)"
HelpUrl="$(var.HelpUrl)"
UpdateUrl="$(var.UpdateUrl)"
Copyright="$(var.BundleCopyright)"
IconSourceFile="bundle\resources\Cryptomator.ico">
<!-- detect outdated WinFsp installations -->
<util:ProductSearch
Variable="InstalledLegacyWinFspVersion"
Result="version"
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"/>
<util:ProductSearch Variable="InstalledLegacyWinFspVersion" Result="version" 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">
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/bal/wixstandardbootstrapperapplication.html -->
<!-- Possible Attributes: LaunchTarget -->
<bal:WixStandardBootstrapperApplication
LicenseFile="bundle\resources\license.rtf"
ShowVersion="yes"
SuppressOptionsUI="yes"
ThemeFile="bundle\customBootstrapperTheme.xml"
LocalizationFile="bundle\customBootstrapperTheme.wxl"
LogoFile="bundle\resources\logo.png"/>
<Payload SourceFile="bundle\resources\logoSide.png" />
</BootstrapperApplicationRef>
<ns0:BootstrapperApplication>
<bal:WixStandardBootstrapperApplication LicenseFile="bundle\resources\license.rtf" ShowVersion="yes"
SuppressOptionsUI="yes"
Theme="rtfLargeLicense"
ThemeFile="bundle\resources\customBootstrapperTheme.xml"
LocalizationFile="bundle\resources\customBootstrapperTheme.wxl"
LogoSideFile="bundle\resources\logoSide.png"
LogoFile="bundle\resources\logo.png"
LaunchTarget="[ProgramFiles64Folder]\$(var.BundleName)\$(var.BundleName).exe" />
<ns0:Payload SourceFile="bundle\resources\logoSide.png"/>
<!-- Required due to https://github.com/wixtoolset/issues/issues/8104 -->
<ns0:Payload Name="Cryptobot.ico" SourceFile="bundle\resources\Cryptomator.ico"/>
</ns0:BootstrapperApplication>
<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" />
<ns0:Variable Name="DISABLEUPDATECHECK" bal:Overridable="yes" Type="string" Value="false"/>
<ns0:Chain>
<ns0:ExePackage Cache="keep" PerMachine="yes" Permanent="no" SourceFile="bundle\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))" UninstallArguments="">
<ns0: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.
<ns0: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"/>
<MsiPackage
SourceFile="resources\winfsp.msi"
CacheId="cryptomator-bundle-winfsp"
Visible="yes"
DisplayInternalUI="no"
Permanent="yes"/>
</Chain>
</Bundle>
</Wix>
<ns0:ExitCode Behavior="success" Value="0" />
<ns0:ExitCode Behavior="success" Value="1" />
<ns0:ExitCode Behavior="error" Value="2" />
<ns0:ExitCode Behavior="error" Value="3" />
<ns0:ExitCode Behavior="forceReboot" Value="4" />
<ns0:ExitCode Behavior="success" Value="5" />
</ns0:ExePackage>
<ns0:MsiPackage SourceFile="bundle\resources\Cryptomator.msi" CacheId="cryptomator-bundle-cryptomator" Visible="no">
<ns0:MsiProperty Name="DISABLEUPDATECHECK" Value="[DISABLEUPDATECHECK]"/>
</ns0:MsiPackage>
<ns0:MsiPackage SourceFile="bundle\resources\winfsp.msi" CacheId="cryptomator-bundle-winfsp" Visible="yes" Permanent="yes" />
</ns0:Chain>
</ns0:Bundle>
</ns0:Wix>

View File

@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="Caption">[WixBundleName] Setup</String>
<String Id="Title">[WixBundleName]</String>
<String Id="InstallHeader">Welcome</String>
<String Id="InstallMessage">This Setup will install [WixBundleName] and additional dependencies on your computer.</String>
<String Id="InstallVersion">Version [WixBundleVersion]</String>
<String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
<String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String>
<String Id="HelpHeader">Setup Help</String>
<String Id="HelpText">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or
creates a complete local copy of the bundle in directory. Install is the default.
/passive | /quiet - displays minimal UI with no prompts or displays no UI and
no prompts. By default UI and all prompts are displayed.
/norestart - suppress any attempts to restart. By default UI will prompt before restart.
/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>
<String Id="HelpCloseButton">&amp;Close</String>
<String Id="InstallLicenseLinkText">[WixBundleName] &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
<String Id="InstallOptionsButton">&amp;Options</String>
<String Id="InstallInstallButton">&amp;Install</String>
<String Id="InstallCloseButton">&amp;Close</String>
<String Id="OptionsHeader">Setup Options</String>
<String Id="OptionsLocationLabel">Install location:</String>
<String Id="OptionsBrowseButton">&amp;Browse</String>
<String Id="OptionsOkButton">&amp;OK</String>
<String Id="OptionsCancelButton">&amp;Cancel</String>
<String Id="ProgressHeader">Setup Progress</String>
<String Id="ProgressLabel">Processing:</String>
<String Id="OverallProgressPackageText">Initializing...</String>
<String Id="ProgressCancelButton">&amp;Cancel</String>
<String Id="ModifyHeader">Modify Setup</String>
<String Id="ModifyRepairButton">&amp;Repair</String>
<String Id="ModifyUninstallButton">&amp;Uninstall</String>
<String Id="ModifyCloseButton">&amp;Close</String>
<String Id="SuccessRepairHeader">Repair Successfully Completed</String>
<String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String>
<String Id="SuccessInstallHeader">Installation Successfully Completed</String>
<String Id="SuccessHeader">Setup Successful</String>
<String Id="SuccessLaunchButton">&amp;Launch</String>
<String Id="SuccessRestartText">You must restart your computer before you can use the software.</String>
<String Id="SuccessRestartButton">&amp;Restart</String>
<String Id="SuccessCloseButton">&amp;Close</String>
<String Id="FailureHeader">Setup Failed</String>
<String Id="FailureInstallHeader">Setup Failed</String>
<String Id="FailureUninstallHeader">Uninstall Failed</String>
<String Id="FailureRepairHeader">Repair Failed</String>
<String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
<String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
<String Id="FailureRestartButton">&amp;Restart</String>
<String Id="FailureCloseButton">&amp;Close</String>
<String Id="FilesInUseHeader">Files In Use</String>
<String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String>
<String Id="FilesInUseCloseRadioButton">Close the &amp;applications and attempt to restart them.</String>
<String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
<String Id="FilesInUseOkButton">&amp;OK</String>
<String Id="FilesInUseCancelButton">&amp;Cancel</String>
<String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
</WixLocalization>

View File

@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<!-- adjusted theme based on https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/HyperlinkSidebarTheme.xml -->
<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">
<Window Width="600" Height="450" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window>
<Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font>
<Font Id="5" Height="-12" Weight="700" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Page Name="Help">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text>
<Text X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text>
<Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button>
</Page>
<Page Name="Install">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text X="185" Y="50" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.InstallHeader)</Text>
<Text X="185" Y="91" Width="-11" Height="64" FontId="3" DisablePrefix="yes">#(loc.InstallMessage)</Text>
<Richedit Name="EulaRichedit" X="185" Y="131" Width="-12" Height="-65" HexStyle="0x00800000" TabStop="yes" FontId="0" />
<Checkbox Name="EulaAcceptCheckbox" X="185" Y="-46" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Text Name="InstallVersion" X="185" Y="-11" Width="-11" Height="17" FontId="3" DisablePrefix="yes" HideWhenDisabled="yes">#(loc.InstallVersion)</Text>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
<Page Name="FilesInUse">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FilesInUseHeader)</Text>
<Text X="11" Y="121" Width="-11" Height="34" FontId="3" DisablePrefix="yes">#(loc.FilesInUseLabel)</Text>
<Text Name="FilesInUseText" X="11" Y="150" Width="-11" Height="-86" FontId="3" DisablePrefix="yes" HexStyle="0x0000000C">A</Text>
<Button Name="FilesInUseCloseRadioButton" X="11" Y="-60" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseCloseRadioButton)</Button>
<Button Name="FilesInUseDontCloseRadioButton" X="11" Y="-40" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseDontCloseRadioButton)</Button>
<Button Name="FilesInUseOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FilesInUseOkButton)</Button>
<Button Name="FilesInUseCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FilesInUseCancelButton)</Button>
</Page>
<Page Name="Progress">
<Text X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text>
<Text X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text>
<Text Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button>
</Page>
<Page Name="Success">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text Name="SuccessHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text>
<Text Name="SuccessInstallHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text>
<Text Name="SuccessRepairHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text>
<Text Name="SuccessUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Text Name="SuccessRestartText" X="185" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button>
</Page>
<Page Name="Failure">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text Name="FailureHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text>
<Text Name="FailureInstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text>
<Text Name="FailureUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text>
<Text Name="FailureRepairHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text>
<Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="185" Y="-80" Width="-11" Height="140" FontId="5" TabStop="yes" HideWhenDisabled="yes" />
<Text Name="FailureRestartText" X="185" Y="-57" Width="-11" Height="80" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button>
</Page>
</Theme>

View File

@@ -0,0 +1,68 @@
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://wixtoolset.org/schemas/v4/wxl">
<String Id="Caption" Value="[WixBundleName] Setup" />
<String Id="Title" Value="[WixBundleName]" />
<String Id="InstallHeader" Value="Welcome" />
<String Id="InstallMessage" Value="Setup will install [WixBundleName] on your computer." />
<String Id="InstallVersion" Value="Version [WixBundleVersion]" />
<String Id="CheckingForUpdatesLabel" Value="Checking for updates" />
<String Id="UpdateButton" Value="&amp;Update to version [WixStdBAUpdateAvailable]" />
<String Id="InstallVersion" Value="Version [WixBundleVersion]" />
<String Id="ConfirmCancelMessage" Value="Are you sure you want to cancel?" />
<String Id="ExecuteUpgradeRelatedBundleMessage" Value="Previous version" />
<String Id="HelpHeader" Value="Setup Help" />
<String Id="HelpText" Value="/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or&#xA; creates a complete local copy of the bundle in directory. Install is the default.&#xA;&#xA;/passive | /quiet - displays minimal UI with no prompts or displays no UI and&#xA; no prompts. By default UI and all prompts are displayed.&#xA;&#xA;/norestart - suppress any attempts to restart. By default UI will prompt before restart.&#xA;/log log.txt - logs to a specific file. By default a log file is created in %TEMP%." />
<String Id="HelpCloseButton" Value="&amp;Close" />
<String Id="InstallAcceptCheckbox" Value="I &amp;agree to the license terms and conditions" />
<String Id="InstallOptionsButton" Value="&amp;Options" />
<String Id="InstallInstallButton" Value="&amp;Install" />
<String Id="InstallCancelButton" Value="&amp;Cancel" />
<String Id="OptionsHeader" Value="Setup Options" />
<String Id="OptionsLocationLabel" Value="Install location:" />
<String Id="OptionsBrowseButton" Value="&amp;Browse" />
<String Id="OptionsOkButton" Value="&amp;OK" />
<String Id="OptionsCancelButton" Value="&amp;Cancel" />
<String Id="ProgressHeader" Value="Setup Progress" />
<String Id="ProgressLabel" Value="Processing:" />
<String Id="OverallProgressPackageText" Value="Initializing..." />
<String Id="ProgressCancelButton" Value="&amp;Cancel" />
<String Id="ModifyHeader" Value="Modify Setup" />
<String Id="ModifyRepairButton" Value="&amp;Repair" />
<String Id="ModifyUninstallButton" Value="&amp;Uninstall" />
<String Id="ModifyCancelButton" Value="&amp;Cancel" />
<String Id="SuccessHeader" Value="Setup Successful" />
<String Id="SuccessCacheHeader" Value="Cache Successfully Completed" />
<String Id="SuccessInstallHeader" Value="Installation Successfully Completed" />
<String Id="SuccessLayoutHeader" Value="Layout Successfully Completed" />
<String Id="SuccessModifyHeader" Value="Modify Successfully Completed" />
<String Id="SuccessRepairHeader" Value="Repair Successfully Completed" />
<String Id="SuccessUninstallHeader" Value="Uninstall Successfully Completed" />
<String Id="SuccessUnsafeUninstallHeader" Value="Uninstall Successfully Completed" />
<String Id="SuccessLaunchButton" Value="&amp;Launch" />
<String Id="SuccessRestartText" Value="You must restart your computer before you can use the software." />
<String Id="SuccessUninstallRestartText" Value="You must restart your computer to complete the removal of the software." />
<String Id="SuccessRestartButton" Value="&amp;Restart" />
<String Id="SuccessCloseButton" Value="&amp;Close" />
<String Id="FailureHeader" Value="Setup Failed" />
<String Id="FailureCacheHeader" Value="Cache Failed" />
<String Id="FailureInstallHeader" Value="Setup Failed" />
<String Id="FailureLayoutHeader" Value="Layout Failed" />
<String Id="FailureModifyHeader" Value="Modify Failed" />
<String Id="FailureRepairHeader" Value="Repair Failed" />
<String Id="FailureUninstallHeader" Value="Uninstall Failed" />
<String Id="FailureUnsafeUninstallHeader" Value="Uninstall Failed" />
<String Id="FailureHyperlinkLogText" Value="One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href=&quot;#&quot;&gt;log file&lt;/a&gt;." />
<String Id="FailureRestartText" Value="You must restart your computer to complete the rollback of the software." />
<String Id="FailureRestartButton" Value="&amp;Restart" />
<String Id="FailureCloseButton" Value="&amp;Close" />
<String Id="FilesInUseTitle" Value="Files In Use" />
<String Id="FilesInUseLabel" Value="The following applications are using files that need to be updated:" />
<String Id="FilesInUseNetfxCloseRadioButton" Value="Close the &amp;applications." />
<String Id="FilesInUseCloseRadioButton" Value="Close the &amp;applications and attempt to restart them." />
<String Id="FilesInUseDontCloseRadioButton" Value="&amp;Do not close applications. A reboot will be required." />
<String Id="FilesInUseRetryButton" Value="&amp;Retry" />
<String Id="FilesInUseIgnoreButton" Value="&amp;Ignore" />
<String Id="FilesInUseExitButton" Value="E&amp;xit" />
</WixLocalization>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
<Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
<Window Width="600" Height="450" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)" IconFile="Cryptobot.ico">
<Page Name="Help">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
<Label X="11" Y="121" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
<Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.HelpCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Loading">
<Label X="185" Y="50" Width="-11" Height="30" FontId="2" DisablePrefix="yes" Visible="no" Name="CheckingForUpdatesLabel" />
</Page>
<Page Name="Install">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.InstallHeader)</Label>
<Label X="185" Y="50" Width="-11" Height="64" FontId="3" DisablePrefix="yes">
<Text Condition="WixStdBASuppressOptionsUI">#(loc.InstallMessage)</Text>
<Text Condition="NOT WixStdBASuppressOptionsUI">#(loc.InstallMessageOptions)</Text>
</Label>
<Richedit Name="EulaRichedit" X="185" Y="91" Width="-12" Height="-64" HexStyle="0x00800000" TabStop="yes" FontId="0" />
<Checkbox Name="EulaAcceptCheckbox" X="185" Y="-39" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="InstallUpdateButton" X="11" Y="-11" Width="200" Height="23" TabStop="yes" FontId="0" EnableCondition="WixStdBAUpdateAvailable" HideWhenDisabled="yes">#(loc.UpdateButton)</Button>
<Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" VisibleCondition="NOT WixStdBASuppressOptionsUI">
<Text>#(loc.InstallOptionsButton)</Text>
<ChangePageAction Page="Options" />
</Button>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.InstallCancelButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Options">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Label>
<Label X="11" Y="121" Width="-11" Height="17" FontId="3">#(loc.OptionsLocationLabel)</Label>
<Editbox Name="InstallFolder" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
<Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">
<Text>#(loc.OptionsBrowseButton)</Text>
<BrowseDirectoryAction VariableName="InstallFolder" />
</Button>
<Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.OptionsOkButton)</Text>
<ChangePageAction Page="Install" />
</Button>
<Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.OptionsCancelButton)</Text>
<ChangePageAction Page="Install" Cancel="yes" />
</Button>
</Page>
<Page Name="Progress">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
<Label X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
<Label Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Label>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Label>
<Label Name="InstallVersion" X="11" Y="-11" Width="-11" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="ModifyUpdateButton" X="11" Y="-11" Width="200" Height="23" TabStop="yes" FontId="0" EnableCondition="WixStdBAUpdateAvailable" HideWhenDisabled="yes">#(loc.UpdateButton)</Button>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.ModifyCancelButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Success">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">
<Text>#(loc.SuccessHeader)</Text>
<Text Condition="WixBundleAction = 2">#(loc.SuccessLayoutHeader)</Text>
<Text Condition="WixBundleAction = 3">#(loc.SuccessUnsafeUninstallHeader)</Text>
<Text Condition="WixBundleAction = 4">#(loc.SuccessUninstallHeader)</Text>
<Text Condition="WixBundleAction = 5">#(loc.SuccessCacheHeader)</Text>
<Text Condition="WixBundleAction = 6">#(loc.SuccessInstallHeader)</Text>
<Text Condition="WixBundleAction = 7">#(loc.SuccessModifyHeader)</Text>
<Text Condition="WixBundleAction = 8">#(loc.SuccessRepairHeader)</Text>
</Label>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Label X="185" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">
<Text>#(loc.SuccessRestartText)</Text>
<Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallRestartText)</Text>
</Label>
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.SuccessCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Failure">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">
<Text>#(loc.FailureHeader)</Text>
<Text Condition="WixBundleAction = 2">#(loc.FailureLayoutHeader)</Text>
<Text Condition="WixBundleAction = 3">#(loc.FailureUnsafeUninstallHeader)</Text>
<Text Condition="WixBundleAction = 4">#(loc.FailureUninstallHeader)</Text>
<Text Condition="WixBundleAction = 5">#(loc.FailureCacheHeader)</Text>
<Text Condition="WixBundleAction = 6">#(loc.FailureInstallHeader)</Text>
<Text Condition="WixBundleAction = 7">#(loc.FailureModifyHeader)</Text>
<Text Condition="WixBundleAction = 8">#(loc.FailureRepairHeader)</Text>
</Label>
<Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="185" Y="-115" Width="-11" Height="80" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Label X="185" Y="-57" Width="-11" Height="80" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.FailureCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
</Window>
</Theme>

18
dist/win/contrib/patchUpdateCheck.bat vendored Normal file
View File

@@ -0,0 +1,18 @@
@echo off
:: Batch wrapper for PowerShell script to modify Cryptomator update check settings
:: This is executed as a Custom Action during MSI installation
:: This file must be located in the INSTALLDIR
set "DISABLEUPDATECHECK=%~1"
:: Log for debugging
echo DISABLEUPDATECHECK=%DISABLEUPDATECHECK%
:: Change to INSTALLDIR
cd %~dp0
:: Execute the PowerShell script
powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File ".\patchUpdateCheck.ps1"^
-DisableUpdateCheck "%DISABLEUPDATECHECK%"
:: Return the exit code from PowerShell
exit /b %ERRORLEVEL%

58
dist/win/contrib/patchUpdateCheck.ps1 vendored Normal file
View File

@@ -0,0 +1,58 @@
# PowerShell script to modify Cryptomator.cfg to set disableUpdateCheck property
# This script is executed as a Custom Action during MSI installation
# If the DisableUpdateCheck parameter is set to true, it disables the update check in Cryptomator by modifying the Cryptomator.cfg file.
# NOTE: This file must be located in the same directory as set in the MSI property INSTALLDIR
param(
[Parameter(Mandatory)][string]$DisableUpdateCheck
)
try {
# Log parameters for debugging (visible in MSI verbose logs)
Write-Host "DisableUpdateCheck: $DisableUpdateCheck"
# Parse DisableUpdateCheck value (handle various input formats)
$shouldDisable = $false
if ($DisableUpdateCheck) {
$DisableUpdateCheck = $DisableUpdateCheck.Trim().ToLower()
$shouldDisable = ($DisableUpdateCheck -eq 'true') -or ($DisableUpdateCheck -eq '1') -or ($DisableUpdateCheck -eq 'yes')
}
Write-Host "Setting cryptomator.disableUpdateCheck to: $shouldDisable"
if (-not $shouldDisable) {
Write-Host 'Disable-Update-Check property is by default "false". Skipping config modification.'
exit 0
}
# Determine the .cfg file path
$cfgDir = Join-Path $PSScriptRoot 'app'
$cfgFiles = Get-ChildItem -Path $cfgDir -Filter '*.cfg' -File
if ($cfgFiles.Count -eq 0) {
Write-Error "No .cfg file found in directory: $cfgDir"
exit 1
}
foreach ($file in $cfgFiles) {
$cfgFile = $file.FullName
Write-Host "Modifying configuration file: $cfgFile"
# Read the current configuration
$content = Get-Content $cfgFile -Raw -ErrorAction Stop
# Add the new option based on the property value
# Use regular expressions substitutions to replace the property
$searchExpression = '(?<Prefix>java-options=-Dcryptomator\.disableUpdateCheck)=false'
$replacementExpression = '${Prefix}=true'
$content = $content -replace $searchExpression,$replacementExpression
# Write the modified content back
Set-Content -Path $cfgFile -Value $content -NoNewline
Write-Host "Successfully updated $cfgFile"
}
exit 0
}
catch {
Write-Error "Error modifying configuration file: $_"
exit 1
}

View File

@@ -1,7 +1,18 @@
@echo off
:: Default values for Cryptomator builds
::REPLACE ME
:: Batch wrapper for PowerShell script to adjust Windows network settings for the Cryptomator WebDAVAdapter
:: This is executed as a Custom Action during MSI installation
:: This file must be located in the INSTALLDIR
set "LOOPBACK_ALIAS=%1"
:: Log for debugging
echo LOOPBACK_ALIAS=%LOOPBACK_ALIAS%
:: Change to INSTALLDIR
cd %~dp0
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command .\patchWebDAV.ps1^
-LoopbackAlias %LOOPBACK_ALIAS%
:: Execute the PowerShell script
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File .\patchWebDAV.ps1^
-LoopbackAlias %LOOPBACK_ALIAS%
:: Return the exit code from PowerShell
exit /b %ERRORLEVEL%

4
dist/win/debug-launcher.properties vendored Normal file
View File

@@ -0,0 +1,4 @@
win-console=true
win-shortcut=false
win-menu=false
description=Debug Launcher with Console for Cryptomator

14
dist/win/launcher.bat vendored
View File

@@ -1,14 +0,0 @@
@echo off
java ^
-p "mods" ^
-cp "libs/*" ^
-Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" ^
-Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^
-Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^
-Dcryptomator.mountPointsDir="~/Cryptomator" ^
-Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" ^
-Xss20m ^
-Xmx512m ^
--enable-preview `
--enable-native-access=org.cryptomator.jfuse.win `
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator

View File

@@ -1,109 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Include>
<Fragment>
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/WixUI_InstallDir.wxs with custom exit dialog-->
<UI Id="CustomWizard">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="InstallDir" />
<DialogRef Id="BrowseDlg" />
<DialogRef Id="DiskCostDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<!-- custom end dialogs -->
<Publish Dialog="MyExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
<Publish Dialog="MyFatalErrorDlg" Control="Finish" Event="EndDialog" Value="Return" Order="998">1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg">NOT Installed</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">LicenseAccepted = "1"</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1">NOT Installed</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
<Property Id="ARPNOMODIFY" Value="1" />
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/ExitDialog.wxs with adjustments-->
<Dialog Id="MyExitDialog" Width="370" Height="270" Title="!(loc.ExitDialog_Title)">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.ExitDialogBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogDescription)" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogTitle)" />
<!-- TODO: localize? -->
<Control Id="Suggestion" Type="Text" X="135" Y="100" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
<Text>We recommend for the best user experience to download and install the following third party Windows driver:</Text>
</Control>
<Control Id="WinFsp" Type="Hyperlink" X="140" Y="125" Width="220" Height="60" Transparent="yes">
<Text><![CDATA[WinFsp (<a href="https://winfsp.dev/">Homepage</a>)]]></Text>
</Control>
</Dialog>
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/FatalError.wxs with adjustments-->
<Dialog Id="MyFatalErrorDlg" Width="370" Height="270" Title="!(loc.FatalError_Title)">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)">
<Publish Event="EndDialog" Value="Exit">1</Publish>
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.FatalErrorBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.FatalErrorTitle)" />
<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="80" Transparent="yes" NoPrefix="yes" Text="!(loc.FatalErrorDescription1) !(loc.FatalErrorDescription2)" />
<Control Id="DescriptionReason1" Type="Text" X="135" Y="160" Width="220" Height="20" Transparent="yes" NoPrefix="yes" Hidden="yes" >
<Text>Reason:</Text>
<Condition Action="show">FOUNDRUNNINGAPP</Condition>
</Control>
<Control Id="DescriptionReason2" Type="Text" X="135" Y="170" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Hidden="yes" >
<Text>Application to update was still running during installation.</Text>
<Condition Action="show">FOUNDRUNNINGAPP</Condition>
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="MyExitDialog" Overridable="yes" OnExit="success"/>
<Show Dialog="MyFatalErrorDlg" Overridable="yes" OnExit="error"/>
</InstallUISequence>
<AdminUISequence>
<Show Dialog="MyExitDialog" Overridable="yes" OnExit="success"/>
<Show Dialog="MyFatalErrorDlg" Overridable="yes" OnExit="error"/>
</AdminUISequence>
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Include>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" >
<?ifdef JpIsSystemWide ?>
<?define JpInstallScope="perMachine"?>
@@ -27,177 +26,179 @@
<?define IconFileEncryptedData= "Cryptomator-Vault.ico" ?>
<?define ProgIdContentType= "application/vnd.cryptomator.encrypted" ?>
<?define CloseApplicationTarget= "cryptomator.exe" ?>
<?define LoopbackAlias= "cryptomator-vault" ?>
<?include $(var.JpConfigDir)/overrides.wxi ?>
<Product
Id="$(var.JpProductCode)"
Name="$(var.JpAppName)"
Language="$(var.JpProductLanguage)"
Version="$(var.JpAppVersion)"
Manufacturer="$(var.JpAppVendor)"
UpgradeCode="$(var.JpProductUpgradeCode)">
<ns0:Package
Name="$(var.JpAppName)"
Language="$(var.JpProductLanguage)"
Version="$(var.JpAppVersion)"
Manufacturer="$(var.JpAppVendor)"
UpgradeCode="$(var.JpProductUpgradeCode)"
InstallerVersion="$(var.JpInstallerVersion)"
Compressed="$(var.JpCompressedMsi)"
ProductCode="$(var.JpProductCode)"
Scope="$(var.JpInstallScope)">
<Package
Description="$(var.JpAppDescription)"
Manufacturer="$(var.JpAppVendor)"
InstallerVersion="$(var.JpInstallerVersion)"
Compressed="$(var.JpCompressedMsi)"
InstallScope="$(var.JpInstallScope)" Platform="x64"
/>
<ns0:SummaryInformation Manufacturer="$(var.JpAppVendor)" Description="$(var.JpAppDescription)"/>
<ns0:Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
<Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
<Upgrade Id="$(var.JpProductUpgradeCode)">
<UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectUpgrade)"
Property="JP_UPGRADABLE_FOUND"
Maximum="$(var.JpAppVersion)"
MigrateFeatures="yes"
IncludeMaximum="yes" /> <!-- TODO: check if this needs to be set to yes-->
<UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)"
Property="JP_DOWNGRADABLE_FOUND"
Minimum="$(var.JpAppVersion)"
MigrateFeatures="yes"
IncludeMinimum="$(var.JpUpgradeVersionOnlyDetectDowngrade)" />
</Upgrade>
<ns0:Upgrade Id="$(var.JpProductUpgradeCode)">
<ns0:UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectUpgrade)"
Property="JP_UPGRADABLE_FOUND"
Maximum="$(var.JpAppVersion)"
MigrateFeatures="yes"
IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)"/> <!-- TODO in earlier versions, this was set to yes-->
<ns0:UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)"
Property="JP_DOWNGRADABLE_FOUND"
Minimum="$(var.JpAppVersion)"
MigrateFeatures="yes"
IncludeMinimum="$(var.JpUpgradeVersionOnlyDetectDowngrade)" />
</ns0:Upgrade>
<?ifndef JpAllowUpgrades ?>
<CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" />
<ns0:CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" />
<?endif?>
<?ifndef JpAllowDowngrades ?>
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
<ns0:CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
<?endif?>
<Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll"/>
<CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" />
<!-- TODO: how does this work again? -->
<ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll" />
<ns0:CustomAction Id="JpFindRelatedProducts" BinaryRef="JpCaDll" DllEntry="FindRelatedProductsEx" />
<?ifndef SkipCryptomatorLegacyCheck ?>
<!-- Block installation if innosetup entry of Cryptomator is found -->
<Property Id="OLDEXEINSTALLER">
<RegistrySearch Id="InnoSetupInstallation" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Cryptomator_is1" Type="raw" Name="DisplayName" />
</Property>
<ns0:Property Id="OLDEXEINSTALLER">
<ns0:RegistrySearch Id="InnoSetupInstallation" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Cryptomator_is1" Type="raw" Name="DisplayName" />
</ns0:Property>
<!-- TODO: localize -->
<Condition Message="A lower version of [ProductName] is already installed. Uninstall it first and then start the setup again. Setup will now exit.">
<![CDATA[Installed OR NOT OLDEXEINSTALLER]]>
</Condition>
<ns0:Launch Message="A lower version of [ProductName] is already installed. Uninstall it first and then start the setup again. Setup will now exit." Condition="Installed OR NOT OLDEXEINSTALLER" />
<?endif?>
<!-- Cryptomator uses UNIX Sockets, which are supported starting with Windows 10 v1803-->
<Property Id="WINDOWSBUILDNUMBER" Secure="yes">
<RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" />
</Property>
<Condition Message="This application requires Windows 10 version 1803 (build 17134) or newer.">
<![CDATA[Installed OR (WINDOWSBUILDNUMBER >= 17134)]]>
</Condition>
<ns0:Property Id="WINDOWSBUILDNUMBER" Secure="yes">
<ns0:RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" />
</ns0:Property>
<ns0:Launch Message="This application requires Windows 10 version 1803 (build 17134) or newer." Condition="Installed OR (WINDOWSBUILDNUMBER >= 17134)" />
<!-- Non-Opening ProgID -->
<DirectoryRef Id="INSTALLDIR">
<Component Win64="yes" Id="nonStartingProgID" >
<File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"></File>
<ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0">
<Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
<MIME ContentType="$(var.ProgIdContentType)" Default="yes"></MIME>
</Extension>
<Extension Id="c9s" Advertise="no" ContentType="$(var.ProgIdContentType)"/>
</ProgId>
</Component>
</DirectoryRef>
<ns0:DirectoryRef Id="INSTALLDIR">
<ns0:Component Bitness="always64" Id="nonStartingProgID" >
<ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/>
<ns0:ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0">
<ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
<ns0:MIME ContentType="$(var.ProgIdContentType)" Default="yes"/>
</ns0:Extension>
<ns0:Extension Id="c9s" Advertise="no" ContentType="$(var.ProgIdContentType)"/>
</ns0:ProgId>
</ns0:Component>
</ns0:DirectoryRef>
<!-- Standard required root -->
<Directory Id="TARGETDIR" Name="SourceDir"/>
<Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
<ComponentGroupRef Id="Shortcuts"/>
<ComponentGroupRef Id="Files"/>
<ComponentGroupRef Id="FileAssociations"/>
<ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
<ns0:ComponentGroupRef Id="Shortcuts"/>
<ns0:ComponentGroupRef Id="Files"/>
<ns0:ComponentGroupRef Id="FileAssociations"/>
<!-- Ref to additional ProgIDs -->
<ComponentRef Id="nonStartingProgID" />
</Feature>
<ns0:ComponentRef Id="nonStartingProgID" />
</ns0:Feature>
<CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<CustomAction Id="JpSetARPCOMMENTS" Property="ARPCOMMENTS" Value="$(var.JpAppDescription)" />
<CustomAction Id="JpSetARPCONTACT" Property="ARPCONTACT" Value="$(var.JpAppVendor)" />
<CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" />
<ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<ns0:CustomAction Id="JpSetARPCOMMENTS" Property="ARPCOMMENTS" Value="$(var.JpAppDescription)" />
<ns0:CustomAction Id="JpSetARPCONTACT" Property="ARPCONTACT" Value="$(var.JpAppVendor)" />
<ns0:CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" />
<?ifdef JpHelpURL ?>
<CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" />
<ns0:CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" />
<?endif?>
<?ifdef JpAboutURL ?>
<CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" />
<ns0:CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" />
<?endif?>
<?ifdef JpUpdateURL ?>
<CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
<ns0:CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
<?endif?>
<Property Id="WixQuietExec64CmdTimeout" Value="20" />
<ns0:Property Id="WixQuietExec64CmdTimeout" Value="20" />
<!-- Note for custom actions: Immediate CAs run BEFORE the files are installed, hence if you depend on installed files, the CAs must be deferred.-->
<!-- Property for controlling update check behavior (can be set via command line) -->
<ns0:Property Id="DISABLEUPDATECHECK" Secure="yes" />
<!-- WebDAV patches -->
<SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot;"
Sequence="execute" Before="PatchWebDAV" />
<CustomAction Id="PatchWebDAV" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
<ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot;" Sequence="execute" Before="PatchWebDAV" />
<ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- Update check configuration -->
<ns0:SetProperty Id="PatchUpdateCheck" Value="&quot;[INSTALLDIR]patchUpdateCheck.bat&quot; &quot;[DISABLEUPDATECHECK]&quot;" Sequence="execute" Before="PatchUpdateCheck" />
<ns0:CustomAction Id="PatchUpdateCheck" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- Running App detection and exit -->
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<ns0:Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<util:CloseApplication
Target="$(var.CloseApplicationTarget)"
Id="Close$(var.JpAppName)"
CloseMessage="no"
RebootPrompt="no"
PromptToContinue="yes"
Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue."
Property="FOUNDRUNNINGAPP"
>
</util:CloseApplication>
<CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
Target="$(var.CloseApplicationTarget)"
Id="Close$(var.JpAppName)"
CloseMessage="no"
RebootPrompt="no"
PromptToContinue="yes"
Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue."
Property="FOUNDRUNNINGAPP"
/>
<ns0:CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
<?ifdef JpIcon ?>
<Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
<Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
<ns0:Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
<ns0:Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
<?endif?>
<UIRef Id="JpUI"/>
<ns0:UIRef Id="JpUI"/>
<InstallExecuteSequence>
<Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize">Not Installed</Custom>
<Custom Action="JpSetARPCOMMENTS" After="CostFinalize">Not Installed</Custom>
<Custom Action="JpSetARPCONTACT" After="CostFinalize">Not Installed</Custom>
<Custom Action="JpSetARPSIZE" After="CostFinalize">Not Installed</Custom>
<ns0:InstallExecuteSequence>
<ns0:Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize" Condition="Not Installed" />
<ns0:Custom Action="JpSetARPCOMMENTS" After="CostFinalize" Condition="Not Installed" />
<ns0:Custom Action="JpSetARPCONTACT" After="CostFinalize" Condition="Not Installed" />
<ns0:Custom Action="JpSetARPSIZE" After="CostFinalize" Condition="Not Installed" />
<?ifdef JpHelpURL ?>
<Custom Action="JpSetARPHELPLINK" After="CostFinalize">Not Installed</Custom>
<ns0:Custom Action="JpSetARPHELPLINK" After="CostFinalize" Condition="Not Installed" />
<?endif?>
<?ifdef JpAboutURL ?>
<Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize">Not Installed</Custom>
<ns0:Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize" Condition="Not Installed" />
<?endif?>
<?ifdef JpUpdateURL ?>
<Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize">Not Installed</Custom>
<ns0:Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize" Condition="Not Installed" />
<?endif?>
<?ifndef JpAllowUpgrades ?>
<Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts">JP_UPGRADABLE_FOUND</Custom>
<ns0:Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts" Condition="JP_UPGRADABLE_FOUND"/>
<?endif?>
<?ifndef JpAllowDowngrades ?>
<Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts">JP_DOWNGRADABLE_FOUND</Custom>
<ns0:Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts" Condition="JP_DOWNGRADABLE_FOUND" />
<?endif?>
<Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
<!-- Check and fail if Cryptomator is running -->
<Custom Action="WixCloseApplications" Before="InstallValidate"></Custom>
<Custom Action="FailOnRunningApp" After="WixCloseApplications" >FOUNDRUNNINGAPP</Custom>
<ns0:Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="InstallValidate" />
<ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" />
<RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications -->
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
<!-- Skip action on uninstall -->
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
<ns0:Custom Action="PatchWebDAV" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
<!-- Configure update check setting if property is provided -->
<ns0:Custom Action="PatchUpdateCheck" After="PatchWebDAV" Condition="DISABLEUPDATECHECK AND NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
</ns0:InstallExecuteSequence>
<Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
</InstallExecuteSequence>
<ns0:InstallUISequence>
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
</ns0:InstallUISequence>
<InstallUISequence>
<Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
</InstallUISequence>
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
</Product>
</Wix>
<ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
<ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
</ns0:Package>
</ns0:Wix>

View File

@@ -41,10 +41,10 @@ Media Type of the encrypted data files. Default is "application/vnd.cryptomator.
Close Application settings:
- CloseApplicationTarget
Full name of executable to be checkd in the close application util. Default is "cryptomator.exe"
Full name of executable to be checked in the close application util. Default is "cryptomator.exe"
Legacy Installation settings:
- SkipCryptomatorLegacyCheck
Should be defined to disable checking for the inno setup installation of Cryptomator and undefined, to enable it.
-->
<Include/>
<ns0:Include xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs"></ns0:Include>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR"></Property>
<WixVariable Id="WixUILicenseRtf" Value="$(var.JpLicenseRtf)"></WixVariable>
<UI Id="JpUI">
<UIRef Id="CustomWizard" />
<DialogRef Id="InstallDirNotEmptyDlg"></DialogRef>
<Publish Dialog="ShortcutPromptDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg">1</Publish>
<Publish Dialog="ShortcutPromptDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ShortcutPromptDlg" Order="6">NOT Installed</Publish>
<UIRef Id="CustomWizard" />
</UI>
</Fragment>
<?include $(env.JP_WIXWIZARD_RESOURCES)\customWizard.wxi ?>
</Wix>

59
pom.xml
View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId>
<version>1.16.2</version>
<version>1.18.0</version>
<name>Cryptomator Desktop App</name>
<organization>
@@ -26,7 +26,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>23</project.jdk.version>
<project.jdk.version>24</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) -->
@@ -34,58 +34,47 @@
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.9.0</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.5.1</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.3.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.3.2</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.5.3</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.0.5</cryptomator.fuse.version>
<cryptomator.webdav.version>2.0.10</cryptomator.webdav.version>
<cryptomator.integrations.version>1.7.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.5.1</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.4.1</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.6.1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.1.0</cryptomator.fuse.version>
<cryptomator.webdav.version>3.0.0</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<commons-lang3.version>3.17.0</commons-lang3.version>
<dagger.version>2.56.1</dagger.version>
<commons-lang3.version>3.19.0</commons-lang3.version>
<dagger.version>2.57.2</dagger.version>
<easybind.version>2.2</easybind.version>
<jackson.version>2.18.3</jackson.version>
<javafx.version>23.0.2</javafx.version>
<jackson.version>2.20.0</jackson.version>
<javafx.version>25</javafx.version>
<jwt.version>4.5.0</jwt.version>
<nimbus-jose.version>9.37.3</nimbus-jose.version>
<logback.version>1.5.18</logback.version>
<nimbus-jose.version>10.5</nimbus-jose.version>
<logback.version>1.5.19</logback.version>
<slf4j.version>2.0.17</slf4j.version>
<tinyoauth2.version>0.8.1</tinyoauth2.version>
<zxcvbn.version>1.9.0</zxcvbn.version>
<!-- test dependencies -->
<junit.jupiter.version>5.12.2</junit.jupiter.version>
<mockito.version>5.17.0</mockito.version>
<junit.jupiter.version>5.13.4</junit.jupiter.version>
<mockito.version>5.20.0</mockito.version>
<hamcrest.version>3.0</hamcrest.version>
<!-- build-time dependencies -->
<jetbrains.annotations.version>26.0.2</jetbrains.annotations.version>
<dependency-check.version>12.1.1</dependency-check.version>
<jetbrains.annotations.version>26.0.2-1</jetbrains.annotations.version>
<dependency-check.version>12.1.5</dependency-check.version>
<jacoco.version>0.8.13</jacoco.version>
<license-generator.version>2.5.0</license-generator.version>
<license-generator.version>2.7.0</license-generator.version>
<junit-tree-reporter.version>1.4.0</junit-tree-reporter.version>
<mvn-compiler.version>3.14.0</mvn-compiler.version>
<mvn-compiler.version>3.14.1</mvn-compiler.version>
<mvn-resources.version>3.3.1</mvn-resources.version>
<mvn-dependency.version>3.8.1</mvn-dependency.version>
<mvn-surefire.version>3.5.3</mvn-surefire.version>
<mvn-surefire.version>3.5.4</mvn-surefire.version>
<mvn-jar.version>3.4.2</mvn-jar.version>
<!-- Property used by surefire to determine jacoco engine -->
<surefire.jacoco.args></surefire.jacoco.args>
</properties>
<!-- TODO: Remove once webdav version 2.0.11 is released -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter-servlet</artifactId>
<version>1.2.9</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Cryptomator Libs -->
<dependency>
@@ -225,7 +214,7 @@
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.2.0</version>
<version>3.2.2</version>
</dependency>
<!-- JUnit / Mockito / Hamcrest -->
<dependency>
@@ -255,7 +244,7 @@
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<version>1.3.0</version>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
@@ -358,7 +347,7 @@
<consoleOutputReporter>
<disable>true</disable>
</consoleOutputReporter>
<argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar}</argLine>
<argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar} --enable-native-access=javafx.graphics</argLine>
<statelessTestsetInfoReporter
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
</statelessTestsetInfoReporter>

View File

@@ -23,6 +23,7 @@ public class Environment {
private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
private static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath";
private static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths";
private static final String WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.windowsHelloKeychainPaths";
private static final String P12_PATH_PROP_NAME = "cryptomator.p12Path";
private static final String LOG_DIR_PROP_NAME = "cryptomator.logDir";
private static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias";
@@ -45,6 +46,7 @@ public class Environment {
logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
logCryptomatorSystemProperty(WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME);
logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
logCryptomatorSystemProperty(LOG_DIR_PROP_NAME);
logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME);
@@ -85,6 +87,10 @@ public class Environment {
return getPaths(KEYCHAIN_PATHS_PROP_NAME);
}
public Stream<Path> getWindowsHelloKeychainPath() {
return getPaths(WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME);
}
public Stream<Path> getP12Path() {
return getPaths(P12_PATH_PROP_NAME);
}

View File

@@ -42,25 +42,11 @@ public class KeychainManager implements KeychainAccessProvider {
return result;
}
@Override
public String displayName() {
return getClass().getName();
}
@Override
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
storePassphrase(key, displayName, passphrase, true);
}
//TODO: remove ignored parameter once the API is fixed
@Override
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean ignored) throws KeychainAccessException {
try {
lock.writeLock().lock();
var kc = getKeychainOrFail();
//this is the only keychain actually using the parameter
var usesOSAuth = (kc.getClass().getName().equals("org.cryptomator.macos.keychain.TouchIdKeychainAccess"));
kc.storePassphrase(key, displayName, passphrase, usesOSAuth);
getKeychainOrFail().storePassphrase(key, displayName, passphrase);
} finally {
lock.writeLock().unlock();
}

View File

@@ -0,0 +1,53 @@
package org.cryptomator.common.recovery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileTime;
import java.util.stream.Stream;
import static org.cryptomator.common.Constants.MASTERKEY_BACKUP_SUFFIX;
public final class BackupRestorer {
private static final Logger LOG = LoggerFactory.getLogger(BackupRestorer.class);
private BackupRestorer() {}
public static void restoreIfBackupPresent(Path vaultPath, String filePrefix) {
Path targetFile = vaultPath.resolve(filePrefix);
try (Stream<Path> files = Files.list(vaultPath)) {
files.filter(file -> isFileMatchingPattern(file.getFileName().toString(), filePrefix))
.max((f1, f2) -> {
try {
FileTime time1 = Files.getLastModifiedTime(f1);
FileTime time2 = Files.getLastModifiedTime(f2);
return time1.compareTo(time2);
} catch (IOException e) {
return 0;
}
})
.ifPresent(backupFile -> copyBackupFile(backupFile, targetFile));
} catch (IOException e) {
LOG.info("Unable to restore backup files in '{}'", vaultPath, e);
}
}
private static boolean isFileMatchingPattern(String fileName, String filePrefix) {
return fileName.startsWith(filePrefix) && fileName.endsWith(MASTERKEY_BACKUP_SUFFIX);
}
private static void copyBackupFile(Path backupFile, Path configPath) {
try {
Files.copy(backupFile, configPath, StandardCopyOption.REPLACE_EXISTING);
LOG.debug("Backup restored - file: '{}' path: '{}'", backupFile, configPath);
} catch (IOException e) {
LOG.warn("Unable to copy backup file from '{}' to '{}'", backupFile, configPath, e);
}
}
}

View File

@@ -0,0 +1,33 @@
package org.cryptomator.common.recovery;
import java.io.IOException;
import java.nio.file.Path;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.api.CryptorProvider;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.MasterkeyLoader;
import static org.cryptomator.common.Constants.DEFAULT_KEY_ID;
public final class CryptoFsInitializer {
private CryptoFsInitializer() {}
public static void init(Path recoveryPath,
Masterkey masterkey,
int shorteningThreshold,
CryptorProvider.Scheme scheme) throws IOException, CryptoException {
MasterkeyLoader loader = ignored -> masterkey.copy();
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties //
.cryptoFileSystemProperties() //
.withCipherCombo(scheme) //
.withKeyLoader(loader) //
.withShorteningThreshold(shorteningThreshold) //
.build();
CryptoFileSystemProvider.initialize(recoveryPath, fsProps, DEFAULT_KEY_ID);
}
}

View File

@@ -0,0 +1,101 @@
package org.cryptomator.common.recovery;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.api.CryptorProvider;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.cryptomator.ui.recoverykey.RecoveryKeyFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Stream;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.cryptofs.common.Constants.DATA_DIR_NAME;
public final class MasterkeyService {
private static final Logger LOG = LoggerFactory.getLogger(MasterkeyService.class);
private MasterkeyService() {}
public static void recoverFromRecoveryKey(String recoveryKey, RecoveryKeyFactory recoveryKeyFactory, Path recoveryPath, CharSequence newPassword) throws IOException {
recoveryKeyFactory.newMasterkeyFileWithPassphrase(recoveryPath, recoveryKey, newPassword);
}
public static Masterkey load(MasterkeyFileAccess masterkeyFileAccess, Path masterkeyFilePath, CharSequence password) throws IOException {
return masterkeyFileAccess.load(masterkeyFilePath, password);
}
public static CryptorProvider.Scheme validateRecoveryKeyAndDetectCombo(RecoveryKeyFactory recoveryKeyFactory, //
Vault vault, String recoveryKey, //
MasterkeyFileAccess masterkeyFileAccess) throws IOException, CryptoException, NoSuchElementException {
String tmpPass = UUID.randomUUID().toString();
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
Path tempRecoveryPath = recoveryDirectory.getRecoveryPath();
recoverFromRecoveryKey(recoveryKey, recoveryKeyFactory, tempRecoveryPath, tmpPass);
Path masterkeyFilePath = tempRecoveryPath.resolve(MASTERKEY_FILENAME);
try (Masterkey mk = load(masterkeyFileAccess, masterkeyFilePath, tmpPass)) {
return detect(mk, vault.getPath()).orElseThrow();
}
}
}
public static Optional<CryptorProvider.Scheme> detect(Masterkey masterkey, Path vaultPath) {
try (Stream<Path> paths = Files.walk(vaultPath.resolve(DATA_DIR_NAME))) {
Optional<Path> c9rFile = paths //
.filter(p -> p.toString().endsWith(".c9r")) //
.filter(p -> !p.endsWith("dir.c9r")) //
.findFirst();
if (c9rFile.isEmpty()) {
LOG.info("Unable to detect Crypto scheme: No *.c9r file found in {}", vaultPath);
return Optional.empty();
}
return determineScheme(c9rFile.get(), masterkey);
} catch (IOException e) {
LOG.info("Unable to detect Crypto scheme: Failed to inspect vault", e);
return Optional.empty();
}
}
private static Optional<CryptorProvider.Scheme> determineScheme(Path c9rFile, Masterkey masterkey) {
return Arrays.stream(CryptorProvider.Scheme.values()).filter(scheme -> {
try (Cryptor cryptor = CryptorProvider.forScheme(scheme).provide(masterkey.copy(), SecureRandom.getInstanceStrong())) {
int headerSize = cryptor.fileHeaderCryptor().headerSize();
ByteBuffer headerBuf = ByteBuffer.allocate(headerSize);
try (FileChannel channel = FileChannel.open(c9rFile, StandardOpenOption.READ)) {
channel.read(headerBuf, 0);
}
headerBuf.flip();
cryptor.fileHeaderCryptor().decryptHeader(headerBuf.duplicate());
LOG.debug("Detected Crypto scheme: {}", scheme);
return true;
} catch (IllegalArgumentException | CryptoException e) {
LOG.debug("Could not decrypt with scheme: {}", scheme);
return false;
} catch (IOException | NoSuchAlgorithmException e) {
LOG.warn("Unable to detect Crypto scheme: Failed to decrypt .c9r file", e);
return false;
}
}).findFirst();
}
}

View File

@@ -0,0 +1,10 @@
package org.cryptomator.common.recovery;
public enum RecoveryActionType {
RESTORE_ALL,
RESTORE_MASTERKEY,
RESTORE_VAULT_CONFIG,
RESET_PASSWORD,
SHOW_KEY,
CONVERT_VAULT
}

View File

@@ -0,0 +1,56 @@
package org.cryptomator.common.recovery;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Comparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class RecoveryDirectory implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(RecoveryDirectory.class);
private final Path recoveryPath;
private final Path vaultPath;
private RecoveryDirectory(Path vaultPath, Path recoveryPath) {
this.vaultPath = vaultPath;
this.recoveryPath = recoveryPath;
}
public static RecoveryDirectory create(Path vaultPath) throws IOException {
Path tempDir = Files.createTempDirectory("cryptomator");
return new RecoveryDirectory(vaultPath, tempDir);
}
public void moveRecoveredFile(String file) throws IOException {
Files.move(recoveryPath.resolve(file), vaultPath.resolve(file), StandardCopyOption.REPLACE_EXISTING);
}
private void deleteRecoveryDirectory() {
try (var paths = Files.walk(recoveryPath)) {
paths.sorted(Comparator.reverseOrder()).forEach(p -> {
try {
Files.delete(p);
} catch (IOException e) {
LOG.info("Unable to delete {}. Please delete it manually.", p);
}
});
} catch (IOException e) {
LOG.error("Failed to clean up recovery directory", e);
}
}
@Override
public void close() {
deleteRecoveryDirectory();
}
public Path getRecoveryPath() {
return recoveryPath;
}
}

View File

@@ -0,0 +1,54 @@
package org.cryptomator.common.recovery;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultComponent;
import org.cryptomator.common.vaults.VaultConfigCache;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.integrations.mount.MountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.ResourceBundle;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
public final class VaultPreparator {
private static final Logger LOG = LoggerFactory.getLogger(VaultPreparator.class);
private VaultPreparator() {}
public static Vault prepareVault(Path selectedDirectory, //
VaultComponent.Factory vaultComponentFactory, //
List<MountService> mountServices, //
ResourceBundle resourceBundle) {
VaultSettings vaultSettings = VaultSettings.withRandomId();
vaultSettings.path.set(selectedDirectory);
if (selectedDirectory.getFileName() != null) {
vaultSettings.displayName.set(selectedDirectory.getFileName().toString());
} else {
vaultSettings.displayName.set(resourceBundle.getString("defaults.vault.vaultName"));
}
var wrapper = new VaultConfigCache(vaultSettings);
Vault vault = vaultComponentFactory.create(vaultSettings, wrapper, LOCKED, null).vault();
try {
VaultListManager.determineVaultState(vault.getPath());
} catch (IOException e) {
LOG.warn("Failed to determine vault state for {}", vaultSettings.path.get(), e);
}
//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 vault;
}
}

View File

@@ -25,6 +25,8 @@ import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.NodeOrientation;
import java.nio.file.Path;
import java.time.Instant;
import java.util.function.Consumer;
@@ -44,7 +46,7 @@ public class Settings {
@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";
"org.cryptomator.linux.keychain.GnomeKeyringKeychainAccess";
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;
@@ -75,6 +77,7 @@ public class Settings {
public final BooleanProperty checkForUpdates;
public final ObjectProperty<Instant> lastUpdateCheckReminder;
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
public final ObjectProperty<Path> previouslyUsedVaultDirectory;
private Consumer<Settings> saveCmd;
@@ -114,6 +117,7 @@ public class Settings {
this.checkForUpdates = new SimpleBooleanProperty(this, "checkForUpdates", json.checkForUpdatesEnabled);
this.lastUpdateCheckReminder = new SimpleObjectProperty<>(this, "lastUpdateCheckReminder", json.lastReminderForUpdateCheck);
this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
this.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory);
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
@@ -143,10 +147,16 @@ public class Settings {
checkForUpdates.addListener(this::somethingChanged);
lastUpdateCheckReminder.addListener(this::somethingChanged);
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
previouslyUsedVaultDirectory.addListener(this::somethingChanged);
}
@SuppressWarnings("deprecation")
private void migrateLegacySettings(SettingsJson json) {
// migrate renamed keychainAccess
if(this.keychainProvider.getValueSafe().equals("org.cryptomator.linux.keychain.SecretServiceKeychainAccess")) {
this.keychainProvider.setValue("org.cryptomator.linux.keychain.GnomeKeyringKeychainAccess");
}
// implicit migration of 1.6.x legacy setting "preferredVolumeImpl":
if (this.mountService.get() == null && json.preferredVolumeImpl != null) {
this.mountService.set(switch (json.preferredVolumeImpl) {
@@ -199,6 +209,7 @@ public class Settings {
json.checkForUpdatesEnabled = checkForUpdates.get();
json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get();
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
return json;
}

View File

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.nio.file.Path;
import java.time.Instant;
import java.util.List;
@@ -92,4 +93,7 @@ class SettingsJson {
@JsonProperty("quickAccessService")
String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE;
@JsonProperty("previouslyUsedVaultDirectory")
Path previouslyUsedVaultDirectory;
}

View File

@@ -23,7 +23,6 @@ import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.MasterkeyLoader;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.cryptomator.event.VaultEvent;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException;
@@ -35,7 +34,6 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
@@ -75,6 +73,7 @@ public class Vault {
private final BooleanBinding missing;
private final BooleanBinding needsMigration;
private final BooleanBinding unknownError;
private final BooleanBinding missingVaultConfig;
private final ObjectBinding<Mountpoint> mountPoint;
private final Mounter mounter;
private final Settings settings;
@@ -103,6 +102,7 @@ public class Vault {
this.processing = Bindings.createBooleanBinding(this::isProcessing, state);
this.unlocked = Bindings.createBooleanBinding(this::isUnlocked, state);
this.missing = Bindings.createBooleanBinding(this::isMissing, state);
this.missingVaultConfig = Bindings.createBooleanBinding(this::isMissingVaultConfig, state);
this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
@@ -336,6 +336,14 @@ public class Vault {
return state.get() == VaultState.Value.ERROR;
}
public BooleanBinding missingVaultConfigProperty() {
return missingVaultConfig;
}
public boolean isMissingVaultConfig() {
return state.get() == VaultState.Value.VAULT_CONFIG_MISSING || state.get() == VaultState.Value.ALL_MISSING;
}
public ReadOnlyStringProperty displayNameProperty() {
return vaultSettings.displayName;
}

View File

@@ -20,7 +20,7 @@ public class VaultConfigCache {
private final VaultSettings settings;
private final AtomicReference<VaultConfig.UnverifiedVaultConfig> config;
VaultConfigCache(VaultSettings settings) {
public VaultConfigCache(VaultSettings settings) {
this.settings = settings;
this.config = new AtomicReference<>(null);
}

View File

@@ -9,12 +9,14 @@
package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.recovery.BackupRestorer;
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.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,8 +35,7 @@ import java.util.ResourceBundle;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.*;
@Singleton
public class VaultListManager {
@@ -65,6 +66,12 @@ public class VaultListManager {
autoLocker.init();
}
public boolean isAlreadyAdded(Path vaultPath) {
assert vaultPath.isAbsolute();
assert vaultPath.normalize().equals(vaultPath);
return vaultList.stream().anyMatch(v -> vaultPath.equals(v.getPath()));
}
public Vault add(Path pathToVault) throws IOException {
Path normalizedPathToVault = pathToVault.normalize().toAbsolutePath();
if (CryptoFileSystemProvider.checkDirStructureForVault(normalizedPathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) == DirStructure.UNRELATED) {
@@ -104,7 +111,7 @@ public class VaultListManager {
vaultList.addAll(vaults);
}
private Optional<Vault> get(Path vaultPath) {
public Optional<Vault> get(Path vaultPath) {
assert vaultPath.isAbsolute();
assert vaultPath.normalize().equals(vaultPath);
return vaultList.stream() //
@@ -112,57 +119,122 @@ public class VaultListManager {
.findAny();
}
public void addVault(Vault vault) {
Path path = vault.getPath().normalize().toAbsolutePath();
if (!isAlreadyAdded(path)) {
vaultList.add(vault);
}
}
private Vault create(VaultSettings vaultSettings) {
var wrapper = new VaultConfigCache(vaultSettings);
try {
if (Objects.isNull(vaultSettings.lastKnownKeyLoader.get())) {
var keyIdScheme = wrapper.get().getKeyId().getScheme();
vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
}
var vaultState = determineVaultState(vaultSettings.path.get());
if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
wrapper.reloadConfig();
}
initializeLastKnownKeyLoaderIfPossible(vaultSettings, vaultState, wrapper);
return vaultComponentFactory.create(vaultSettings, wrapper, vaultState, null).vault();
} catch (IOException e) {
LOG.warn("Failed to determine vault state for " + vaultSettings.path.get(), e);
LOG.warn("Failed to determine vault state for {}", vaultSettings.path.get(), e);
return vaultComponentFactory.create(vaultSettings, wrapper, ERROR, e).vault();
}
}
private void initializeLastKnownKeyLoaderIfPossible(VaultSettings vaultSettings, VaultState.Value vaultState, VaultConfigCache wrapper) throws IOException {
if (vaultSettings.lastKnownKeyLoader.get() != null) {
return;
}
switch (vaultState) {
case LOCKED -> {
wrapper.reloadConfig();
vaultSettings.lastKnownKeyLoader.set(wrapper.get().getKeyId().getScheme());
}
case NEEDS_MIGRATION -> {
//for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
vaultSettings.lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME);
}
case VAULT_CONFIG_MISSING -> {
//Nothing to do here, since there is no config to read
}
case MISSING, ALL_MISSING, ERROR, PROCESSING -> {
// no config available or not safe to load
}
default -> {
if (Files.exists(vaultSettings.path.get().resolve(VAULTCONFIG_FILENAME))) {
try {
wrapper.reloadConfig();
vaultSettings.lastKnownKeyLoader.set(wrapper.get().getKeyId().getScheme());
} catch (IOException e) {
LOG.debug("Unable to load config for {}", vaultSettings.path.get(), e);
}
}
}
}
}
public static VaultState.Value redetermineVaultState(Vault vault) {
VaultState state = vault.stateProperty();
VaultState.Value previousState = state.getValue();
return switch (previousState) {
case LOCKED, NEEDS_MIGRATION, MISSING -> {
try {
var determinedState = determineVaultState(vault.getPath());
if (determinedState == LOCKED) {
vault.getVaultConfigCache().reloadConfig();
}
state.set(determinedState);
yield determinedState;
} catch (IOException e) {
LOG.warn("Failed to determine vault state for " + vault.getPath(), e);
state.set(ERROR);
vault.setLastKnownException(e);
yield ERROR;
}
VaultState.Value previous = state.getValue();
if (previous.equals(UNLOCKED) || previous.equals(PROCESSING)) {
return previous;
}
try {
VaultState.Value determined = determineVaultState(vault.getPath());
if (determined == LOCKED) {
vault.getVaultConfigCache().reloadConfig();
}
case ERROR, UNLOCKED, PROCESSING -> previousState;
};
state.set(determined);
return determined;
} catch (IOException e) {
LOG.warn("Failed to (re)determine vault state for {}", vault.getPath(), e);
vault.setLastKnownException(e);
state.set(ERROR);
return ERROR;
}
}
private static VaultState.Value determineVaultState(Path pathToVault) throws IOException {
public static VaultState.Value determineVaultState(Path pathToVault) throws IOException {
if (!Files.exists(pathToVault)) {
return VaultState.Value.MISSING;
return MISSING;
}
VaultState.Value structureResult = checkDirStructure(pathToVault);
if (structureResult == LOCKED || structureResult == NEEDS_MIGRATION) {
return structureResult;
}
Path pathToVaultConfig = pathToVault.resolve(VAULTCONFIG_FILENAME);
Path pathToMasterkey = pathToVault.resolve(MASTERKEY_FILENAME);
if (!Files.exists(pathToVaultConfig)) {
BackupRestorer.restoreIfBackupPresent(pathToVault, VAULTCONFIG_FILENAME);
}
if (!Files.exists(pathToMasterkey)) {
BackupRestorer.restoreIfBackupPresent(pathToVault, MASTERKEY_FILENAME);
}
boolean hasConfig = Files.exists(pathToVaultConfig);
if (!hasConfig && !Files.exists(pathToMasterkey)) {
return ALL_MISSING;
}
if (!hasConfig) {
return VAULT_CONFIG_MISSING;
}
return checkDirStructure(pathToVault);
}
private static VaultState.Value checkDirStructure(Path pathToVault) throws IOException {
return switch (CryptoFileSystemProvider.checkDirStructureForVault(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME)) {
case VAULT -> VaultState.Value.LOCKED;
case UNRELATED -> VaultState.Value.MISSING;
case MAYBE_LEGACY -> Migrators.get().needsMigration(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) ? //
VaultState.Value.NEEDS_MIGRATION //
: VaultState.Value.MISSING;
case VAULT -> LOCKED;
case UNRELATED -> MISSING;
case MAYBE_LEGACY -> Migrators.get().needsMigration(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) ? NEEDS_MIGRATION : MISSING;
};
}

View File

@@ -25,6 +25,16 @@ public class VaultState extends ObservableValueBase<VaultState.Value> implements
*/
MISSING,
/**
* No vault config found at the provided path
*/
VAULT_CONFIG_MISSING,
/**
* No vault config and masterkey found at the provided path
*/
ALL_MISSING,
/**
* Vault requires migration to a newer vault format
*/

View File

@@ -53,18 +53,26 @@ class Server implements IpcCommunicator {
@Override
public void listen(IpcMessageListener listener, Executor executor) {
executor.execute(() -> {
int errorCount = 0;
while (serverSocketChannel.isOpen()) {
try (var ch = serverSocketChannel.accept()) {
while (ch.isConnected()) {
var msg = IpcMessage.receive(ch);
listener.handleMessage(msg);
}
errorCount = 0;
} catch (AsynchronousCloseException e) {
LOG.info("Closing server socket due to closed channel.");
return; // serverSocketChannel closed or listener interrupted
} catch (EOFException | ClosedChannelException e) {
// continue with next connected client
} catch (IOException e) {
errorCount++;
LOG.error("Failed to read IPC message", e);
if(errorCount > 100) { //apparently something is broken, prevent log spam
LOG.info("Closing server socket due to too many failed requests.");
return;
}
}
}
});

View File

@@ -90,6 +90,9 @@ public class LogbackConfigurator extends ContextAwareBase implements Configurato
// configure fuse file locking logger:
Logger fuseLocking = context.getLogger("org.cryptomator.frontend.fuse.locks");
fuseLocking.setLevel(Level.OFF);
//deactivate kwallet unsettling message
Logger kdeWallet = context.getLogger("org.purejava.kwallet.freedesktop.dbus.handlers");
kdeWallet.setLevel(Level.OFF);
}
return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
}

View File

@@ -26,7 +26,7 @@ public class CreateNewVaultExpertSettingsController implements FxController {
public static final int MAX_SHORTENING_THRESHOLD = 220;
public static final int MIN_SHORTENING_THRESHOLD = 36;
private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/architecture/#name-shortening";
private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/vault/#name-shortening";
private final Stage window;
private final Lazy<Application> application;

View File

@@ -4,6 +4,7 @@ import dagger.Lazy;
import org.cryptomator.common.ObservableUtil;
import org.cryptomator.common.locationpresets.LocationPreset;
import org.cryptomator.common.locationpresets.LocationPresetsProvider;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -38,6 +39,7 @@ import javafx.stage.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
@@ -64,6 +66,7 @@ public class CreateNewVaultLocationController implements FxController {
private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false);
private final ObservableList<Node> radioButtons;
private final ObservableList<Node> sortedRadioButtons;
private final Settings settings;
private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
@@ -82,6 +85,7 @@ public class CreateNewVaultLocationController implements FxController {
@FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, //
ObjectProperty<Path> vaultPath, //
@Named("vaultName") StringProperty vaultName, //
Settings settings, //
ExecutorService backgroundExecutor, ResourceBundle resourceBundle) {
this.window = window;
this.chooseNameScene = chooseNameScene;
@@ -96,6 +100,18 @@ public class CreateNewVaultLocationController implements FxController {
this.usePresetPath = new SimpleBooleanProperty();
this.radioButtons = FXCollections.observableArrayList();
this.sortedRadioButtons = radioButtons.sorted(this::compareLocationPresets);
this.settings = settings;
Path previouslyUsedDirectory = settings.previouslyUsedVaultDirectory.get();
if (previouslyUsedDirectory != null) {
try {
if (Files.exists(previouslyUsedDirectory) && Files.isDirectory(previouslyUsedDirectory) && isActuallyWritable(previouslyUsedDirectory)) {
this.customVaultPath = previouslyUsedDirectory;
}
} catch (InvalidPathException | NullPointerException e) {
LOG.warn("Invalid previously used vault directory path: {}", previouslyUsedDirectory, e);
}
}
}
private VaultPathStatus validatePath(Path p) throws NullPointerException {
@@ -196,6 +212,12 @@ public class CreateNewVaultLocationController implements FxController {
@FXML
public void next() {
if (validVaultPath.getValue()) {
if (this.getVaultPath() != null) {
Path parentPath = this.getVaultPath().getParent();
if (parentPath != null) {
this.settings.previouslyUsedVaultDirectory.setValue(parentPath);
}
}
window.setScene(chooseExpertSettingsScene.get());
}
}

View File

@@ -79,7 +79,7 @@ public class ReadmeGenerator {
} else if (c <= 0xFF) {
sb.append("\\'").append(String.format("%02X", c));
} else if (c < 0xFFFF) {
sb.append("\\uc1\\u").append(c);
sb.append("\\u").append(c);
}
});
}

View File

@@ -20,7 +20,6 @@ import java.util.ResourceBundle;
public class PasswordStrengthUtil {
private static final int PW_TRUNC_LEN = 100; // truncate very long passwords, since zxcvbn memory and runtime depends vastly on the length
private static final String RESSOURCE_PREFIX = "passwordStrength.messageLabel.";
private static final List<String> SANITIZED_INPUTS = List.of("cryptomator");
private final ResourceBundle resourceBundle;
@@ -48,13 +47,15 @@ public class PasswordStrengthUtil {
}
public String getStrengthDescription(Number score) {
if (score.intValue() == -1) {
return String.format(resourceBundle.getString(RESSOURCE_PREFIX + "tooShort"), minPwLength);
} else if (resourceBundle.containsKey(RESSOURCE_PREFIX + score.intValue())) {
return resourceBundle.getString(RESSOURCE_PREFIX + score.intValue());
} else {
return "";
}
return switch (score.intValue()) {
case -1 -> String.format(resourceBundle.getString("passwordStrength.messageLabel.tooShort"), minPwLength);
case 0 -> resourceBundle.getString("passwordStrength.messageLabel.0");
case 1 -> resourceBundle.getString("passwordStrength.messageLabel.1");
case 2 -> resourceBundle.getString("passwordStrength.messageLabel.2");
case 3 -> resourceBundle.getString("passwordStrength.messageLabel.3");
case 4 -> resourceBundle.getString("passwordStrength.messageLabel.4");
default -> "";
};
}
}

View File

@@ -42,9 +42,10 @@ public enum FxmlFile {
QUIT("/fxml/quit.fxml"), //
QUIT_FORCED("/fxml/quit_forced.fxml"), //
RECOVERYKEY_CREATE("/fxml/recoverykey_create.fxml"), //
RECOVERYKEY_EXPERT_SETTINGS("/fxml/recoverykey_expert_settings.fxml"), //
RECOVERYKEY_ONBOARDING("/fxml/recoverykey_onboarding.fxml"), //
RECOVERYKEY_RECOVER("/fxml/recoverykey_recover.fxml"), //
RECOVERYKEY_RESET_PASSWORD("/fxml/recoverykey_reset_password.fxml"), //
RECOVERYKEY_RESET_PASSWORD_SUCCESS("/fxml/recoverykey_reset_password_success.fxml"), //
RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), //
SHARE_VAULT("/fxml/share_vault.fxml"), //
SIMPLE_DIALOG("/fxml/simple_dialog.fxml"), //

View File

@@ -4,8 +4,10 @@ import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.recovery.RecoveryActionType;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.VaultConfig;
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.cryptomator.ui.changepassword.NewPasswordController;
import org.cryptomator.ui.changepassword.PasswordStrengthUtil;
import org.cryptomator.ui.common.DefaultSceneFactory;
@@ -20,6 +22,7 @@ import org.cryptomator.ui.recoverykey.RecoveryKeyValidateController;
import javax.inject.Named;
import javax.inject.Provider;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
@@ -119,8 +122,8 @@ abstract class ConvertVaultModule {
@Provides
@IntoMap
@FxControllerKey(RecoveryKeyValidateController.class)
static FxController bindRecoveryKeyValidateController(@ConvertVaultWindow Vault vault, @ConvertVaultWindow VaultConfig.UnverifiedVaultConfig vaultConfig, @ConvertVaultWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) {
return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory);
static FxController provideRecoveryKeyValidateController(@ConvertVaultWindow Vault vault, @ConvertVaultWindow VaultConfig.UnverifiedVaultConfig vaultConfig, @ConvertVaultWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory, MasterkeyFileAccess masterkeyFileAccess) {
return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, masterkeyFileAccess, new SimpleObjectProperty<>(RecoveryActionType.CONVERT_VAULT), new SimpleObjectProperty<>(null));
}
}

View File

@@ -2,6 +2,7 @@ package org.cryptomator.ui.dialogs;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.StageFactory;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.cryptomator.ui.fxapp.FxApplicationScoped;
@@ -19,17 +20,21 @@ public class Dialogs {
private final ResourceBundle resourceBundle;
private final StageFactory stageFactory;
private final DefaultSceneFactory sceneFactory;
private static final String BUTTON_KEY_CLOSE = "generic.button.close";
@Inject
public Dialogs(ResourceBundle resourceBundle, StageFactory stageFactory) {
public Dialogs(ResourceBundle resourceBundle, StageFactory stageFactory, DefaultSceneFactory sceneFactory) {
this.resourceBundle = resourceBundle;
this.stageFactory = stageFactory;
this.sceneFactory = sceneFactory;
}
private static final Logger LOG = LoggerFactory.getLogger(Dialogs.class);
private SimpleDialog.Builder createDialogBuilder() {
return new SimpleDialog.Builder(resourceBundle, stageFactory);
return new SimpleDialog.Builder(resourceBundle, stageFactory, sceneFactory);
}
public SimpleDialog.Builder prepareRemoveVaultDialog(Stage window, Vault vault, ObservableList<Vault> vaults) {
@@ -47,6 +52,43 @@ public class Dialogs {
});
}
public SimpleDialog.Builder prepareContactHubVaultOwner(Stage window) {
return createDialogBuilder().setOwner(window) //
.setTitleKey("contactHubVaultOwner.title") //
.setMessageKey("contactHubVaultOwner.message") //
.setDescriptionKey("contactHubVaultOwner.description") //
.setIcon(FontAwesome5Icon.EXCLAMATION)//
.setOkButtonKey(BUTTON_KEY_CLOSE);
}
public SimpleDialog.Builder prepareRecoveryVaultAdded(Stage window, String displayName) {
return createDialogBuilder().setOwner(window) //
.setTitleKey("recover.existing.title") //
.setMessageKey("recover.existing.message") //
.setDescriptionKey("recover.existing.description", displayName) //
.setIcon(FontAwesome5Icon.CHECK)//
.setOkButtonKey(BUTTON_KEY_CLOSE);
}
public SimpleDialog.Builder prepareRecoveryVaultAlreadyExists(Stage window, String displayName) {
return createDialogBuilder().setOwner(window) //
.setTitleKey("recover.alreadyExists.title") //
.setMessageKey("recover.alreadyExists.message") //
.setDescriptionKey("recover.alreadyExists.description", displayName) //
.setIcon(FontAwesome5Icon.EXCLAMATION)//
.setOkButtonKey(BUTTON_KEY_CLOSE);
}
public SimpleDialog.Builder prepareRecoverPasswordSuccess(Stage window) {
return createDialogBuilder()
.setOwner(window) //
.setTitleKey("recoveryKey.recover.title") //
.setMessageKey("recoveryKey.recover.resetSuccess.message") //
.setDescriptionKey("recoveryKey.recover.resetSuccess.description") //
.setIcon(FontAwesome5Icon.CHECK)
.setOkAction(Stage::close)
.setOkButtonKey(BUTTON_KEY_CLOSE);
}
public SimpleDialog.Builder prepareRemoveCertDialog(Stage window, Settings settings) {
return createDialogBuilder() //
.setOwner(window) //
@@ -69,7 +111,7 @@ public class Dialogs {
.setMessageKey("dokanySupportEnd.message") //
.setDescriptionKey("dokanySupportEnd.description") //
.setIcon(FontAwesome5Icon.EXCLAMATION) //
.setOkButtonKey("generic.button.close") //
.setOkButtonKey(BUTTON_KEY_CLOSE) //
.setCancelButtonKey("dokanySupportEnd.preferencesBtn") //
.setOkAction(Stage::close) //
.setCancelAction(cancelAction);
@@ -83,8 +125,20 @@ public class Dialogs {
.setDescriptionKey("retryIfReadonly.description") //
.setIcon(FontAwesome5Icon.EXCLAMATION) //
.setOkButtonKey("retryIfReadonly.retry") //
.setCancelButtonKey("generic.button.close") //
.setCancelButtonKey(BUTTON_KEY_CLOSE) //
.setOkAction(okAction) //
.setCancelAction(Stage::close);
}
public SimpleDialog.Builder prepareNoDDirectorySelectedDialog(Stage window) {
return createDialogBuilder() //
.setOwner(window) //
.setTitleKey("recover.invalidSelection.title") //
.setMessageKey("recover.invalidSelection.message") //
.setDescriptionKey("recover.invalidSelection.description") //
.setIcon(FontAwesome5Icon.EXCLAMATION) //
.setOkButtonKey("generic.button.change") //
.setOkAction(Stage::close);
}
}

View File

@@ -1,5 +1,6 @@
package org.cryptomator.ui.dialogs;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.StageFactory;
@@ -30,15 +31,15 @@ public class SimpleDialog {
FxmlLoaderFactory loaderFactory = FxmlLoaderFactory.forController( //
new SimpleDialogController(resolveText(builder.messageKey, null), //
resolveText(builder.descriptionKey, null), //
resolveText(builder.descriptionKey, builder.descriptionArgs), //
builder.icon, //
resolveText(builder.okButtonKey, null), //
builder.cancelButtonKey != null ? resolveText(builder.cancelButtonKey, null) : null, //
() -> builder.okAction.accept(dialogStage), //
() -> builder.cancelAction.accept(dialogStage)), //
Scene::new, builder.resourceBundle);
builder.sceneFactory, builder.resourceBundle);
dialogStage.setScene(new Scene(loaderFactory.load(FxmlFile.SIMPLE_DIALOG.getRessourcePathString()).getRoot()));
dialogStage.setScene(loaderFactory.createScene(FxmlFile.SIMPLE_DIALOG));
}
public void showAndWait() {
@@ -62,19 +63,22 @@ public class SimpleDialog {
private Stage owner;
private final ResourceBundle resourceBundle;
private final StageFactory stageFactory;
private final DefaultSceneFactory sceneFactory;
private String titleKey;
private String[] titleArgs;
private String messageKey;
private String descriptionKey;
private String[] descriptionArgs;
private String okButtonKey;
private String cancelButtonKey;
private FontAwesome5Icon icon;
private Consumer<Stage> okAction = Stage::close;
private Consumer<Stage> cancelAction = Stage::close;
public Builder(ResourceBundle resourceBundle, StageFactory stageFactory) {
public Builder(ResourceBundle resourceBundle, StageFactory stageFactory, DefaultSceneFactory sceneFactory) {
this.resourceBundle = resourceBundle;
this.stageFactory = stageFactory;
this.sceneFactory = sceneFactory;
}
public Builder setOwner(Stage owner) {
@@ -93,8 +97,9 @@ public class SimpleDialog {
return this;
}
public Builder setDescriptionKey(String descriptionKey) {
public Builder setDescriptionKey(String descriptionKey, String... args) {
this.descriptionKey = descriptionKey;
this.descriptionArgs = args;
return this;
}

View File

@@ -20,8 +20,8 @@ public interface ErrorComponent {
default Stage show() {
Stage stage = window();
stage.setScene(scene());
stage.setMinWidth(420);
stage.setMinHeight(300);
stage.setMinWidth(450);
stage.setMinHeight(450);
stage.show();
return stage;
}

View File

@@ -133,9 +133,9 @@ public class EventListCellController implements FxController {
eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenFileNode.message"));
eventDescription.setValue(bfe.ciphertextPath().getFileName().toString());
if (revealService != null) {
addAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, convertVaultPathToSystemPath(bfe.ciphertextPath())));
addAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, bfe.ciphertextPath()));
} else {
addAction("eventView.entry.brokenFileNode.copyEncrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.ciphertextPath()).toString()));
addAction("eventView.entry.brokenFileNode.copyEncrypted", () -> copyToClipboard(bfe.ciphertextPath().toString()));
}
addAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString()));
}

View File

@@ -49,7 +49,7 @@ public class EventViewController implements FxController {
}
/**
* Comparison method for the lru cache. During comparsion the map is accessed.
* Comparison method for the lru cache. During comparison the map is accessed.
* First the entries are compared by the event timestamp, then vaultId, then identifying path and lastly by class name.
*
* @param left an entry of a {@link FSEventBucket} and its content

View File

@@ -12,6 +12,7 @@ import javax.inject.Named;
import javafx.application.Platform;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
@@ -58,29 +59,30 @@ class AppLaunchEventHandler {
switch (event.type()) {
case REVEAL_APP -> appWindows.showMainWindow();
case OPEN_FILE -> Platform.runLater(() -> {
event.pathsToOpen().forEach(this::addOrRevealVault);
event.pathsToOpen().forEach(this::openPotentialVault);
});
default -> LOG.warn("Unsupported event type: {}", event.type());
}
}
// TODO deduplicate MainWindowController...
private void addOrRevealVault(Path potentialVaultPath) {
private void openPotentialVault(Path path) {
assert Platform.isFxApplicationThread();
try {
final Vault v;
if (potentialVaultPath.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
v = vaultListManager.add(potentialVaultPath.getParent());
Path potentialVaultPath = path.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT) ? path.getParent() : path;
final Optional<Vault> v = vaultListManager.get(potentialVaultPath);
if (v.isPresent()) {
if (v.get().isUnlocked()) {
vaultService.reveal(v.get());
} else if (v.get().isLocked()) {
appWindows.startUnlockWorkflow(v.get(), null);
}
} else {
v = vaultListManager.add(potentialVaultPath);
vaultListManager.add(potentialVaultPath);
LOG.debug("Added vault {}", potentialVaultPath);
}
if (v.isUnlocked()) {
vaultService.reveal(v);
}
LOG.debug("Added vault {}", potentialVaultPath);
} catch (IOException e) {
LOG.error("Failed to add vault " + potentialVaultPath, e);
LOG.error("Failed to add vault " + path, e);
}
}

View File

@@ -15,15 +15,13 @@ 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.recoverykey.RecoveryKeyComponent;
import org.cryptomator.ui.sharevault.ShareVaultComponent;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javax.inject.Named;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.image.Image;
import java.io.IOException;
import java.io.InputStream;
@@ -40,7 +38,8 @@ import java.io.InputStream;
HealthCheckComponent.class, //
UpdateReminderComponent.class, //
ShareVaultComponent.class, //
EventViewComponent.class})
EventViewComponent.class, //
RecoveryKeyComponent.class})
abstract class FxApplicationModule {
private static Image createImageFromResource(String resourceName) throws IOException {

View File

@@ -28,7 +28,7 @@ import static org.cryptomator.common.vaults.VaultState.Value.*;
@FxApplicationScoped
public class FxApplicationTerminator {
private static final Set<VaultState.Value> STATES_ALLOWING_TERMINATION = EnumSet.of(LOCKED, NEEDS_MIGRATION, MISSING, ERROR);
private static final Set<VaultState.Value> STATES_ALLOWING_TERMINATION = EnumSet.of(LOCKED, NEEDS_MIGRATION, MISSING, ERROR, VAULT_CONFIG_MISSING, ALL_MISSING);
private static final Set<VaultState.Value> STATES_PREVENT_TERMINATION = EnumSet.of(PROCESSING);
private static final Logger LOG = LoggerFactory.getLogger(FxApplicationTerminator.class);
@@ -110,7 +110,7 @@ public class FxApplicationTerminator {
} else if (settings.autoCloseVaults.get() && !preventQuitWithGracefulLock.get()) {
var lockAllTask = vaultService.createLockAllTask(vaults.filtered(Vault::isUnlocked), false);
lockAllTask.setOnSucceeded(event -> {
LOG.info("Locked remaining vaults was succesful.");
LOG.info("Locked remaining vaults was successful.");
exitingResponse.performQuit();
});
lockAllTask.setOnFailed(event -> {

View File

@@ -46,15 +46,16 @@ public interface KeyLoadingStrategy extends MasterkeyLoader {
/**
* Determines whether the provided key loader scheme corresponds to a Masterkey File Vault.
* <p>
* This method checks if the {@code keyLoader} parameter matches the known Masterkey File Vault scheme
* This method checks if the {@code keyLoader} parameter starts with the known Masterkey File Vault scheme
* {@link MasterkeyFileLoadingStrategy#SCHEME}.
* This allows identifying not only exact matches but also variants or extended schemes based on the Masterkey scheme.
* </p>
*
* @param keyLoader A string representing the key loader scheme to be checked.
* @return {@code true} if the given key loader scheme represents a Masterkey File Vault; {@code false} otherwise.
* @return {@code true} if the given key loader scheme starts with the Masterkey File Vault scheme; {@code false} otherwise.
*/
static boolean isMasterkeyFileVault(String keyLoader) {
return MasterkeyFileLoadingStrategy.SCHEME.equals(keyLoader);
return keyLoader.startsWith(MasterkeyFileLoadingStrategy.SCHEME);
}
/**

View File

@@ -1,14 +1,18 @@
package org.cryptomator.ui.keyloading.masterkeyfile;
import org.cryptomator.common.recovery.RecoveryActionType;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
@@ -27,17 +31,41 @@ public class ChooseMasterkeyFileController implements FxController {
private final Stage window;
private final Vault vault;
private final CompletableFuture<Path> result;
private final RecoveryKeyComponent.Factory recoveryKeyWindow;
private final ResourceBundle resourceBundle;
@FXML
private CheckBox restoreInsteadCheckBox;
@FXML
private Button forwardButton;
@Inject
public ChooseMasterkeyFileController(@KeyLoading Stage window, @KeyLoading Vault vault, CompletableFuture<Path> result, ResourceBundle resourceBundle) {
public ChooseMasterkeyFileController(@KeyLoading Stage window, //
@KeyLoading Vault vault, //
CompletableFuture<Path> result, //
RecoveryKeyComponent.Factory recoveryKeyWindow, //
ResourceBundle resourceBundle) {
this.window = window;
this.vault = vault;
this.result = result;
this.recoveryKeyWindow = recoveryKeyWindow;
this.resourceBundle = resourceBundle;
this.window.setOnHiding(this::windowClosed);
}
@FXML
private void initialize() {
restoreInsteadCheckBox.selectedProperty().addListener((_, _, newVal) -> {
if (newVal) {
forwardButton.setText(resourceBundle.getString("addvaultwizard.existing.restore"));
forwardButton.setOnAction(_ -> restoreMasterkey());
} else {
forwardButton.setText(resourceBundle.getString("generic.button.choose"));
forwardButton.setOnAction(_ -> proceed());
}
});
}
@FXML
public void cancel() {
window.close();
@@ -47,6 +75,13 @@ public class ChooseMasterkeyFileController implements FxController {
result.cancel(true);
}
@FXML
void restoreMasterkey() {
Stage ownerStage = (Stage) window.getOwner();
window.close();
recoveryKeyWindow.create(vault, ownerStage, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_MASTERKEY)).showOnboardingDialogWindow();
}
@FXML
public void proceed() {
LOG.trace("proceed()");
@@ -62,7 +97,7 @@ public class ChooseMasterkeyFileController implements FxController {
//--- Setter & Getter ---
public String getDisplayName(){
public String getDisplayName() {
return vault.getDisplayName();
}

View File

@@ -18,6 +18,7 @@ import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.fxapp.FxApplicationTerminator;
import org.cryptomator.ui.fxapp.PrimaryStage;
import org.cryptomator.ui.migration.MigrationComponent;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import org.cryptomator.ui.stats.VaultStatisticsComponent;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
@@ -32,7 +33,7 @@ import javafx.stage.Stage;
import java.util.Map;
import java.util.ResourceBundle;
@Module(subcomponents = {AddVaultWizardComponent.class, MigrationComponent.class, VaultStatisticsComponent.class, WrongFileAlertComponent.class, ErrorComponent.class})
@Module(subcomponents = {AddVaultWizardComponent.class, MigrationComponent.class, VaultStatisticsComponent.class, WrongFileAlertComponent.class, ErrorComponent.class, RecoveryKeyComponent.class})
abstract class MainWindowModule {
@Provides

View File

@@ -52,7 +52,7 @@ public class VaultDetailController implements FxController {
case LOCKED -> FontAwesome5Icon.LOCK;
case PROCESSING -> FontAwesome5Icon.SPINNER;
case UNLOCKED -> FontAwesome5Icon.LOCK_OPEN;
case NEEDS_MIGRATION, MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
};
} else {
return FontAwesome5Icon.EXCLAMATION_TRIANGLE;

View File

@@ -1,20 +1,26 @@
package org.cryptomator.ui.mainwindow;
import org.cryptomator.common.recovery.RecoveryActionType;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.dialogs.Dialogs;
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import javax.inject.Inject;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
import java.nio.file.Files;
import java.util.ResourceBundle;
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_GLOB;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
@MainWindowScoped
public class VaultDetailMissingVaultController implements FxController {
@@ -23,6 +29,7 @@ public class VaultDetailMissingVaultController implements FxController {
private final ObservableList<Vault> vaults;
private final ResourceBundle resourceBundle;
private final Stage window;
private final RecoveryKeyComponent.Factory recoveryKeyWindow;
private final Dialogs dialogs;
@Inject
@@ -30,11 +37,13 @@ public class VaultDetailMissingVaultController implements FxController {
ObservableList<Vault> vaults, //
ResourceBundle resourceBundle, //
@MainWindow Stage window, //
Dialogs dialogs) {
Dialogs dialogs, //
RecoveryKeyComponent.Factory recoveryKeyWindow) {
this.vault = vault;
this.vaults = vaults;
this.resourceBundle = resourceBundle;
this.window = window;
this.recoveryKeyWindow = recoveryKeyWindow;
this.dialogs = dialogs;
}
@@ -48,6 +57,19 @@ public class VaultDetailMissingVaultController implements FxController {
dialogs.prepareRemoveVaultDialog(window, vault.get(), vaults).build().showAndWait();
}
@FXML
void restoreVaultConfig() {
if(KeyLoadingStrategy.isHubVault(vault.get().getVaultSettings().lastKnownKeyLoader.get())){
dialogs.prepareContactHubVaultOwner(window).build().showAndWait();
}
else if(Files.exists(vault.get().getPath().resolve(MASTERKEY_FILENAME))){
recoveryKeyWindow.create(vault.get(), window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_VAULT_CONFIG)).showOnboardingDialogWindow();
}
else {
recoveryKeyWindow.create(vault.get(), window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_ALL)).showOnboardingDialogWindow();
}
}
@FXML
void changeLocation() {
// copied from ChooseExistingVaultController class

View File

@@ -55,7 +55,7 @@ public class VaultListCellController implements FxController {
case LOCKED -> FontAwesome5Icon.LOCK;
case PROCESSING -> FontAwesome5Icon.SPINNER;
case UNLOCKED -> FontAwesome5Icon.LOCK_OPEN;
case NEEDS_MIGRATION, MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
};
} else {
return FontAwesome5Icon.EXCLAMATION_TRIANGLE;

View File

@@ -20,11 +20,13 @@ import javafx.stage.Stage;
import java.util.EnumSet;
import java.util.Objects;
import static org.cryptomator.common.vaults.VaultState.Value.ALL_MISSING;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.MISSING;
import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
import static org.cryptomator.common.vaults.VaultState.Value.UNLOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.VAULT_CONFIG_MISSING;
@MainWindowScoped
public class VaultListContextMenuController implements FxController {
@@ -63,7 +65,7 @@ public class VaultListContextMenuController implements FxController {
this.selectedVaultState = selectedVault.flatMap(Vault::stateProperty).orElse(null);
this.selectedVaultPassphraseStored = selectedVault.map(this::isPasswordStored).orElse(false);
this.selectedVaultRemovable = selectedVaultState.map(EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION)::contains).orElse(false);
this.selectedVaultRemovable = selectedVaultState.map(EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION, ALL_MISSING, VAULT_CONFIG_MISSING)::contains).orElse(false);
this.selectedVaultUnlockable = selectedVaultState.map(LOCKED::equals).orElse(false);
this.selectedVaultLockable = selectedVaultState.map(UNLOCKED::equals).orElse(false);
}
@@ -102,6 +104,12 @@ public class VaultListContextMenuController implements FxController {
vaultService.reveal(vault);
}
@FXML
public void didClickShareVault() {
var vault = Objects.requireNonNull(selectedVault.get());
appWindows.showShareVaultWindow(vault);
}
// Getter and Setter
public ObservableValue<Boolean> selectedVaultUnlockableProperty() {

View File

@@ -1,11 +1,16 @@
package org.cryptomator.ui.mainwindow;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.recovery.RecoveryActionType;
import org.cryptomator.common.recovery.VaultPreparator;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultComponent;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.cryptofs.common.Constants;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.VaultService;
@@ -13,6 +18,7 @@ import org.cryptomator.ui.dialogs.Dialogs;
import org.cryptomator.ui.fxapp.FxFSEventList;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,6 +28,7 @@ import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
@@ -37,11 +44,14 @@ import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
@@ -50,10 +60,12 @@ import java.util.stream.Collectors;
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_EXT;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
import static org.cryptomator.common.vaults.VaultState.Value.ALL_MISSING;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.MISSING;
import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
import static org.cryptomator.common.vaults.VaultState.Value.VAULT_CONFIG_MISSING;
@MainWindowScoped
public class VaultListController implements FxController {
@@ -75,6 +87,10 @@ public class VaultListController implements FxController {
private final ObservableValue<Double> cellSize;
private final Dialogs dialogs;
private final VaultComponent.Factory vaultComponentFactory;
private final RecoveryKeyComponent.Factory recoveryKeyWindow;
private final List<MountService> mountServices;
public ListView<Vault> vaultList;
public StackPane root;
@FXML
@@ -94,6 +110,9 @@ public class VaultListController implements FxController {
FxApplicationWindows appWindows, //
Settings settings, //
Dialogs dialogs, //
RecoveryKeyComponent.Factory recoveryKeyWindow, //
VaultComponent.Factory vaultComponentFactory, //
List<MountService> mountServices, //
FxFSEventList fxFSEventList) {
this.mainWindow = mainWindow;
this.vaults = vaults;
@@ -105,6 +124,9 @@ public class VaultListController implements FxController {
this.resourceBundle = resourceBundle;
this.appWindows = appWindows;
this.dialogs = dialogs;
this.recoveryKeyWindow = recoveryKeyWindow;
this.vaultComponentFactory = vaultComponentFactory;
this.mountServices = mountServices;
this.emptyVaultList = Bindings.isEmpty(vaults);
this.unreadEvents = fxFSEventList.unreadEventsProperty();
@@ -204,6 +226,26 @@ public class VaultListController implements FxController {
VaultListManager.redetermineVaultState(newValue);
}
private Optional<Path> chooseValidVaultDirectory() {
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory;
do {
selectedDirectory = directoryChooser.showDialog(mainWindow);
if (selectedDirectory == null) {
return Optional.empty();
}
Path selectedPath = selectedDirectory.toPath();
if (!Files.isDirectory(selectedPath.resolve(Constants.DATA_DIR_NAME))) {
dialogs.prepareNoDDirectorySelectedDialog(mainWindow).build().showAndWait();
selectedDirectory = null;
}
} while (selectedDirectory == null);
return Optional.of(selectedDirectory.toPath());
}
@FXML
public void didClickAddNewVault() {
addVaultWizard.build().showAddNewVaultWizard(resourceBundle);
@@ -214,9 +256,40 @@ public class VaultListController implements FxController {
addVaultWizard.build().showAddExistingVaultWizard(resourceBundle);
}
@FXML
public void didClickRecoverExistingVault() {
Optional<Path> selectedDirectory = chooseValidVaultDirectory();
if (selectedDirectory.isEmpty()) {
return;
}
Path path = selectedDirectory.get();
Optional<Vault> matchingVaultListEntry = vaultListManager.get(path);
if (matchingVaultListEntry.isPresent()) {
dialogs.prepareRecoveryVaultAlreadyExists(mainWindow, matchingVaultListEntry.get().getDisplayName()) //
.setOkAction(Stage::close) //
.build().showAndWait();
return;
}
Vault preparedVault = VaultPreparator.prepareVault(path, vaultComponentFactory, mountServices, resourceBundle);
VaultListManager.redetermineVaultState(preparedVault);
switch (preparedVault.getState()) {
case VAULT_CONFIG_MISSING -> recoveryKeyWindow.create(preparedVault, mainWindow, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_VAULT_CONFIG)).showOnboardingDialogWindow();
case ALL_MISSING -> recoveryKeyWindow.create(preparedVault, mainWindow, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_ALL)).showOnboardingDialogWindow();
case LOCKED, NEEDS_MIGRATION -> {
vaultListManager.addVault(preparedVault);
dialogs.prepareRecoveryVaultAdded(mainWindow, preparedVault.getDisplayName()).setOkAction(Stage::close).build().showAndWait();
}
default -> LOG.warn("Unhandled vault state during recovery: {}", preparedVault.getState());
}
}
private void pressedShortcutToRemoveVault() {
final var vault = selectedVault.get();
if (vault != null && EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION).contains(vault.getState())) {
if (vault != null && EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION, ALL_MISSING, VAULT_CONFIG_MISSING).contains(vault.getState())) {
dialogs.prepareRemoveVaultDialog(mainWindow, vault, vaults).build().showAndWait();
}
}

View File

@@ -85,7 +85,7 @@ public class GeneralPreferencesController implements FxController {
var keychainSettingsConverter = new ServiceToSettingsConverter<>(keychainAccessProviders);
keychainBackendChoiceBox.getItems().addAll(keychainAccessProviders);
keychainBackendChoiceBox.setValue(keychainSettingsConverter.fromString(settings.keychainProvider.get()));
keychainBackendChoiceBox.setConverter(new KeychainProviderDisplayNameConverter());
keychainBackendChoiceBox.setConverter(new NamedServiceConverter<>());
Bindings.bindBidirectional(settings.keychainProvider, keychainBackendChoiceBox.valueProperty(), keychainSettingsConverter);
useKeychainCheckbox.selectedProperty().bindBidirectional(settings.useKeychain);
keychainBackendChoiceBox.disableProperty().bind(useKeychainCheckbox.selectedProperty().not());
@@ -106,13 +106,13 @@ public class GeneralPreferencesController implements FxController {
var idsAndNames = settings.directories.stream().collect(Collectors.toMap(vs -> vs.id, vs -> vs.displayName.getValue()));
if (!idsAndNames.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Migrating keychain entries {} from {} to {}", idsAndNames.keySet(), oldProvider.displayName(), newProvider.displayName());
LOG.debug("Migrating keychain entries {} from {} to {}", idsAndNames.keySet(), oldProvider.getName(), newProvider.getName());
}
keychainMigrations = keychainMigrations.thenRunAsync(() -> {
try {
KeychainManager.migrate(oldProvider, newProvider, idsAndNames);
} catch (KeychainAccessException e) {
LOG.warn("Failed to migrate all entries from {} to {}", oldProvider.displayName(), newProvider.displayName(), e);
LOG.warn("Failed to migrate all entries from {} to {}", oldProvider.getName(), newProvider.getName(), e);
}
}, backgroundExecutor);
}
@@ -151,25 +151,6 @@ public class GeneralPreferencesController implements FxController {
}
/* Helper classes */
private static class KeychainProviderDisplayNameConverter extends StringConverter<KeychainAccessProvider> {
@Override
public String toString(KeychainAccessProvider provider) {
if (provider == null) {
return null;
} else {
return provider.displayName();
}
}
@Override
public KeychainAccessProvider fromString(String string) {
throw new UnsupportedOperationException();
}
}
private static class NamedServiceConverter<T extends NamedServiceProvider> extends StringConverter<T> {
@Override

View File

@@ -3,11 +3,13 @@ package org.cryptomator.ui.recoverykey;
import dagger.BindsInstance;
import dagger.Lazy;
import dagger.Subcomponent;
import org.cryptomator.common.recovery.RecoveryActionType;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javax.inject.Named;
import javafx.beans.property.ObjectProperty;
import javafx.scene.Scene;
import javafx.stage.Stage;
@@ -24,6 +26,9 @@ public interface RecoveryKeyComponent {
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER)
Lazy<Scene> recoverScene();
@FxmlScene(FxmlFile.RECOVERYKEY_ONBOARDING)
Lazy<Scene> recoverOnboardingScene();
default void showRecoveryKeyCreationWindow() {
Stage stage = window();
stage.setScene(creationScene().get());
@@ -38,11 +43,19 @@ public interface RecoveryKeyComponent {
stage.show();
}
default void showOnboardingDialogWindow() {
Stage stage = window();
stage.setScene(recoverOnboardingScene().get());
stage.sizeToScene();
stage.show();
}
@Subcomponent.Factory
interface Factory {
RecoveryKeyComponent create(@BindsInstance @RecoveryKeyWindow Vault vault, @BindsInstance @Named("keyRecoveryOwner") Stage owner);
RecoveryKeyComponent create(@BindsInstance @RecoveryKeyWindow Vault vault, //
@BindsInstance @Named("keyRecoveryOwner") Stage owner, //
@BindsInstance @Named("recoverType") ObjectProperty<RecoveryActionType> recoverType);
}
}

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