Compare commits

...

500 Commits

Author SHA1 Message Date
Armin Schrenk
390bdc33e0 Merge branch 'hotfix/1.19.2' 2026-03-20 08:14:04 +01:00
Armin Schrenk
2284d1fcee Update Changelog 2026-03-20 08:13:37 +01:00
Sebastian Stenzel
62a439e10e CHANGELOG.md: moved security fixes to subsection
[ci skip]
2026-03-20 08:02:58 +01:00
Sebastian Stenzel
ddad663489 add release to metainfo file 2026-03-19 16:41:17 +01:00
Sebastian Stenzel
f08e7d9b92 bump version to 1.19.2 2026-03-19 16:34:42 +01:00
Sebastian Stenzel
6c2865a09d simplify port/scheme check 2026-03-19 16:27:09 +01:00
Armin Schrenk
4be327608a Merge branch 'release/1.19.1' 2026-03-12 14:35:20 +01:00
Armin Schrenk
929ef37ded finalize release 2026-03-12 14:12:41 +01:00
Armin Schrenk
6fce1807f0 prepare 1.19.1 2026-03-12 14:08:50 +01:00
Armin Schrenk
c1d72650cc [skip ci] update changelog 2026-03-12 14:06:30 +01:00
Armin Schrenk
dab368e44b Update org.cryptomator.integrations-api to 1.8.0
closes #4176
2026-03-12 14:00:06 +01:00
Armin Schrenk
7548174e4f Update org.cryptomator.integrations-linux to 1.7.0
closes #4175
2026-03-12 13:46:04 +01:00
Armin Schrenk
b513060744 Update dependency org.cryptomator.integrations-mac from 1.5.0-beta3 to 1.5.0
closes #4177
2026-03-12 13:40:18 +01:00
Armin Schrenk
311a9ef70b [skip ci] update changelog 2026-03-12 13:36:56 +01:00
Armin Schrenk
7331144f9d Set cryptomator.hub.enableTrustOnFirstUse (#4182)
in installers/package containers
2026-03-12 13:13:49 +01:00
Cryptobot
d576b36f7b New Crowdin updates (#4172)
New translations strings.properties:
Danish; Korean; Portuguese, Brazilian; Chinese Traditional
2026-03-12 12:43:14 +01:00
Armin Schrenk
7a6340aac6 Merge pull request #4181 from cryptomator/feature/pin-appimagetool
pin appimagetool
2026-03-12 12:31:37 +01:00
Sebastian Stenzel
6b82abcd80 Merge pull request #4179 from cryptomator/feature/admin-config-allowlist
Hub: Trust on first use
2026-03-12 12:26:59 +01:00
Armin Schrenk
97bde05422 adjust wording
use singular because in most cases hub and auth are on either pre-trusted or on the same domain
2026-03-12 12:23:30 +01:00
Armin Schrenk
3bc50eee47 add checksum of appimage tool 2026-03-12 12:16:46 +01:00
Armin Schrenk
b95a220de7 Adjust wording 2026-03-12 12:08:27 +01:00
Armin Schrenk
2896e18429 Adjust dialog message to show current status
checking vs user interaction
2026-03-12 11:42:44 +01:00
Armin Schrenk
29db91f976 fix javafx display issue
do not change scene in initialize() method
2026-03-12 11:28:38 +01:00
Sebastian Stenzel
1e3dfe3de1 Merge pull request #4180 from cryptomator/feature/patched-masterkey-loading
don't load masterkey from arbitrary paths
2026-03-12 10:23:43 +01:00
Sebastian Stenzel
dcb1f5e80f pin appimagetool 2026-03-12 10:21:12 +01:00
Sebastian Stenzel
5c75eeab27 reuse existing constant 2026-03-12 10:18:19 +01:00
Sebastian Stenzel
8e4bff8c19 don't load masterkey from arbitrary paths 2026-03-12 09:58:52 +01:00
Sebastian Stenzel
e066f155b2 filter out "" 2026-03-12 09:21:55 +01:00
Sebastian Stenzel
c3c7a23ccd added test 2026-03-12 09:14:27 +01:00
Sebastian Stenzel
c816411644 deserialize null as empty 2026-03-12 09:13:40 +01:00
Sebastian Stenzel
f752490624 default to mutable collections 2026-03-12 09:12:09 +01:00
Sebastian Stenzel
d196b66b4e refined rules 2026-03-12 09:02:19 +01:00
Sebastian Stenzel
d803a1d71e apply suggestions from code review 2026-03-11 23:17:16 +01:00
Sebastian Stenzel
c75430cde2 only trust subdomains of .cryptomator.cloud
not `notcryptomator.cloud`
2026-03-11 23:13:50 +01:00
Sebastian Stenzel
f44c3531c7 devicesResourceUrl: optional consistency check 2026-03-11 23:12:13 +01:00
Sebastian Stenzel
596829bc77 dedup 2026-03-11 23:09:04 +01:00
Sebastian Stenzel
096aeb0c54 renamed var
[ci skip]
2026-03-11 22:49:28 +01:00
Sebastian Stenzel
1a12684557 fix test 2026-03-11 22:42:25 +01:00
Sebastian Stenzel
998664acc3 distrust http (except for localhost) 2026-03-11 22:01:21 +01:00
Sebastian Stenzel
c52b3fc4ad change scene without lag 2026-03-11 22:01:14 +01:00
Sebastian Stenzel
1fde3650ca renamed classes 2026-03-11 21:47:33 +01:00
Sebastian Stenzel
57614f59e4 trust *.cryptomator.cloud 2026-03-11 21:38:51 +01:00
Sebastian Stenzel
a95883f98b renamed system properties 2026-03-11 21:32:51 +01:00
Sebastian Stenzel
6cf18c33a1 simplify sorting 2026-03-11 21:12:47 +01:00
Sebastian Stenzel
232e6fbf71 add tests 2026-03-11 21:05:14 +01:00
Sebastian Stenzel
d15731d5a4 add plural label 2026-03-11 20:30:00 +01:00
Sebastian Stenzel
45d7421e4f add "reset trusted hosts" button to general preferences 2026-03-11 20:24:56 +01:00
Sebastian Stenzel
4d0aabfe6e cleanup 2026-03-11 20:12:16 +01:00
Sebastian Stenzel
db0e266fde clean up dialog 2026-03-11 19:48:37 +01:00
Sebastian Stenzel
6281561ab4 add -Dcryptomator.allowUnknownHubHosts=true 2026-03-11 18:53:14 +01:00
Sebastian Stenzel
b981f0dc19 moved logic to separate controller 2026-03-11 18:52:36 +01:00
Armin Schrenk
bc41429982 Use environment for cryptomator system properties 2026-03-11 17:59:58 +01:00
Armin Schrenk
a31621cfde validate hub config and check allowed hosts file 2026-03-11 17:35:22 +01:00
Armin Schrenk
aa68224d63 Add new properties to admin config
* allowUnknownHubHosts
* allowedHubHosts
2026-03-11 16:49:48 +01:00
Armin Schrenk
b8413a21a3 update appstream info 2026-03-09 17:01:46 +01:00
Armin Schrenk
af59196f19 [skip ci] Merge branch 'main' into develop 2026-03-09 09:32:54 +01:00
Armin Schrenk
3a58f560fc Merge branch 'release/1.19.0' 2026-03-09 09:27:31 +01:00
Armin Schrenk
a2cca0b624 finalize release 2026-03-08 23:53:07 +01:00
Armin Schrenk
0c4ba94f10 Merge branch 'develop' into release/1.19.0 2026-03-08 23:47:36 +01:00
Cryptobot
0f8b6a8f51 New Crowdin updates (#4170)
* New translations strings.properties (Korean)
[ci skip]
2026-03-08 23:45:59 +01:00
Armin Schrenk
8ca6946fe6 Suppress CVE-2025-11143
Jetty is used only locally
2026-03-08 18:08:23 +01:00
Armin Schrenk
e583b70931 use correct filename for admin config on Windows 2026-03-07 12:06:13 +01:00
Armin Schrenk
6f6d0d8771 Update wording in release draft 2026-03-06 12:58:17 +01:00
Armin Schrenk
9d3d67b605 Update changelog 2026-03-05 23:12:58 +01:00
Armin Schrenk
8da27e36d6 Merge branch 'develop' into release/1.19.0 2026-03-05 23:10:11 +01:00
dependabot[bot]
1123fa28a3 Bump org.apache.maven.plugins:maven-resources-plugin (#4167)
Bumps the maven-build-plugins group with 1 update: [org.apache.maven.plugins:maven-resources-plugin](https://github.com/apache/maven-resources-plugin).


Updates `org.apache.maven.plugins:maven-resources-plugin` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/apache/maven-resources-plugin/releases)
- [Commits](https://github.com/apache/maven-resources-plugin/compare/v3.4.0...maven-resources-plugin-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-resources-plugin
  dependency-version: 3.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 23:09:12 +01:00
Armin Schrenk
be3ecc536a Update to cryptofs 2.10.0 2026-03-05 17:47:52 +01:00
Armin Schrenk
94c8dd911b [skip ci] update changelog 2026-03-05 17:45:14 +01:00
Armin Schrenk
7e888b0e3b ensure logging for Substituting properties 2026-03-05 17:44:47 +01:00
dependabot[bot]
a066afe37d Bump the java-production-dependencies group with 8 updates (#4152)
* Bump the java-production-dependencies group with 8 updates

Bumps the java-production-dependencies group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [ch.qos.logback:logback-core](https://github.com/qos-ch/logback) | `1.5.31` | `1.5.32` |
| [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) | `1.5.31` | `1.5.32` |
| [com.auth0:java-jwt](https://github.com/auth0/java-jwt) | `4.5.0` | `4.5.1` |
| [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) | `2.21.0` | `2.21.1` |
| com.fasterxml.jackson.datatype:jackson-datatype-jsr310 | `2.21.0` | `2.21.1` |
| [com.google.dagger:dagger](https://github.com/google/dagger) | `2.59.1` | `2.59.2` |
| [com.google.dagger:dagger-compiler](https://github.com/google/dagger) | `2.59.1` | `2.59.2` |
| [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) | `26.0.2-1` | `26.1.0` |


Updates `ch.qos.logback:logback-core` from 1.5.31 to 1.5.32
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.31...v_1.5.32)

Updates `ch.qos.logback:logback-classic` from 1.5.31 to 1.5.32
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.31...v_1.5.32)

Updates `ch.qos.logback:logback-classic` from 1.5.31 to 1.5.32
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.31...v_1.5.32)

Updates `com.auth0:java-jwt` from 4.5.0 to 4.5.1
- [Release notes](https://github.com/auth0/java-jwt/releases)
- [Changelog](https://github.com/auth0/java-jwt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/java-jwt/compare/4.5.0...4.5.1)

Updates `com.fasterxml.jackson.core:jackson-databind` from 2.21.0 to 2.21.1
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.21.0 to 2.21.1

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.21.0 to 2.21.1

Updates `com.google.dagger:dagger` from 2.59.1 to 2.59.2
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.59.1...dagger-2.59.2)

Updates `com.google.dagger:dagger-compiler` from 2.59.1 to 2.59.2
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.59.1...dagger-2.59.2)

Updates `org.jetbrains:annotations` from 26.0.2-1 to 26.1.0
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/26.0.2-1...26.1.0)

Updates `com.google.dagger:dagger-compiler` from 2.59.1 to 2.59.2
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.59.1...dagger-2.59.2)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-core
  dependency-version: 1.5.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.auth0:java-jwt
  dependency-version: 4.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-version: 2.21.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger
  dependency-version: 2.59.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.jetbrains:annotations
  dependency-version: 26.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* [skip ci] update changelog

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2026-03-05 17:29:09 +01:00
Cryptobot
21c8cbf709 New Crowdin updates (#4148)
New translations strings.properties

Arabic; Bulgarian; Chinese Simplified; Chinese Traditional; Danish; Dutch; Finnish; French; German; Greek; Italian; Japanese; Korean; Latvian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Russian; Slovak; Spanish; Swedish; Turkish; Ukrainian; Vietnamese; 

[ci skip]
2026-03-05 17:28:41 +01:00
dependabot[bot]
ea236d45a3 Bump the java-test-dependencies group across 1 directory with 2 updates (#4079)
Bumps the java-test-dependencies group with 2 updates in the / directory: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) and [org.mockito:mockito-core](https://github.com/mockito/mockito).


Updates `org.junit.jupiter:junit-jupiter` from 5.13.4 to 6.0.1
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.4...r6.0.1)

Updates `org.mockito:mockito-core` from 5.20.0 to 5.21.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.20.0...v5.21.0)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-version: 6.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: java-test-dependencies
- dependency-name: org.mockito:mockito-core
  dependency-version: 5.21.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: java-test-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 17:27:42 +01:00
dependabot[bot]
fab5ac3726 Bump the maven-build-plugins group across 1 directory with 8 updates (#4151)
* Bump the maven-build-plugins group across 1 directory with 8 updates

Bumps the maven-build-plugins group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [me.fabriciorby:maven-surefire-junit5-tree-reporter](https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter) | `1.4.0` | `1.5.1` |
| [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) | `3.14.1` | `3.15.0` |
| [org.apache.maven.plugins:maven-resources-plugin](https://github.com/apache/maven-resources-plugin) | `3.3.1` | `3.4.0` |
| [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) | `3.8.1` | `3.10.0` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.5.4` | `3.5.5` |
| [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) | `2.7.0` | `2.7.1` |
| [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) | `3.4.2` | `3.5.0` |
| [org.owasp:dependency-check-maven](https://github.com/dependency-check/DependencyCheck) | `12.1.5` | `12.2.0` |



Updates `me.fabriciorby:maven-surefire-junit5-tree-reporter` from 1.4.0 to 1.5.1
- [Release notes](https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter/releases)
- [Commits](https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter/compare/v1.4.0...v1.5.1)

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

Updates `org.apache.maven.plugins:maven-resources-plugin` from 3.3.1 to 3.4.0
- [Release notes](https://github.com/apache/maven-resources-plugin/releases)
- [Commits](https://github.com/apache/maven-resources-plugin/compare/maven-resources-plugin-3.3.1...v3.4.0)

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

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

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

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

Updates `org.owasp:dependency-check-maven` from 12.1.5 to 12.2.0
- [Release notes](https://github.com/dependency-check/DependencyCheck/releases)
- [Changelog](https://github.com/dependency-check/DependencyCheck/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dependency-check/DependencyCheck/compare/v12.1.5...v12.2.0)

---
updated-dependencies:
- dependency-name: me.fabriciorby:maven-surefire-junit5-tree-reporter
  dependency-version: 1.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-version: 3.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.apache.maven.plugins:maven-resources-plugin
  dependency-version: 3.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.apache.maven.plugins:maven-dependency-plugin
  dependency-version: 3.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-version: 3.5.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven-build-plugins
- dependency-name: org.codehaus.mojo:license-maven-plugin
  dependency-version: 2.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven-build-plugins
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
- dependency-name: org.owasp:dependency-check-maven
  dependency-version: 12.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven-build-plugins
...

Signed-off-by: dependabot[bot] <support@github.com>

* downgrade maven surefire

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2026-03-05 17:23:36 +01:00
dependabot[bot]
57666a620c Bump the github-actions group with 3 updates (#4162)
Bumps the github-actions group with 3 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact), [actions/download-artifact](https://github.com/actions/download-artifact) and [actions/stale](https://github.com/actions/stale).


Updates `actions/upload-artifact` from 6.0.0 to 7.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](b7c566a772...bbbca2ddaa)

Updates `actions/download-artifact` from 7.0.0 to 8.0.0
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](37930b1c2a...70fc10c6e5)

Updates `actions/stale` from 10.1.1 to 10.2.0
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](997185467f...b5d41d4e1d)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/stale
  dependency-version: 10.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 17:12:30 +01:00
Armin Schrenk
e49fe23b35 Explicitly define webdav-nio-adapter-servlet dependency
and update changelog
2026-03-03 18:22:57 +01:00
Armin Schrenk
254a7696c8 [skip ci] update changelog 2026-03-03 18:13:54 +01:00
Armin Schrenk
62bd43ef9b Update fuse-nio-adapter from 6.0.0 to 6.0.1
closes #4121
2026-03-03 18:12:49 +01:00
Tobias Hagemann
b73510ec0f Merge pull request #4166 from cryptomator/feature/liquid-glass-icon
Add Liquid Glass icon for macOS 26 and remove DockTilePlugin workaround
2026-03-03 14:31:23 +01:00
Tobias Hagemann
3fba62ef72 revert icns to legacy icon and recompile Assets.car without fallback bitmaps 2026-03-03 14:16:22 +01:00
Armin Schrenk
7daca70a15 Feature: Replace JavaFX host services with RevealPathService impls (#4165)
when a OS path need to be shown in the OS file browser.
2026-03-03 11:25:29 +01:00
Tobias Hagemann
90228a1d5c add Liquid Glass icon and remove DockTilePlugin workaround 2026-03-03 06:55:24 +01:00
Armin Schrenk
4090413290 increase slightly notify window heigth 2026-02-27 15:52:30 +01:00
Armin Schrenk
29bfbdc524 Adjust wording for in use feature 2026-02-27 15:08:32 +01:00
Armin Schrenk
688090095e harden curl downloads on CI (#4158) 2026-02-26 17:49:38 +01:00
Armin Schrenk
98db9649c3 Merge branch 'main' into develop
# Conflicts:
#	pom.xml
2026-02-26 16:58:00 +01:00
Armin Schrenk
7a4c8f113e Merge branch 'hotfix/1.18.1' 2026-02-26 16:57:10 +01:00
Armin Schrenk
50f6a87788 [skip metadata check] fix release check workflow 2026-02-26 16:53:21 +01:00
Armin Schrenk
d601088948 [skip metadata check] update workflow for hotfix 2026-02-26 16:44:50 +01:00
Armin Schrenk
4d62f2303d prepare version 1.18.1 2026-02-26 16:27:57 +01:00
Armin Schrenk
792734b486 add unit tests 2026-02-26 16:20:34 +01:00
Armin Schrenk
f884861373 skip fallback if failing to load 2026-02-26 15:48:35 +01:00
Armin Schrenk
da3c5e901f fixes #4156
for Windows fallback on JDK shipped cacert file if well-known CA are not present
2026-02-26 15:15:48 +01:00
Armin Schrenk
f7ccc326de drain eventual logger events after debug Mode is enabled 2026-02-25 12:27:06 +01:00
Armin Schrenk
246eb19c3c CI: Build cryptomator-bin package before creating PR. (#4149)
use arch container to build cryptomator-bin package
2026-02-23 11:48:38 +01:00
Armin Schrenk
c073b26d8f fix slack notification for makepkg flow 2026-02-23 11:39:46 +01:00
Armin Schrenk
227a3258ec Update slack webhook in post-publish flow 2026-02-20 18:56:42 +01:00
Armin Schrenk
3279df68c7 Update appimage workflow
* use env variables in action generated/generated input
* use cryptobot as actor for PR
* update slack webhook
2026-02-20 17:33:36 +01:00
Armin Schrenk
bf6598302b add correct info in PR description 2026-02-20 17:18:17 +01:00
Armin Schrenk
dccb4ef072 disable gits safe directory 2026-02-20 17:03:00 +01:00
Armin Schrenk
cbae2413ae use correct github expression varaible
in create-pr step
2026-02-20 16:45:43 +01:00
Armin Schrenk
113ab66a49 Merge pull request #4139 from cryptomator/feature/aur-build
CI: Build arch package
2026-02-20 16:40:05 +01:00
Armin Schrenk
34eb336e5f only commit PKGBUILD and SRCINFO 2026-02-20 16:30:22 +01:00
Armin Schrenk
2cab0c59a1 update javafx to version 25.0.2 2026-02-20 16:23:21 +01:00
Armin Schrenk
3822136e69 update year 2026-02-20 16:23:10 +01:00
Armin Schrenk
1fa4d42d27 use yml multiline syntax 2026-02-20 16:22:55 +01:00
Armin Schrenk
d5bc0914f4 fix description text for PR 2026-02-20 16:17:08 +01:00
Armin Schrenk
ee5165320d Update Git user email for automation commits 2026-02-19 12:04:36 +01:00
Armin Schrenk
1dab85d265 Merge branch 'develop' into release/1.19.0 2026-02-18 16:25:04 +01:00
Armin Schrenk
423752e720 [skip ci] update changelog 2026-02-18 16:22:31 +01:00
Cryptobot
4efcec7e93 New Crowdin updates (#4041)
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]
2026-02-18 15:56:30 +01:00
Armin Schrenk
619d981ded [skip ci] Update README 2026-02-18 15:46:47 +01:00
mindmonk
72d93e943b fix text wrapping in ResetPasswordDialog (#4123) 2026-02-18 15:43:50 +01:00
Armin Schrenk
f07523267d Bump javafx to version 25.0.2 (#4145) 2026-02-18 15:42:51 +01:00
Armin Schrenk
5409470750 update wix 2026-02-18 15:27:36 +01:00
Armin Schrenk
70b7f39bcc revert 5ab12c1b1a for windows build 2026-02-18 15:16:39 +01:00
Armin Schrenk
5ab12c1b1a Update to latest JDK 25 2026-02-18 11:49:13 +01:00
Armin Schrenk
0ac63e7aba Closes #4136 2026-02-18 11:26:42 +01:00
Armin Schrenk
ac6f34fe17 reorder changelog 2026-02-18 11:15:46 +01:00
Armin Schrenk
dba3de230b Update dependencies
* org.cryptomator:integrations-win from 1.5.1 to 1.6.0
* org.cryptomator:webdav-nio-adapter from 3.0.0 to 3.0.1
2026-02-18 11:15:00 +01:00
Armin Schrenk
e11d42bb07 update IDE file 2026-02-18 11:07:18 +01:00
Jan-Peter Klein
171d5d5a4c Fixes #4141 2026-02-18 10:55:49 +01:00
Armin Schrenk
b86d8ca790 [skip ci] update changelog 2026-02-17 15:30:20 +01:00
Armin Schrenk
74fc77ab8d fix pom inconsistency 2026-02-17 15:21:16 +01:00
Armin Schrenk
044dbcb11f Update cryptofs to version 2.10.0-beta3 2026-02-17 15:13:46 +01:00
Armin Schrenk
1b243bb725 suppress logging of expected exception 2026-02-17 15:12:25 +01:00
Armin Schrenk
f21cb90e7d Merge pull request #4025 from purejava/new-secret-service
New keychain backend SecretService for Linux
2026-02-17 13:16:06 +01:00
Armin Schrenk
1e8f272f6a Merge pull request #4143 from cryptomator/dependabot/maven/java-production-dependencies-d98826387a
Bump the java-production-dependencies group across 1 directory with 11 updates
2026-02-17 13:15:07 +01:00
Armin Schrenk
5c1f8e7576 update IDE file 2026-02-17 12:46:19 +01:00
Armin Schrenk
bc0bb38e4c remove dagger formatting due to compile error 2026-02-17 12:45:46 +01:00
Armin Schrenk
b9b02acbe5 Merge pull request #4134 from cryptomator/feature/javafx-color-scheme-change
Feature: Use JavaFX built ins to adapt to OS color scheme
2026-02-17 10:36:23 +01:00
Armin Schrenk
e53598cfce update azure signing to stable version 2026-02-16 17:06:00 +01:00
Armin Schrenk
3fb0e9328f ensure curl only uses https 2026-02-16 17:01:52 +01:00
Armin Schrenk
eb369ba5bd use envsubst also in create-pr job 2026-02-16 16:53:25 +01:00
Armin Schrenk
738bd56270 ensure curl is installed in container 2026-02-16 16:53:07 +01:00
Armin Schrenk
5e29f08d2b make pr-creation condition more explicit 2026-02-16 16:52:27 +01:00
Armin Schrenk
b3a5265b98 add adminConfig path as property 2026-02-16 16:29:01 +01:00
Armin Schrenk
d7d439947d Merge branch 'develop' into feature/aur-build 2026-02-16 16:17:09 +01:00
Armin Schrenk
a79fd63634 [skip ci] update changelog 2026-02-16 16:15:05 +01:00
Armin Schrenk
f753ddc9be Apply suggestions from code review
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2026-02-16 16:05:26 +01:00
Armin Schrenk
2eda795219 create cryptomator dir in opt before copy 2026-02-16 16:01:32 +01:00
Armin Schrenk
158b454b0d fix NPE in EventualLogger 2026-02-16 12:45:57 +01:00
Armin Schrenk
9e6bd913cb refactor FxApplicationStyle
use pattern (removeOldListeners, addNewListerner, applyTheme)
2026-02-16 12:37:46 +01:00
Armin Schrenk
83ef9d06d9 simplify JfxUiAppearanceProvider
and move loading of appearance service into the fx app
2026-02-16 11:55:03 +01:00
Armin Schrenk
cf0052b4f5 revert lambda processing 2026-02-16 11:07:04 +01:00
Armin Schrenk
18ce7d333d fix build
* use JDK 25
* first install git, then checkout
2026-02-16 11:01:43 +01:00
Armin Schrenk
0b4d86768a Closes #4088 2026-02-16 10:13:21 +01:00
Armin Schrenk
f32d0c463f use $GITHUB_WORKSPACE
instead of github.workspace; bug in GitHubs CI system
2026-02-16 10:03:23 +01:00
dependabot[bot]
a77e90738a Bump the java-production-dependencies group across 1 directory with 11 updates
Bumps the java-production-dependencies group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [org.cryptomator:cryptolib](https://github.com/cryptomator/cryptolib) | `2.2.1` | `2.2.2` |
| [org.cryptomator:fuse-nio-adapter](https://github.com/cryptomator/fuse-nio-adapter) | `5.1.0` | `6.0.0` |
| [ch.qos.logback:logback-core](https://github.com/qos-ch/logback) | `1.5.19` | `1.5.31` |
| [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) | `1.5.19` | `1.5.31` |
| org.apache.commons:commons-lang3 | `3.19.0` | `3.20.0` |
| [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) | `2.20.0` | `2.21.0` |
| com.fasterxml.jackson.datatype:jackson-datatype-jsr310 | `2.20.0` | `2.21.0` |
| [com.google.dagger:dagger](https://github.com/google/dagger) | `2.57.2` | `2.59.1` |
| [com.google.dagger:dagger-compiler](https://github.com/google/dagger) | `2.57.2` | `2.59.1` |
| [com.github.ben-manes.caffeine:caffeine](https://github.com/ben-manes/caffeine) | `3.2.2` | `3.2.3` |
| [org.cryptomator:integrations-linux](https://github.com/cryptomator/integrations-linux) | `1.7.0-beta3` | `1.7.0-beta4` |



Updates `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
- [Release notes](https://github.com/cryptomator/cryptolib/releases)
- [Changelog](https://github.com/cryptomator/cryptolib/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/cryptolib/compare/2.2.1...2.2.2)

Updates `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.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.1.0...6.0.0)

Updates `ch.qos.logback:logback-core` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `ch.qos.logback:logback-classic` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `ch.qos.logback:logback-classic` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0

Updates `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.0
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0

Updates `com.google.dagger:dagger` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `com.google.dagger:dagger-compiler` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.2.2...v3.2.3)

Updates `com.google.dagger:dagger-compiler` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `org.cryptomator:integrations-linux` from 1.7.0-beta3 to 1.7.0-beta4
- [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.7.0-beta3...1.7.0-beta4)

---
updated-dependencies:
- dependency-name: org.cryptomator:cryptolib
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:fuse-nio-adapter
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-core
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.github.ben-manes.caffeine:caffeine
  dependency-version: 3.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-linux
  dependency-version: 1.7.0-beta4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 06:06:54 +00:00
Armin Schrenk
7275ec9a61 fix envsubst command 2026-02-13 18:17:14 +01:00
Armin Schrenk
0fa34dba33 replace PKGBUILD with PKGBUILD.template
use envsubst to create actual PKGBUILD
2026-02-13 17:49:45 +01:00
Armin Schrenk
49f070977a use proper quotes 2026-02-13 13:59:11 +01:00
Armin Schrenk
35f39a9eaf minor fixes 2026-02-13 13:58:04 +01:00
Armin Schrenk
b9d21b1b7a replace hypens with underscore in pkgbuild version 2026-02-13 13:55:56 +01:00
Armin Schrenk
2e698317e5 Indirect github action inputs with env vars 2026-02-13 13:50:39 +01:00
Armin Schrenk
9c88fbab5e merge tarball job into pr creation job 2026-02-13 13:41:54 +01:00
Armin Schrenk
1a51642eb1 fix workflow 2026-02-13 13:30:47 +01:00
Armin Schrenk
fdaf5d1c36 rename 'aur' dir to ' makepkg'
mention the format rather a specific repository
2026-02-13 13:29:38 +01:00
Armin Schrenk
00e824a1ba fix workflow 2026-02-13 13:24:04 +01:00
Armin Schrenk
9c5ab7e311 build arch package on CLI 2026-02-13 13:18:34 +01:00
mindmonk
0bec741c2b Merge pull request #4120 from cryptomator/feature/disable-password-tab-if-masterkey-missing
Disable recovery key actions in Vault Password options when masterkey is missing
2026-02-12 18:08:52 +01:00
Armin Schrenk
af43aeca15 Merge branch 'develop' into feature/javafx-color-scheme-change 2026-02-12 10:18:32 +01:00
Armin Schrenk
1629eae5d3 [skip ci] update changelog 2026-02-11 15:55:34 +01:00
Armin Schrenk
99898b74fb minor cleanup 2026-02-11 15:55:19 +01:00
Armin Schrenk
327d6065e9 Merge pull request #4105 from cryptomator/feature/admin-properties
Feature: Admin Config
2026-02-11 15:25:31 +01:00
Armin Schrenk
2a5ef5d999 log inconsistent state 2026-02-11 15:21:55 +01:00
Armin Schrenk
34e5d19a04 prevent resource leak 2026-02-11 15:16:11 +01:00
Armin Schrenk
33851a8559 Refactor admin props
* rename class to AdminPropertiesFactory
* rename factory method to "create"
* remove side effects from methods
* returned properties default to system properties
2026-02-11 15:12:52 +01:00
Armin Schrenk
fb54d96997 fix wrong method delegation 2026-02-11 14:49:56 +01:00
Armin Schrenk
cff47b1c73 wrap system properties instead of direct modification 2026-02-11 14:36:55 +01:00
Armin Schrenk
5db05d8bc7 Apply suggestions from codereview 2026-02-11 14:33:01 +01:00
Armin Schrenk
b85780eae9 Disable JavaFX based UiAppearanceProvider for macOS 2026-02-11 12:22:22 +01:00
Ralph Plawetzki
bdfd22c483 Partially reverts dd1af8cd78
Not needed anymore, see https://github.com/cryptomator/integrations-linux/pull/125#issuecomment-3876060158
2026-02-11 06:07:01 +01:00
Armin Schrenk
e3433cb312 Refactor FxApplicationStyle class 2026-02-10 18:17:09 +01:00
Armin Schrenk
46d1d605ad refactor JfxUiAppearanceProvider class
* use delegate pattern for initialization
* add logging
2026-02-10 18:01:36 +01:00
Armin Schrenk
a4eadd4817 remove theme change restrictions 2026-02-10 17:58:29 +01:00
Armin Schrenk
c6717bd4e1 Rely on javafx to change color theme 2026-02-09 17:48:23 +01:00
Armin Schrenk
53f368108a Rename jvm property and actual config file 2026-02-09 16:54:04 +01:00
Armin Schrenk
5e52811c74 Remove hard coded default locations for admin config 2026-02-09 16:49:12 +01:00
Armin Schrenk
cad7b45808 Refactor to first check system property cryptomator.adminConfig for config path 2026-02-09 16:16:26 +01:00
Armin Schrenk
a057bf6f70 Merge branch 'develop' into feature/admin-properties 2026-02-09 15:03:06 +01:00
Armin Schrenk
4cf11cf293 [skip ci] update changelog 2026-02-09 14:56:37 +01:00
Armin Schrenk
2523609996 disable loading of user defined config for windows msi (#4132) 2026-02-09 14:49:07 +01:00
dependabot[bot]
80276ee992 Bump the github-actions group across 1 directory with 8 updates (#4124)
Bumps the github-actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `6.0.1` | `6.0.2` |
| [actions/setup-java](https://github.com/actions/setup-java) | `5.1.0` | `5.2.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `5.0.0` | `6.0.0` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `6.0.0` | `7.0.0` |
| [actions/cache](https://github.com/actions/cache) | `4.3.0` | `5.0.3` |
| [skymatic/workflows/.github/workflows/run-dependency-check.yml](https://github.com/skymatic/workflows) | `3.0.1` | `3.0.2` |
| [fjogeleit/http-request-action](https://github.com/fjogeleit/http-request-action) | `1.16.6` | `2.0.0` |
| [skymatic/workflows](https://github.com/skymatic/workflows) | `3.0.1` | `3.0.2` |



Updates `actions/checkout` from 6.0.1 to 6.0.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](8e8c483db8...de0fac2e45)

Updates `actions/setup-java` from 5.1.0 to 5.2.0
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](f2beeb24e1...be666c2fcd)

Updates `actions/upload-artifact` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](330a01c490...b7c566a772)

Updates `actions/download-artifact` from 6.0.0 to 7.0.0
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](018cc2cf5b...37930b1c2a)

Updates `actions/cache` from 4.3.0 to 5.0.3
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](0057852bfa...cdf6c1fa76)

Updates `skymatic/workflows/.github/workflows/run-dependency-check.yml` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](1074588008...2d0c27a7b0)

Updates `fjogeleit/http-request-action` from 1.16.6 to 2.0.0
- [Release notes](https://github.com/fjogeleit/http-request-action/releases)
- [Changelog](https://github.com/fjogeleit/http-request-action/blob/main/RELEASE.md)
- [Commits](c0b95d02a0...551353b829)

Updates `skymatic/workflows` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](1074588008...2d0c27a7b0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-java
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/cache
  dependency-version: 5.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: skymatic/workflows/.github/workflows/run-dependency-check.yml
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: fjogeleit/http-request-action
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: skymatic/workflows
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 09:27:49 +01:00
Ralph Plawetzki
561432bc98 Revert "Make SecretServiceKeychainAccess the default selection"
This reverts commit 9a74194391.
Users decide when to migrate.
2026-02-05 08:15:10 +01:00
Ralph Plawetzki
cd0a640a36 Enable migrating KeychainEntries on Linux as well 2026-02-05 07:09:38 +01:00
Armin Schrenk
a7b8541912 Update Slack webhook URL secret in workflow 2026-01-30 15:27:31 +01:00
Jan-Peter Klein
d4382f3130 remove docTooltip 2026-01-28 18:40:56 +01:00
Jan-Peter Klein
2983745be5 remove docs link 2026-01-28 18:20:18 +01:00
Armin Schrenk
77983fe00a simplify EventualLogger init 2026-01-28 17:44:48 +01:00
Armin Schrenk
a4836f6528 cleanup 2026-01-28 17:36:52 +01:00
Armin Schrenk
e9b3b505a8 apply suggestions from code review 2026-01-28 17:35:34 +01:00
Armin Schrenk
19c9eada9d check first the filesize before opening a Reader to the config file 2026-01-28 17:32:10 +01:00
Jan-Peter Klein
2a5bce2c5c disable password tab when masterkey.file is missing 2026-01-27 17:42:04 +01:00
mindmonk
9ee81a0e35 Merge pull request #4106 from cryptomator/feature/move-recover-io-tasks-to-background
Move recovery I/O to background thread
2026-01-26 13:30:39 +01:00
Jan-Peter Klein
8b05ae0a54 dedup createTask 2026-01-23 16:09:06 +01:00
Jan-Peter Klein
aa898c634f refactor recovery restore to sync logic with async task wrapper for testability 2026-01-23 13:57:38 +01:00
Armin Schrenk
efbd107fb5 increase null safety 2026-01-21 18:09:26 +01:00
Armin Schrenk
300cac5441 don't forget log markers 2026-01-21 16:36:56 +01:00
Armin Schrenk
b651b9ac26 config file can be exactly the max size 2026-01-21 16:08:00 +01:00
Armin Schrenk
29e76e7f93 keep throwables in EventualLogger 2026-01-21 16:07:17 +01:00
Armin Schrenk
5cac6b8114 also adjust distribution 2026-01-21 15:55:04 +01:00
Armin Schrenk
35c2141fd6 cleanup 2026-01-21 15:34:34 +01:00
Armin Schrenk
b00c81c20a use "cryptomator.config" for config file 2026-01-21 15:34:24 +01:00
Armin Schrenk
7ee0606306 adjust unit tests 2026-01-21 15:34:08 +01:00
Armin Schrenk
046372f95b refactored BufferedLog
* rename to EventualLogger
* adhere to slf4j API
* ensure single instance
2026-01-21 15:33:26 +01:00
Armin Schrenk
c198adaf3f switch back to properties 2026-01-21 11:53:31 +01:00
Armin Schrenk
d53f0880ca add test for AdminPropertiesSetter 2026-01-15 18:06:24 +01:00
Armin Schrenk
088b177c0e Ensure that null map is also logged 2026-01-15 15:11:46 +01:00
Armin Schrenk
287ab4e792 [skip ci] Update changelog 2026-01-15 15:11:12 +01:00
Armin Schrenk
0e9cad5b09 Merge pull request #4103 from cryptomator/feature/basic-accessibility
Feature: Improve accessibility for core functionality
2026-01-15 10:44:16 +01:00
Armin Schrenk
a0c9caeb21 [skip ci] update changelog 2026-01-14 17:57:24 +01:00
Armin Schrenk
f620c6685a apply suggestions from AI review 2026-01-14 17:53:07 +01:00
Armin Schrenk
61be8c449c fixed flush does not clear BufferedLog 2026-01-14 17:39:49 +01:00
Armin Schrenk
43343b9954 fix wrong Linux path 2026-01-14 17:36:07 +01:00
Armin Schrenk
460b7e6225 [skip ci] update changelog 2026-01-14 17:33:45 +01:00
Armin Schrenk
e2430bfb22 add null check 2026-01-14 17:29:56 +01:00
Armin Schrenk
ac7c9c2165 use a bracket to "describe" the vault state 2026-01-14 17:28:20 +01:00
Jan-Peter Klein
efd73e0d3e move recovery IO operations to background 2026-01-14 17:14:23 +01:00
Armin Schrenk
b441803462 also adjust wix installer to new config format 2026-01-14 16:28:48 +01:00
Armin Schrenk
42b06aa556 Switch to JSON as config format
Java Properties require ISO 8859-1 character encoding, leading to manual edits of file.
2026-01-14 14:12:28 +01:00
Armin Schrenk
b1c21501a6 Add dummy admin properties file in Windows installer 2026-01-13 18:40:53 +01:00
Armin Schrenk
45633837e0 only allow overwriting a subset of JVM properties 2026-01-13 17:26:48 +01:00
Armin Schrenk
b23bd0b27a Implement logic to overwrite system properties set in app internal config file 2026-01-13 13:14:40 +01:00
Armin Schrenk
b3f3faf4ee add DIALOG role to more dialogs 2026-01-13 11:02:01 +01:00
Armin Schrenk
33f26bf804 Refactor notificationbar
* rename to InfoBar
* replace closeButton text with graphic and add accessibilityText
* use common base class for styling and use CSS lookup for variants
2026-01-12 23:31:37 +01:00
Armin Schrenk
a06accb80f add accessibletext to vault storage location 2026-01-12 23:15:40 +01:00
Armin Schrenk
a50e372f05 add correct accessible role to dialogs 2026-01-12 23:14:09 +01:00
Armin Schrenk
06726303fb add proper accessibility text for vault list 2026-01-12 23:13:15 +01:00
Armin Schrenk
11c86f7287 impl idea 2026-01-12 11:59:17 +01:00
mindmonk
8e68a62ab0 Merge pull request #4081 from cryptomator/feature/hub-vault-archived-dialog
Feature: Show dedicated “Archived Vault” screen on unlock when Hub returns 410
2026-01-06 11:20:29 +01:00
Jan-Peter Klein
787d0b8e12 code cleanup 2026-01-05 14:00:20 +01:00
Jan-Peter Klein
ba765f7a69 code cleanup 2026-01-05 13:31:45 +01:00
Jan-Peter Klein
e9d7e631c7 fix typo 2026-01-05 13:27:50 +01:00
Jan-Peter Klein
88acbc8ed7 fix typo 2026-01-05 13:22:01 +01:00
Jan-Peter Klein
e84a73b9c3 use SimpleDialog 2026-01-05 13:17:10 +01:00
Jan-Peter Klein
2324ddad8b update changelog 2026-01-05 11:53:51 +01:00
Jan-Peter Klein
04da2504de Merge branch 'develop' into feature/hub-vault-archived-dialog 2026-01-05 11:28:08 +01:00
Armin Schrenk
ad240eb18b Merge branch 'develop' into release/1.19.0
# Conflicts:
#	pom.xml
2025-12-30 12:40:06 +01:00
Armin Schrenk
8105dbc236 Closes #4058 2025-12-30 12:31:45 +01:00
Armin Schrenk
ceed70c314 [skip ci] update changelog 2025-12-29 16:59:01 +01:00
Armin Schrenk
eddf586b81 Merge pull request #4078 from cryptomator/feature/files-in-use
Feature: Files in use
2025-12-29 16:00:36 +01:00
Armin Schrenk
0d7ddd3189 [skip ci] Update changelog 2025-12-29 15:55:49 +01:00
Armin Schrenk
491cd5e550 install/remove the encrypted mime type on install/uninstall 2025-12-29 15:22:26 +01:00
Armin Schrenk
93d95ecd93 make message more clear
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-21 12:42:11 +01:00
Armin Schrenk
05a41a625c reset selection index everytime window is shown
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-21 12:32:35 +01:00
Armin Schrenk
2aff02a186 cleanup
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-21 12:27:07 +01:00
Armin Schrenk
4b7de11750 dedup css
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-21 12:26:08 +01:00
Armin Schrenk
aaf921afcf Adjust notification dialog
* add scrollbar to description content
* move filename to own visual element
* move vaultName above message

Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-21 11:40:02 +01:00
Armin Schrenk
7718445f7c rename method
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-21 11:00:01 +01:00
Armin Schrenk
0fa27f66c9 Use proper icon for in-use event 2025-12-19 13:54:47 +01:00
Armin Schrenk
111c5ae2de correctly convert URI path to system path 2025-12-19 13:25:42 +01:00
Armin Schrenk
8841bb1c6a add c9u as file extension 2025-12-18 17:55:43 +01:00
Armin Schrenk
8ca7e34d8f minor fixes 2025-12-18 16:47:45 +01:00
Armin Schrenk
0fa6f0d915 only close notification window on index error 2025-12-18 16:20:58 +01:00
Armin Schrenk
4ffd8f4467 add localization for file-is-in-use-event in event view 2025-12-18 16:19:42 +01:00
Armin Schrenk
bb0c1b54c1 Add log message to get used mount service 2025-12-18 15:39:56 +01:00
Armin Schrenk
8eb91f6471 Change design of files-in-use-notification
* add timestamp of event occurance
* move filename into message section
* remove translations
2025-12-18 13:28:04 +01:00
Armin Schrenk
eb20fd7278 add device name to filesystemowner and display device name in notification 2025-12-17 16:55:42 +01:00
Armin Schrenk
d836798361 only one instance of notification window 2025-12-17 16:27:10 +01:00
Jan-Peter Klein
760e260eba show archived vault dialog on unlock when Hub returns 410 2025-12-17 09:56:56 +01:00
Armin Schrenk
0cd6eb8b5e use Path api to concat (string) paths for events
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-16 12:52:35 +01:00
Armin Schrenk
0b2107309b guard the notification window from theoretical thread races
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-16 12:33:25 +01:00
dependabot[bot]
309881b339 Bump the github-actions group across 1 directory with 8 updates (#4073)
Bumps the github-actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `5.0.0` | `6.0.1` |
| [actions/setup-java](https://github.com/actions/setup-java) | `5.0.0` | `5.1.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4.6.2` | `5.0.0` |
| [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `2.4.1` | `2.5.0` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `5.0.0` | `6.0.0` |
| [fjogeleit/http-request-action](https://github.com/fjogeleit/http-request-action) | `1.16.5` | `1.16.6` |
| [actions/stale](https://github.com/actions/stale) | `10.1.0` | `10.1.1` |
| [skymatic/workflows](https://github.com/skymatic/workflows) | `450e322ff2214d0be0b079b63343c894f3ef735f` | `1074588008ae3326a2221ea451783280518f0366` |



Updates `actions/checkout` from 5.0.0 to 6.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](08c6903cd8...8e8c483db8)

Updates `actions/setup-java` from 5.0.0 to 5.1.0
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](dded088883...f2beeb24e1)

Updates `actions/upload-artifact` from 4.6.2 to 5.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](ea165f8d65...330a01c490)

Updates `softprops/action-gh-release` from 2.4.1 to 2.5.0
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](6da8fa9354...a06a81a03e)

Updates `actions/download-artifact` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](634f93cb29...018cc2cf5b)

Updates `fjogeleit/http-request-action` from 1.16.5 to 1.16.6
- [Release notes](https://github.com/fjogeleit/http-request-action/releases)
- [Commits](1297c6fc63...c0b95d02a0)

Updates `actions/stale` from 10.1.0 to 10.1.1
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](5f858e3efb...997185467f)

Updates `skymatic/workflows` from 450e322ff2214d0be0b079b63343c894f3ef735f to 1074588008ae3326a2221ea451783280518f0366
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](450e322ff2...1074588008)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/setup-java
  dependency-version: 5.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: softprops/action-gh-release
  dependency-version: 2.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: fjogeleit/http-request-action
  dependency-version: 1.16.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/stale
  dependency-version: 10.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: skymatic/workflows
  dependency-version: 1074588008ae3326a2221ea451783280518f0366
  dependency-type: direct:production
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-16 09:54:39 +01:00
Armin Schrenk
532cdf30ac Fix typos 2025-12-12 17:41:29 +01:00
Armin Schrenk
d746e9e215 add translation to event 2025-12-12 16:55:15 +01:00
Armin Schrenk
408c80744a Show notification for fileIsInUseEvent 2025-12-12 13:29:46 +01:00
Armin Schrenk
bf890d2165 Merge pull request #4069 from cryptomator/feature/notify-fallback
Feature: Notification Window with JavaFX
2025-12-12 12:42:37 +01:00
Armin Schrenk
eb90a7fb33 Merge branch 'feature/files-in-use' into feature/notify-fallback
# Conflicts:
#	src/main/java/org/cryptomator/common/EventMap.java
#	src/main/java/org/cryptomator/common/vaults/Vault.java
2025-12-12 12:31:08 +01:00
Armin Schrenk
a47814f38c cleanup 2025-12-12 12:26:46 +01:00
Armin Schrenk
8b157fd935 add dark theme 2025-12-12 12:25:47 +01:00
Armin Schrenk
5e582f666c add accessibleText 2025-12-12 11:37:42 +01:00
Armin Schrenk
bebe3064ee hide paging if there is only one event 2025-12-12 11:21:39 +01:00
Armin Schrenk
bbf8e1d1e5 Ensure that keyloader is not reused between vaults 2025-12-11 14:35:23 +01:00
Armin Schrenk
98d2442deb For hub vaults set filesystem owner 2025-12-11 14:34:45 +01:00
Armin Schrenk
cac5c86dab Merge branch 'develop' into feature/files-in-use
# Conflicts:
#	pom.xml
2025-12-10 13:04:34 +01:00
Armin Schrenk
5a0145800d Redesign notifcation dialog
* add Cryptomator title
* include vault name in message
* remove bottom section and move button to current message area
2025-12-10 13:01:07 +01:00
Armin Schrenk
f4b56e5e51 rename variable 2025-12-10 12:34:33 +01:00
Armin Schrenk
7cfb63ed48 cleanup in NotificationController 2025-12-10 12:34:09 +01:00
Armin Schrenk
2521cd2bfb cleanup
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-09 18:13:04 +01:00
Armin Schrenk
1e861ac187 fix av-whitelist workflow 2025-12-09 09:34:25 +01:00
Tobias Hagemann
a4c85be61c Add accessible text to form controls and table columns (#4066) 2025-12-06 07:41:39 +01:00
Armin Schrenk
5b9e70da33 implement code suggestions
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 17:32:24 +01:00
Armin Schrenk
b83a3c27c6 [skip ci] remove unused import
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 16:52:04 +01:00
Armin Schrenk
5c2954de03 guard controller from NPE
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 16:43:39 +01:00
Armin Schrenk
8a834fe71c fix window placement
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 16:38:37 +01:00
Armin Schrenk
4ff2905723 regularly poll for notification updates
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 16:37:31 +01:00
Armin Schrenk
538e01b1e5 consider location of system bar when placing notification window
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 15:54:05 +01:00
Armin Schrenk
3135be9178 fix logic in notificationManager
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 12:14:07 +01:00
Armin Schrenk
2c456f5323 fix more issues
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 11:58:16 +01:00
Armin Schrenk
9d464e3a4f fix threading issue in notification manager
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 11:53:43 +01:00
Armin Schrenk
83199eb1de use VaultEvent for notification to also show affected vault
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 11:35:54 +01:00
Armin Schrenk
5772ffec17 activate notifications by consuming vault events
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 11:27:01 +01:00
Armin Schrenk
f3415277d7 cleanup
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 11:23:52 +01:00
Armin Schrenk
8e9a001fde clean up
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 10:50:48 +01:00
Armin Schrenk
5e229395f1 remove test code
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-05 10:50:32 +01:00
Armin Schrenk
18dd9770f2 add second fake event
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-04 17:03:47 +01:00
Armin Schrenk
185c5a4f5d implement more ui logic
and reduce css

Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-04 17:03:36 +01:00
Armin Schrenk
285ddac219 ai thoughts
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-04 16:20:49 +01:00
Armin Schrenk
9e631a78f2 Pimp notification dialog
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-12-04 15:35:05 +01:00
Tobias Hagemann
7fe9049266 Improve accessibility for icon-only controls and input labels (#4064) 2025-12-01 22:06:57 +01:00
Tobias Hagemann
39ab9ad63f Merge pull request #4055 from tamaracha/fix_a11y_buttons
Fix a11y for no-graphics buttons in main window
2025-12-01 16:13:10 +01:00
Armin Schrenk
b4528f825e [skip ci] drop interface approach and just add fx window 2025-11-29 18:03:55 +01:00
Armin Schrenk
3d679c73e7 [skip ci] impl draft
Signed-off-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-11-28 14:31:04 +01:00
Sebastian Stenzel
04bdb2d8c4 fix mocked update check 2025-11-24 20:58:57 +01:00
Sebastian Stenzel
f32d24c1c0 Merge branch 'develop' into release/1.19.0 2025-11-24 20:58:25 +01:00
Sebastian Stenzel
f4f093bb42 update GitHub Releases Template
[ci skip]
2025-11-24 19:57:24 +01:00
Sebastian Stenzel
3f06460667 bump version 2025-11-24 14:50:19 +01:00
Sebastian Stenzel
617f1bf2c9 CHANGELOG.md: added
[ci skip]
2025-11-24 14:49:12 +01:00
Sebastian Stenzel
02ad38f871 Merge pull request #3948 from purejava/feature/app-update
Implement new update API
2025-11-24 14:41:55 +01:00
Sebastian Stenzel
7a2944cbea bump integrations version 2025-11-24 14:39:17 +01:00
Sebastian Stenzel
4c47204f92 Merge branch 'develop' into feature/app-update 2025-11-24 14:34:44 +01:00
Tamara Cook
b6d0823c24 Add accessible text and tooltips to no-graphics buttons in main window 2025-11-23 22:24:31 +01:00
Tamara Cook
7f4776a995 Make buttons clickable by any input device 2025-11-23 19:26:55 +01:00
Armin Schrenk
9d2b31cd56 Merge branch 'develop' into feature/files-in-use 2025-11-21 10:15:24 +01:00
Tobias Hagemann
f052395a7f Add section on use of Generative AI 2025-11-17 15:03:08 +01:00
Sebastian Stenzel
57be83b38d update license-merges 2025-11-12 11:56:09 +01:00
Sebastian Stenzel
c2cd4f5bbf update compiler.xml
[ci skip]
2025-11-12 11:55:59 +01:00
Sebastian Stenzel
d3d57312ba Merge branch 'develop' into feature/app-update
# Conflicts:
#	.github/workflows/appimage.yml
#	.github/workflows/check-jdk-updates.yml
#	.github/workflows/debian.yml
#	.github/workflows/mac-dmg-x64.yml
#	.github/workflows/mac-dmg.yml
#	.github/workflows/win-exe.yml
2025-11-12 11:50:21 +01:00
Sebastian Stenzel
593a64c9bd Bump JDK to version 25 (#4031)
* first draft for JDK 25 migration (including comments)

* fix unresolvable version in setup-java action

* switch to official `openjdk-25-jdk` ubuntu package

see https://packages.ubuntu.com/search?suite=jammy&arch=any&searchon=names&keywords=openjdk-25

* update jacoco to support JDK 25

* use jdk 25.0.1 for building the app

# Conflicts:
#	.github/workflows/win-exe.yml

* Use correct SHA256 value for openjfx linux arm64

* zulu version is different to temurin :rolling_eyes:

* fix check-jdk-updates

---------

Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-11-12 10:50:37 +01:00
sunnyraindy
19dc4fb6ff chore: fix typo in comment (#4036)
Signed-off-by: sunnyraindy <sunnyraindy@outlook.com>
2025-11-12 10:49:14 +01:00
Armin Schrenk
81f45012f3 [skip ci] Merge branch 'main' into develop 2025-11-12 10:45:38 +01:00
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
f91cc2374c fix syntax error (really!) 2025-11-08 10:48:29 +01:00
Sebastian Stenzel
48298bb161 fix syntax error 2025-11-08 10:37:10 +01:00
Sebastian Stenzel
7a1cd9026c use dmg update mechanism 2025-11-08 10:24:11 +01:00
Sebastian Stenzel
754e53d8db cleanup 2025-11-08 10:18:40 +01:00
Sebastian Stenzel
c36f1bc8d0 moved update mechanism classes to integrations-* 2025-11-07 13:59:10 +01:00
Sebastian Stenzel
7315b59a6d simplify + allow IDE to find used i18n strings 2025-11-06 15:36:08 +01:00
Sebastian Stenzel
8a243a01aa cleanup + error handling 2025-11-06 15:35:12 +01:00
Sebastian Stenzel
9e4006cc89 improved error handling 2025-11-06 10:47:15 +01:00
Sebastian Stenzel
26b69beb87 prevent updates while having unlocked vaults 2025-11-06 10:08:49 +01:00
Sebastian Stenzel
f95bf87a4b reordered getters
[ci skip]
2025-11-06 07:41:30 +01:00
Sebastian Stenzel
e854c7d189 detect failed update attempt via new setting 2025-11-05 22:26:45 +01:00
Sebastian Stenzel
8a434dcd96 more robust settings, exposed saveNow() 2025-11-05 22:23:34 +01:00
Sebastian Stenzel
6b7324723e apply more suggestions from code review 2025-11-04 22:07:05 +01:00
Sebastian Stenzel
0bdcb2b3be adjust to type-safe api 2025-11-04 21:42:24 +01:00
Sebastian Stenzel
c3931d9d29 apply review suggestions 2025-11-04 21:42:14 +01:00
Sebastian Stenzel
307825a339 fix param order 2025-11-04 11:43:08 +01:00
Sebastian Stenzel
093f0e8c94 cleanup updater 2025-11-04 11:12:43 +01:00
Sebastian Stenzel
c938c42c00 unified "check for update" and "do update" button 2025-11-02 15:40:32 +01:00
Armin Schrenk
cee22e34db adjust display text 2025-10-31 14:18:07 +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
Ralph Plawetzki
9a74194391 Make SecretServiceKeychainAccess the default selection 2025-10-27 05:33:35 +01:00
Armin Schrenk
18300ee67f [skip ci] adjust to changed API 2025-10-21 15:36:51 +02:00
Sebastian Stenzel
59560193ee adjust to new multi-step update API 2025-10-21 11:32:45 +02:00
Sebastian Stenzel
a6b31e19b9 Merge branch 'feature/jdk25' into feature/app-update
# Conflicts:
#	.idea/compiler.xml
#	pom.xml
2025-10-17 17:03:43 +02:00
Sebastian Stenzel
8a44115234 update jacoco to support JDK 25 2025-10-17 15:25:18 +02:00
Sebastian Stenzel
43a1f00bea switch to official openjdk-25-jdk ubuntu package
see https://packages.ubuntu.com/search?suite=jammy&arch=any&searchon=names&keywords=openjdk-25
2025-10-17 12:47:13 +02:00
Sebastian Stenzel
3e458060bc Merge branch 'develop' into feature/jdk25
# Conflicts:
#	.github/workflows/debian.yml
#	.github/workflows/dependency-check.yml
#	.github/workflows/win-exe.yml
#	.idea/misc.xml
#	dist/linux/debian/control
2025-10-17 12:27:28 +02:00
Sebastian Stenzel
4bb5a3f10d fix unresolvable version in setup-java action 2025-10-17 12:12:44 +02: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
5797108dfe Merge branch 'develop' into feature/files-in-use 2025-10-16 12:33:14 +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
e1ff552f08 [skip ci] pick a distinguishable name for fs owner 2025-10-15 17:27:12 +02:00
Armin Schrenk
f3d4494d91 [skip ci] Adjust event view to new API 2025-10-15 17:21:20 +02:00
Armin Schrenk
bdc1cc3f05 Merge branch 'develop' into feature/files-in-use
# Conflicts:
#	pom.xml
2025-10-15 17:20:37 +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
cdcd43a805 first draft for JDK 25 migration (including comments) 2025-09-25 12:28:12 +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
Armin Schrenk
f5bd23de51 test impl 2025-09-02 09:58:52 +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
Sebastian Stenzel
d5245009f4 Merge branch 'feature/self-update-poc' into feature/app-update
# Conflicts:
#	src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java
#	src/main/resources/fxml/preferences_updates.fxml
2025-08-09 09:26:38 +02:00
Sebastian Stenzel
8f4392711e moved update API to integrations-api 2025-08-08 18:21:42 +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
Ralph Plawetzki
79bb4a5215 Correlate with API as suggested in a separate PoC: UpdateMechanism and UpdateProcess 2025-08-02 11:32:07 +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
Ralph Plawetzki
2ce7fee06d Log error messages 2025-07-30 19:43:39 +02:00
Ralph Plawetzki
99e9e92f10 Fix progress bar due to JavaFX limitations 2025-07-30 19:21:34 +02:00
Ralph Plawetzki
8e6500d93f Implement update button that updates and respawns the app 2025-07-30 19:21:34 +02:00
Ralph Plawetzki
89ce99deaf Wire UpdateService 2025-07-30 19:21:34 +02:00
Ralph Plawetzki
510e134605 Have multiple services 2025-07-30 19:21:34 +02:00
Ralph Plawetzki
62b434f549 Invent UpdatesModule 2025-07-30 19:21:33 +02:00
Ralph Plawetzki
1f1e336d57 Start FlatpakUpdater 2025-07-30 19:21:33 +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
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
Jan-Peter Klein
b00ee4740a legacy vaults supported now 2025-07-07 14:58:19 +02:00
Sebastian Stenzel
02186ca17a hooked up in UI 2025-07-06 20:02:41 +02:00
Sebastian Stenzel
b0ed133e05 PoC 2025-07-06 14:28:57 +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
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
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
Jan-Peter Klein
6fcec26eea removed additional redetermineVaultState 2025-06-17 14:39:10 +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
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
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
Jan-Peter Klein
8c84720e24 solve some todos 2025-06-04 10:47:56 +02:00
Jan-Peter Klein
968e8f51e4 new onboarding dialog
remove is hub vault dialog
2025-05-30 15:30:38 +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
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
301 changed files with 9857 additions and 2500 deletions

View File

@@ -20,6 +20,10 @@
Translations are not managed directly in this repository. Instead, we use [Crowdin](https://translate.cryptomator.org/), which automatically synchronizes translations with this repository. If you want to help us with translations, please visit our translation project on Crowdin.
## Use of Generative AI
AI tools may assist your work, but every contribution must be fully understood, reviewed, and tested by you. Only submit changes you can clearly explain and justify. Unverified or low-quality AI output that wastes our time and resources will be closed without further review.
## Code of Conduct
Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md).

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/artifact-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0
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 }}
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

@@ -14,6 +14,9 @@ updates:
versions: ["2.0.1.MR"]
- dependency-name: "org.openjfx:*"
update-types: ["version-update:semver-major"]
# due to https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter/issues/68
- dependency-name: "org.apache.maven.plugins:maven-surefire-plugin"
versions: [ "3.5.4", "3.5.5" ]
groups:
java-test-dependencies:
patterns:

View File

@@ -8,6 +8,10 @@ on:
version:
description: 'Version'
required: false
create-pr:
description: 'Create a PR for aur-bin repo'
type: boolean
default: false
push:
branches-ignore:
- 'dependabot/**'
@@ -19,7 +23,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '24.0.1+9'
JAVA_VERSION: '25.0.2+10.0.LTS'
jobs:
get-version:
@@ -31,22 +35,28 @@ jobs:
name: Build AppImage
runs-on: ${{ matrix.os }}
needs: [get-version]
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
SEMVER_NUM: ${{ needs.get-version.outputs.semVerNum }}
REV_NUM: ${{ needs.get-version.outputs.revNum }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-x64_bin-jmods.zip'
openjfx-sha: '425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
arch: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
appimagetool-sha: 'ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0'
- os: ubuntu-24.04-arm
appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-aarch64_bin-jmods.zip'
openjfx-sha: '7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
arch: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
appimagetool-sha: 'f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -55,7 +65,7 @@ jobs:
- name: Download OpenJFX jmods
id: download-jmods
run: |
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
curl --silent --fail-with-body --proto "=https" -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
echo "${{ matrix.openjfx-sha }} openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods
unzip -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
@@ -73,9 +83,9 @@ jobs:
exit 1
fi
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
run : mvn versions:set -DnewVersion="$SEMVER_STR"
- 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
@@ -94,13 +104,15 @@ jobs:
${JAVA_HOME}/bin/jlink
--verbose
--output runtime
--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.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
--strip-debug
--compress zip-0
env:
JMOD_PATHS: ${{ steps.jep-493-check.outputs.jmod_paths }}
- name: Run jpackage
run: >
${JAVA_HOME}/bin/jpackage
@@ -114,25 +126,25 @@ jobs:
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--app-version "${SEMVER_NUM}.${REV_NUM}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator"
--java-options "--sun-misc-unsafe-memory-access=allow"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\""
--java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--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.buildNumber=\"appimage-${REV_NUM}\""
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
--resource-dir dist/linux/resources
- name: Patch Cryptomator.AppDir
@@ -156,7 +168,8 @@ jobs:
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
- name: Download AppImageKit
run: |
curl -L https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.appimage-suffix }}.AppImage -o appimagetool.AppImage
curl --silent --fail-with-body --proto "=https" -L "https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-${{ matrix.arch }}.AppImage" -o appimagetool.AppImage
echo "${{ matrix.appimagetool-sha }} appimagetool.AppImage" | shasum -a256 --check
chmod +x appimagetool.AppImage
./appimagetool.AppImage --appimage-extract
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
@@ -168,17 +181,17 @@ jobs:
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- 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"
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${SEMVER_STR}-${{ matrix.arch }}.AppImage
-u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.arch }}.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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: appimage-${{ matrix.appimage-suffix }}
name: appimage-${{ matrix.arch }}
path: |
cryptomator-*.AppImage
cryptomator-*.AppImage.zsync
@@ -186,7 +199,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@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
@@ -197,65 +210,77 @@ jobs:
create-aur-bin-pr:
name: Create PR for aur-bin repo
needs: [build, get-version]
if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
runs-on: ubuntu-latest
if: github.event_name == 'release'
needs: [build, get-version]
container:
image: archlinux:base-devel
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
PKGDEST: ${{ github.workspace }}/pkgdest
SRCDEST: ${{ github.workspace }}/srcdest
steps:
- name: Download AppImages
uses: actions/download-artifact@v5
with:
path: downloads/
merge-multiple: true
- name: Compute sha256 hash of AppImages
id: checksums
- name: Prepare pacman
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@v5
pacman-key --init
pacman-key --populate archlinux
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl pacman-contrib
- name: Checkout cryptomator/aur-bin
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: 'cryptomator/aur-bin'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Install dependencies
- name: Create build user
run: |
sudo apt-get update
sudo apt-get -y install makepkg pacman-package-manager
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
chown -R builder:builder "$GITHUB_WORKSPACE"
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
- name: Import Cryptomator release signing key
# try first ubuntu. on failure try openpgp keyservers
run: >
sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|| sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
git config --global safe.directory '*'
git checkout -b "release/${SEMVER_STR}"
- name: Update build file
run: |
sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
sed -i -e "s|^pkgver=.*$|pkgver=${SEMVER_STR}|" 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
sudo -u builder updpkgsums
sudo -u builder makepkg --printsrcinfo > .SRCINFO
- name: Build package with makepkg
run: >
sudo -u builder
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
makepkg --syncdeps --cleanbuild --noconfirm --log
- 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 user.name "cryptobot"
git config user.email "cryptobot@users.noreply.github.com"
git config push.autoSetupRemote true
git stage .
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
git stage PKGBUILD .SRCINFO
git commit -m "Prepare release ${SEMVER_STR}"
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"
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
PR_URL=$(gh pr create --title "Release ${SEMVER_STR}" --body-file pr_body.md)
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- 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_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
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_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ needs.get-version.outputs.semVerStr }} created."
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
SLACK_FOOTER: false
MSG_MINIMAL: true

View File

@@ -1,93 +0,0 @@
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'
outputs:
url: ${{ steps.url.outputs.url}}
sha256: ${{ steps.sha256.outputs.sha256}}
steps:
- name: Determine tarball url
id: url
run: |
URL="";
if [[ -n "${{ inputs.tag }}" ]]; then
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ inputs.tag }}.tar.gz"
else
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz"
fi
echo "url=${URL}" >> "$GITHUB_OUTPUT"
- name: Download source tarball and compute checksum
id: 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@v5
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
uses: rtCamp/action-slack-notify@v2
if: github.event_name == 'release'
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "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

@@ -7,6 +7,16 @@ on:
description: "Url to the file to upload"
required: true
type: string
avast:
description: "Upload to Avast"
required: false
type: boolean
default: true
kaspersky:
description: "Upload to Kaspersky"
required: false
type: boolean
default: true
workflow_dispatch:
inputs:
url:
@@ -30,16 +40,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 --silent --fail-with-body --proto "=https" -L "${INPUT_URL}" -o "${{steps.extractName.outputs.fileName}}"
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ steps.extractName.outputs.fileName }}
path: ${{ steps.extractName.outputs.fileName }}
@@ -48,15 +60,15 @@ jobs:
name: Anti Virus Allowlisting Kaspersky
runs-on: ubuntu-latest
needs: download-file
if: github.event_name == 'workflow_call' || inputs.kaspersky
if: inputs.kaspersky
steps:
- name: Download artifact
uses: actions/download-artifact@v5
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
uses: SamKirkland/FTP-Deploy-Action@a51268f67f6605236975928ae28b0f7e9971d50a # v4.6.3
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
@@ -68,15 +80,15 @@ jobs:
name: Anti Virus Allowlisting Avast
runs-on: ubuntu-latest
needs: download-file
if: github.event_name == 'workflow_call' || inputs.avast
if: inputs.avast
steps:
- name: Download artifact
uses: actions/download-artifact@v5
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Avast
uses: wlixcc/SFTP-Deploy-Action@v1.2.6
- name: Upload to Avast
uses: wlixcc/SFTP-Deploy-Action@a5ccb9c6211a94cc59404f0fdb2a9936a6dfee64 # v1.2.6
with:
server: whitelisting.avast.com
port: 22

View File

@@ -11,7 +11,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 24
JAVA_VERSION: 25
defaults:
run:
@@ -22,14 +22,14 @@ jobs:
name: Compile and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-java@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Cache SonarCloud packages
uses: actions/cache@v4
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
@@ -37,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
@@ -49,28 +49,28 @@ 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@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
draft: true
discussion_category_name: releases
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
generate_release_notes: true
body: |-
:construction: Work in Progress
> [!NOTE]
> 🚧 Work in Progress 🚧
>
> Please be patient, the [builds are still running](https://github.com/cryptomator/cryptomator/actions). Binary packages can be found here in a few moments.
<!--REPLACE with auto-generated release notes (see below)
### What's New 🎉
### Bugfixes 🐛
### Other Changes 📎
END REPLACE-->
For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md).
---
TODO FULL CHANGELOG
📜 List of closed issues is available [here](TODO)
---
⏳ Please be patient, the builds are still [running](https://github.com/cryptomator/cryptomator/actions). New versions of Cryptomator can be found here in a few moments. ⏳
<!-- Don't forget to include the
💾 SHA-256 checksums of release artifacts:
@@ -78,4 +78,9 @@ jobs:
```
-->
As usual, the GPG signatures can be checked using [our public key `5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
> [!TIP]
> You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
<!-- Auto-Generated Release Notes: -->

View File

@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
JDK_VERSION: '24.0.1+9'
JDK_VERSION: '25.0.1+8.0.LTS'
JDK_VENDOR: temurin
RUNTIME_VERSION_HELPER: >
public class Test {
@@ -23,10 +23,10 @@ jobs:
JDK_MAJOR_VERSION: 'toBeFilled'
steps:
- name: Determine current major version
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,20) >> "$env:GITHUB_ENV"
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV"
shell: pwsh
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.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

@@ -23,13 +23,12 @@ on:
env:
JAVA_DIST: 'temurin'
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/24.0.1/openjfx-24.0.1_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
JAVA_VERSION: '25.0.2+10.0.LTS'
DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
jobs:
get-version:
@@ -41,38 +40,42 @@ jobs:
name: Build Debian Package
runs-on: ubuntu-22.04
needs: [get-version]
env:
INPUT_PPAVER: ${{ inputs.ppaver }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- id: deb-version
name: Determine deb-version
run: |
if [ -n "${{inputs.ppaver}}" ]; then
echo "debVersion=${{inputs.ppaver }}" >> "$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 }}
sudo apt-get install devscripts dput
sudo apt-get satisfy "${DEB_BUILD_DEPENDS}"
env:
DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }}
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.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: |
curl -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip
curl --silent --fail-with-body --proto "=https" -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip
echo "${{ env.OPENJFX_JMODS_AMD64_HASH }} openjfx-amd64.zip" | shasum -a256 --check
mkdir -p jmods/amd64
unzip -j openjfx-amd64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/amd64
curl -L ${{ env.OPENJFX_JMODS_AARCH64 }} -o openjfx-aarch64.zip
curl --silent --fail-with-body --proto "=https" -L ${{ env.OPENJFX_JMODS_AARCH64 }} -o openjfx-aarch64.zip
echo "${{ env.OPENJFX_JMODS_AARCH64_HASH }} openjfx-aarch64.zip" | shasum -a256 --check
mkdir -p jmods/aarch64
unzip -j openjfx-aarch64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/aarch64
@@ -140,7 +143,7 @@ jobs:
run: |
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: linux-deb-package
path: |

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@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # v3.0.3
with:
runner-os: 'ubuntu-latest'
java-distribution: 'temurin'
java-version: 24
check-command: 'mvn -B validate -Pdependency-check -Djavafx.platform=linux'
java-version: 25
secrets:
nvd-api-key: ${{ secrets.NVD_API_KEY }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
ossindex-token: ${{ secrets.OSSINDEX_API_TOKEN }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- name: Get download count of latest releases
id: get-stats
uses: actions/github-script@v8
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@551353b829c3646756b2ec2b3694f819d7957495 # v2.0.0
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@v8
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,17 +26,14 @@ 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: |
curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
echo "sha512=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
flathub:
@@ -46,7 +43,7 @@ jobs:
env:
FLATHUB_PR_URL: tbd
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
@@ -74,7 +71,7 @@ jobs:
env:
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: 24
JAVA_VERSION: 25
jobs:
determine-version:
@@ -35,11 +35,11 @@ jobs:
revNum: ${{ steps.versions.outputs.revNum }}
type: ${{ steps.versions.outputs.type}}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.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 }}

200
.github/workflows/linux-makepkg.yml vendored Normal file
View File

@@ -0,0 +1,200 @@
name: Build Arch package
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version'
required: false
create-pr:
description: 'Create a PR for aur repo'
type: boolean
default: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/linux-makepkg.yml'
- 'dist/linux/makepkg/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }}
makepkg:
name: Build with makepkg
needs: [get-version]
runs-on: ubuntu-latest
container:
image: archlinux:base-devel
env:
PKGDEST: ${{ github.workspace }}/pkgdest
SRCDEST: ${{ github.workspace }}/srcdest
steps:
- name: Prepare pacman
run: |
pacman-key --init
pacman-key --populate archlinux
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: cryptomator
- name: Create build user
run: |
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
chown -R builder:builder "$GITHUB_WORKSPACE"
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
- name: Prepare PKGBUILD
# cannot use github.workspace due to https://github.com/actions/runner/issues/2058
run: |
export SOURCES="${SOURCES_1}${GITHUB_WORKSPACE}${SOURCES_2}"
envsubst '$PKG_VERSION $PKG_RELEASE $SOURCES $SOURCES_SHA' < cryptomator/dist/linux/makepkg/PKGBUILD.template > PKGBUILD
env:
PKG_VERSION: ${{ needs.get-version.outputs.semVerNum }}
PKG_RELEASE: 1
SOURCES_1: '"${_src_app_dir}::git+file://'
SOURCES_2: '/cryptomator"'
SOURCES_SHA: "'SKIP'"
- name: Build package with makepkg
run: >
sudo -u builder
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
makepkg --syncdeps --cleanbuild --noconfirm --log
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: arch-package
if-no-files-found: error
path: |
${{ env.PKGDEST }}/*.pkg.tar.zst
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: pkgbuild-file
if-no-files-found: error
path: |
cryptomator/dist/linux/makepkg/PKGBUILD.template
create-pr:
name: Create PR for aur repo
if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
runs-on: ubuntu-latest
needs: [get-version, makepkg]
container:
image: archlinux:base-devel
env:
PKGDEST: ${{ github.workspace }}/pkgdest
SRCDEST: ${{ github.workspace }}/srcdest
steps:
- name: Prepare pacman
run: |
pacman-key --init
pacman-key --populate archlinux
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl
- name: Download source tarball and compute checksum
id: sha256
run: |
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz"
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${URL} --output cryptomator.tar.gz
TARBALL_SHA256=$(sha256sum cryptomator.tar.gz | cut -d ' ' -f1)
echo "value=${TARBALL_SHA256}" >> "$GITHUB_OUTPUT"
env:
TAG: ${{ needs.get-version.outputs.semVerStr || github.event.release.tag_name }}
- name: Checkout cryptomator/aur repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: 'cryptomator/aur'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Create build user
run: |
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
chown -R builder:builder "$GITHUB_WORKSPACE"
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
- name: Import Cryptomator release signing key
# try first ubuntu. on failure try openpgp keyservers
run: >
sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|| sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
- name: Checkout release branch
run: |
git config --global safe.directory '*'
git checkout -b release/${VERSION}
env:
VERSION: ${{ needs.get-version.outputs.semVerStr }}
- name: Determine pkgrel
id: pkgrel
run: |
TARGET_VERSION='${{ needs.get-version.outputs.semVerStr }}'
CURRENT_VERSION="$(sed -nE 's/^pkgver=(.*)$/\1/p' PKGBUILD | head -n1)"
CURRENT_REL="$(sed -nE 's/^pkgrel=([0-9]+).*$/\1/p' PKGBUILD | head -n1)"
if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" && "$CURRENT_REL" =~ ^[0-9]+$ ]]; then
NEXT_REL=$((CURRENT_REL + 1))
else
NEXT_REL=1
fi
echo "value=${NEXT_REL}" >> "$GITHUB_OUTPUT"
echo "dist-version=${VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT"
env:
VERSION: ${{ needs.get-version.outputs.semVerStr }}
- name: Download PKGBUILD template
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: pkgbuild-file
- name: Prepare PKGBUILD
run: |
envsubst '$PKG_VERSION $PKG_RELEASE $SOURCES $SOURCES_SHA' < PKGBUILD.template > PKGBUILD
sudo -u builder makepkg --printsrcinfo > .SRCINFO
env:
PKG_VERSION: ${{ needs.get-version.outputs.semVerNum }}
PKG_RELEASE: ${{ steps.pkgrel.outputs.value }}
SOURCES: |-
"cryptomator-${pkgver//_/-}.tar.gz::https://github.com/cryptomator/cryptomator/archive/refs/tags/${pkgver//_/-}.tar.gz"
"cryptomator-${pkgver//_/-}.tar.gz.asc::https://github.com/cryptomator/cryptomator/releases/download/${pkgver//_/-}/cryptomator-${pkgver//_/-}.tar.gz.asc"
SOURCES_SHA: |-
'${{steps.sha256.outputs.value}}'
'SKIP'
- name: Build package with makepkg
run: >
sudo -u builder
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
makepkg --syncdeps --cleanbuild --noconfirm --log
- name: Commit and push
run: |
git config user.name "cryptobot"
git config user.email "cryptobot@users.noreply.github.com"
git config push.autoSetupRemote true
git stage PKGBUILD .SRCINFO
git commit -m "Prepare release ${DIST_VERSION}"
git push
env:
DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }}
- name: Create pull request
id: create-pr
run: |
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
PR_URL=$(gh pr create --title "Release $DIST_VERSION" --body-file pr_body.md)
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
env:
DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }}
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_CRYPTOMATOR_DESKTOP }}
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 }} ${{ steps.pkgrel.outputs.dist-version }} ."
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
SLACK_FOOTER: false
MSG_MINIMAL: true

View File

@@ -24,7 +24,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '24.0.1+9'
JAVA_VERSION: '25.0.2+10.0.LTS'
jobs:
get-version:
@@ -44,12 +44,12 @@ jobs:
architecture: x64
output-suffix: x64
fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_osx-x64_bin-jmods.zip'
openjfx-sha: '6e62a426d43c168a488521f904a523f3dd6ee2cf103e08136f2fd465c828a105'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -59,7 +59,7 @@ jobs:
- name: Download OpenJFX jmods
id: download-jmods
run: |
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
curl --silent --fail-with-body --proto "=https" -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods/
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
@@ -79,7 +79,7 @@ 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
@@ -99,7 +99,7 @@ jobs:
--verbose
--output runtime
--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.unsupported,jdk.accessibility,jdk.management.jfr,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.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
@@ -121,7 +121,6 @@ jobs:
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "--sun-misc-unsafe-memory-access=allow"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\""
@@ -129,21 +128,24 @@ jobs:
--java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--mac-package-identifier org.cryptomator
--resource-dir dist/mac/resources
- name: Patch Cryptomator.app
run: |
mv appdir/Cryptomator.app Cryptomator.app
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
@@ -153,7 +155,7 @@ jobs:
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- 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
@@ -248,7 +250,7 @@ jobs:
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 }}
@@ -269,7 +271,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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: dmg-${{ matrix.output-suffix }}
path: |
@@ -278,7 +280,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@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}

View File

@@ -22,7 +22,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '24.0.1+9'
JAVA_VERSION: '25.0.2+10.0.LTS'
jobs:
get-version:
@@ -42,12 +42,12 @@ jobs:
architecture: aarch64
output-suffix: arm64
fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_osx-aarch64_bin-jmods.zip'
openjfx-sha: 'b5a94a13077507003fa852512bfa33f4fb680bc8076d8002e4227a84c85171d4'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: '4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -57,7 +57,7 @@ jobs:
- name: Download OpenJFX jmods
id: download-jmods
run: |
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
curl --silent --fail-with-body --proto "=https" -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods/
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
@@ -77,7 +77,7 @@ 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
@@ -97,7 +97,7 @@ jobs:
--verbose
--output runtime
--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.unsupported,jdk.accessibility,jdk.management.jfr,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.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
@@ -119,7 +119,6 @@ jobs:
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "--sun-misc-unsafe-memory-access=allow"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\""
@@ -127,22 +126,25 @@ jobs:
--java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--mac-package-identifier org.cryptomator
--resource-dir dist/mac/resources
- name: Patch Cryptomator.app
run: |
mv appdir/Cryptomator.app Cryptomator.app
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
@@ -152,7 +154,7 @@ jobs:
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- 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
@@ -247,7 +249,7 @@ jobs:
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 }}
@@ -268,7 +270,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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: dmg-${{ matrix.output-suffix }}
path: |
@@ -277,7 +279,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@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
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@v10
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
days-before-stale: 14
days-before-close: 0

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- name: Download source tarball
run: |
curl -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz
- name: Sign source tarball with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -19,16 +19,16 @@ 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@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
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_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'

View File

@@ -5,7 +5,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 24
JAVA_VERSION: 25
defaults:
run:
@@ -16,11 +16,11 @@ jobs:
name: Compile and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-java@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.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

@@ -12,16 +12,16 @@ defaults:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 23
JAVA_VERSION: 25
jobs:
check-preconditions:
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -43,13 +43,14 @@ jobs:
exit 1
fi
- name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file
if: ${{ ! (contains(github.event.head_commit.message, '[skip metadata check]') || contains(github.event.head_commit.message, '[metadata check skip]')) }}
run: |
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\">" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml"
exit 1
fi
- name: Cache NVD DB
uses: actions/cache@v4
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.m2/repository/org/owasp/dependency-check-data/
key: dependency-check-${{ github.run_id }}
@@ -60,6 +61,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@v10
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
days-before-stale: 365
days-before-close: 90

View File

@@ -8,10 +8,6 @@ on:
version:
description: 'Version'
required: false
isDebug:
description: 'Build debug version with console output'
type: boolean
default: false
sign:
description: 'Sign binaries'
required: false
@@ -26,11 +22,12 @@ on:
env:
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
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'
WIX_VERSION: '6.0.2'
defaults:
run:
@@ -51,18 +48,13 @@ jobs:
include:
- arch: x64
os: windows-latest
java-dist: 'zulu'
java-version: '24.0.1+9'
java-dist: 'zulu' #cannot use temurin, see https://github.com/cryptomator/cryptomator/issues/3824#issuecomment-2829827427
java-version: '25.0.1+8'
java-package: 'jdk'
- arch: arm64
os: windows-11-arm
java-dist: 'liberica'
java-version: '24.0.1+11'
java-package: 'jdk+fx' #This is needed, as liberica contains JFX 24 Jmods for Windows ARM64
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }}
@@ -71,14 +63,16 @@ jobs:
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
dotnet tool install --global wix --version ${WIX_VERSION}
wix.exe extension add --global WixToolset.UI.wixext/${WIX_VERSION}
wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
env:
WIX_VERSION: ${{ env.WIX_VERSION }}
- 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 openjfx-jmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}"
curl --silent --fail-with-body --proto "=https" -L "${{ env.OPENJFX_JMODS_AMD64 }}" --output openjfx-jmods.zip
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 }}.";
}
@@ -102,7 +96,7 @@ jobs:
- name: Set version
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
@@ -122,7 +116,7 @@ jobs:
--verbose
--output runtime
--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.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,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.crypto.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
@@ -144,14 +138,13 @@ jobs:
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
--java-options "--sun-misc-unsafe-memory-access=allow"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dcryptomator.adminConfigPath=\"C:/ProgramData/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{localappdata}/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{appdata}/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{localappdata}/Cryptomator/ipc.socket\""
@@ -164,6 +157,7 @@ jobs:
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
--java-options "-Dcryptomator.disableUpdateCheck=false"
--java-options "-XX:ErrorFile=C:/cryptomator/cryptomator_crash.log"
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--resource-dir dist/win/resources
--icon dist/win/resources/Cryptomator.ico
--add-launcher "Cryptomator (Debug)=dist/win/debug-launcher.properties"
@@ -198,9 +192,19 @@ 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: Sign DLLs with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
uses: ./.github/actions/win-sign-action
with:
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
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with:
base-dir: 'appdir'
file-extensions: 'dll,exe,ps1'
@@ -225,7 +229,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"
@@ -257,16 +261,16 @@ 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: Sign msi with Actalis CodeSigner
- name: Sign MSI with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f
uses: ./.github/actions/win-sign-action
with:
base-dir: 'installer'
file-extensions: 'msi'
sign-description: 'Cryptomator Installer'
sign-url: 'https://cryptomator.org'
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
password: ${{ secrets.WIN_CODESIGN_PW }}
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
@@ -277,7 +281,7 @@ 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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: msi-${{ matrix.arch }}
path: |
@@ -298,28 +302,24 @@ jobs:
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
- arch: arm64
os: windows-11-arm
executable-suffix: arm64
java-dist: 'liberica'
java-version: '24.0.1+11'
java-package: 'jdk+fx' #This is needed, as liberica contains JFX 24 Jmods for Windows ARM64
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- 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
dotnet tool install --global wix --version ${WIX_VERSION}
wix.exe extension add --global WixToolset.BootstrapperApplications.wixext/${WIX_VERSION}
wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
env:
WIX_VERSION: ${{ env.WIX_VERSION }}
- name: Download .msi
uses: actions/download-artifact@v5
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
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
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }}
@@ -328,7 +328,7 @@ jobs:
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"
@@ -339,7 +339,7 @@ jobs:
shell: pwsh
- name: Download WinFsp
run: |
curl --output $env:WINFSP_PATH -L ${{ env.WINFSP_MSI }}
curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_MSI }} --output $env:WINFSP_PATH
$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)."
@@ -349,7 +349,7 @@ jobs:
shell: pwsh
- name: Download Legacy-WinFsp uninstaller
run: |
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_UNINSTALLER }} --output dist/win/bundle/resources/winfsp-uninstaller.exe
shell: pwsh
- name: Create Wix Burn bundle
working-directory: dist/win
@@ -369,9 +369,20 @@ jobs:
- name: Detach burn engine in preparation to sign
run: >
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:
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
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with:
base-dir: 'tmp'
file-extensions: 'exe'
@@ -382,9 +393,20 @@ jobs:
- name: Reattach signed burn engine to installer
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:
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
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with:
base-dir: 'installer'
file-extensions: 'exe'
@@ -402,7 +424,7 @@ 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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: exe-${{ matrix.executable-suffix }}
path: |
@@ -417,26 +439,22 @@ jobs:
needs: [ build-msi, build-exe ]
outputs:
download-url-msi-x64: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-msi-arm64: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }}
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
download-url-exe-arm64: ${{ fromJSON(steps.publish.outputs.assets)[3].browser_download_url }}
steps:
- name: Download installers
uses: actions/download-artifact@v5
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
merge-multiple: true
- name: Publish installers on GitHub Releases
id: publish
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
# do not change ordering of filelist, required for correct job output
files: |
*x64.msi
*arm64.msi
*x64.exe
*arm64.exe
*.asc
allowlist-msi-x64:
@@ -446,13 +464,6 @@ jobs:
url: ${{ needs.publish.outputs.download-url-msi-x64 }}
secrets: inherit
allowlist-msi-arm64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish ]
with:
url: ${{ needs.publish.outputs.download-url-msi-arm64 }}
secrets: inherit
allowlist-exe-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-x64 ]
@@ -460,13 +471,6 @@ jobs:
url: ${{ needs.publish.outputs.download-url-exe-x64 }}
secrets: inherit
allowlist-exe-arm64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-arm64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe-arm64 }}
secrets: inherit
notify-winget:
name: Notify for winget-release
if: needs.get-version.outputs.versionType == 'stable'
@@ -474,7 +478,7 @@ 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'

View File

@@ -18,7 +18,7 @@ jobs:
env:
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 }}

48
.idea/compiler.xml generated
View File

@@ -12,18 +12,15 @@
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<option name="dagger.fastInit" value="enabled" />
<option name="dagger.formatGeneratedSource" value="enabled" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.55/dagger-compiler-2.55.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.55/dagger-2.55.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.59.1/dagger-compiler-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.59.1/dagger-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.55/dagger-spi-2.55.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.59.1/dagger-spi-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.0.21-1.0.28/symbol-processing-api-2.0.21-1.0.28.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.21/kotlin-stdlib-2.0.21.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.2.20-2.0.3/symbol-processing-api-2.2.20-2.0.3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.33.0/google-java-format-1.33.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
@@ -31,14 +28,41 @@
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.2.20/kotlin-metadata-jvm-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.59.1/dagger-compiler-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.59.1/dagger-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.59.1/dagger-spi-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.2.20-2.0.3/symbol-processing-api-2.2.20-2.0.3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.33.0/google-java-format-1.33.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.41.0/checker-qual-3.41.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.2.20/kotlin-metadata-jvm-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
</processorPath>
<module name="cryptomator" />
</profile>
@@ -46,7 +70,7 @@
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled" />
<module name="cryptomator" options="-Adagger.fastInit=enabled" />
</option>
</component>
</project>

View File

@@ -1,10 +1,8 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="true">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="Deprecation" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="DEPRECATED_ATTRIBUTES" />
<inspection_tool class="MarkedForRemoval" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="MARKED_FOR_REMOVAL_ATTRIBUTES" />
<inspection_tool class="RedundantScheduledForRemovalAnnotation" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="MARKED_FOR_REMOVAL_ATTRIBUTES" />
</profile>
</component>

2
.idea/misc.xml generated
View File

@@ -8,7 +8,7 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="24" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" 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,javafx.graphics" />
<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 -Dcryptomator.hub.enableTrustOnFirstUse=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,javafx.graphics" />
<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 -Dcryptomator.hub.enableTrustOnFirstUse=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.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" />
<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 -Dcryptomator.hub.enableTrustOnFirstUse=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.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" />
<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 -Dcryptomator.hub.enableTrustOnFirstUse=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,javafx.graphics" />
<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 -Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism -Dcryptomator.hub.enableTrustOnFirstUse=true -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,javafx.graphics" />
<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 -Dcryptomator.hub.enableTrustOnFirstUse=true -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
<method v="2">
<option name="Make" enabled="true" />
</method>

83
CHANGELOG.md Normal file
View File

@@ -0,0 +1,83 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
The changelog starts with version 1.19.0.
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
## [1.19.2](https://github.com/cryptomator/cryptomator/releases/1.19.2) - 2026-03-20
### Security
* Cryptomamtor Hub Vaults: Additional patch for (#4179, [GHSA-34rf-rwr3-7g43](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-34rf-rwr3-7g43))
## [1.19.1](https://github.com/cryptomator/cryptomator/releases/1.19.1) - 2026-03-12
### Security
* Cryptomamtor Hub Vaults: Fixed possible man-in-the-middle attack with tampered vault config (#4179, [GHSA-34rf-rwr3-7g43](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-34rf-rwr3-7g43))
* Disallow unencrypted http connections to hub by default ([CVE-2026-32309](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-vv33-h7qx-c264))
* Disallow loading of masterkey file from arbitrary paths (#4180, [CVE-2026-32310](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-5phc-5pfx-hr52))
* Fixed not-configured plugin directory does not disable plugin search ([#4176](https://github.com/cryptomator/cryptomator/pull/4176))
### Added
* Trust on first use, adding new config properties `cryptomator.hub.allowedHosts` and `cryptomator.hub.enableTrustOnFirstUse` (#4179)
### Fixed
* Fixed Finder window opens twice when revealing vault on macOS ([#4177](https://github.com/cryptomator/cryptomator/pull/4177))
* Fixed app does not start due to secret service detection failure on Linux ([#4175](https://github.com/cryptomator/cryptomator/pull/4175))
### Changed
* Pin version of appimagetool([#4181](https://github.com/cryptomator/cryptomator/pull/4181))
* Updated translations
* Updated dependencies:
* `org.cryptomator:integrations-api` from 1.8.0-beta1 to 1.8.0
* `org.cryptomator:integrations-linux` from 1.7.0-beta4 to 1.7.0
* `org.cryptomator:integrations-mac` from 1.5.0-beta3 to 1.5.0
## [1.19.0](https://github.com/cryptomator/cryptomator/releases/tag/1.19.0) - 2026-03-09
### Added
* Self-Update Mechanism ([#3948](https://github.com/cryptomator/cryptomator/pull/3948))
* Implemented `.dmg` update mechanism
* Implemented Flatpak update mechanism
* App notifications ([#4069](https://github.com/cryptomator/cryptomator/pull/4069))
* Mark files in-use for Hub vaults ([#4078](https://github.com/cryptomator/cryptomator/pull/4078))
* Accessibility: Adjust app to be used with a screen reader ([#547](https://github.com/cryptomator/cryptomator/issues/547))
* Show Archived Vault Dialog on unlock when Hub returns 410 ([#4081](https://github.com/cryptomator/cryptomator/pull/4081))
* Support automatic app theme selection according to OS theme on Linux ([#4027](https://github.com/cryptomator/cryptomator/issues/4027))
* Admin configuration: Allow overwriting certain app properties by external config file ([#4105](https://github.com/cryptomator/cryptomator/pull/4105))
* New keychain backend using [secret service API](https://specifications.freedesktop.org/secret-service/0.2) for Linux ([#4025](https://github.com/cryptomator/cryptomator/pull/4025))
* Liquid Glass icon for macOS ([#4166](https://github.com/cryptomator/cryptomator/pull/4166))
### Fixed
* Fixed password reset/show recovery possible for vaults without masterkey file ([#4120](https://github.com/cryptomator/cryptomator/pull/4120))
* Fixed restore vault config failed due to selecting a directory instead of file ([#4141](https://github.com/cryptomator/cryptomator/issues/4141))
* Fixed leaking of cleartext paths into application log ([GHSA-j83j-mwhc-rcgw](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-j83j-mwhc-rcgw))
### Changed
* Disable user defined app start config on Windows ([#4132](https://github.com/cryptomator/cryptomator/issues/4132))
* Disable plugin loading by default ([#4136](https://github.com/cryptomator/cryptomator/4136))
* Use JDK 25 ([#4031](https://github.com/cryptomator/cryptomator/pull/4031))
* Update JavaFX to 25.0.2 ([#4145](https://github.com/cryptomator/cryptomator/pull/4145))
* Updated translations
* Updated dependencies
* `ch.qos.logback:*` from 1.5.19 to 1.5.32
* `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.1
* `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.1
* `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
* `com.google.dagger:*` from 2.57.2 to 2.59.2
* `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0
* `org.cryptomator:cryptofs` from 2.9.0 to 2.10.0
* `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
* `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.1
* `org.cryptomator:integrations-api` from 1.7.0 to 1.8.0-beta1
* `org.cryptomator:integrations-linux` from 1.6.1 to 1.7.0-beta4
* `org.cryptomator:integrations-mac` from 1.4.1 to 1.5.0-beta3
* `org.cryptomator:integrations-win` from 1.5.1 to 1.6.0
* `org.cryptomator:webdav-nio-adapter` from 3.0.0 to 3.0.1
* `org.cryptomator:webdav-nio-adapter-servlet` to 1.2.12

View File

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

8
dist/common/config.properties vendored Normal file
View File

@@ -0,0 +1,8 @@
# This is the Cryptomator administrative configuration file.
# It is a simple key-value pair file.
# Lines starting with '#' are comments and will be ignored.
# For more info, read the docs at https://docs.cryptomator.org/desktop/advanced-settings/
#
# Example:
# Sets the plugin directory and enables plugin loading
# cryptomator.pluginDir=@{userhome}/Cryptomator/Plugins

View File

@@ -19,16 +19,16 @@ if [[ ! "${CPU_ARCH}" =~ x86_64|aarch64 ]]; then echo "Platform ${CPU_ARCH} not
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=24.0.1
JAVAFX_VERSION=25.0.2
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
JAVAFX_JMODS_SHA256='e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
JAVAFX_JMODS_SHA256='c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
fi
# download javaFX jmods
@@ -62,7 +62,7 @@ ${JAVA_HOME}/bin/jlink \
--verbose \
--output runtime \
--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.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 \
@@ -88,8 +88,8 @@ ${JAVA_HOME}/bin/jpackage \
--app-version "${VERSION}.${REVISION_NO}" \
--java-options "-Dfile.encoding=\"utf-8\"" \
--java-options "-Djava.net.useSystemProxies=true" \
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
@@ -99,6 +99,7 @@ ${JAVA_HOME}/bin/jpackage \
--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" \
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
--resource-dir ../resources
# transform AppDir
@@ -115,6 +116,7 @@ cp ../common/org.cryptomator.Cryptomator.tray-unlocked.svg Cryptomator.AppDir/us
cp ../common/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop
cp ../common/org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.metainfo.xml
cp ../common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.xml
cp ../common/application-vnd.cryptomator.encrypted.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.encrypted.xml
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/org.cryptomator.Cryptomator.desktop
@@ -122,7 +124,7 @@ ln -s org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/meta
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
# load AppImageTool
curl -L https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${CPU_ARCH}.AppImage -o /tmp/appimagetool.AppImage
curl -L https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-${CPU_ARCH}.AppImage -o /tmp/appimagetool.AppImage
chmod +x /tmp/appimagetool.AppImage
# create AppImage

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/vnd.cryptomator.encrypted">
<comment>Cryptomator Encrypted Data</comment>
<glob pattern="*.c9r"/>
<glob pattern="*.c9s"/>
<glob pattern="*.c9u"/>
</mime-type>
</mime-info>

View File

@@ -73,6 +73,7 @@
<url type="faq">https://community.cryptomator.org/c/kb/faq</url>
<url type="help">https://docs.cryptomator.org/</url>
<url type="translate">https://translate.cryptomator.org</url>
<url type="vcs-browser">https://github.com/cryptomator/cryptomator</url>
<developer id="de.skymatic">
<name>Skymatic GmbH</name>
@@ -83,6 +84,18 @@
</content_rating>
<releases>
<release date="2026-03-20" version="1.19.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.2</url>
</release>
<release date="2026-03-12" version="1.19.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.1</url>
</release>
<release date="2026-03-09" version="1.19.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.0</url>
</release>
<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>

View File

@@ -2,7 +2,7 @@ Source: cryptomator
Maintainer: Cryptobot <releases@cryptomator.org>
Section: utils
Priority: optional
Build-Depends: debhelper (>=10), coffeelibs-jdk-24 (>= 24.0.1+9-0ppa3), libgtk-3-0, libxxf86vm1, libgl1
Build-Depends: debhelper (>=10), openjdk-25-jdk (>= 25+36), 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

@@ -6,4 +6,5 @@ common/org.cryptomator.Cryptomator.tray-unlocked.svg usr/share/icons/hicolor/sca
common/org.cryptomator.Cryptomator256.png usr/share/icons/hicolor/256x256/apps
common/org.cryptomator.Cryptomator512.png usr/share/icons/hicolor/512x512/apps
common/org.cryptomator.Cryptomator.metainfo.xml usr/share/metainfo
common/application-vnd.cryptomator.vault.xml usr/share/mime/packages
common/application-vnd.cryptomator.vault.xml usr/share/mime/packages
common/application-vnd.cryptomator.encrypted.xml usr/share/mime/packages

View File

@@ -25,6 +25,7 @@ case "$1" in
fi
xdg-desktop-menu install --novendor /usr/share/applications/org.cryptomator.Cryptomator.desktop
xdg-mime install /usr/share/mime/packages/application-vnd.cryptomator.vault.xml
xdg-mime install /usr/share/mime/packages/application-vnd.cryptomator.encrypted.xml
;;
abort-upgrade|abort-remove|abort-deconfigure)

View File

@@ -23,6 +23,7 @@ case "$1" in
xdg-desktop-menu uninstall --novendor /usr/share/applications/org.cryptomator.Cryptomator.desktop
xdg-mime uninstall /usr/share/mime/packages/application-vnd.cryptomator.vault.xml
xdg-mime uninstall /usr/share/mime/packages/application-vnd.cryptomator.encrypted.xml
;;
failed-upgrade)

View File

@@ -4,11 +4,12 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
JAVA_HOME = /usr/lib/jvm/java-24-coffeelibs
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
ifeq ($(DEB_BUILD_ARCH),amd64)
JAVA_HOME = /usr/lib/jvm/java-25-openjdk-amd64
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
else ifeq ($(DEB_BUILD_ARCH),arm64)
JAVA_HOME = /usr/lib/jvm/java-25-openjdk-arm64
JMODS_PATH = jmods/aarch64:${JAVA_HOME}/jmods
endif
@@ -28,7 +29,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 \
@@ -45,14 +46,13 @@ override_dh_auto_build:
--vendor "Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--java-options "--sun-misc-unsafe-memory-access=allow" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \
--java-options "-Djava.net.useSystemProxies=true" \
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
@@ -64,6 +64,7 @@ override_dh_auto_build:
--java-options "-Dcryptomator.disableUpdateCheck=\"${DISABLE_UPDATE_CHECK}\"" \
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
--app-version "${VERSION_NUM}.${REVISION_NUM}" \
--resource-dir resources \
--verbose

119
dist/linux/makepkg/PKGBUILD.template vendored Normal file
View File

@@ -0,0 +1,119 @@
# Maintainer: Aaron Graves <linux@ajgraves.com>
# Contributor: Julian Raufelder <arch@raufelder.com>
# Contributor: Morten Linderud <morten@linderud.pw>
# Contributor: Sebastian Stenzel <sebastian.stenzel@gmail.com>
# Contributor: Armin Schrenk <armin.schrenk@skymatic.de>
pkgname=cryptomator
pkgver=$PKG_VERSION
pkgrel=$PKG_RELEASE
pkgdesc="Multiplatform transparent client-side encryption of your files in the cloud."
arch=('any')
url="https://cryptomator.org/"
license=('GPL3')
depends=('fuse3' 'alsa-lib' 'hicolor-icon-theme' 'libxtst' 'libnet' 'libxrender')
makedepends=('maven' 'unzip')
optdepends=('keepassxc-cryptomator: Use KeePassXC to store vault passwords' 'ttf-hanazono: Install this font when using Japanese system language')
_jdkver=25.0.2+10
_jfxver=25.0.2
_src_app_dir=cryptomator-${pkgver//_/-}
source=($SOURCES);
source_x86_64=("jdk-${_jdkver}.tar.gz::https://github.com/adoptium/temurin${_jdkver:0:2}-binaries/releases/download/jdk-${_jdkver//\+/%2B}/OpenJDK${_jdkver:0:2}U-jdk_x64_linux_hotspot_${_jdkver//\+/_}.tar.gz"
"openjfx-${_jfxver}.zip::https://download2.gluonhq.com/openjfx/${_jfxver}/openjfx-${_jfxver}_linux-x64_bin-jmods.zip")
source_aarch64=("jdk-${_jdkver}.tar.gz::https://github.com/adoptium/temurin${_jdkver:0:2}-binaries/releases/download/jdk-${_jdkver//\+/%2B}/OpenJDK${_jdkver:0:2}U-jdk_aarch64_linux_hotspot_${_jdkver//\+/_}.tar.gz"
"openjfx-${_jfxver}.zip::https://download2.gluonhq.com/openjfx/${_jfxver}/openjfx-${_jfxver}_linux-aarch64_bin-jmods.zip")
noextract=("jdk-${_jdkver}.tar.gz" "openjfx-${_jfxver}.zip")
sha256sums=($SOURCES_SHA)
sha256sums_x86_64=('987387933b64b9833846dee373b640440d3e1fd48a04804ec01a6dbf718e8ab8'
'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b')
sha256sums_aarch64=('a9d73e711d967dc44896d4f430f73a68fd33590dabc29a7f2fb9f593425b854c'
'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646')
options=('!strip')
validpgpkeys=('58117AFA1F85B3EEC154677D615D449FE6E6A235')
build() {
export JAVA_HOME="${srcdir}/jdk-${_jdkver}"
JMODS_PATH="${srcdir}/openjfx-${_jfxver}-jmods"
#JEP 493
if ! $(${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"); then
JMODS_PATH="${JMODS_PATH}:${JAVA_HOME}/jmods:"
fi
tar xfz "jdk-${_jdkver}.tar.gz"
mkdir "openjfx-${_jfxver}-jmods"
unzip -j "openjfx-${_jfxver}.zip" \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d "openjfx-${_jfxver}-jmods"
cd "${srcdir}/${_src_app_dir}"
mvn -B clean package -DskipTests -Plinux
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
cd target
"$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.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
--strip-debug \
--compress=zip-0
##Note: jpackage does not allow -beta suffixes, have to strip those
"$JAVA_HOME/bin/jpackage" \
--type app-image \
--runtime-image runtime \
--input libs \
--module-path mods \
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator \
--dest . \
--name cryptomator \
--vendor "Skymatic GmbH" \
--copyright "(C) 2016 - 2026 Skymatic GmbH" \
--java-options "--enable-preview" \
--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 "-Dfile.encoding=\"utf-8\"" \
--java-options "-Djava.net.useSystemProxies=true" \
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
--java-options "-Dcryptomator.appVersion=\"${pkgver//_/-}\"" \
--java-options "-Dcryptomator.buildNumber=\"aur-${pkgrel}\"" \
--java-options "-Dcryptomator.disableUpdateCheck=true" \
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
--app-version "${pkgver//_*/}" \
--verbose
}
package() {
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/application-vnd.cryptomator.vault.xml" "${pkgdir}/usr/share/mime/packages/cryptomator-vault.xml"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.desktop" "${pkgdir}/usr/share/applications/org.cryptomator.Cryptomator.desktop"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator256.png" "${pkgdir}/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator512.png" "${pkgdir}/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray.svg"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray-unlocked.svg"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray.svg" "${pkgdir}/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg"
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg" "${pkgdir}/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.svg"
mkdir -p "${pkgdir}/opt/cryptomator/"
cp -R "${srcdir}/${_src_app_dir}/target/cryptomator" "${pkgdir}/opt/"
install -Dm644 "${srcdir}/${_src_app_dir}/target/LICENSE.txt" -t "${pkgdir}/usr/share/licenses/${pkgname}"
mkdir -p "${pkgdir}/usr/bin"
ln -s "/opt/cryptomator/bin/cryptomator" "${pkgdir}/usr/bin/cryptomator"
}

17
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=24.0.1
JAVAFX_VERSION=25.0.2
JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="b5a94a13077507003fa852512bfa33f4fb680bc8076d8002e4227a84c85171d4"
JAVAFX_JMODS_SHA256="4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a"
else
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="6e62a426d43c168a488521f904a523f3dd6ee2cf103e08136f2fd465c828a105"
JAVAFX_JMODS_SHA256="0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c"
fi
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
@@ -71,7 +71,7 @@ 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
@@ -85,7 +85,7 @@ fi
${JAVA_HOME}/bin/jlink \
--output runtime \
--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.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,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,java.compiler \
--strip-native-commands \
--no-header-files \
--no-man-pages \
@@ -114,27 +114,30 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dapple.awt.enableTemplateImages=true" \
--java-options "-Dsun.java2d.metal=true" \
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" \
--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\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/${APP_NAME}/key.p12\"" \
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"${APP_NAME}\"" \
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support${APP_NAME}/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism" \
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
--mac-package-identifier ${PACKAGE_IDENTIFIER} \
--resource-dir ../resources
# transform app dir
cp ../resources/${APP_NAME}-Vault.icns ${APP_NAME}.app/Contents/Resources/
cp ../resources/Assets.car ${APP_NAME}.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
# generate license
mvn -B -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 \

BIN
dist/mac/resources/Assets.car vendored Normal file

Binary file not shown.

View File

@@ -12,6 +12,8 @@
<string>Cryptomator</string>
<key>CFBundleIconFile</key>
<string>Cryptomator.icns</string>
<key>CFBundleIconName</key>
<string>Cryptomator</string>
<key>CFBundleIdentifier</key>
<string>org.cryptomator</string>
<key>CFBundleInfoDictionaryVersion</key>
@@ -105,6 +107,7 @@
<array>
<string>c9r</string>
<string>c9s</string>
<string>c9u</string>
</array>
<key>public.mime-type</key>
<array>

25
dist/win/build.ps1 vendored
View File

@@ -34,20 +34,20 @@ if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
}
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)'
Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.2)'
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)'
Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.2 --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)'
Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.2 --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)'
Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.2 --global)'
exit 1
}
@@ -65,7 +65,7 @@ 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
@@ -86,16 +86,16 @@ 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 full JDK (including jmods) is installed."
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='24.0.1'
$javaFxVersion='25.0.2'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f'
$javaFxJmodsSHA256 = '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
@@ -133,7 +133,7 @@ if ((& "$Env:JAVA_HOME\bin\jlink" --help | Select-String -Pattern "Linking from
--verbose `
--output runtime `
--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.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,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 `
@@ -155,7 +155,7 @@ $javaOptions = @(
"--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.adminConfigPath=`"C:/ProgramData/$AppName/config.properties`""
"--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`""
@@ -167,6 +167,7 @@ $javaOptions = @(
"--java-options", "-Dcryptomator.showTrayIcon=true"
"--java-options", "-Dcryptomator.buildNumber=`"msi-$revisionNo`""
"--java-options", "-Dcryptomator.disableUpdateCheck=false"
"--java-options", "-Dcryptomator.hub.enableTrustOnFirstUse=true"
)
@@ -194,7 +195,7 @@ if ($LASTEXITCODE -ne 0) {
}
#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\" `
@@ -237,7 +238,7 @@ if ($LASTEXITCODE -ne 0) {
}
#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\" `

12
dist/win/contrib/disableUserConfig.bat vendored Normal file
View File

@@ -0,0 +1,12 @@
@echo off
:: Batch wrapper for PowerShell script to disable user configuration in Cryptomator
:: This is executed as a Custom Action during MSI installation
:: This file must be located in the INSTALLDIR
:: Change to INSTALLDIR
cd %~dp0
:: Execute the PowerShell script
powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File ".\disableUserConfig.ps1"
:: Return the exit code from PowerShell
exit /b %ERRORLEVEL%

24
dist/win/contrib/disableUserConfig.ps1 vendored Normal file
View File

@@ -0,0 +1,24 @@
# PowerShell script to disable user configuration
# This script is executed as a Custom Action during MSI installation
# It deletes the file .package, effectively disabling user specific jpackage configuration.
# NOTE: This file must be located in the same directory as set in the MSI property INSTALLDIR
try {
# Determine file path
$packageFile = Join-Path $PSScriptRoot 'app\.package'
#check if file exists
if (Test-Path -Path $packageFile) {
Write-Host "Deleting file: $packageFile"
Remove-Item -Path $packageFile -Force -ErrorAction Stop
} else {
Write-Host "File not found: $packageFile. Skipping deletion."
}
exit 0
}
catch {
Write-Error "Error deleting package file: $_"
exit 1
}

View File

@@ -87,17 +87,37 @@
<!-- Non-Opening ProgID -->
<ns0:DirectoryRef Id="INSTALLDIR">
<ns0:Component Bitness="always64" Id="nonStartingProgID" >
<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:Extension Id="c9u" Advertise="no" ContentType="$(var.ProgIdContentType)"/>
</ns0:ProgId>
</ns0:Component>
</ns0:DirectoryRef>
<ns0:StandardDirectory Id="CommonAppDataFolder">
<ns0:Directory Id="CryptomatorDesktopProgramData" Name="Cryptomator">
<ns0:Component Id="AdminConfigDir" Guid="c078b7da-ba6e-4069-a5ab-5c0f0f9856a0">
<ns0:CreateFolder>
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
<util:PermissionEx User="Administrators" GenericAll="yes"/>
<util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
</ns0:CreateFolder>
</ns0:Component>
<ns0:Component Id="AdminConfigFile" NeverOverwrite="yes" Permanent="yes">
<ns0:File Id="EmptyAdminConfig" Source="$(env.JP_WIXWIZARD_RESOURCES)\..\..\common\config.properties" Name="config.properties" KeyPath="yes">
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
<util:PermissionEx User="Administrators" GenericAll="yes"/>
<util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
</ns0:File>
</ns0:Component>
</ns0:Directory>
</ns0:StandardDirectory>
<!-- Standard required root -->
<ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
@@ -105,7 +125,9 @@
<ns0:ComponentGroupRef Id="Files"/>
<ns0:ComponentGroupRef Id="FileAssociations"/>
<!-- Ref to additional ProgIDs -->
<ns0:ComponentRef Id="nonStartingProgID" />
<ns0:ComponentRef Id="nonStartingProgID"/>
<ns0:ComponentRef Id="AdminConfigDir"/>
<ns0:ComponentRef Id="AdminConfigFile"/>
</ns0:Feature>
<ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
@@ -131,6 +153,10 @@
<!-- Property for controlling update check behavior (can be set via command line) -->
<ns0:Property Id="DISABLEUPDATECHECK" Secure="yes" />
<!-- Disable user config -->
<ns0:SetProperty Id="DisableUserConfig" Value="&quot;[INSTALLDIR]disableUserConfig.bat&quot;" Sequence="execute" Before="DisableUserConfig" />
<ns0:CustomAction Id="DisableUserConfig" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- WebDAV patches -->
<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"/>
@@ -187,9 +213,10 @@
<ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" />
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
<ns0:Custom Action="DisableUserConfig" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
<!-- 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)"/>
<ns0:Custom Action="PatchWebDAV" After="DisableUserConfig" 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>

View File

@@ -1,6 +1,6 @@
Apache License v2.0|Apache License, Version 2.0|The Apache Software License, Version 2.0|Apache 2.0|Apache Software License - Version 2.0|Apache-2.0
MIT License|The MIT License (MIT)|The MIT License|MIT license
LGPL 2.1|LGPL, version 2.1|GNU Lesser/Library General Public License version 2|GNU Lesser General Public License Version 2.1
Apache License v2.0|Apache License, Version 2.0|The Apache License, Version 2.0|The Apache Software License, Version 2.0|Apache 2.0|Apache Software License - Version 2.0|Apache-2.0
MIT License|MIT|The MIT License (MIT)|The MIT License|MIT license
LGPL 2.1|LGPL, version 2.1|GNU Lesser/Library General Public License version 2|GNU Lesser General Public License Version 2.1|GNU Lesser General Public License
GPLv2|GNU General Public License Version 2
GPLv2+CE|CDDL + GPLv2 with classpath exception
Eclipse Public License - Version 1.0|Eclipse Public License - v 1.0

83
pom.xml
View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId>
<version>1.18.0</version>
<version>1.19.2</version>
<name>Cryptomator Desktop App</name>
<organization>
@@ -26,61 +26,83 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>24</project.jdk.version>
<project.jdk.version>25</project.jdk.version>
<!-- Group IDs of jars that need to stay on the class path for now -->
<!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) -->
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.9.0</cryptomator.cryptofs.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>
<cryptomator.cryptofs.version>2.10.0</cryptomator.cryptofs.version>
<cryptomator.cryptolib.version>2.2.2</cryptomator.cryptolib.version>
<cryptomator.integrations.version>1.8.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.5.0</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.7.0</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>6.0.1</cryptomator.fuse.version>
<cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
<cryptomator.webdav-servlet.version>1.2.12</cryptomator.webdav-servlet.version>
<!-- 3rd party dependencies -->
<commons-lang3.version>3.18.0</commons-lang3.version>
<dagger.version>2.57.1</dagger.version>
<caffeine.version>3.2.3</caffeine.version>
<commons-lang3.version>3.20.0</commons-lang3.version>
<dagger.version>2.59.2</dagger.version>
<easybind.version>2.2</easybind.version>
<jackson.version>2.20.0</jackson.version>
<javafx.version>24.0.1</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>
<jackson.version>2.21.1</jackson.version>
<javafx.version>25.0.2</javafx.version>
<jwt.version>4.5.1</jwt.version>
<nimbus-jose.version>10.5</nimbus-jose.version>
<logback.version>1.5.32</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.13.4</junit.jupiter.version>
<mockito.version>5.20.0</mockito.version>
<junit.jupiter.version>6.0.3</junit.jupiter.version>
<mockito.version>5.22.0</mockito.version>
<hamcrest.version>3.0</hamcrest.version>
<!-- build-time dependencies -->
<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.7.0</license-generator.version>
<junit-tree-reporter.version>1.4.0</junit-tree-reporter.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.4</mvn-surefire.version>
<mvn-jar.version>3.4.2</mvn-jar.version>
<jetbrains.annotations.version>26.1.0</jetbrains.annotations.version>
<dependency-check.version>12.2.0</dependency-check.version>
<jacoco.version>0.8.14</jacoco.version>
<license-generator.version>2.7.1</license-generator.version>
<junit-tree-reporter.version>1.5.1</junit-tree-reporter.version>
<mvn-compiler.version>3.15.0</mvn-compiler.version>
<mvn-resources.version>3.5.0</mvn-resources.version>
<mvn-dependency.version>3.10.0</mvn-dependency.version>
<mvn-surefire.version>3.5.3</mvn-surefire.version>
<mvn-jar.version>3.5.0</mvn-jar.version>
<!-- Property used by surefire to determine jacoco engine -->
<surefire.jacoco.args></surefire.jacoco.args>
</properties>
<repositories>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<!-- Cryptomator Libs -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter-servlet</artifactId>
<version>${cryptomator.webdav-servlet.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId>
<version>2.2.1</version>
<version>${cryptomator.cryptolib.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
@@ -214,7 +236,7 @@
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.2.2</version>
<version>${caffeine.version}</version>
</dependency>
<!-- JUnit / Mockito / Hamcrest -->
<dependency>
@@ -316,7 +338,6 @@
</annotationProcessorPaths>
<compilerArgs>
<arg>-Adagger.fastInit=enabled</arg>
<arg>-Adagger.formatGeneratedSource=enabled</arg>
</compilerArgs>
</configuration>
</plugin>

View File

@@ -1,5 +1,4 @@
import ch.qos.logback.classic.spi.Configurator;
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider;
import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider;
import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider;
@@ -14,11 +13,16 @@ import org.cryptomator.common.locationpresets.OneDriveLinuxLocationPresetsProvid
import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider;
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
import org.cryptomator.networking.SSLContextWithMacKeychain;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.logging.LogbackConfiguratorFactory;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.networking.SSLContextWithMacKeychain;
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
import org.cryptomator.ui.fxapp.JfxRevealPathService;
import org.cryptomator.ui.fxapp.JfxUiAppearanceProvider;
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
open module org.cryptomator.desktop {
@@ -50,17 +54,19 @@ open module org.cryptomator.desktop {
requires io.github.coffeelibs.tinyoauth2client;
requires org.slf4j;
requires org.apache.commons.lang3;
requires com.github.benmanes.caffeine;
/* dagger bs */
requires jakarta.inject;
requires static javax.inject;
requires java.compiler;
requires com.github.benmanes.caffeine;
uses org.cryptomator.common.locationpresets.LocationPresetsProvider;
uses SSLContextProvider;
uses org.cryptomator.event.NotificationHandler;
provides UiAppearanceProvider with JfxUiAppearanceProvider;
provides RevealPathService with JfxRevealPathService;
provides TrayMenuController with AwtTrayMenuController;
provides Configurator with LogbackConfiguratorFactory;
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;

View File

@@ -22,8 +22,6 @@ import javax.inject.Named;
import javax.inject.Singleton;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Comparator;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
@@ -76,15 +74,8 @@ public abstract class CommonsModule {
@Provides
@Singleton
@Named("SemVer")
static Comparator<String> providesSemVerComparator() {
return new SemVerComparator();
}
@Provides
@Singleton
static Optional<RevealPathService> provideRevealPathService() {
return RevealPathService.get().findFirst();
static RevealPathService provideRevealPathService() {
return RevealPathService.get().findFirst().orElseThrow();
}

View File

@@ -13,5 +13,7 @@ public interface Constants {
String CRYPTOMATOR_FILENAME_GLOB = "*.cryptomator";
URI DEFAULT_KEY_ID = URI.create(MasterkeyFileLoadingStrategy.SCHEME + ":" + MASTERKEY_FILENAME);
byte[] PEPPER = new byte[0];
// Separator used to concatenate Hub username and device name in the filesystem owner identifier.
String HUB_USER_DEVICE_SEPARATOR = "&";
}

View File

@@ -9,10 +9,13 @@ import org.slf4j.LoggerFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -20,20 +23,22 @@ public class Environment {
private static final Logger LOG = LoggerFactory.getLogger(Environment.class);
private static final int DEFAULT_MIN_PW_LENGTH = 8;
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";
private static final String MOUNTPOINT_DIR_PROP_NAME = "cryptomator.mountPointsDir";
private static final String MIN_PW_LENGTH_PROP_NAME = "cryptomator.minPwLength";
private static final String APP_VERSION_PROP_NAME = "cryptomator.appVersion";
private static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
private static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
public static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
public static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath";
public static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths";
public static final String WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.windowsHelloKeychainPaths";
public static final String P12_PATH_PROP_NAME = "cryptomator.p12Path";
public static final String LOG_DIR_PROP_NAME = "cryptomator.logDir";
public static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias";
public static final String MOUNTPOINT_DIR_PROP_NAME = "cryptomator.mountPointsDir";
public static final String MIN_PW_LENGTH_PROP_NAME = "cryptomator.minPwLength";
public static final String APP_VERSION_PROP_NAME = "cryptomator.appVersion";
public static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
public static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
public static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
public static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
public static final String HUB_ALLOWED_HOSTS_PROP_NAME = "cryptomator.hub.allowedHosts";
public static final String HUB_TOFU_PROP_NAME = "cryptomator.hub.enableTrustOnFirstUse";
private Environment() {}
@@ -57,6 +62,8 @@ public class Environment {
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
logCryptomatorSystemProperty(DISABLE_UPDATE_CHECK_PROP_NAME);
logCryptomatorSystemProperty(HUB_ALLOWED_HOSTS_PROP_NAME);
logCryptomatorSystemProperty(HUB_TOFU_PROP_NAME);
}
public static Environment getInstance() {
@@ -124,6 +131,15 @@ public class Environment {
return Optional.ofNullable(System.getProperty(BUILD_NUMBER_PROP_NAME));
}
/**
* Returns the app version concatenated with the build number (if defined).
*
* @return version string formatted like {@code 1.2.3-4567} or {@code 1.2.3} if no build number is defined.
*/
public String getAppVersionWithBuildNumber() {
return getAppVersion() + getBuildNumber().map("-"::concat).orElse("");
}
public Optional<Path> getPluginDir() {
return getPath(PLUGIN_DIR_PROP_NAME);
}
@@ -136,6 +152,18 @@ public class Environment {
return Boolean.getBoolean(DISABLE_UPDATE_CHECK_PROP_NAME);
}
public Set<String> hubAllowedHosts() {
var allowedHubHostsString = System.getProperty(HUB_ALLOWED_HOSTS_PROP_NAME, "");
return Arrays.stream(allowedHubHostsString.split(","))
.map(String::trim)
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.toUnmodifiableSet());
}
public boolean hubTrustOnFirstUse() {
return Boolean.getBoolean(HUB_TOFU_PROP_NAME);
}
private Optional<Path> getPath(String propertyName) {
String value = System.getProperty(propertyName);
return Optional.ofNullable(value).map(Paths::get);

View File

@@ -1,160 +0,0 @@
package org.cryptomator.common;
import org.cryptomator.cryptofs.event.BrokenDirFileEvent;
import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.event.VaultEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
/**
* Map containing {@link VaultEvent}s.
* The map is keyed by the ciphertext path of the affected resource _and_ the {@link FilesystemEvent}s class in order to group same events
* <p>
* Use {@link EventMap#put(VaultEvent)} to add an element and {@link EventMap#remove(VaultEvent)} to remove it.
* <p>
* The map is size restricted to {@value MAX_SIZE} elements. If a _new_ element (i.e. not already present) is added, the least recently added is removed.
*/
@Singleton
public class EventMap implements ObservableMap<EventMap.EventKey, VaultEvent> {
private static final int MAX_SIZE = 300;
public record EventKey(Path ciphertextPath, Class<? extends FilesystemEvent> c) {}
private final ObservableMap<EventMap.EventKey, VaultEvent> delegate;
@Inject
public EventMap() {
delegate = FXCollections.observableHashMap();
}
@Override
public void addListener(MapChangeListener<? super EventKey, ? super VaultEvent> mapChangeListener) {
delegate.addListener(mapChangeListener);
}
@Override
public void removeListener(MapChangeListener<? super EventKey, ? super VaultEvent> mapChangeListener) {
delegate.removeListener(mapChangeListener);
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
@Override
public VaultEvent get(Object key) {
return delegate.get(key);
}
@Override
public @Nullable VaultEvent put(EventKey key, VaultEvent value) {
return delegate.put(key, value);
}
@Override
public VaultEvent remove(Object key) {
return delegate.remove(key);
}
@Override
public void putAll(@NotNull Map<? extends EventKey, ? extends VaultEvent> m) {
delegate.putAll(m);
}
@Override
public void clear() {
delegate.clear();
}
@Override
public @NotNull Set<EventKey> keySet() {
return delegate.keySet();
}
@Override
public @NotNull Collection<VaultEvent> values() {
return delegate.values();
}
@Override
public @NotNull Set<Entry<EventKey, VaultEvent>> entrySet() {
return delegate.entrySet();
}
@Override
public void addListener(InvalidationListener invalidationListener) {
delegate.addListener(invalidationListener);
}
@Override
public void removeListener(InvalidationListener invalidationListener) {
delegate.removeListener(invalidationListener);
}
public synchronized void put(VaultEvent e) {
//compute key
var key = computeKey(e.actualEvent());
//if-else
var nullOrEntry = delegate.get(key);
if (nullOrEntry == null) {
if (size() == MAX_SIZE) {
delegate.entrySet().stream() //
.min(Comparator.comparing(entry -> entry.getValue().actualEvent().getTimestamp())) //
.ifPresent(oldestEntry -> delegate.remove(oldestEntry.getKey()));
}
delegate.put(key, e);
} else {
delegate.put(key, nullOrEntry.incrementCount(e.actualEvent()));
}
}
public synchronized VaultEvent remove(VaultEvent similar) {
//compute key
var key = computeKey(similar.actualEvent());
return this.remove(key);
}
private EventKey computeKey(FilesystemEvent e) {
var p = switch (e) {
case DecryptionFailedEvent(_, Path ciphertextPath, _) -> ciphertextPath;
case ConflictResolvedEvent(_, _, _, _, Path resolvedCiphertext) -> resolvedCiphertext;
case ConflictResolutionFailedEvent(_, _, Path conflictingCiphertext, _) -> conflictingCiphertext;
case BrokenDirFileEvent(_, Path ciphertext) -> ciphertext;
case BrokenFileNodeEvent(_, _, Path ciphertext) -> ciphertext;
};
return new EventKey(p, e.getClass());
}
}

View File

@@ -0,0 +1,18 @@
package org.cryptomator.common;
import java.util.function.Supplier;
/**
* Interface marking a class to be used in {@link org.cryptomator.cryptofs.CryptoFileSystemProperties.Builder#withOwnerGetter(Supplier)}.
*/
@FunctionalInterface
public interface FilesystemOwnerSupplier {
/**
* Get the filesystem owner.
*
* @return the filesystem owner
*/
String getOwner();
}

View File

@@ -1,81 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* All rights reserved.
* This program and the accompanying materials are made available under the terms of the accompanying LICENSE file.
*
* Contributors:
* Sebastian Stenzel - initial API and implementation
*******************************************************************************/
package org.cryptomator.common;
import org.apache.commons.lang3.StringUtils;
import java.util.Comparator;
/**
* Compares version strings according to <a href="http://semver.org/spec/v2.0.0.html">SemVer 2.0.0</a>.
*/
public class SemVerComparator implements Comparator<String> {
private static final char VERSION_SEP = '.'; // http://semver.org/spec/v2.0.0.html#spec-item-2
private static final String PRE_RELEASE_SEP = "-"; // http://semver.org/spec/v2.0.0.html#spec-item-9
private static final String BUILD_SEP = "+"; // http://semver.org/spec/v2.0.0.html#spec-item-10
@Override
public int compare(String version1, String version2) {
// "Build metadata SHOULD be ignored when determining version precedence.
// Thus two versions that differ only in the build metadata, have the same precedence."
String v1WithoutBuildMetadata = StringUtils.substringBefore(version1, BUILD_SEP);
String v2WithoutBuildMetadata = StringUtils.substringBefore(version2, BUILD_SEP);
if (v1WithoutBuildMetadata.equals(v2WithoutBuildMetadata)) {
return 0;
}
String v1MajorMinorPatch = StringUtils.substringBefore(v1WithoutBuildMetadata, PRE_RELEASE_SEP);
String v2MajorMinorPatch = StringUtils.substringBefore(v2WithoutBuildMetadata, PRE_RELEASE_SEP);
String v1PreReleaseVersion = StringUtils.substringAfter(v1WithoutBuildMetadata, PRE_RELEASE_SEP);
String v2PreReleaseVersion = StringUtils.substringAfter(v2WithoutBuildMetadata, PRE_RELEASE_SEP);
return compare(v1MajorMinorPatch, v1PreReleaseVersion, v2MajorMinorPatch, v2PreReleaseVersion);
}
private int compare(String v1MajorMinorPatch, String v1PreReleaseVersion, String v2MajorMinorPatch, String v2PreReleaseVersion) {
int comparisonResult = compareNumericallyThenLexicographically(v1MajorMinorPatch, v2MajorMinorPatch);
if (comparisonResult == 0) {
if (v1PreReleaseVersion.isEmpty()) {
return 1; // 1.0.0 > 1.0.0-BETA
} else if (v2PreReleaseVersion.isEmpty()) {
return -1; // 1.0.0-BETA < 1.0.0
} else {
return compareNumericallyThenLexicographically(v1PreReleaseVersion, v2PreReleaseVersion);
}
} else {
return comparisonResult;
}
}
private int compareNumericallyThenLexicographically(String version1, String version2) {
final String[] vComps1 = StringUtils.split(version1, VERSION_SEP);
final String[] vComps2 = StringUtils.split(version2, VERSION_SEP);
final int commonCompCount = Math.min(vComps1.length, vComps2.length);
for (int i = 0; i < commonCompCount; i++) {
int subversionComparisonResult = 0;
try {
final int v1 = Integer.parseInt(vComps1[i]);
final int v2 = Integer.parseInt(vComps2[i]);
subversionComparisonResult = v1 - v2;
} catch (NumberFormatException ex) {
// ok, lets compare this fragment lexicographically
subversionComparisonResult = vComps1[i].compareTo(vComps2[i]);
}
if (subversionComparisonResult != 0) {
return subversionComparisonResult;
}
}
// all in common so far? longest version string is considered the higher version:
return vComps1.length - vComps2.length;
}
}

View File

@@ -1,7 +1,7 @@
package org.cryptomator.common;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import java.util.Map;
import java.util.Properties;
@@ -13,10 +13,12 @@ public class SubstitutingProperties extends PropertiesDecorator {
private static final Pattern TEMPLATE = Pattern.compile("@\\{(\\w+)}");
private final Map<String, String> env;
private final Logger logger;
public SubstitutingProperties(Properties props, Map<String, String> systemEnvironment) {
public SubstitutingProperties(Properties props, Map<String, String> systemEnvironment, Logger logger) {
super(props);
this.env = systemEnvironment;
this.logger = logger;
}
@Override
@@ -44,7 +46,7 @@ public class SubstitutingProperties extends PropertiesDecorator {
case "localappdata" -> resolveFrom("LOCALAPPDATA", Source.ENV);
case "userhome" -> resolveFrom("user.home", Source.PROPS);
default -> {
LoggerFactory.getLogger(SubstitutingProperties.class).warn("Unknown variable {} in property value {}.", match.group(), value);
logger.warn("Unknown variable {} in property value {}.", match.group(), value);
yield match.group();
}
});
@@ -56,7 +58,7 @@ public class SubstitutingProperties extends PropertiesDecorator {
case PROPS -> delegate.getProperty(key);
};
if (val == null) {
LoggerFactory.getLogger(SubstitutingProperties.class).warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src);
logger.warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src);
return "";
} else {
return Matcher.quoteReplacement(val);

View File

@@ -167,6 +167,7 @@ public class Mounter {
usedMountServices.add(mountService);
var builder = mountService.forFileSystem(cryptoFsRoot);
LOG.debug("Using mount service {} for mounting vault {}", mountService.getClass().getName(), vaultSettings.displayName);
var internal = new SettledMounter(mountService, builder, vaultSettings); // FIXME: no need for an inner class
var cleanup = internal.prepare();
return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup);

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,102 @@
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")) //
.filter(Files::isRegularFile) //
.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

@@ -24,11 +24,12 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableSet;
import javafx.geometry.NodeOrientation;
import java.nio.file.Path;
import java.time.Instant;
import java.util.function.Consumer;
import java.util.HashSet;
import java.util.Set;
public class Settings {
@@ -53,6 +54,7 @@ public class Settings {
static final String DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT.name();
public static final Instant DEFAULT_TIMESTAMP = Instant.parse("2000-01-01T00:00:00Z");
private final SettingsProvider provider;
public final ObservableList<VaultSettings> directories;
public final BooleanProperty startHidden;
public final BooleanProperty autoCloseVaults;
@@ -78,13 +80,13 @@ public class Settings {
public final ObjectProperty<Instant> lastUpdateCheckReminder;
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
public final ObjectProperty<Path> previouslyUsedVaultDirectory;
public final StringProperty lastUpdateAttemptedByVersion;
public final ObservableSet<String> trustedHosts;
private Consumer<Settings> saveCmd;
public static Settings create(Environment env) {
public static Settings create(SettingsProvider provider, Environment env) {
var defaults = new SettingsJson();
defaults.showTrayIcon = env.showTrayIcon();
return new Settings(defaults);
return new Settings(provider, defaults);
}
/**
@@ -92,7 +94,8 @@ public class Settings {
*
* @param json The parsed settings.json
*/
Settings(SettingsJson json) {
Settings(SettingsProvider provider, SettingsJson json) {
this.provider = provider;
this.directories = FXCollections.observableArrayList(VaultSettings::observables);
this.startHidden = new SimpleBooleanProperty(this, "startHidden", json.startHidden);
this.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults);
@@ -118,6 +121,8 @@ public class Settings {
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.lastUpdateAttemptedByVersion = new SimpleStringProperty(this, "lastUpdateAttemptedByVersion", json.lastUpdateAttemptedByVersion);
this.trustedHosts = FXCollections.observableSet(json.trustedHosts);
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
@@ -148,15 +153,12 @@ public class Settings {
lastUpdateCheckReminder.addListener(this::somethingChanged);
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
previouslyUsedVaultDirectory.addListener(this::somethingChanged);
lastUpdateAttemptedByVersion.addListener(this::somethingChanged);
trustedHosts.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) {
@@ -210,6 +212,8 @@ public class Settings {
json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get();
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
json.lastUpdateAttemptedByVersion = lastUpdateAttemptedByVersion.get();
json.trustedHosts = Set.copyOf(trustedHosts);
return json;
}
@@ -222,20 +226,12 @@ public class Settings {
}
}
// TODO rename to setChangeListener
void setSaveCmd(Consumer<Settings> saveCmd) {
this.saveCmd = saveCmd;
}
private void somethingChanged(@SuppressWarnings("unused") Observable observable) {
this.save();
provider.scheduleSave(this);
}
void save() {
if (saveCmd != null) {
saveCmd.accept(this);
}
public void saveNow() {
provider.saveNow(this);
}
}

View File

@@ -4,17 +4,23 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
class SettingsJson {
@JsonProperty("directories")
List<VaultSettingsJson> directories = List.of();
@JsonSetter(nulls = Nulls.AS_EMPTY)
List<VaultSettingsJson> directories = new ArrayList<>();
@JsonProperty("writtenByVersion")
String writtenByVersion;
@@ -96,4 +102,11 @@ class SettingsJson {
@JsonProperty("previouslyUsedVaultDirectory")
Path previouslyUsedVaultDirectory;
@JsonProperty("lastUpdateAttemptedByVersion")
String lastUpdateAttemptedByVersion;
@JsonProperty("trustedHosts")
@JsonSetter(nulls = Nulls.AS_EMPTY)
Set<String> trustedHosts = new HashSet<>();
}

View File

@@ -26,7 +26,9 @@ import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -61,8 +63,7 @@ public class SettingsProvider implements Supplier<Settings> {
Settings settings = env.getSettingsPath() //
.flatMap(this::tryLoad) //
.findFirst() //
.orElseGet(() -> Settings.create(env));
settings.setSaveCmd(this::scheduleSave);
.orElseGet(() -> Settings.create(this, env));
return settings;
}
@@ -71,7 +72,7 @@ public class SettingsProvider implements Supplier<Settings> {
try (InputStream in = Files.newInputStream(path, StandardOpenOption.READ)) {
var json = JSON.reader().readValue(in, SettingsJson.class);
LOG.info("Settings loaded from {}", path);
var settings = new Settings(json);
var settings = new Settings(this, json);
return Stream.of(settings);
} catch (JacksonException e) {
LOG.warn("Failed to parse json file {}", path, e);
@@ -84,19 +85,33 @@ public class SettingsProvider implements Supplier<Settings> {
}
}
private void scheduleSave(Settings settings) {
if (settings == null) {
return;
void saveNow(Settings settings) {
try {
scheduleSave(settings, 0L).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Saving settings was interrupted.", e);
} catch (ExecutionException e) {
LOG.error("Unexpected exception while saving.", e);
}
final Optional<Path> settingsPath = env.getSettingsPath().findFirst(); // always save to preferred (first) path
settingsPath.ifPresent(path -> {
Runnable saveCommand = () -> this.save(settings, path);
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, SAVE_DELAY_MS, TimeUnit.MILLISECONDS);
ScheduledFuture<?> previouslyScheduledTask = scheduledSaveCmd.getAndSet(scheduledTask);
if (previouslyScheduledTask != null) {
previouslyScheduledTask.cancel(false);
}
});
}
void scheduleSave(Settings settings) {
scheduleSave(settings, SAVE_DELAY_MS);
}
private Future<?> scheduleSave(Settings settings, long delayMillis) {
if (settings == null) {
return CompletableFuture.completedFuture(null);
}
final Path settingsPath = env.getSettingsPath().findFirst().orElseThrow(); // always save to preferred (first) path
Runnable saveCommand = () -> this.save(settings, settingsPath);
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, delayMillis, TimeUnit.MILLISECONDS);
ScheduledFuture<?> previouslyScheduledTask = scheduledSaveCmd.getAndSet(scheduledTask);
if (previouslyScheduledTask != null) {
previouslyScheduledTask.cancel(false);
}
return scheduledTask;
}
private void save(Settings settings, Path settingsPath) {
@@ -107,7 +122,7 @@ public class SettingsProvider implements Supplier<Settings> {
Path tmpPath = settingsPath.resolveSibling(settingsPath.getFileName().toString() + ".tmp");
try (OutputStream out = Files.newOutputStream(tmpPath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
var jsonObj = settings.serialized();
jsonObj.writtenByVersion = env.getAppVersion() + env.getBuildNumber().map("-"::concat).orElse("");
jsonObj.writtenByVersion = env.getAppVersionWithBuildNumber();
JSON.writerWithDefaultPrettyPrinter().writeValue(out, jsonObj);
}
Files.move(tmpPath, settingsPath, StandardCopyOption.REPLACE_EXISTING);

View File

@@ -10,14 +10,6 @@ public enum UiTheme {
DARK("preferences.interface.theme.dark"), //
AUTOMATIC("preferences.interface.theme.automatic");
public static UiTheme[] applicableValues() {
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) {
return values();
} else {
return new UiTheme[]{LIGHT, DARK};
}
}
private final String displayName;
UiTheme(String displayName) {

View File

@@ -10,7 +10,7 @@ package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
import org.cryptomator.event.FileSystemEventAggregator;
import org.cryptomator.common.FilesystemOwnerSupplier;
import org.cryptomator.common.mount.Mounter;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
@@ -23,7 +23,8 @@ 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.event.FileSystemEventAggregator;
import org.cryptomator.event.NotificationManager;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException;
@@ -35,7 +36,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,10 +75,12 @@ 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;
private final FileSystemEventAggregator fileSystemEventAggregator;
private final NotificationManager notificationManager;
private final BooleanProperty showingStats;
private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@@ -91,7 +93,8 @@ public class Vault {
@Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
VaultStats stats, //
Mounter mounter, Settings settings, //
FileSystemEventAggregator fileSystemEventAggregator) {
FileSystemEventAggregator fileSystemEventAggregator, //
NotificationManager notificationManager) {
this.vaultSettings = vaultSettings;
this.configCache = configCache;
this.cryptoFileSystem = cryptoFileSystem;
@@ -103,12 +106,14 @@ 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);
this.mounter = mounter;
this.settings = settings;
this.fileSystemEventAggregator = fileSystemEventAggregator;
this.notificationManager = notificationManager;
this.showingStats = new SimpleBooleanProperty(false);
this.quickAccessEntry = new AtomicReference<>(null);
}
@@ -145,14 +150,17 @@ public class Vault {
LOG.warn("Limiting cleartext filename length on this device to {}.", vaultSettings.maxCleartextFilenameLength.get());
}
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() //
var fsPropsBuilder = CryptoFileSystemProperties.cryptoFileSystemProperties() //
.withKeyLoader(keyLoader) //
.withFlags(flags) //
.withMaxCleartextNameLength(vaultSettings.maxCleartextFilenameLength.get()) //
.withVaultConfigFilename(Constants.VAULTCONFIG_FILENAME) //
.withFilesystemEventConsumer(this::consumeVaultEvent) //
.build();
return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
.withFilesystemEventConsumer(this::consumeVaultEvent);
if (keyLoader instanceof FilesystemOwnerSupplier oo) {
fsPropsBuilder.withOwnerGetter(oo::getOwner);
}
return CryptoFileSystemProvider.newFileSystem(getPath(), fsPropsBuilder.build());
}
private void destroyCryptoFileSystem() {
@@ -262,6 +270,7 @@ public class Vault {
private void consumeVaultEvent(FilesystemEvent e) {
fileSystemEventAggregator.put(this, e);
notificationManager.offer(this, e);
}
// ******************************************************************************
@@ -336,6 +345,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,6 +9,7 @@
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;
@@ -34,9 +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.NEEDS_MIGRATION;
import static org.cryptomator.common.vaults.VaultState.Value.*;
@Singleton
public class VaultListManager {
@@ -67,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) {
@@ -114,59 +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 {
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();
if (Objects.isNull(vaultSettings.lastKnownKeyLoader.get())) {
var keyIdScheme = wrapper.get().getKeyId().getScheme();
vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
}
} else if (vaultState == NEEDS_MIGRATION) {
vaultSettings.lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME);
}
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

@@ -6,6 +6,7 @@ import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.cryptofs.event.FileIsInUseEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import javax.inject.Inject;
@@ -101,6 +102,7 @@ public class FileSystemEventAggregator {
case ConflictResolutionFailedEvent(_, _, Path conflictingCiphertext, _) -> conflictingCiphertext;
case BrokenDirFileEvent(_, Path ciphertext) -> ciphertext;
case BrokenFileNodeEvent(_, _, Path ciphertext) -> ciphertext;
case FileIsInUseEvent(_, _, Path ciphertext, _, _, _) -> ciphertext;
};
return new FSEventBucket(v, p, event.getClass());
}

View File

@@ -0,0 +1,85 @@
package org.cryptomator.event;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.event.FileIsInUseEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.nio.file.Path;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Manager for notifications.
* <p>
* To add (filesystem) events, use method {@link #offer(Vault, FilesystemEvent)}. If the input event is eligible, it is added to an internal queue.
* An event is eligible, if
* <ul>
* <li>the event should trigger a notification and</li>
* <li>it is not added within the last {@value DEBOUNCE_THRESHOLD_SECONDS} seconds</li>
* </ul>
*
* @see org.cryptomator.ui.fxapp.FxNotificationManager
*/
@Singleton
public class NotificationManager {
private static final int DEBOUNCE_THRESHOLD_SECONDS = 5;
private final Cache<FSEventBucket, FilesystemEvent> debounceCache;
private final ConcurrentLinkedQueue<VaultEvent> pendingEvents;
@Inject
public NotificationManager() {
debounceCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofSeconds(DEBOUNCE_THRESHOLD_SECONDS)).build();
pendingEvents = new ConcurrentLinkedQueue<>();
}
/**
* Offers the given filesystem event to the notification manager.
*
* @param v The vault where the filesystem event happened
* @param e the actual filesystem event
* @return {@code true} if the filesystem event is accepted, otherwise {@code false}.
*/
public boolean offer(Vault v, FilesystemEvent e) {
return switch (e) {
case FileIsInUseEvent fiiue -> addEvent(v, fiiue.ciphertextPath(), fiiue);
default -> false;
};
}
boolean addEvent(Vault v, Path keyPath, FilesystemEvent e) {
var key = new FSEventBucket(v, keyPath, e.getClass());
var isAdded = new AtomicBoolean(false);
debounceCache.asMap().computeIfAbsent(key, _ -> {
synchronized (this) {
pendingEvents.add(new VaultEvent(v, e));
isAdded.set(true);
}
return e;
});
return isAdded.get();
}
/**
* Adds all events to the target list and clears afterward the pending-event-queue
*
* @param target list where the filesystem events are copied to
* @return {@code true}, if elements were copied
*/
public boolean appendToAndClear(List<VaultEvent> target) {
//it is not clear, if addAll iterates thread-safe over the pendingEvents
//hence we synchronize moving (copy then clear) and adding-single-element operations
synchronized (this) {
var result = target.addAll(pendingEvents);
pendingEvents.clear();
return result;
}
}
}

View File

@@ -3,25 +3,6 @@ package org.cryptomator.event;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import java.time.Instant;
public record VaultEvent(Vault v, FilesystemEvent actualEvent) {
public record VaultEvent(Vault v, FilesystemEvent actualEvent, int count) implements Comparable<VaultEvent> {
public VaultEvent(Vault v, FilesystemEvent actualEvent) {
this(v, actualEvent, 1);
}
@Override
public int compareTo(VaultEvent other) {
var timeResult = actualEvent.getTimestamp().compareTo(other.actualEvent().getTimestamp());
if(timeResult != 0) {
return timeResult;
} else {
return this.equals(other) ? 0 : this.actualEvent.getClass().getName().compareTo(other.actualEvent.getClass().getName());
}
}
public VaultEvent incrementCount(FilesystemEvent update) {
return new VaultEvent(v, update, count+1);
}
}

View File

@@ -0,0 +1,101 @@
package org.cryptomator.launcher;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.Reader;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Properties;
import java.util.Set;
/**
* Factory to generate admin properties.
*
* <p>
* Admin properties are {@link Properties} using system properties as defaults, but allow overwriting a specific set of properties with an external config file.
* Those properties are created by calling {@link #create()}. The method first reads system property {@value #ADMIN_PROP_FILE_KEY}. If it contains a path to a valid properties file, all overridable properties from the file are loaded into the returned admin properties.
* <p>
* The overridable properties are:
* <ul>
* <li>cryptomator.logDir</li>
* <li>cryptomator.pluginDir</li>
* <li>cryptomator.p12Path</li>
* <li>cryptomator.mountPointsDir</li>
* <li>cryptomator.disableUpdateCheck</li>
* <li>cryptomator.hub.allowedHosts</li>
* <li>cryptomator.hub.enableTrustOnFirstUse</li>
* </ul>
*
* @see Properties
* @see System#getProperties()
*/
class AdminPropertiesFactory {
private static final Logger LOG = EventualLogger.INSTANCE;
private static final long MAX_CONFIG_SIZE_BYTES = 8192;
private static final String ADMIN_PROP_FILE_KEY = "cryptomator.adminConfigPath";
private static final Set<String> ALLOWED_OVERRIDES = Set.of( //
"cryptomator.logDir", //
"cryptomator.pluginDir", //
"cryptomator.p12Path", //
"cryptomator.mountPointsDir", //
"cryptomator.disableUpdateCheck", //
"cryptomator.hub.allowedHosts", //
"cryptomator.hub.enableTrustOnFirstUse");
/**
* Creates new {@link Properties} containing overridable properties from the admin config.
* <p>
* The returned properties object uses as default the {@link System} properties.
* For a list of overridable properties, see {@link AdminPropertiesFactory}
*
* @return {@link Properties} containing overridable properties from the admin config and defaulting to system properties.
*/
static Properties create() {
var systemProps = System.getProperties();
var adminProps = new Properties(systemProps);
final String adminCfgPath = System.getProperty(ADMIN_PROP_FILE_KEY);
if (adminCfgPath == null) {
LOG.debug("Admin config property is not defined. Skipping.");
return adminProps;
}
var propsFromFile = loadPropertiesFromFile(Path.of(adminCfgPath));
for (var key : propsFromFile.stringPropertyNames()) {
if (ALLOWED_OVERRIDES.contains(key)) {
var value = propsFromFile.getProperty(key);
LOG.info("Overwriting {} with value {} from admin config.", key, value);
adminProps.setProperty(key, value);
} else {
LOG.debug("Property {} in admin config is not supported for override.", key);
}
}
return adminProps;
}
//visible for testing
static Properties loadPropertiesFromFile(Path adminPropertiesPath) {
var adminProps = new Properties();
try (FileChannel ch = FileChannel.open(adminPropertiesPath, StandardOpenOption.READ); //
Reader reader = Channels.newReader(ch, StandardCharsets.UTF_8)) {
if (ch.size() > MAX_CONFIG_SIZE_BYTES) {
throw new IOException("Config file %s exceeds maximum size of %d".formatted(adminPropertiesPath, MAX_CONFIG_SIZE_BYTES));
}
adminProps.load(reader);
} catch (NoSuchFileException _) {
//NO-OP
LOG.debug("No admin properties found at {}.", adminPropertiesPath);
} catch (IOException | IllegalArgumentException e) {
LOG.warn("Failed to read administrative properties from {}. Returning empty properties.", adminPropertiesPath, e);
}
return adminProps;
}
}

View File

@@ -11,9 +11,9 @@ import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Environment;
import org.cryptomator.common.ShutdownHook;
import org.cryptomator.common.SubstitutingProperties;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.ipc.IpcCommunicator;
import org.cryptomator.logging.DebugMode;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +35,8 @@ public class Cryptomator {
private static final long STARTUP_TIME = System.currentTimeMillis();
static {
var lazyProcessedProps = new SubstitutingProperties(System.getProperties(), System.getenv());
var adminProps = AdminPropertiesFactory.create();
var lazyProcessedProps = new SubstitutingProperties(adminProps, System.getenv(), EventualLogger.INSTANCE);
System.setProperties(lazyProcessedProps);
CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
LOG = LoggerFactory.getLogger(Cryptomator.class);
@@ -89,10 +90,11 @@ public class Cryptomator {
* @return Nonzero exit code in case of an error.
*/
private int run(String[] args) {
debugMode.initialize();
EventualLogger.INSTANCE.drainTo(LOG);
env.log();
LOG.debug("Dagger graph initialized after {}ms", System.currentTimeMillis() - STARTUP_TIME);
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
debugMode.initialize();
supportedLanguages.applyPreferred();
changeDefaultSSLContext();
/*

View File

@@ -4,7 +4,6 @@ import dagger.Module;
import dagger.Provides;
import org.cryptomator.integrations.autostart.AutoStartProvider;
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import javax.inject.Named;
@@ -30,11 +29,6 @@ class CryptomatorModule {
return new ArrayBlockingQueue<>(10);
}
@Provides
@Singleton
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides
@Singleton

View File

@@ -0,0 +1,106 @@
package org.cryptomator.launcher;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.event.DefaultLoggingEvent;
import org.slf4j.event.Level;
import org.slf4j.event.LoggingEvent;
import org.slf4j.helpers.AbstractLogger;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
class EventualLogger extends AbstractLogger {
static final EventualLogger INSTANCE = new EventualLogger();
private final Queue<LoggingEvent> bufferedEvents = new ArrayDeque<>();
private EventualLogger() {
}
synchronized void drainTo(Logger gutter) {
for (var event : bufferedEvents) {
var builder = gutter.atLevel(event.getLevel()) //
.setCause(event.getThrowable()) //
.setMessage(event.getMessage());
Objects.requireNonNullElse(event.getArguments(), List.of()).forEach(builder::addArgument);
Objects.requireNonNullElse(event.getMarkers(), List.<Marker>of()).forEach(builder::addMarker);
builder.log();
}
bufferedEvents.clear();
}
@Override
protected synchronized void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, Throwable throwable) {
var event = new DefaultLoggingEvent(level, this);
if (marker != null) {
event.addMarker(marker);
}
event.setMessage(messagePattern);
for (var arg : Objects.requireNonNullElse(arguments, new Object[]{})) {
event.addArgument(arg);
}
event.setThrowable(throwable);
bufferedEvents.add(event);
}
//Unclear, unused and undocumented method of slf4j, see also https://github.com/qos-ch/slf4j/discussions/348
@Override
protected String getFullyQualifiedCallerName() {
return getClass().getCanonicalName();
}
@Override
public boolean isTraceEnabled() {
return true;
}
@Override
public boolean isTraceEnabled(Marker marker) {
return true;
}
@Override
public boolean isDebugEnabled() {
return true;
}
@Override
public boolean isDebugEnabled(Marker marker) {
return true;
}
@Override
public boolean isInfoEnabled() {
return true;
}
@Override
public boolean isInfoEnabled(Marker marker) {
return true;
}
@Override
public boolean isWarnEnabled() {
return true;
}
@Override
public boolean isWarnEnabled(Marker marker) {
return true;
}
@Override
public boolean isErrorEnabled() {
return true;
}
@Override
public boolean isErrorEnabled(Marker marker) {
return true;
}
}

View File

@@ -18,7 +18,7 @@ abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider {
public SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException {
try {
KeyStore truststore = getTruststore();
truststore.load(null, null);
ensureLoaded(truststore);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(truststore);
@@ -30,4 +30,13 @@ abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider {
throw new SSLContextBuildException(e);
}
}
static void ensureLoaded(KeyStore truststore) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
try {
truststore.aliases();
} catch (KeyStoreException e) {
// Not initialized yet (e.g. custom KeyStore SPI); initialize without replacing preloaded stores.
truststore.load(null, null);
}
}
}

View File

@@ -1,21 +1,73 @@
package org.cryptomator.networking;
import org.cryptomator.common.Nullable;
import org.cryptomator.integrations.common.OperatingSystem;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Properties;
/**
* SSLContextProvider for Windows using the Windows certificate store as trust store
* SSLContextProvider for Windows using the Windows certificate store as trust store and the bundled JDK cacerts as fallback
* <p>
* In order to work, the jdk.crypto.mscapi jmod is needed
*/
@OperatingSystem(OperatingSystem.Value.WINDOWS)
public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider {
private static final Logger LOG = LoggerFactory.getLogger(SSLContextWithWindowsCertStore.class);
private static final String DEFAULT_TRUSTSTORE_PASSWORD = "changeit"; //default JDK cacerts password
@Override
KeyStore getTruststore() throws KeyStoreException {
return KeyStore.getInstance("WINDOWS-ROOT");
KeyStore getTruststore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
var windowsKeyStore = KeyStore.getInstance("WINDOWS-ROOT");
var jdkKeyStore = getShippedCaCertsStore();
if (jdkKeyStore == null) {
return windowsKeyStore;
}
ensureLoaded(windowsKeyStore);
ensureLoaded(jdkKeyStore);
try {
CombinedKeyStoreSpi spi = CombinedKeyStoreSpi.create(windowsKeyStore, jdkKeyStore);
Provider dummyProvider = new Provider("CombinedKeyStoreProvider", "1.0", "Provides a combined, read-only KeyStore") {};
return new KeyStore(spi, dummyProvider, "CombinedKeyStoreProvider") {};
} catch (IllegalArgumentException e) {
throw new KeyStoreException(e);
}
}
@Nullable
KeyStore getShippedCaCertsStore() {
return getCaCertsStoreByProperties(System.getProperties());
}
//for testability
@VisibleForTesting
@Nullable
KeyStore getCaCertsStoreByProperties(Properties props) {
var javaHome = Path.of(props.getProperty("java.home"));
var trustStorePassword = props.getProperty("javax.net.ssl.trustStorePassword", DEFAULT_TRUSTSTORE_PASSWORD).toCharArray();
for (var candidate : List.of(javaHome.resolve("lib/security/cacerts"), javaHome.resolve("conf/security/cacerts"))) {
try {
if (Files.isRegularFile(candidate)) {
return KeyStore.getInstance(candidate.toFile(), trustStorePassword);
}
} catch (CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException e) {
LOG.info("Unable to load fallback cacerts {} file. Skipping fallback.", candidate, e);
}
}
return null;
}
}

View File

@@ -59,7 +59,7 @@ public class ChooseExistingVaultController implements FxController {
this.vault = vault;
this.vaultListManager = vaultListManager;
this.resourceBundle = resourceBundle;
this.screenshot = applicationStyle.appliedThemeProperty().map(this::selectScreenshot);
this.screenshot = applicationStyle.appliedAppThemeProperty().map(this::selectScreenshot);
}
private Image selectScreenshot(Theme theme) {

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

@@ -19,6 +19,7 @@ public enum FxmlFile {
HEALTH_START("/fxml/health_start.fxml"), //
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
HUB_NO_KEYCHAIN("/fxml/hub_no_keychain.fxml"), //
HUB_CHECK_HOST_TRUST("/fxml/hub_check_host_trust.fxml"), //
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
@@ -29,6 +30,7 @@ public enum FxmlFile {
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"), //
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), //
HUB_UNTRUSTED_HOST("/fxml/hub_untrusted_host.fxml"), //
HUB_REQUIRE_ACCOUNT_INIT("/fxml/hub_require_account_init.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), //
@@ -38,13 +40,15 @@ public enum FxmlFile {
MIGRATION_RUN("/fxml/migration_run.fxml"), //
MIGRATION_START("/fxml/migration_start.fxml"), //
MIGRATION_SUCCESS("/fxml/migration_success.fxml"), //
NOTIFICATION("/fxml/notification.fxml"), //
PREFERENCES("/fxml/preferences.fxml"), //
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"), //
@@ -58,6 +62,7 @@ public enum FxmlFile {
VAULT_STATISTICS("/fxml/stats.fxml"), //
WRONGFILEALERT("/fxml/wrongfilealert.fxml");
private final String ressourcePathString;
FxmlFile(String ressourcePathString) {

View File

@@ -0,0 +1,56 @@
package org.cryptomator.ui.common;
import javafx.stage.Screen;
/**
* Utility class providing methods regarding the OS bar.
*/
public class SystemBarUtil {
public enum Placement {
/**
* OS Bar placed at the left screen edge
*/
LEFT,
/**
* OS Bar placed at the top screen edge
*/
TOP,
/**
* OS Bar placed at the right screen edge
*/
RIGHT,
/**
* OS Bar placed at the bottom screen edge
*/
BOTTOM;
}
/**
* Determines the placement of the OS bar on the given screen.
* <p>
* <b>Assuming the OS bar fills one screen edge completely</b>,
* this method determines that screen edge by comparing the actual screen bounds with the visual ones.
* <p>
* If the screen does not have a system bar, the bottom placement is returned.
* If the screen does have multiple system bars, the first in following priority is returned:
* LEFT, TOP, RIGHT, BOTTOM.
*
* @param screen a {@link Screen} where an OS bar exists
* @return {@link Placement} indicating the screen edge.
*/
public static Placement getPlacementOfSystembar(Screen screen) {
var bounds = screen.getBounds();
var vBounds = screen.getVisualBounds();
//assumption: the system bar fills a whole screen side
if (bounds.getMinX() != vBounds.getMinX()) {
return Placement.LEFT;
} else if (bounds.getMinY() != vBounds.getMinY()) {
return Placement.TOP;
} else if (bounds.getMaxX() != vBounds.getMaxX()) {
return Placement.RIGHT;
} else {
return Placement.BOTTOM;
}
}
}

View File

@@ -1,17 +1,16 @@
package org.cryptomator.ui.common;
import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException;
import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.ui.fxapp.FxApplicationScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.concurrent.Task;
import javafx.stage.Stage;
import java.io.IOException;
@@ -28,12 +27,12 @@ public class VaultService {
private static final Logger LOG = LoggerFactory.getLogger(VaultService.class);
private final Lazy<Application> application;
private final RevealPathService revealPathService;
private final ExecutorService executorService;
@Inject
public VaultService(Lazy<Application> application, ExecutorService executorService) {
this.application = application;
public VaultService(RevealPathService revealPathService, ExecutorService executorService) {
this.revealPathService = revealPathService;
this.executorService = executorService;
}
@@ -47,9 +46,9 @@ public class VaultService {
* @param vault The vault to reveal
*/
public Task<Vault> createRevealTask(Vault vault) {
Task<Vault> task = new RevealVaultTask(vault, application.get().getHostServices());
task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayName()));
task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), evt.getSource().getException()));
Task<Vault> task = new RevealVaultTask(vault, revealPathService);
task.setOnSucceeded(_ -> LOG.info("Revealed {}", vault.getDisplayName()));
task.setOnFailed(evt -> LOG.warn("Failed to reveal {}", vault.getDisplayName(), evt.getSource().getException()));
return task;
}
@@ -110,19 +109,18 @@ public class VaultService {
private static class RevealVaultTask extends Task<Vault> {
private final Vault vault;
private final HostServices hostServices;
private final RevealPathService rs;
public RevealVaultTask(Vault vault, HostServices hostServices) {
public RevealVaultTask(Vault vault, RevealPathService revealPathService) {
this.vault = vault;
this.hostServices = hostServices;
setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), getException()));
this.rs = revealPathService;
}
@Override
protected Vault call() {
protected Vault call() throws RevealFailedException {
switch (vault.getMountPoint()) {
case null -> LOG.warn("Not currently mounted");
case Mountpoint.WithPath m -> hostServices.showDocument(m.uri().toString());
case Mountpoint.WithPath m -> rs.reveal(m.path());
case Mountpoint.WithUri m -> LOG.info("Vault mounted at {}", m.uri()); // TODO show in UI?
}
return vault;

View File

@@ -12,6 +12,8 @@ public enum FontAwesome5Icon {
CARET_DOWN("\uF0D7"), //
CARET_RIGHT("\uF0Da"), //
CHECK("\uF00C"), //
CHEVRON_LEFT("\uF053"), //
CHEVRON_RIGHT("\uF054"), //
CLOCK("\uF017"), //
CLIPBOARD("\uF328"), //
COG("\uF013"), //
@@ -60,6 +62,7 @@ public enum FontAwesome5Icon {
TRASH("\uF1F8"), //
UNLINK("\uf127"), //
USER_COG("\uf4fe"), //
USER_LOCK("\uf502"), //
WRENCH("\uF0AD"), //
WINDOW_MINIMIZE("\uF2D1"), //
;

View File

@@ -4,24 +4,27 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.AccessibleRole;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import java.util.ResourceBundle;
public class NotificationBar extends HBox {
public class InfoBar extends HBox {
@FXML
private Label notificationLabel;
private Label infoMessage;
private final BooleanProperty dismissable = new SimpleBooleanProperty();
private final BooleanProperty notify = new SimpleBooleanProperty();
public NotificationBar() {
public InfoBar() {
setAlignment(Pos.CENTER);
setStyle("-fx-alignment: center;");
getStyleClass().addAll("info-bar");
Region spacer = new Region();
spacer.setMinWidth(40);
@@ -36,14 +39,21 @@ public class NotificationBar extends HBox {
vbox.setAlignment(Pos.CENTER);
HBox.setHgrow(vbox, javafx.scene.layout.Priority.ALWAYS);
notificationLabel = new Label();
notificationLabel.getStyleClass().add("notification-label");
notificationLabel.setStyle("-fx-alignment: center;");
vbox.getChildren().add(notificationLabel);
infoMessage = new Label();
infoMessage.setFocusTraversable(true);
infoMessage.setAccessibleRole(AccessibleRole.BUTTON);
vbox.getChildren().add(infoMessage);
Button closeButton = new Button("X");
var closeGraphic = new FontAwesome5IconView();
closeGraphic.setGlyph(FontAwesome5Icon.TIMES);
closeGraphic.setGlyphSize(12);
closeGraphic.getStyleClass().add("glyph");
Button closeButton = new Button();
closeButton.setGraphic(closeGraphic);
closeButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
closeButton.setAccessibleText(ResourceBundle.getBundle("i18n.strings").getString("main.notification.closeButton.tooltip"));
closeButton.setMinWidth(40);
closeButton.setStyle("-fx-background-color: transparent; -fx-text-fill: white; -fx-font-weight: bold;");
closeButton.visibleProperty().bind(dismissable);
closeButton.setOnAction(_ -> {
@@ -61,11 +71,11 @@ public class NotificationBar extends HBox {
}
public String getText() {
return notificationLabel.getText();
return infoMessage.getText();
}
public void setText(String text) {
notificationLabel.setText(text);
infoMessage.setText(text);
}
public void setStyleClass(String styleClass) {

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

@@ -194,7 +194,7 @@ public class DecryptFileNamesViewController implements FxController {
}
}
//obvservable getter
//observable getter
public ObservableValue<String> dropZoneTextProperty() {
return dropZoneText;

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,52 @@ 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 prepareHubVaultArchived(Stage window, Vault vault) {
return createDialogBuilder().setOwner(window) //
.setTitleKey("unlock.title", vault.getDisplayName()) //
.setMessageKey("hub.archived.message") //
.setDescriptionKey("hub.archived.description") //
.setIcon(FontAwesome5Icon.BAN)//
.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 +120,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 +134,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

@@ -1,16 +1,18 @@
package org.cryptomator.ui.eventview;
import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.event.FileSystemEventAggregator;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
import org.cryptomator.common.Nullable;
import org.cryptomator.common.ObservableUtil;
import org.cryptomator.cryptofs.CryptoPath;
import org.cryptomator.cryptofs.event.BrokenDirFileEvent;
import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.cryptofs.event.FileIsInUseEvent;
import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.event.FileSystemEventAggregator;
import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.ui.common.FxController;
@@ -43,7 +45,6 @@ import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.function.Function;
@@ -54,7 +55,6 @@ public class EventListCellController implements FxController {
private static final DateTimeFormatter LOCAL_TIME_FORMATTER = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withZone(ZoneId.systemDefault());
private final FileSystemEventAggregator fileSystemEventAggregator;
@Nullable
private final RevealPathService revealService;
private final ResourceBundle resourceBundle;
private final ObjectProperty<Map.Entry<FSEventBucket, FSEventBucketContent>> eventEntry;
@@ -79,15 +79,17 @@ public class EventListCellController implements FxController {
Button eventActionsButton;
@Inject
public EventListCellController(FileSystemEventAggregator fileSystemEventAggregator, Optional<RevealPathService> revealService, ResourceBundle resourceBundle) {
public EventListCellController(FileSystemEventAggregator fileSystemEventAggregator,
RevealPathService revealService,
ResourceBundle resourceBundle) {
this.fileSystemEventAggregator = fileSystemEventAggregator;
this.revealService = revealService.orElseGet(() -> null);
this.revealService = revealService;
this.resourceBundle = resourceBundle;
this.eventEntry = new SimpleObjectProperty<>(null);
this.eventMessage = new SimpleStringProperty();
this.eventDescription = new SimpleStringProperty();
this.eventIcon = new SimpleObjectProperty<>();
this.eventCount = ObservableUtil.mapWithDefault(eventEntry, e -> e.getValue().count() == 1? "" : "("+ e.getValue().count() +")", "");
this.eventCount = ObservableUtil.mapWithDefault(eventEntry, e -> e.getValue().count() == 1 ? "" : "(" + e.getValue().count() + ")", "");
this.vaultUnlocked = ObservableUtil.mapWithDefault(eventEntry.flatMap(e -> e.getKey().vault().unlockedProperty()), Function.identity(), false);
this.readableTime = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_TIME_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
this.readableDate = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_DATE_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
@@ -115,7 +117,7 @@ public class EventListCellController implements FxController {
eventActionsMenu.hide();
eventActionsMenu.getItems().clear();
eventTooltip.setText(item.getKey().vault().getDisplayName());
addAction("generic.action.dismiss", () -> {
addLocalizedAction("generic.action.dismiss", () -> {
fileSystemEventAggregator.remove(item.getKey());
});
switch (item.getValue().mostRecentEvent()) {
@@ -124,70 +126,70 @@ public class EventListCellController implements FxController {
case DecryptionFailedEvent fse -> this.adjustToDecryptionFailedEvent(fse);
case BrokenDirFileEvent fse -> this.adjustToBrokenDirFileEvent(fse);
case BrokenFileNodeEvent fse -> this.adjustToBrokenFileNodeEvent(fse);
case FileIsInUseEvent fse -> this.adjustToFileInUseEvent(fse);
}
}
private void adjustToFileInUseEvent(FileIsInUseEvent fiiue) {
eventIcon.setValue(FontAwesome5Icon.USER_LOCK);
eventMessage.setValue(resourceBundle.getString("eventView.entry.inUse.message"));
var indexFileName = fiiue.cleartextPath().lastIndexOf("/");
eventDescription.setValue(fiiue.cleartextPath().substring(indexFileName + 1));
addLocalizedAction("eventView.entry.inUse.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(fiiue.cleartextPath())));
addLocalizedAction("eventView.entry.inUse.showEncrypted", () -> reveal(revealService, fiiue.ciphertextPath()));
var userAndDevice = fiiue.owner().split(Constants.HUB_USER_DEVICE_SEPARATOR);
var user = userAndDevice[0];
var device = userAndDevice.length == 1 ? userAndDevice[0] : userAndDevice[1];
addLocalizedAction("eventView.entry.inUse.copyUserAndDevice", () -> copyToClipboard(user + ", " + device));
addLocalizedAction("eventView.entry.inUse.ignoreLock", fiiue.ignoreMethod());
}
private void adjustToBrokenFileNodeEvent(BrokenFileNodeEvent bfe) {
eventIcon.setValue(FontAwesome5Icon.TIMES);
eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenFileNode.message"));
eventDescription.setValue(bfe.ciphertextPath().getFileName().toString());
if (revealService != null) {
addAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, bfe.ciphertextPath()));
} else {
addAction("eventView.entry.brokenFileNode.copyEncrypted", () -> copyToClipboard(bfe.ciphertextPath().toString()));
}
addAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString()));
addLocalizedAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, bfe.ciphertextPath()));
addLocalizedAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString()));
}
private void adjustToConflictResolvedEvent(ConflictResolvedEvent cre) {
eventIcon.setValue(FontAwesome5Icon.CHECK);
eventMessage.setValue(resourceBundle.getString("eventView.entry.conflictResolved.message"));
eventDescription.setValue(cre.resolvedCiphertextPath().getFileName().toString());
if (revealService != null) {
addAction("eventView.entry.conflictResolved.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cre.resolvedCleartextPath())));
} else {
addAction("eventView.entry.conflictResolved.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(cre.resolvedCleartextPath()).toString()));
}
addLocalizedAction("eventView.entry.conflictResolved.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cre.resolvedCleartextPath())));
}
private void adjustToConflictEvent(ConflictResolutionFailedEvent cfe) {
eventIcon.setValue(FontAwesome5Icon.COMPRESS_ALT);
eventMessage.setValue(resourceBundle.getString("eventView.entry.conflict.message"));
eventDescription.setValue(cfe.conflictingCiphertextPath().getFileName().toString());
if (revealService != null) {
addAction("eventView.entry.conflict.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cfe.canonicalCleartextPath())));
addAction("eventView.entry.conflict.showEncrypted", () -> reveal(revealService, cfe.conflictingCiphertextPath()));
} else {
addAction("eventView.entry.conflict.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(cfe.canonicalCleartextPath()).toString()));
addAction("eventView.entry.conflict.copyEncrypted", () -> copyToClipboard(cfe.conflictingCiphertextPath().toString()));
}
addLocalizedAction("eventView.entry.conflict.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cfe.canonicalCleartextPath())));
addLocalizedAction("eventView.entry.conflict.showEncrypted", () -> reveal(revealService, cfe.conflictingCiphertextPath()));
}
private void adjustToDecryptionFailedEvent(DecryptionFailedEvent dfe) {
eventIcon.setValue(FontAwesome5Icon.BAN);
eventMessage.setValue(resourceBundle.getString("eventView.entry.decryptionFailed.message"));
eventDescription.setValue(dfe.ciphertextPath().getFileName().toString());
if (revealService != null) {
addAction("eventView.entry.decryptionFailed.showEncrypted", () -> reveal(revealService, dfe.ciphertextPath()));
} else {
addAction("eventView.entry.decryptionFailed.copyEncrypted", () -> copyToClipboard(dfe.ciphertextPath().toString()));
}
addLocalizedAction("eventView.entry.decryptionFailed.showEncrypted", () -> reveal(revealService, dfe.ciphertextPath()));
}
private void adjustToBrokenDirFileEvent(BrokenDirFileEvent bde) {
eventIcon.setValue(FontAwesome5Icon.TIMES);
eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenDirFile.message"));
eventDescription.setValue(bde.ciphertextPath().getParent().getFileName().toString());
if (revealService != null) {
addAction("eventView.entry.brokenDirFile.showEncrypted", () -> reveal(revealService, bde.ciphertextPath()));
} else {
addAction("eventView.entry.brokenDirFile.copyEncrypted", () -> copyToClipboard(bde.ciphertextPath().toString()));
}
addLocalizedAction("eventView.entry.brokenDirFile.showEncrypted", () -> reveal(revealService, bde.ciphertextPath()));
}
private void addAction(String localizationKey, Runnable action) {
var entry = new MenuItem(resourceBundle.getString(localizationKey));
private void addLocalizedAction(String localizationKey, Runnable action) {
var entryText = resourceBundle.getString(localizationKey);
addAction(entryText, action);
}
private void addAction(String entryText, Runnable action) {
var entry = new MenuItem(entryText);
entry.getStyleClass().addLast("dropdown-button-context-menu-item");
entry.setOnAction(_ -> action.run());
eventActionsMenu.getItems().addLast(entry);
@@ -234,18 +236,17 @@ public class EventListCellController implements FxController {
}
}
private Path convertVaultPathToSystemPath(Path p) {
if (!(p instanceof CryptoPath)) {
throw new IllegalArgumentException("Path " + p + " is not a vault path");
}
private Path convertVaultPathToSystemPath(String vaultInternalPath) {
var v = eventEntry.getValue().getKey().vault();
if (!v.isUnlocked()) {
return Path.of(System.getProperty("user.home"));
}
var mountUri = v.getMountPoint().uri();
var internalPath = p.toString().substring(1);
return Path.of(mountUri.getPath().concat(internalPath).substring(1));
var mountPoint = v.getMountPoint().uri().getPath();
if (SystemUtils.IS_OS_WINDOWS) {
mountPoint = mountPoint.substring(1); //strip away any leading "/", otherwise there are errors
}
return Path.of(mountPoint, vaultInternalPath.substring(1)); //vaultPaths are always absolute
}
private void reveal(RevealPathService s, Path p) {

View File

@@ -10,16 +10,20 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Application;
import javafx.application.Platform;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@FxApplicationScoped
public class FxApplication {
private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class);
static final AtomicReference<Application> INSTANCE = new AtomicReference<>();
private final long startupTime;
private final Environment environment;
private final Settings settings;
@@ -30,9 +34,21 @@ public class FxApplication {
private final FxApplicationTerminator applicationTerminator;
private final AutoUnlocker autoUnlocker;
private final FxFSEventList fxFSEventList;
private final FxNotificationManager notificationManager;
@Inject
FxApplication(@Named("startupTime") long startupTime, Environment environment, Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker, FxFSEventList fxFSEventList) {
FxApplication(Application fxApp,
@Named("startupTime") long startupTime, //
Environment environment, //
Settings settings, //
AppLaunchEventHandler launchEventHandler, //
Lazy<TrayMenuComponent> trayMenu, //
FxApplicationWindows appWindows, //
FxApplicationStyle applicationStyle, //
FxApplicationTerminator applicationTerminator, //
AutoUnlocker autoUnlocker, //
FxFSEventList fxFSEventList, //
FxNotificationManager notificationManager) {
this.startupTime = startupTime;
this.environment = environment;
this.settings = settings;
@@ -43,6 +59,9 @@ public class FxApplication {
this.applicationTerminator = applicationTerminator;
this.autoUnlocker = autoUnlocker;
this.fxFSEventList = fxFSEventList;
this.notificationManager = notificationManager;
INSTANCE.set(fxApp);
}
public void start() {
@@ -88,6 +107,7 @@ public class FxApplication {
launchEventHandler.startHandlingLaunchEvents();
fxFSEventList.schedulePollForUpdates();
notificationManager.schedulePollForUpdates();
autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES);
}

View File

@@ -7,28 +7,29 @@ package org.cryptomator.ui.fxapp;
import dagger.Module;
import dagger.Provides;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.ui.decryptname.DecryptNameComponent;
import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.eventview.EventViewComponent;
import org.cryptomator.ui.health.HealthCheckComponent;
import org.cryptomator.ui.lock.LockComponent;
import org.cryptomator.ui.mainwindow.MainWindowComponent;
import org.cryptomator.ui.notification.NotificationComponent;
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;
import java.util.Optional;
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, //
@Module(subcomponents = {TrayMenuComponent.class, //
DecryptNameComponent.class, //
MainWindowComponent.class, //
PreferencesComponent.class, //
@@ -40,7 +41,9 @@ import java.io.InputStream;
HealthCheckComponent.class, //
UpdateReminderComponent.class, //
ShareVaultComponent.class, //
EventViewComponent.class})
EventViewComponent.class, //
RecoveryKeyComponent.class, //
NotificationComponent.class})
abstract class FxApplicationModule {
private static Image createImageFromResource(String resourceName) throws IOException {
@@ -49,6 +52,12 @@ abstract class FxApplicationModule {
}
}
@Provides
@FxApplicationScoped
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides
@FxApplicationScoped
static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) {
@@ -79,4 +88,10 @@ abstract class FxApplicationModule {
return factory.create();
}
@Provides
@FxApplicationScoped
static NotificationComponent provideNotificationComponent(NotificationComponent.Factory factory) {
return factory.create();
}
}

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