diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03d913c91..39b6ce77d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,15 +39,11 @@ jobs: profile: mac steps: - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: 'temurin' java-version: ${{ env.JAVA_VERSION }} - - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- + cache: 'maven' - name: Ensure to use tagged version run: mvn versions:set -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags' if: startsWith(github.ref, 'refs/tags/') @@ -156,8 +152,9 @@ jobs: --resource-dir dist/mac/resources steps: - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: 'temurin' java-version: ${{ env.JAVA_VERSION }} - name: Download ${{ matrix.profile }}-buildkit uses: actions/download-artifact@v2 @@ -207,7 +204,7 @@ jobs: ppa: name: Upload source package to PPA needs: [buildkit, metadata] - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 - name: install build tools @@ -502,8 +499,9 @@ jobs: name: win-appdir - name: Untar appdir.tar run: tar -xvf appdir.tar - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: 'temurin' java-version: ${{ env.JAVA_VERSION }} - name: Patch Application Directory run: | diff --git a/README.md b/README.md index 4e29763ba..7ffb1fba1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,14 @@ Cryptomator is provided free of charge as an open-source project despite the hig ### Silver Sponsors + + + + + + +
Mow Capital
+ - [Jameson Lopp](https://www.lopp.net/) --- diff --git a/dist/linux/debian/changelog b/dist/linux/debian/changelog index 84a9756f9..2c7606733 100644 --- a/dist/linux/debian/changelog +++ b/dist/linux/debian/changelog @@ -1,4 +1,4 @@ -cryptomator (${PPA_VERSION}) focal; urgency=low +cryptomator (${PPA_VERSION}) bionic; urgency=low * Full changelog can be found on https://github.com/cryptomator/cryptomator/releases diff --git a/dist/mac/dmg/.gitignore b/dist/mac/dmg/.gitignore index 738927994..c186170c9 100644 --- a/dist/mac/dmg/.gitignore +++ b/dist/mac/dmg/.gitignore @@ -1,3 +1,4 @@ # created during build runtime/ -*.app/ +dmg/ +*.dmg diff --git a/dist/mac/dmg/build.sh b/dist/mac/dmg/build.sh index 6051e6f4c..b8d17cbe0 100755 --- a/dist/mac/dmg/build.sh +++ b/dist/mac/dmg/build.sh @@ -16,13 +16,14 @@ shift "$((OPTIND-1))" # prepare working dir and variables cd $(dirname $0) -rm -rf runtime *.app +rm -rf runtime dmg 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'` # check preconditions if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found."; exit 1; } +command -v create-dmg >/dev/null 2>&1 || { echo >&2 "create-dmg not found."; exit 1; } if [ -n "${CODESIGN_IDENTITY}" ]; then command -v codesign >/dev/null 2>&1 || { echo >&2 "codesign not found. Fix by 'xcode-select --install'."; exit 1; } if [[ ! `security find-identity -v -p codesigning | grep -w "${CODESIGN_IDENTITY}"` ]]; then echo "Given codesign identity is invalid."; exit 1; fi @@ -59,6 +60,7 @@ ${JAVA_HOME}/bin/jpackage \ --java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \ --app-version "${VERSION_NO}" \ --java-options "-Dfile.encoding=\"utf-8\"" \ + --java-options "-Dapple.awt.enableTemplateImages=true" \ --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\"" \ @@ -94,3 +96,27 @@ if [ -n "${CODESIGN_IDENTITY}" ]; then echo "Codesigning Cryptomator.app..." codesign --force --deep --entitlements ../Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app fi + +# prepare dmg contents +mkdir dmg +mv Cryptomator.app dmg +cp resources/macFUSE.webloc dmg + +# create dmg +create-dmg \ + --volname Cryptomator \ + --volicon "resources/Cryptomator-Volume.icns" \ + --background "resources/Cryptomator-background.tiff" \ + --window-pos 400 100 \ + --window-size 640 694 \ + --icon-size 128 \ + --icon "Cryptomator.app" 128 245 \ + --hide-extension "Cryptomator.app" \ + --icon "macFUSE.webloc" 320 501 \ + --hide-extension "macFUSE.webloc" \ + --app-drop-link 512 245 \ + --eula "resources/license.rtf" \ + --icon ".background" 128 758 \ + --icon ".fseventsd" 320 758 \ + --icon ".VolumeIcon.icns" 512 758 \ + Cryptomator-${VERSION_NO}.dmg dmg diff --git a/dist/win/.gitignore b/dist/win/.gitignore new file mode 100644 index 000000000..2b66ddbed --- /dev/null +++ b/dist/win/.gitignore @@ -0,0 +1,3 @@ +runtime +Cryptomator +installer \ No newline at end of file diff --git a/dist/win/build.bat b/dist/win/build.bat new file mode 100644 index 000000000..8ca9183b4 --- /dev/null +++ b/dist/win/build.bat @@ -0,0 +1,2 @@ +@echo off +powershell -NoLogo -NoExit -ExecutionPolicy Unrestricted -Command .\build.ps1 \ No newline at end of file diff --git a/dist/win/build.ps1 b/dist/win/build.ps1 new file mode 100644 index 000000000..8ed5d9193 --- /dev/null +++ b/dist/win/build.ps1 @@ -0,0 +1,90 @@ +# check preconditions +if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null) +{ + Write-Host "Unable to find git.exe in your PATH (try: choco install git)" + exit 1 +} +if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null) +{ + Write-Host "Unable to find mvn.cmd in your PATH (try: choco install maven)" + exit 1 +} + +$buildDir = Split-Path -Parent $PSCommandPath +$version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout) +$semVerNo = $version -replace '(\d\.\d\.\d).*','$1' +$revisionNo = $(git rev-list --count HEAD) + +Write-Output "`$version=$version" +Write-Output "`$semVerNo=$semVerNo" +Write-Output "`$revisionNo=$revisionNo" +Write-Output "`$buildDir=$buildDir" +Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME" + +# compile +&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin +Copy-Item "$buildDir\..\..\target\cryptomator-*.jar" -Destination "$buildDir\..\..\target\mods" + +# add runtime +& "$Env:JAVA_HOME\bin\jlink" ` + --verbose ` + --output runtime ` + --module-path "$Env:JAVA_HOME/jmods" ` + --add-modules java.base,java.desktop,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility ` + --no-header-files ` + --no-man-pages ` + --strip-debug ` + --compress=1 + +# create app dir +& "$Env:JAVA_HOME\bin\jpackage" ` + --verbose ` + --type app-image ` + --runtime-image runtime ` + --input ../../target/libs ` + --module-path ../../target/mods ` + --module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator ` + --dest . ` + --name Cryptomator ` + --vendor "Skymatic GmbH" ` + --copyright "(C) 2016 - 2021 Skymatic GmbH" ` + --java-options "-Xss5m" ` + --java-options "-Xmx256m" ` + --java-options "-Dcryptomator.appVersion=`"$semVerNo`"" ` + --app-version "$semVerNo.$revisionNo" ` + --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.ipcSocketPath=`"~/AppData/Roaming/Cryptomator/ipc.socket`"" ` + --java-options "-Dcryptomator.keychainPath=`"~/AppData/Roaming/Cryptomator/keychain.json`"" ` + --java-options "-Dcryptomator.mountPointsDir=`"~/Cryptomator`"" ` + --java-options "-Dcryptomator.showTrayIcon=true" ` + --java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" ` + --resource-dir resources ` + --icon resources/Cryptomator.ico + +# patch app dir +Copy-Item "contrib\*" -Destination "Cryptomator" +attrib -r "Cryptomator\Cryptomator.exe" + +# create .msi bundle +$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources" +& "$Env:JAVA_HOME\bin\jpackage" ` + --verbose ` + --type msi ` + --win-upgrade-uuid bda45523-42b1-4cae-9354-a45475ed4775 ` + --app-image Cryptomator ` + --dest installer ` + --name Cryptomator ` + --vendor "Skymatic GmbH" ` + --copyright "(C) 2016 - 2021 Skymatic GmbH" ` + --app-version "$semVerNo" ` + --win-menu ` + --win-dir-chooser ` + --win-shortcut-prompt ` + --win-update-url "https:\\cryptomator.org" ` + --win-menu-group Cryptomator ` + --resource-dir resources ` + --license-file resources/license.rtf ` + --file-associations resources/FAvaultFile.properties \ No newline at end of file diff --git a/dist/win/contrib/patchWebDAV.bat b/dist/win/contrib/patchWebDAV.bat new file mode 100644 index 000000000..e31249831 --- /dev/null +++ b/dist/win/contrib/patchWebDAV.bat @@ -0,0 +1,3 @@ +@echo off +cd %~dp0 +powershell -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -Command .\patchWebDAV.ps1 \ No newline at end of file diff --git a/dist/win/contrib/patchWebDAV.ps1 b/dist/win/contrib/patchWebDAV.ps1 new file mode 100644 index 000000000..51b063560 --- /dev/null +++ b/dist/win/contrib/patchWebDAV.ps1 @@ -0,0 +1,61 @@ +#Requires -RunAsAdministrator + +# Adds for address 127.0.0.1 the 'cryptomator-vault' alias to the hosts file +function Add-AliasToHost { + $sysdir = [Environment]::SystemDirectory + $hostsFile = "$sysdir\drivers\etc\hosts" + $aliasLine = '127.0.0.1 cryptomator-vault' + + foreach ($line in Get-Content $hostsFile) { + if ($line -eq $aliasLine){ + return + } + } + + Add-Content -Path $hostsFile -Encoding ascii -Value "`r`n$aliasLine" +} + + +# Sets in the registry the webclient file size limit to the maximum value +function Set-WebDAVFileSizeLimit { + # Set variables to indicate value and key to set + $RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\WebClient\Parameters' + $Name = 'FileSizeLimitInBytes' + $Value = '0xffffffff' + + # Create the key if it does not exist + If (-NOT (Test-Path $RegistryPath)) { + New-Item -Path $RegistryPath -Force | Out-Null + } + + # Now set the value + New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force | Out-Null +} + + +# Changes the network provider order such that the builtin Windows webclient is always first +function Edit-ProviderOrder { + $RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\NetworkProvider\HwOrder' + $Name = 'ProviderOrder' + $WebClientString = 'webclient' + + $CurrentOrder = (Get-ItemProperty $RegistryPath $Name).$Name + + $OrderWithoutWebclientArray = $CurrentOrder -split ',' | Where-Object {$_ -ne $WebClientString} + $WebClientArray = @($WebClientString) + + $UpdatedOrder = ($WebClientArray + $OrderWithoutWebclientArray) -join "," + New-ItemProperty -Path $RegistryPath -Name $Name -Value $UpdatedOrder -PropertyType String -Force | Out-Null +} + + +Add-AliasToHost +Write-Output 'Ensured alias exists in hosts file' + +Set-WebDAVFileSizeLimit +Write-Output 'Set WebDAV file size limit' + +Edit-ProviderOrder +Write-Output 'Ensured correct provider order' + +exit 0 diff --git a/dist/win/resources/main.wxs b/dist/win/resources/main.wxs index cd9677a1c..4954e1ea8 100644 --- a/dist/win/resources/main.wxs +++ b/dist/win/resources/main.wxs @@ -124,6 +124,9 @@ + + + @@ -153,6 +156,8 @@ JP_DOWNGRADABLE_FOUND + + NOT Installed OR REINSTALL diff --git a/pom.xml b/pom.xml index a14ecd291..0ad640f72 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.cryptomator cryptomator - 1.6.3 + 1.6.4 Cryptomator Desktop App @@ -27,8 +27,8 @@ com.github.serceman,com.github.jnr,org.ow2.asm,net.java.dev.jna,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh - 2.1.1 - 1.0.0 + 2.3.0 + 1.1.0-beta1 1.0.0 1.0.0 1.0.1 @@ -37,16 +37,16 @@ 1.2.6 - 17.0.0.1 + 17.0.1 3.12.0 3.18.2 2.2 31.0-jre - 2.39 - 2.8.8 + 2.40.3 + 2.8.9 1.5.2 1.7.32 - 1.2.6 + 1.2.7 5.8.1 diff --git a/src/main/java/org/cryptomator/common/keychain/KeychainManager.java b/src/main/java/org/cryptomator/common/keychain/KeychainManager.java index c97d0e9c9..d6adadfe4 100644 --- a/src/main/java/org/cryptomator/common/keychain/KeychainManager.java +++ b/src/main/java/org/cryptomator/common/keychain/KeychainManager.java @@ -49,6 +49,12 @@ public class KeychainManager implements KeychainAccessProvider { setPassphraseStored(key, true); } + @Override + public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException { + getKeychainOrFail().storePassphrase(key, displayName, passphrase); + setPassphraseStored(key, true); + } + @Override public char[] loadPassphrase(String key) throws KeychainAccessException { char[] passphrase = getKeychainOrFail().loadPassphrase(key); @@ -70,6 +76,14 @@ public class KeychainManager implements KeychainAccessProvider { } } + @Override + public void changePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException { + if (isPassphraseStored(key)) { + getKeychainOrFail().changePassphrase(key, displayName, passphrase); + setPassphraseStored(key, true); + } + } + @Override public boolean isSupported() { return keychain.getValue() != null; diff --git a/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java b/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java index 54519f21f..c715f0466 100644 --- a/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java +++ b/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java @@ -2,7 +2,7 @@ package org.cryptomator.ui.changepassword; import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; -import org.cryptomator.cryptofs.common.MasterkeyBackupHelper; +import org.cryptomator.cryptofs.common.BackupHelper; import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; @@ -83,7 +83,7 @@ public class ChangePasswordController implements FxController { Path masterkeyPath = vault.getPath().resolve(MASTERKEY_FILENAME); byte[] oldMasterkeyBytes = Files.readAllBytes(masterkeyPath); byte[] newMasterkeyBytes = masterkeyFileAccess.changePassphrase(oldMasterkeyBytes, oldPassphrase, newPassphrase); - Path backupKeyPath = vault.getPath().resolve(MASTERKEY_FILENAME + MasterkeyBackupHelper.generateFileIdSuffix(oldMasterkeyBytes) + MASTERKEY_BACKUP_SUFFIX); + Path backupKeyPath = vault.getPath().resolve(MASTERKEY_FILENAME + BackupHelper.generateFileIdSuffix(oldMasterkeyBytes) + MASTERKEY_BACKUP_SUFFIX); Files.move(masterkeyPath, backupKeyPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); Files.write(masterkeyPath, newMasterkeyBytes, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE); LOG.info("Successfully changed password for {}", vault.getDisplayName()); @@ -102,7 +102,7 @@ public class ChangePasswordController implements FxController { private void updatePasswordInSystemkeychain() { if (keychain.isSupported() && !keychain.isLocked()) { try { - keychain.changePassphrase(vault.getId(), newPasswordController.passwordField.getCharacters()); + keychain.changePassphrase(vault.getId(), vault.getDisplayName(), newPasswordController.passwordField.getCharacters()); LOG.info("Successfully updated password in system keychain for {}", vault.getDisplayName()); } catch (KeychainAccessException e) { LOG.error("Failed to update password in system keychain.", e); diff --git a/src/main/java/org/cryptomator/ui/common/ErrorController.java b/src/main/java/org/cryptomator/ui/common/ErrorController.java index c75df26ce..a2204fae3 100644 --- a/src/main/java/org/cryptomator/ui/common/ErrorController.java +++ b/src/main/java/org/cryptomator/ui/common/ErrorController.java @@ -1,5 +1,6 @@ package org.cryptomator.ui.common; +import org.cryptomator.common.Environment; import org.cryptomator.common.ErrorCode; import org.cryptomator.common.Nullable; @@ -25,7 +26,11 @@ public class ErrorController implements FxController { private static final String REPORT_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/new?category=Errors&title=Error+%s&body=%s"; private static final String SEARCH_ERRORCODE_DELIM = " OR "; private static final String REPORT_BODY_TEMPLATE = """ + OS: %s / %s + App: %s / %s + + """; @@ -34,16 +39,18 @@ public class ErrorController implements FxController { private final ErrorCode errorCode; private final Scene previousScene; private final Stage window; + private final Environment environment; private BooleanProperty copiedDetails = new SimpleBooleanProperty(); @Inject - ErrorController(Application application, @Named("stackTrace") String stackTrace, ErrorCode errorCode, @Nullable Scene previousScene, Stage window) { + ErrorController(Application application, @Named("stackTrace") String stackTrace, ErrorCode errorCode, @Nullable Scene previousScene, Stage window, Environment environment) { this.application = application; this.stackTrace = stackTrace; this.errorCode = errorCode; this.previousScene = previousScene; this.window = window; + this.environment = environment; } @FXML @@ -67,7 +74,12 @@ public class ErrorController implements FxController { @FXML public void reportError() { var title = URLEncoder.encode(getErrorCode(), StandardCharsets.UTF_8); - var body = URLEncoder.encode(REPORT_BODY_TEMPLATE, StandardCharsets.UTF_8); + var enhancedTemplate = String.format(REPORT_BODY_TEMPLATE, // + System.getProperty("os.name"), // + System.getProperty("os.version"), // + environment.getAppVersion().orElse("undefined"), // + environment.getBuildNumber().orElse("undefined")); + var body = URLEncoder.encode(enhancedTemplate, StandardCharsets.UTF_8); application.getHostServices().showDocument(REPORT_URL_FORMAT.formatted(title, body)); } diff --git a/src/main/java/org/cryptomator/ui/common/UserInteractionLock.java b/src/main/java/org/cryptomator/ui/common/UserInteractionLock.java index f0c199648..4eba62552 100644 --- a/src/main/java/org/cryptomator/ui/common/UserInteractionLock.java +++ b/src/main/java/org/cryptomator/ui/common/UserInteractionLock.java @@ -16,7 +16,11 @@ public class UserInteractionLock { private volatile E state; public UserInteractionLock(E initialValue) { - state = initialValue; + this.state = initialValue; + } + + public synchronized void reset(E value) { + this.state = value; } public void interacted(E result) { diff --git a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java index 8eda41cd0..44d7ebfb0 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java +++ b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java @@ -47,7 +47,7 @@ class MasterkeyFileLoadingFinisher { private void savePasswordToSystemkeychain() { if (keychain.isSupported()) { try { - keychain.storePassphrase(vault.getId(), CharBuffer.wrap(enteredPassword.get())); + keychain.storePassphrase(vault.getId(), vault.getDisplayName(), CharBuffer.wrap(enteredPassword.get())); } catch (KeychainAccessException e) { LOG.error("Failed to store passphrase in system keychain.", e); } diff --git a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java index 39db1cc04..1fa7dd986 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java +++ b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java @@ -3,6 +3,7 @@ package org.cryptomator.ui.keyloading.masterkeyfile; import com.google.common.base.Preconditions; import dagger.Lazy; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.cryptofs.common.BackupHelper; import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; @@ -20,6 +21,7 @@ import javafx.application.Platform; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.stage.Window; +import java.io.IOException; import java.net.URI; import java.nio.CharBuffer; import java.nio.file.Files; @@ -61,14 +63,24 @@ public class MasterkeyFileLoadingStrategy implements KeyLoadingStrategy { @Override public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException { Preconditions.checkArgument(SCHEME.equalsIgnoreCase(keyId.getScheme()), "Only supports keys with scheme " + SCHEME); - try { Path filePath = vault.getPath().resolve(keyId.getSchemeSpecificPart()); if (!Files.exists(filePath)) { filePath = getAlternateMasterkeyFilePath(); } CharSequence passphrase = getPassphrase(); - return masterkeyFileAccess.load(filePath, passphrase); + var masterkey = masterkeyFileAccess.load(filePath, passphrase); + //backup + if (filePath.startsWith(vault.getPath())) { + try { + BackupHelper.attemptBackup(filePath); + } catch (IOException e) { + LOG.warn("Unable to create backup for masterkey file."); + } + } else { + LOG.info("Masterkey file not stored inside vault. Not creating a backup."); + } + return masterkey; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new UnlockCancelledException("Unlock interrupted", e); diff --git a/src/main/java/org/cryptomator/ui/lock/LockForcedController.java b/src/main/java/org/cryptomator/ui/lock/LockForcedController.java index 8d4ce32d3..c3a452acc 100644 --- a/src/main/java/org/cryptomator/ui/lock/LockForcedController.java +++ b/src/main/java/org/cryptomator/ui/lock/LockForcedController.java @@ -35,7 +35,13 @@ public class LockForcedController implements FxController { } @FXML - public void confirmForcedLock() { + public void retry() { + forceLockDecisionLock.interacted(LockModule.ForceLockDecision.RETRY); + window.close(); + } + + @FXML + public void force() { forceLockDecisionLock.interacted(LockModule.ForceLockDecision.FORCE); window.close(); } @@ -54,4 +60,8 @@ public class LockForcedController implements FxController { return vault.getDisplayName(); } + public boolean isForceSupported() { + return vault.supportsForcedUnmount(); + } + } diff --git a/src/main/java/org/cryptomator/ui/lock/LockModule.java b/src/main/java/org/cryptomator/ui/lock/LockModule.java index 160dcf6fb..d1eb5f189 100644 --- a/src/main/java/org/cryptomator/ui/lock/LockModule.java +++ b/src/main/java/org/cryptomator/ui/lock/LockModule.java @@ -28,6 +28,7 @@ abstract class LockModule { enum ForceLockDecision { CANCEL, + RETRY, FORCE; } diff --git a/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java b/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java index 73b4844b9..00b25c507 100644 --- a/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java +++ b/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java @@ -51,20 +51,26 @@ public class LockWorkflow extends Task { @Override protected Void call() throws Volume.VolumeException, InterruptedException, LockNotCompletedException { - try { - vault.lock(false); - } catch (Volume.VolumeException | LockNotCompletedException e) { - LOG.debug("Regular lock of {} failed.", vault.getDisplayName(), e); - var decision = askUserForAction(); - switch (decision) { - case FORCE -> vault.lock(true); - case CANCEL -> cancel(false); - } - } + lock(false); return null; } + private void lock(boolean forced) throws InterruptedException { + try { + vault.lock(forced); + } catch (Volume.VolumeException | LockNotCompletedException e) { + LOG.info("Locking {} failed (forced: {}).", vault.getDisplayName(), forced, e); + var decision = askUserForAction(); + switch (decision) { + case RETRY -> lock(false); + case FORCE -> lock(true); + case CANCEL -> cancel(false); + } + } + } + private LockModule.ForceLockDecision askUserForAction() throws InterruptedException { + forceLockDecisionLock.reset(null); // show forcedLock dialogue ... Platform.runLater(() -> { lockWindow.setScene(lockForcedScene.get()); diff --git a/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java b/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java index 02b8bab91..db2554d67 100644 --- a/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java +++ b/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java @@ -34,10 +34,10 @@ public class SupporterCertificateController implements FxController { public void initialize() { supporterCertificateField.setText(licenseHolder.getLicenseKey().orElse(null)); supporterCertificateField.textProperty().addListener(this::registrationKeyChanged); - supporterCertificateField.setTextFormatter(new TextFormatter<>(this::checkVaultNameLength)); + supporterCertificateField.setTextFormatter(new TextFormatter<>(this::removeWhitespaces)); } - private TextFormatter.Change checkVaultNameLength(TextFormatter.Change change) { + private TextFormatter.Change removeWhitespaces(TextFormatter.Change change) { if (change.isContentChange()) { var strippedText = CharMatcher.whitespace().removeFrom(change.getText()); change.setText(strippedText); diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java index c078c718b..311f5746e 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java @@ -2,7 +2,7 @@ package org.cryptomator.ui.recoverykey; import com.google.common.base.Preconditions; import com.google.common.hash.Hashing; -import org.cryptomator.cryptofs.common.MasterkeyBackupHelper; +import org.cryptomator.cryptofs.common.BackupHelper; import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.cryptolib.api.Masterkey; @@ -86,7 +86,7 @@ public class RecoveryKeyFactory { if (Files.exists(masterkeyPath)) { byte[] oldMasterkeyBytes = Files.readAllBytes(masterkeyPath); // TODO: deduplicate with ChangePasswordController: - Path backupKeyPath = vaultPath.resolve(MASTERKEY_FILENAME + MasterkeyBackupHelper.generateFileIdSuffix(oldMasterkeyBytes) + MASTERKEY_BACKUP_SUFFIX); + Path backupKeyPath = vaultPath.resolve(MASTERKEY_FILENAME + BackupHelper.generateFileIdSuffix(oldMasterkeyBytes) + MASTERKEY_BACKUP_SUFFIX); Files.move(masterkeyPath, backupKeyPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); } masterkeyFileAccess.persist(masterkey, masterkeyPath, newPassword); diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java index a35b108d9..633797820 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java @@ -47,7 +47,7 @@ public class GeneralVaultOptionsController implements FxController { public void initialize() { vaultName.textProperty().set(vault.getVaultSettings().displayName().get()); vaultName.focusedProperty().addListener(this::trimVaultNameOnFocusLoss); - vaultName.setTextFormatter(new TextFormatter<>(this::removeWhitespaces)); + vaultName.setTextFormatter(new TextFormatter<>(this::checkVaultNameLength)); unlockOnStartupCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().unlockAfterStartup()); actionAfterUnlockChoiceBox.getItems().addAll(WhenUnlocked.values()); actionAfterUnlockChoiceBox.valueProperty().bindBidirectional(vault.getVaultSettings().actionAfterUnlock()); @@ -63,7 +63,7 @@ public class GeneralVaultOptionsController implements FxController { } } - private TextFormatter.Change removeWhitespaces(TextFormatter.Change change) { + private TextFormatter.Change checkVaultNameLength(TextFormatter.Change change) { if (change.isContentChange() && change.getControlNewText().length() > VAULTNAME_TRUNCATE_THRESHOLD) { return null; // reject any change that would lead to a text exceeding threshold } else { diff --git a/src/main/resources/fxml/lock_forced.fxml b/src/main/resources/fxml/lock_forced.fxml index 4596af119..b0b5baa63 100644 --- a/src/main/resources/fxml/lock_forced.fxml +++ b/src/main/resources/fxml/lock_forced.fxml @@ -33,11 +33,11 @@ - +