diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 7cc13ff3c..8c3d2a7d5 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -2,123 +2,25 @@
## Reporting a Vulnerability
-For reporting security-related vulnerabilities or exploits that [haven't been reported yet](https://github.com/cryptomator/cryptomator/labels/type%3Asecurity-issue), contact us at: security@cryptomator.org
+We take security seriously at Cryptomator. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
-
-PGP Key
+To report a security vulnerability, please use the [GitHub Security Advisory feature](https://github.com/cryptomator/cryptomator/security/advisories). This feature allows you to privately discuss, fix, and publish information about security vulnerabilities.
-```
------BEGIN PGP PUBLIC KEY BLOCK-----
-Comment: GPGTools - https://gpgtools.org
+If you prefer to report the vulnerability via email, please send an email to security@cryptomator.org.
-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
-=W1Ri
------END PGP PUBLIC KEY BLOCK-----
-```
-
+PGP key fingerprint: `3647 9903 B23A E0A5 9359 9A3E 23B5 DBEF 94D4 D81D` ([public key](https://gist.github.com/cryptobot/864300b6b44ae2d2a15abedfe14bd040))
+
+## Expectations
+
+When reporting a vulnerability, please provide us with a detailed report that includes:
+
+- A description of the vulnerability
+- Steps to reproduce the vulnerability
+- Possible impact of the vulnerability
+- Any additional information that may be helpful
+
+We ask that you do not publicly disclose the vulnerability until we have had a chance to address it.
+
+## Thank You
+
+We appreciate your help in keeping Cryptomator secure. Thank you for your contributions to the security of our project.
diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml
index 0bd01fe60..6fcc12605 100644
--- a/.github/workflows/appimage.yml
+++ b/.github/workflows/appimage.yml
@@ -86,12 +86,12 @@ jobs:
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dfile.encoding=\"utf-8\""
- --java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\""
- --java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\""
- --java-options "-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\""
- --java-options "-Dcryptomator.p12Path=\"~/.config/Cryptomator/key.p12\""
- --java-options "-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\""
- --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\""
+ --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=false"
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"${TRAYICONSDIR}\"" \
--java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.get-version.outputs.revNum }}\""
diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml
index bad80138b..1190444d3 100644
--- a/.github/workflows/mac-dmg.yml
+++ b/.github/workflows/mac-dmg.yml
@@ -98,13 +98,13 @@ 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.logDir=\"~/Library/Logs/Cryptomator\""
- --java-options "-Dcryptomator.pluginDir=\"~/Library/Application Support/Cryptomator/Plugins\""
- --java-options "-Dcryptomator.settingsPath=\"~/Library/Application Support/Cryptomator/settings.json\""
- --java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/Cryptomator/key.p12\""
- --java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\""
+ --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=\"~/Cryptomator\""
+ --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Cryptomator\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--mac-package-identifier org.cryptomator
diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml
index df67c1dcb..23dcae7c5 100644
--- a/.github/workflows/win-exe.yml
+++ b/.github/workflows/win-exe.yml
@@ -112,17 +112,17 @@ jobs:
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dfile.encoding=\"utf-8\""
- --java-options "-Dcryptomator.logDir=\"~/AppData/Roaming/Cryptomator\""
- --java-options "-Dcryptomator.pluginDir=\"~/AppData/Roaming/Cryptomator/Plugins\""
- --java-options "-Dcryptomator.settingsPath=\"~/AppData/Roaming/Cryptomator/settings.json\""
- --java-options "-Dcryptomator.p12Path=\"~/AppData/Roaming/Cryptomator/key.p12\""
- --java-options "-Dcryptomator.ipcSocketPath=\"~/AppData/Roaming/Cryptomator/ipc.socket\""
- --java-options "-Dcryptomator.mountPointsDir=\"~/Cryptomator\""
+ --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\""
+ --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Cryptomator\""
--java-options "-Dcryptomator.loopbackAlias=\"${{ env.LOOPBACK_ALIAS }}\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\""
- --java-options "-Dcryptomator.integrationsWin.keychainPaths=\"~/AppData/Roaming/Cryptomator/keychain.json\""
+ --java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json:@{userhome}/AppData/Roaming/Cryptomator/keychain.json\""
--java-options "-Djavafx.verbose=${{ inputs.isDebug }}"
--resource-dir dist/win/resources
--icon dist/win/resources/Cryptomator.ico
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index d361191e8..dd49b35b0 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -53,9 +53,10 @@
-
+
+
diff --git a/.idea/runConfigurations/Cryptomator_Linux.xml b/.idea/runConfigurations/Cryptomator_Linux.xml
index 54ff47a2f..1a1b394b5 100644
--- a/.idea/runConfigurations/Cryptomator_Linux.xml
+++ b/.idea/runConfigurations/Cryptomator_Linux.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/.idea/runConfigurations/Cryptomator_Linux_Dev.xml b/.idea/runConfigurations/Cryptomator_Linux_Dev.xml
index 7d842c690..ac4df5630 100644
--- a/.idea/runConfigurations/Cryptomator_Linux_Dev.xml
+++ b/.idea/runConfigurations/Cryptomator_Linux_Dev.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/.idea/runConfigurations/Cryptomator_Windows.xml b/.idea/runConfigurations/Cryptomator_Windows.xml
index 3c4ecc4a3..36d1e4e14 100644
--- a/.idea/runConfigurations/Cryptomator_Windows.xml
+++ b/.idea/runConfigurations/Cryptomator_Windows.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/.idea/runConfigurations/Cryptomator_Windows_Dev.xml b/.idea/runConfigurations/Cryptomator_Windows_Dev.xml
index 2093aee5e..778043a91 100644
--- a/.idea/runConfigurations/Cryptomator_Windows_Dev.xml
+++ b/.idea/runConfigurations/Cryptomator_Windows_Dev.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/.idea/runConfigurations/Cryptomator_macOS.xml b/.idea/runConfigurations/Cryptomator_macOS.xml
index 03e231c77..006986c2c 100644
--- a/.idea/runConfigurations/Cryptomator_macOS.xml
+++ b/.idea/runConfigurations/Cryptomator_macOS.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/.idea/runConfigurations/Cryptomator_macOS_Dev.xml b/.idea/runConfigurations/Cryptomator_macOS_Dev.xml
index 4aed7aed5..8b0de0e93 100644
--- a/.idea/runConfigurations/Cryptomator_macOS_Dev.xml
+++ b/.idea/runConfigurations/Cryptomator_macOS_Dev.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/dist/linux/appimage/build.sh b/dist/linux/appimage/build.sh
index 1374bd329..80519cc51 100755
--- a/dist/linux/appimage/build.sh
+++ b/dist/linux/appimage/build.sh
@@ -50,12 +50,12 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Xmx256m" \
--app-version "${VERSION}.${REVISION_NO}" \
--java-options "-Dfile.encoding=\"utf-8\"" \
- --java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\"" \
- --java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\"" \
- --java-options "-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
- --java-options "-Dcryptomator.p12Path=\"~/.config/Cryptomator/key.p12\"" \
- --java-options "-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\"" \
- --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \
+ --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=false" \
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"${TRAYICONSDIR}\"" \
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
index 036798650..3df3691bc 100644
--- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
+++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
@@ -66,6 +66,7 @@
+
diff --git a/dist/linux/debian/rules b/dist/linux/debian/rules
index 3b03857bc..e2d6bec9b 100755
--- a/dist/linux/debian/rules
+++ b/dist/linux/debian/rules
@@ -48,12 +48,12 @@ override_dh_auto_build:
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \
- --java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\"" \
- --java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\"" \
- --java-options "-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
- --java-options "-Dcryptomator.p12Path=\"~/.config/Cryptomator/key.p12\"" \
- --java-options "-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\"" \
- --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \
+ --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=false" \
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"/usr/share/icons/hicolor/symbolic/apps\"" \
--java-options "-Dcryptomator.buildNumber=\"deb-${REVISION_NUM}\"" \
diff --git a/dist/mac/dmg/build.sh b/dist/mac/dmg/build.sh
index 23917f9c5..2807af9c7 100755
--- a/dist/mac/dmg/build.sh
+++ b/dist/mac/dmg/build.sh
@@ -74,13 +74,13 @@ ${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.logDir=\"~/Library/Logs/${APP_NAME}\"" \
- --java-options "-Dcryptomator.pluginDir=\"~/Library/Application Support/${APP_NAME}/Plugins\"" \
- --java-options "-Dcryptomator.settingsPath=\"~/Library/Application Support/${APP_NAME}/settings.json\"" \
- --java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/${APP_NAME}/ipc.socket\"" \
- --java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/${APP_NAME}/key.p12\"" \
+ --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/${APP_NAME}\"" \
+ --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=\"~/${APP_NAME}\"" \
+ --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/${APP_NAME}\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
--mac-package-identifier ${PACKAGE_IDENTIFIER} \
diff --git a/dist/win/build.ps1 b/dist/win/build.ps1
index 74532a96a..b8394bf3f 100644
--- a/dist/win/build.ps1
+++ b/dist/win/build.ps1
@@ -82,15 +82,15 @@ if ($clean -and (Test-Path -Path $appPath)) {
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
--app-version "$semVerNo.$revisionNo" `
--java-options "-Dfile.encoding=`"utf-8`"" `
- --java-options "-Dcryptomator.logDir=`"~/AppData/Roaming/$AppName`"" `
- --java-options "-Dcryptomator.pluginDir=`"~/AppData/Roaming/$AppName/Plugins`"" `
- --java-options "-Dcryptomator.settingsPath=`"~/AppData/Roaming/$AppName/settings.json`"" `
- --java-options "-Dcryptomator.ipcSocketPath=`"~/AppData/Roaming/$AppName/ipc.socket`"" `
- --java-options "-Dcryptomator.p12Path=`"~/AppData/Roaming/$AppName/key.p12`"" `
- --java-options "-Dcryptomator.mountPointsDir=`"~/$AppName`"" `
+ --java-options "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" `
+ --java-options "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" `
+ --java-options "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json:@{userhome}/AppData/Roaming/$AppName/settings.json`"" `
+ --java-options "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`"" `
+ --java-options "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12:@{userhome}/AppData/Roaming/$AppName/key.p12`"" `
+ --java-options "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`"" `
--java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" `
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" `
- --java-options "-Dcryptomator.integrationsWin.keychainPaths=`"~/AppData/Roaming/$AppName/keychain.json`"" `
+ --java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json:@{userhome}/AppData/Roaming/$AppName/keychain.json`"" `
--java-options "-Dcryptomator.showTrayIcon=true" `
--java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" `
--resource-dir resources `
diff --git a/pom.xml b/pom.xml
index e31960273..449e33063 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,8 +33,8 @@
org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents
- 2.6.4
- 1.3.0-beta1
+ 2.6.5
+ 1.2.0
1.2.0
1.2.0
1.3.0-beta4
@@ -46,8 +46,8 @@
3.12.0
2.45
2.2
- 32.0.0-jre
- 2.10.1
+ 32.0.1-jre
+ 2.15.2
20.0.1
4.4.0
9.31
@@ -63,7 +63,7 @@
23.0.0
- 8.1.0
+ 8.1.2
0.8.9
@@ -157,6 +157,11 @@
nimbus-jose-jwt
${nimbus-jose.version}
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
@@ -206,11 +211,6 @@
dagger
${dagger.version}
-
- com.google.code.gson
- gson
- ${gson.version}
-
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 54938a0f0..b353b7a8a 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -5,6 +5,7 @@ import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvi
import org.cryptomator.common.locationpresets.GoogleDriveLocationPresetsProvider;
import org.cryptomator.common.locationpresets.ICloudMacLocationPresetsProvider;
import org.cryptomator.common.locationpresets.ICloudWindowsLocationPresetsProvider;
+import org.cryptomator.common.locationpresets.LeitzcloudLocationPresetsProvider;
import org.cryptomator.common.locationpresets.LocationPresetsProvider;
import org.cryptomator.common.locationpresets.MegaLocationPresetsProvider;
import org.cryptomator.common.locationpresets.OneDriveLinuxLocationPresetsProvider;
@@ -37,7 +38,7 @@ open module org.cryptomator.desktop {
requires ch.qos.logback.core;
requires com.auth0.jwt;
requires com.google.common;
- requires com.google.gson;
+ requires com.fasterxml.jackson.databind;
requires com.nimbusds.jose.jwt;
requires com.nulabinc.zxcvbn;
requires com.tobiasdiez.easybind;
@@ -53,11 +54,12 @@ open module org.cryptomator.desktop {
provides TrayMenuController with AwtTrayMenuController;
provides Configurator with LogbackConfiguratorFactory;
- provides LocationPresetsProvider with DropboxMacLocationPresetsProvider, //
- DropboxWindowsLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, //
- ICloudMacLocationPresetsProvider, ICloudWindowsLocationPresetsProvider, //
+ provides LocationPresetsProvider with //
+ DropboxWindowsLocationPresetsProvider, DropboxMacLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, //
GoogleDriveLocationPresetsProvider, //
- PCloudLocationPresetsProvider, MegaLocationPresetsProvider, //
- OneDriveLinuxLocationPresetsProvider, OneDriveWindowsLocationPresetsProvider, //
- OneDriveMacLocationPresetsProvider;
+ ICloudWindowsLocationPresetsProvider, ICloudMacLocationPresetsProvider, //
+ LeitzcloudLocationPresetsProvider, //
+ MegaLocationPresetsProvider, //
+ OneDriveWindowsLocationPresetsProvider, OneDriveMacLocationPresetsProvider, OneDriveLinuxLocationPresetsProvider, //
+ PCloudLocationPresetsProvider;
}
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/common/CommonsModule.java b/src/main/java/org/cryptomator/common/CommonsModule.java
index 8ecfa51b6..4ac07495e 100644
--- a/src/main/java/org/cryptomator/common/CommonsModule.java
+++ b/src/main/java/org/cryptomator/common/CommonsModule.java
@@ -139,9 +139,9 @@ public abstract class CommonsModule {
@Provides
@Singleton
static ObservableValue provideServerSocketAddressBinding(Settings settings) {
- return settings.port().map(port -> {
+ return settings.port.map(port -> {
String host = SystemUtils.IS_OS_WINDOWS ? "127.0.0.1" : "localhost";
- return InetSocketAddress.createUnresolved(host, settings.port().intValue());
+ return InetSocketAddress.createUnresolved(host, settings.port.intValue());
});
}
diff --git a/src/main/java/org/cryptomator/common/Environment.java b/src/main/java/org/cryptomator/common/Environment.java
index 383261119..66374fc17 100644
--- a/src/main/java/org/cryptomator/common/Environment.java
+++ b/src/main/java/org/cryptomator/common/Environment.java
@@ -18,7 +18,6 @@ import java.util.stream.StreamSupport;
public class Environment {
private static final Logger LOG = LoggerFactory.getLogger(Environment.class);
- private static final Path RELATIVE_HOME_DIR = Paths.get("~");
private static final char PATH_LIST_SEP = ':';
private static final int DEFAULT_MIN_PW_LENGTH = 8;
private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
@@ -80,7 +79,7 @@ public class Environment {
return getPaths(P12_PATH_PROP_NAME);
}
- public Stream ipcSocketPath() {
+ public Stream getIpcSocketPath() {
return getPaths(IPC_SOCKET_PATH_PROP_NAME);
}
@@ -89,7 +88,7 @@ public class Environment {
}
public Optional getLogDir() {
- return getPath(LOG_DIR_PROP_NAME).map(this::replaceHomeDir);
+ return getPath(LOG_DIR_PROP_NAME);
}
public Optional getLoopbackAlias() {
@@ -97,11 +96,11 @@ public class Environment {
}
public Optional getPluginDir() {
- return getPath(PLUGIN_DIR_PROP_NAME).map(this::replaceHomeDir);
+ return getPath(PLUGIN_DIR_PROP_NAME);
}
public Optional getMountPointsDir() {
- return getPath(MOUNTPOINT_DIR_PROP_NAME).map(this::replaceHomeDir);
+ return getPath(MOUNTPOINT_DIR_PROP_NAME);
}
/**
@@ -131,22 +130,9 @@ public class Environment {
}
// visible for testing
- public Path getHomeDir() {
- return getPath("user.home").orElseThrow();
- }
-
- // visible for testing
- public Stream getPaths(String propertyName) {
+ Stream getPaths(String propertyName) {
Stream rawSettingsPaths = getRawList(propertyName, PATH_LIST_SEP);
- return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Paths::get).map(this::replaceHomeDir);
- }
-
- private Path replaceHomeDir(Path path) {
- if (path.startsWith(RELATIVE_HOME_DIR)) {
- return getHomeDir().resolve(RELATIVE_HOME_DIR.relativize(path));
- } else {
- return path;
- }
+ return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Path::of);
}
private Stream getRawList(String propertyName, char separator) {
diff --git a/src/main/java/org/cryptomator/common/ErrorCode.java b/src/main/java/org/cryptomator/common/ErrorCode.java
index 7def1287b..7363e2278 100644
--- a/src/main/java/org/cryptomator/common/ErrorCode.java
+++ b/src/main/java/org/cryptomator/common/ErrorCode.java
@@ -32,18 +32,15 @@ public class ErrorCode {
this.rootCauseSpecificFrames = rootCauseSpecificFrames;
}
- // visible for testing
- String methodCode() {
+ public String methodCode() {
return format(traceCode(rootCause, LATEST_FRAME));
}
- // visible for testing
- String rootCauseCode() {
+ public String rootCauseCode() {
return format(traceCode(rootCause, rootCauseSpecificFrames));
}
- // visible for testing
- String throwableCode() {
+ public String throwableCode() {
return format(traceCode(throwable, ALL_FRAMES));
}
diff --git a/src/main/java/org/cryptomator/common/LicenseHolder.java b/src/main/java/org/cryptomator/common/LicenseHolder.java
index be36e6968..bc52966ea 100644
--- a/src/main/java/org/cryptomator/common/LicenseHolder.java
+++ b/src/main/java/org/cryptomator/common/LicenseHolder.java
@@ -30,7 +30,7 @@ public class LicenseHolder {
this.licenseSubject = validJwtClaims.map(DecodedJWT::getSubject);
this.validLicenseProperty = validJwtClaims.isNotNull();
- Optional claims = licenseChecker.check(settings.licenseKey().get());
+ Optional claims = licenseChecker.check(settings.licenseKey.get());
validJwtClaims.set(claims.orElse(null));
}
@@ -38,7 +38,7 @@ public class LicenseHolder {
Optional claims = licenseChecker.check(licenseKey);
validJwtClaims.set(claims.orElse(null));
if (claims.isPresent()) {
- settings.licenseKey().set(licenseKey);
+ settings.licenseKey.set(licenseKey);
return true;
} else {
return false;
diff --git a/src/main/java/org/cryptomator/common/PropertiesDecorator.java b/src/main/java/org/cryptomator/common/PropertiesDecorator.java
new file mode 100644
index 000000000..5235d50b5
--- /dev/null
+++ b/src/main/java/org/cryptomator/common/PropertiesDecorator.java
@@ -0,0 +1,171 @@
+package org.cryptomator.common;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.InvalidPropertiesFormatException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+class PropertiesDecorator extends Properties {
+
+ protected final Properties delegate;
+
+ PropertiesDecorator(Properties delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public String getProperty(String key) {return delegate.getProperty(key);}
+
+ @Override
+ public String getProperty(String key, String defaultValue) {return delegate.getProperty(key, defaultValue);}
+
+ @Override
+ public synchronized Object setProperty(String key, String value) {
+ return delegate.setProperty(key, value);
+ }
+
+ @Override
+ public synchronized void load(Reader reader) throws IOException {delegate.load(reader);}
+
+ @Override
+ public synchronized void load(InputStream inStream) throws IOException {delegate.load(inStream);}
+
+ @Override
+ public void store(Writer writer, String comments) throws IOException {delegate.store(writer, comments);}
+
+ @Override
+ public void store(OutputStream out, @Nullable String comments) throws IOException {delegate.store(out, comments);}
+
+ @Override
+ public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException {delegate.loadFromXML(in);}
+
+ @Override
+ public void storeToXML(OutputStream os, String comment) throws IOException {delegate.storeToXML(os, comment);}
+
+ @Override
+ public void storeToXML(OutputStream os, String comment, String encoding) throws IOException {delegate.storeToXML(os, comment, encoding);}
+
+ @Override
+ public void storeToXML(OutputStream os, String comment, Charset charset) throws IOException {delegate.storeToXML(os, comment, charset);}
+
+ @Override
+ public Enumeration> propertyNames() {return delegate.propertyNames();}
+
+ @Override
+ public Set stringPropertyNames() {return delegate.stringPropertyNames();}
+
+ @Override
+ public void list(PrintStream out) {delegate.list(out);}
+
+ @Override
+ public void list(PrintWriter out) {delegate.list(out);}
+
+ @Override
+ public int size() {return delegate.size();}
+
+ @Override
+ public boolean isEmpty() {return delegate.isEmpty();}
+
+ @Override
+ public Enumeration