diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml
new file mode 100644
index 000000000..aab954476
--- /dev/null
+++ b/.github/workflows/appimage.yml
@@ -0,0 +1,151 @@
+name: Build AppImage
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+env:
+ JAVA_VERSION: 17
+
+jobs:
+ build:
+ name: Build AppImage
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: 'maven'
+ - id: versions
+ name: Apply version information
+ run: |
+ if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
+ SEM_VER_STR=${GITHUB_REF##*/}
+ mvn versions:set -DnewVersion=${SEM_VER_STR}
+ else
+ SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
+ fi
+ SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
+ REVCOUNT=`git rev-list --count HEAD`
+ echo "::set-output name=semVerStr::${SEM_VER_STR}"
+ echo "::set-output name=semVerNum::${SEM_VER_NUM}"
+ echo "::set-output name=revNum::${REVCOUNT}"
+ - name: Validate Version
+ uses: skymatic/semver-validation-action@v1
+ with:
+ version: ${{ steps.versions.outputs.semVerStr }}
+ - name: Run maven
+ run: mvn -B clean package -Pdependency-check,linux -DskipTests
+ - name: Patch target dir
+ run: |
+ cp LICENSE.txt target
+ cp dist/linux/launcher.sh target
+ cp target/cryptomator-*.jar target/mods
+ - name: Run jlink
+ run: >
+ ${JAVA_HOME}/bin/jlink
+ --verbose
+ --output runtime
+ --module-path "${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,jdk.management.jfr
+ --no-header-files
+ --no-man-pages
+ --strip-debug
+ --compress=1
+ - name: Run jpackage
+ run: >
+ ${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 appdir
+ --name Cryptomator
+ --vendor "Skymatic GmbH"
+ --copyright "(C) 2016 - 2022 Skymatic GmbH"
+ --app-version "${{ steps.versions.outputs.semVerNum }}.${{ steps.versions.outputs.revNum }}"
+ --java-options "-Xss5m"
+ --java-options "-Xmx256m"
+ --java-options "-Dcryptomator.appVersion=\"${{ steps.versions.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.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\""
+ --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\""
+ --java-options "-Dcryptomator.showTrayIcon=false"
+ --java-options "-Dcryptomator.buildNumber=\"appimage-${{ steps.versions.outputs.revNum }}\""
+ --resource-dir dist/linux/resources
+ - name: Patch Cryptomator.AppDir
+ run: |
+ mv appdir/Cryptomator Cryptomator.AppDir
+ cp -r dist/linux/appimage/resources/AppDir/* Cryptomator.AppDir/
+ envsubst '${REVISION_NO} ${SEMVER_STR}' < dist/linux/appimage/resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
+ cp dist/linux/common/org.cryptomator.Cryptomator256.png Cryptomator.AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png
+ cp dist/linux/common/org.cryptomator.Cryptomator512.png Cryptomator.AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png
+ cp dist/linux/common/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
+ cp dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.metainfo.xml
+ cp dist/linux/common/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop
+ cp dist/linux/common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.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/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/Cryptomator.desktop
+ ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
+ env:
+ REVISION_NO: ${{ steps.versions.outputs.revNum }}
+ SEMVER_STR: ${{ steps.versions.outputs.semVerStr }}
+ - name: Extract libjffi.so # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
+ run: |
+ JFFI_NATIVE_JAR=`ls lib/app/ | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'`
+ ${JAVA_HOME}/bin/jar -xf lib/app/${JFFI_NATIVE_JAR} /jni/x86_64-Linux/
+ mv jni/x86_64-Linux/* lib/app/libjffi.so
+ working-directory: Cryptomator.AppDir
+ - name: Download AppImageKit
+ run: |
+ curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o appimagetool.AppImage
+ chmod +x appimagetool.AppImage
+ ./appimagetool.AppImage --appimage-extract
+ - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
+ run: |
+ echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
+ echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign README.md
+ env:
+ GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
+ GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
+ - name: Build AppImage
+ run: >
+ ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ steps.versions.outputs.semVerStr }}-x86_64.AppImage
+ -u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
+ --sign --sign-key=615D449FE6E6A235 --sign-args="--batch --pinentry-mode loopback"
+ - 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@v3
+ with:
+ name: appimage
+ path: |
+ cryptomator-*.AppImage
+ cryptomator-*.AppImage.zsync
+ cryptomator-*.asc
+ if-no-files-found: error
+ - name: Publish AppImage on GitHub Releases
+ if: startsWith(github.ref, 'refs/tags/')
+ uses: softprops/action-gh-release@v1
+ with:
+ fail_on_unmatched_files: true
+ token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+ files: |
+ cryptomator-*.AppImage
+ cryptomator-*.zsync
+ cryptomator-*.asc
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 750b64826..40d2b2e1b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -48,4 +48,16 @@ jobs:
run: bash <(curl -Ls https://coverage.codacy.com/get.sh)
env:
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
- continue-on-error: true
\ No newline at end of file
+ continue-on-error: true
+ - name: Draft a release
+ if: startsWith(github.ref, 'refs/tags/')
+ uses: softprops/action-gh-release@v1
+ with:
+ draft: true
+ discussion_category_name: releases
+ token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+ generate_release_notes: true
+ body: |-
+ :construction: Work in Progress
+
+ ---
diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml
new file mode 100644
index 000000000..f7893bbaa
--- /dev/null
+++ b/.github/workflows/debian.yml
@@ -0,0 +1,118 @@
+name: Build Debian Package
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+ inputs:
+ dput:
+ description: 'Upload to PPA'
+ required: true
+ default: false
+ type: boolean
+
+env:
+ JAVA_VERSION: 17
+
+jobs:
+ build:
+ name: Build Debian Package
+ runs-on: ubuntu-18.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Install build tools
+ run: |
+ sudo apt-get update
+ sudo apt-get install debhelper devscripts dput
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: 'maven'
+ - id: versions
+ name: Apply version information
+ run: |
+ if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
+ SEM_VER_STR=${GITHUB_REF##*/}
+ mvn versions:set -DnewVersion=${SEM_VER_STR}
+ else
+ SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
+ fi
+ SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
+ REVCOUNT=`git rev-list --count HEAD`
+ echo "::set-output name=semVerStr::${SEM_VER_STR}"
+ echo "::set-output name=semVerNum::${SEM_VER_NUM}"
+ echo "::set-output name=revNum::${REVCOUNT}"
+ echo "::set-output name=ppaVerStr::${SEM_VER_STR/-/\~}-${REVCOUNT}"
+ - name: Validate Version
+ uses: skymatic/semver-validation-action@v1
+ with:
+ version: ${{ steps.versions.outputs.semVerStr }}
+ - name: Run maven
+ run: mvn -B clean package -Pdependency-check,linux -DskipTests
+ - name: Create orig.tar.gz with common/ libs/ mods/
+ run: |
+ mkdir pkgdir
+ cp -r target/libs pkgdir
+ cp -r target/mods pkgdir
+ cp -r dist/linux/common/ pkgdir
+ cp target/cryptomator-*.jar pkgdir/mods
+ tar -cJf cryptomator_${{ steps.versions.outputs.ppaVerStr }}.orig.tar.xz -C pkgdir .
+ - name: Patch and rename pkgdir
+ run: |
+ cp -r dist/linux/debian/ pkgdir
+ export RFC2822_TIMESTAMP=`date --rfc-2822`
+ envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM}' < dist/linux/debian/rules > pkgdir/debian/rules
+ envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog
+ find . -name "*.jar" >> pkgdir/debian/source/include-binaries
+ mv pkgdir cryptomator_${{ steps.versions.outputs.ppaVerStr }}
+ env:
+ SEMVER_STR: ${{ steps.versions.outputs.semVerStr }}
+ VERSION_NUM: ${{ steps.versions.outputs.semVerNum }}
+ REVISION_NUM: ${{ steps.versions.outputs.revNum }}
+ PPA_VERSION: ${{ steps.versions.outputs.ppaVerStr }}-0ppa1
+ - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
+ run: |
+ echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
+ echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign README.md
+ env:
+ GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
+ GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
+ - name: debuild
+ run: |
+ debuild -S -sa -d
+ debuild -b -sa -d
+ env:
+ DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback
+ DEBSIGN_KEYID: 615D449FE6E6A235
+ working-directory: cryptomator_${{ steps.versions.outputs.ppaVerStr }}
+ - name: Create detached GPG signatures
+ run: |
+ gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: linux-deb-package
+ path: |
+ cryptomator_*.dsc
+ cryptomator_*.orig.tar.xz
+ cryptomator_*.debian.tar.xz
+ cryptomator_*_source.buildinfo
+ cryptomator_*_source.changes
+ cryptomator_*_amd64.deb
+ cryptomator_*.asc
+ - name: Publish on PPA
+ if: startsWith(github.ref, 'refs/tags/') || github.event.inputs.dput == 'true'
+ run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes
+ - name: Publish Debian package on GitHub Releases
+ if: startsWith(github.ref, 'refs/tags/')
+ uses: softprops/action-gh-release@v1
+ with:
+ fail_on_unmatched_files: true
+ token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+ files: |
+ cryptomator_*_amd64.deb
+ cryptomator_*.asc
\ No newline at end of file
diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml
new file mode 100644
index 000000000..66af92d6d
--- /dev/null
+++ b/.github/workflows/mac-dmg.yml
@@ -0,0 +1,232 @@
+name: Build macOS .dmg
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+env:
+ JAVA_VERSION: 17
+
+jobs:
+ build:
+ name: Build Cryptomator.app
+ runs-on: macos-11
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: 'maven'
+ - id: versions
+ name: Apply version information
+ run: |
+ if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
+ SEM_VER_STR=${GITHUB_REF##*/}
+ mvn versions:set -DnewVersion=${SEM_VER_STR}
+ else
+ SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
+ fi
+ SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
+ REVCOUNT=`git rev-list --count HEAD`
+ echo "::set-output name=semVerStr::${SEM_VER_STR}"
+ echo "::set-output name=semVerNum::${SEM_VER_NUM}"
+ echo "::set-output name=revNum::${REVCOUNT}"
+ - name: Validate Version
+ uses: skymatic/semver-validation-action@v1
+ with:
+ version: ${{ steps.versions.outputs.semVerStr }}
+ - name: Run maven
+ run: mvn -B clean package -Pdependency-check,mac -DskipTests
+ - name: Patch target dir
+ run: |
+ cp LICENSE.txt target
+ cp dist/mac/launcher.sh target
+ cp target/cryptomator-*.jar target/mods
+ - name: Run jlink
+ run: >
+ ${JAVA_HOME}/bin/jlink
+ --verbose
+ --output runtime
+ --module-path "${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,jdk.management.jfr
+ --strip-native-commands
+ --no-header-files
+ --no-man-pages
+ --strip-debug
+ --compress=1
+ - name: Run jpackage
+ run: >
+ ${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 appdir
+ --name Cryptomator
+ --vendor "Skymatic GmbH"
+ --copyright "(C) 2016 - 2022 Skymatic GmbH"
+ --app-version "${{ steps.versions.outputs.semVerNum }}"
+ --java-options "-Xss5m"
+ --java-options "-Xmx256m"
+ --java-options "-Dcryptomator.appVersion=\"${{ steps.versions.outputs.semVerStr }}\""
+ --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\""
+ --java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\""
+ --java-options "-Dcryptomator.showTrayIcon=true"
+ --java-options "-Dcryptomator.buildNumber=\"dmg-${{ steps.versions.outputs.revNum }}\""
+ --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/
+ 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
+ env:
+ VERSION_NO: ${{ steps.versions.outputs.semVerNum }}
+ REVISION_NO: ${{ steps.versions.outputs.revNum }}
+ - name: Install codesign certificate
+ run: |
+ # create variables
+ CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
+ KEYCHAIN_PATH=$RUNNER_TEMP/codesign.keychain-db
+
+ # import certificate and provisioning profile from secrets
+ echo -n "$CODESIGN_P12_BASE64" | base64 --decode --output $CERTIFICATE_PATH
+
+ # create temporary keychain
+ security create-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
+ security set-keychain-settings -lut 900 $KEYCHAIN_PATH
+ security unlock-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
+
+ # import certificate to keychain
+ security import $CERTIFICATE_PATH -P "$CODESIGN_P12_PW" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
+ security list-keychain -d user -s $KEYCHAIN_PATH
+ env:
+ CODESIGN_P12_BASE64: ${{ secrets.MACOS_CODESIGN_P12_BASE64 }}
+ CODESIGN_P12_PW: ${{ secrets.MACOS_CODESIGN_P12_PW }}
+ CODESIGN_TMP_KEYCHAIN_PW: ${{ secrets.MACOS_CODESIGN_TMP_KEYCHAIN_PW }}
+ - name: Codesign
+ run: |
+ find Cryptomator.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
+ for JAR_PATH in `find Cryptomator.app -name "*.jar"`; do
+ if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
+ JAR_FILENAME=$(basename ${JAR_PATH})
+ OUTPUT_PATH=${JAR_PATH%.*}
+ echo "Codesigning libs in ${JAR_FILENAME}..."
+ unzip -q ${JAR_PATH} -d ${OUTPUT_PATH}
+ find ${OUTPUT_PATH} -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
+ find ${OUTPUT_PATH} -name '*.jnilib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
+ rm ${JAR_PATH}
+ pushd ${OUTPUT_PATH} > /dev/null
+ zip -qr ../${JAR_FILENAME} *
+ popd > /dev/null
+ rm -r ${OUTPUT_PATH}
+ fi
+ done
+ echo "Codesigning Cryptomator.app..."
+ codesign --force --deep --entitlements dist/mac/Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app
+ env:
+ CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
+ - name: Prepare .dmg contents
+ run: |
+ mkdir dmg
+ mv Cryptomator.app dmg
+ cp dist/mac/dmg/resources/macFUSE.webloc dmg
+ ls -l dmg
+ - name: Install create-dmg
+ run: |
+ brew install create-dmg
+ create-dmg --help
+ - name: Create .dmg
+ run: >
+ create-dmg
+ --volname Cryptomator
+ --volicon "dist/mac/dmg/resources/Cryptomator-Volume.icns"
+ --background "dist/mac/dmg/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 "dist/mac/dmg/resources/license.rtf"
+ --icon ".background" 128 758
+ --icon ".fseventsd" 320 758
+ --icon ".VolumeIcon.icns" 512 758
+ Cryptomator-${VERSION_NO}.dmg dmg
+ env:
+ VERSION_NO: ${{ steps.versions.outputs.semVerNum }}
+ - name: Install notarization credentials
+ if: startsWith(github.ref, 'refs/tags/')
+ run: |
+ # create temporary keychain
+ KEYCHAIN_PATH=$RUNNER_TEMP/notarization.keychain-db
+ security create-keychain -p "${NOTARIZATION_TMP_KEYCHAIN_PW}" ${KEYCHAIN_PATH}
+ security set-keychain-settings -lut 900 ${KEYCHAIN_PATH}
+ security unlock-keychain -p "${NOTARIZATION_TMP_KEYCHAIN_PW}" ${KEYCHAIN_PATH}
+
+ # import credentials from secrets
+ sudo xcode-select -s /Applications/Xcode_13.0.app
+ xcrun notarytool store-credentials "${NOTARIZATION_KEYCHAIN_PROFILE}" --apple-id "${NOTARIZATION_APPLE_ID}" --password "${NOTARIZATION_PW}" --team-id "${NOTARIZATION_TEAM_ID}" --keychain "${KEYCHAIN_PATH}"
+ env:
+ NOTARIZATION_KEYCHAIN_PROFILE: ${{ secrets.MACOS_NOTARIZATION_KEYCHAIN_PROFILE }}
+ NOTARIZATION_APPLE_ID: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
+ NOTARIZATION_PW: ${{ secrets.MACOS_NOTARIZATION_PW }}
+ NOTARIZATION_TEAM_ID: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
+ NOTARIZATION_TMP_KEYCHAIN_PW: ${{ secrets.MACOS_NOTARIZATION_TMP_KEYCHAIN_PW }}
+ - name: Notarize .dmg
+ if: startsWith(github.ref, 'refs/tags/')
+ run: |
+ KEYCHAIN_PATH=$RUNNER_TEMP/notarization.keychain-db
+ sudo xcode-select -s /Applications/Xcode_13.0.app
+ xcrun notarytool submit Cryptomator-*.dmg --keychain-profile "${NOTARIZATION_KEYCHAIN_PROFILE}" --keychain "${KEYCHAIN_PATH}" --wait
+ xcrun stapler staple Cryptomator-*.dmg
+ env:
+ NOTARIZATION_KEYCHAIN_PROFILE: ${{ secrets.MACOS_NOTARIZATION_KEYCHAIN_PROFILE }}
+ - name: Add possible alpha/beta tags to installer name
+ run: mv Cryptomator-*.dmg Cryptomator-${{ steps.versions.outputs.semVerStr }}.dmg
+ - name: Create detached GPG signature with key 615D449FE6E6A235
+ run: |
+ echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
+ echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a Cryptomator-*.dmg
+ env:
+ GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
+ GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
+ - name: Clean up codesign certificate
+ if: ${{ always() }}
+ run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
+ continue-on-error: true
+ - name: Clean up notarization credentials
+ if: ${{ always() }}
+ run: security delete-keychain $RUNNER_TEMP/notarization.keychain-db
+ continue-on-error: true
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: dmg
+ path: Cryptomator-*.dmg
+ if-no-files-found: error
+ - name: Publish dmg on GitHub Releases
+ if: startsWith(github.ref, 'refs/tags/')
+ uses: softprops/action-gh-release@v1
+ with:
+ fail_on_unmatched_files: true
+ token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+ files: |
+ Cryptomator-*.dmg
+ Cryptomator-*.asc
+
+
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 630d5bbf2..000000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,630 +0,0 @@
-name: Installers and Release
-
-on:
- workflow_dispatch:
- inputs:
- semver:
- description: 'SemVer'
- required: true
- default: '0.99.99-SNAPSHOT'
- push:
- tags: # see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
- - '[0-9]+.[0-9]+.[0-9]+'
- - '[0-9]+.[0-9]+.[0-9]+-*'
-
-env:
- JAVA_VERSION: 17
-
-defaults:
- run:
- shell: bash
-
-jobs:
-
-#
-# Buildkit
-#
- buildkit:
- name: Build ${{ matrix.profile }}-buildkit
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: true
- matrix:
- include:
- - os: ubuntu-latest
- profile: linux
- - os: windows-latest
- profile: win
- - os: macos-latest
- profile: mac
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-java@v2
- with:
- distribution: 'temurin'
- java-version: ${{ env.JAVA_VERSION }}
- 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/')
- - name: Build and Test
- run: mvn -B clean package -Pdependency-check,${{ matrix.profile }}
- - name: Patch buildkit
- run: |
- cp LICENSE.txt target
- cp dist/${{ matrix.profile }}/launcher* target
- cp target/cryptomator-*.jar target/mods
- - name: Upload ${{ matrix.profile }}-buildkit
- uses: actions/upload-artifact@v2
- with:
- name: ${{ matrix.profile }}-buildkit
- path: |
- target/libs
- target/mods
- target/LICENSE.txt
- target/launcher*
- if-no-files-found: error
-
-#
-# Release Metadata
-#
- metadata:
- name: Determine Version Metadata
- runs-on: ubuntu-latest
- outputs:
- semVerNum: ${{ steps.versions.outputs.semVerNum }}
- semVerStr: ${{ steps.versions.outputs.semVerStr }}
- ppaVerStr: ${{ steps.versions.outputs.ppaVerStr }}
- revNum: ${{ steps.versions.outputs.revNum }}
- steps:
- - uses: actions/checkout@v2
- with:
- fetch-depth: 0
- - id: versions
- run: |
- if [[ $GITHUB_REF == refs/tags/* ]]; then
- SEM_VER_STR=${GITHUB_REF##*/}
- else
- SEM_VER_STR=${{ github.event.inputs.semver }}
- fi
- SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
- REVCOUNT=`git rev-list --count HEAD`
- echo "::set-output name=semVerStr::${SEM_VER_STR}"
- echo "::set-output name=semVerNum::${SEM_VER_NUM}"
- echo "::set-output name=ppaVerStr::${SEM_VER_STR/-/\~}-${REVCOUNT}"
- echo "::set-output name=revNum::${REVCOUNT}"
- - uses: skymatic/semver-validation-action@v1
- with:
- version: ${{ steps.versions.outputs.semVerStr }}
-
-#
-# Application Directory
-#
- appdir:
- name: Create ${{ matrix.profile }}-appdir
- needs: [buildkit, metadata]
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: true
- matrix:
- include:
- - os: ubuntu-latest
- profile: linux
- jpackageoptions: >
- --app-version "${{ needs.metadata.outputs.semVerNum }}.${{ needs.metadata.outputs.revNum }}"
- --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.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\""
- --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\""
- --java-options "-Dcryptomator.showTrayIcon=false"
- --java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.metadata.outputs.revNum }}\""
- --resource-dir dist/linux/resources
- - os: windows-latest
- profile: win
- jpackageoptions: >
- --app-version "${{ needs.metadata.outputs.semVerNum }}.${{ needs.metadata.outputs.revNum }}"
- --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-${{ needs.metadata.outputs.revNum }}\""
- --resource-dir dist/win/resources
- --icon dist/win/resources/Cryptomator.ico
- - os: macos-latest
- profile: mac
- jpackageoptions: >
- --app-version "${{ needs.metadata.outputs.semVerNum }}"
- --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\""
- --java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\""
- --java-options "-Dcryptomator.showTrayIcon=true"
- --java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.metadata.outputs.revNum }}\""
- --mac-package-identifier org.cryptomator
- --resource-dir dist/mac/resources
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-java@v2
- with:
- distribution: 'temurin'
- java-version: ${{ env.JAVA_VERSION }}
- - name: Download ${{ matrix.profile }}-buildkit
- uses: actions/download-artifact@v2
- with:
- name: ${{ matrix.profile }}-buildkit
- path: buildkit
- - name: Create Runtime Image
- run: >
- ${JAVA_HOME}/bin/jlink
- --verbose
- --output runtime
- --module-path "${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
- - name: Create App Directory
- run: >
- ${JAVA_HOME}/bin/jpackage
- --verbose
- --type app-image
- --runtime-image runtime
- --input buildkit/libs
- --module-path buildkit/mods
- --module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
- --dest appdir
- --name Cryptomator
- --vendor "Skymatic GmbH"
- --copyright "(C) 2016 - 2022 Skymatic GmbH"
- --java-options "-Xss5m"
- --java-options "-Xmx256m"
- --java-options "-Dcryptomator.appVersion=\"${{ needs.metadata.outputs.semVerStr }}\""
- ${{ matrix.jpackageoptions }}
- - name: Create appdir.tar
- run: tar -cvf appdir.tar appdir
- - name: Upload ${{ matrix.profile }}-appdir
- uses: actions/upload-artifact@v2
- with:
- name: ${{ matrix.profile }}-appdir
- path: appdir.tar
- if-no-files-found: error
-
-#
-# Linux PPA Source Package
-#
- ppa:
- name: Upload source package to PPA
- needs: [buildkit, metadata]
- runs-on: ubuntu-18.04
- steps:
- - uses: actions/checkout@v2
- - name: install build tools
- run: |
- sudo apt-get update
- sudo apt-get install debhelper devscripts dput
- - name: Download linux-buildkit
- uses: actions/download-artifact@v2
- with:
- name: linux-buildkit
- path: pkgdir
- - name: create orig.tar.gz
- run: tar -cJf cryptomator_${{ needs.metadata.outputs.ppaVerStr }}.orig.tar.xz -C pkgdir .
- - name: patch and rename pkgdir
- run: |
- cp -r dist/linux/debian/ pkgdir
- cp -r dist/linux/resources/ pkgdir
- export RFC2822_TIMESTAMP=`date --rfc-2822`
- envsubst '${VERSION_STR} ${VERSION_NUM} ${REVISION_NUM}' < dist/linux/debian/rules > pkgdir/debian/rules
- envsubst '${VERSION_STR}' < dist/linux/debian/org.cryptomator.Cryptomator.desktop > pkgdir/debian/org.cryptomator.Cryptomator.desktop
- envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog
- find . -name "*.jar" >> pkgdir/debian/source/include-binaries
- mv pkgdir cryptomator_${{ needs.metadata.outputs.ppaVerStr }}
- env:
- VERSION_STR: ${{ needs.metadata.outputs.semVerStr }}
- VERSION_NUM: ${{ needs.metadata.outputs.semVerNum }}
- REVISION_NUM: ${{ needs.metadata.outputs.revNum }}
- PPA_VERSION: ${{ needs.metadata.outputs.ppaVerStr }}-0ppa1
- - name: import gpg key 615D449FE6E6A235
- run: |
- echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
- echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign dist/linux/debian/rules
- env:
- GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
- GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- - name: debuild
- run: debuild -S -sa -d
- env:
- DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback
- DEBSIGN_KEYID: 615D449FE6E6A235
- working-directory: cryptomator_${{ needs.metadata.outputs.ppaVerStr }}
- - name: Upload artifacts
- uses: actions/upload-artifact@v2
- with:
- name: linux-deb-source-package
- path: |
- cryptomator_*.dsc
- cryptomator_*.orig.tar.xz
- cryptomator_*.debian.tar.xz
- cryptomator_*_source.changes
- cryptomator_*_source.buildinfo
- - name: dput to beta repo
- run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_${PPA_VERSION}_source.changes
- env:
- PPA_VERSION: ${{ needs.metadata.outputs.ppaVerStr }}-0ppa1
-
-#
-# Linux Cryptomator.AppImage
-#
- linux-appimage:
- name: Build Cryptomator.AppImage
- runs-on: ubuntu-latest
- needs: [appdir, metadata]
- steps:
- - uses: actions/checkout@v2
- - name: Download linux-appdir
- uses: actions/download-artifact@v2
- with:
- name: linux-appdir
- - name: Untar appdir.tar
- run: |
- tar -xvf appdir.tar
- - name: Patch Cryptomator.AppDir
- run: |
- mv appdir/Cryptomator Cryptomator.AppDir
- cp -r dist/linux/appimage/resources/AppDir/* Cryptomator.AppDir/
- envsubst '${REVISION_NO} ${SEMVER_STR}' < dist/linux/appimage/resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
- 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/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/Cryptomator.desktop
- ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
- env:
- REVISION_NO: ${{ needs.metadata.outputs.revNum }}
- SEMVER_STR: ${{ needs.metadata.outputs.semVerStr }}
- - name: Extract libjffi.so # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
- run: |
- JFFI_NATIVE_JAR=`ls lib/app/ | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'`
- ${JAVA_HOME}/bin/jar -xf lib/app/${JFFI_NATIVE_JAR} /jni/x86_64-Linux/
- mv jni/x86_64-Linux/* lib/app/libjffi.so
- working-directory: Cryptomator.AppDir
- - name: Download AppImageKit
- run: |
- curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o appimagetool.AppImage
- chmod +x appimagetool.AppImage
- ./appimagetool.AppImage --appimage-extract
- - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
- run: |
- echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
- echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign Cryptomator.AppDir/AppRun
- env:
- GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
- GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- - name: Build AppImage
- run: >
- ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.metadata.outputs.semVerStr }}-x86_64.AppImage
- -u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
- --sign --sign-key=615D449FE6E6A235 --sign-args="--batch --pinentry-mode loopback"
- - name: Upload AppImage
- uses: actions/upload-artifact@v2
- with:
- name: linux-appimage
- path: |
- cryptomator-*.AppImage
- cryptomator-*.AppImage.zsync
- if-no-files-found: error
-
-#
-# macOS Cryptomator.app
-#
- mac-app:
- name: Build Cryptomator.app
- runs-on: macos-latest
- needs: [appdir, metadata]
- steps:
- - uses: actions/checkout@v2
- - name: Download mac-appdir
- uses: actions/download-artifact@v2
- with:
- name: mac-appdir
- - name: Untar appdir.tar
- run: tar -xvf appdir.tar
- - name: Patch Cryptomator.app
- run: |
- mv appdir/Cryptomator.app Cryptomator.app
- mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
- sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
- sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
- env:
- VERSION_NO: ${{ needs.metadata.outputs.semVerNum }}
- REVISION_NO: ${{ needs.metadata.outputs.revNum }}
- - name: Install codesign certificate
- env:
- CODESIGN_P12_BASE64: ${{ secrets.MACOS_CODESIGN_P12_BASE64 }}
- CODESIGN_P12_PW: ${{ secrets.MACOS_CODESIGN_P12_PW }}
- CODESIGN_TMP_KEYCHAIN_PW: ${{ secrets.MACOS_CODESIGN_TMP_KEYCHAIN_PW }}
- run: |
- # create variables
- CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
- KEYCHAIN_PATH=$RUNNER_TEMP/codesign.keychain-db
-
- # import certificate and provisioning profile from secrets
- echo -n "$CODESIGN_P12_BASE64" | base64 --decode --output $CERTIFICATE_PATH
-
- # create temporary keychain
- security create-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
- security set-keychain-settings -lut 900 $KEYCHAIN_PATH
- security unlock-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
-
- # import certificate to keychain
- security import $CERTIFICATE_PATH -P "$CODESIGN_P12_PW" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
- security list-keychain -d user -s $KEYCHAIN_PATH
- - name: Codesign
- env:
- CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
- run: |
- find Cryptomator.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
- for JAR_PATH in `find Cryptomator.app -name "*.jar"`; do
- if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
- JAR_FILENAME=$(basename ${JAR_PATH})
- OUTPUT_PATH=${JAR_PATH%.*}
- echo "Codesigning libs in ${JAR_FILENAME}..."
- unzip -q ${JAR_PATH} -d ${OUTPUT_PATH}
- find ${OUTPUT_PATH} -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
- find ${OUTPUT_PATH} -name '*.jnilib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
- rm ${JAR_PATH}
- pushd ${OUTPUT_PATH} > /dev/null
- zip -qr ../${JAR_FILENAME} *
- popd > /dev/null
- rm -r ${OUTPUT_PATH}
- fi
- done
- echo "Codesigning Cryptomator.app..."
- codesign --force --deep --entitlements dist/mac/Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app
- - name: Clean up codesign certificate
- if: ${{ always() }}
- run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
- - name: Create app.tar
- run: tar -cvf app.tar Cryptomator.app
- - name: Upload mac-app
- uses: actions/upload-artifact@v2
- with:
- name: mac-app
- path: app.tar
- if-no-files-found: error
-
-#
-# macOS Cryptomator.dmg
-#
- mac-dmg:
- name: Build Cryptomator.dmg
- runs-on: macos-11
- needs: [mac-app, metadata]
- steps:
- - uses: actions/checkout@v2
- - name: Download mac-appdir
- uses: actions/download-artifact@v2
- with:
- name: mac-app
- - name: Untar app.tar
- run: tar -xvf app.tar
- - name: Prepare .dmg contents
- run: |
- mkdir dmg
- mv Cryptomator.app dmg
- cp dist/mac/dmg/resources/macFUSE.webloc dmg
- ls -l dmg
- - name: Install create-dmg
- run: |
- brew install create-dmg
- create-dmg --help
- - name: Create .dmg
- run: >
- create-dmg
- --volname Cryptomator
- --volicon "dist/mac/dmg/resources/Cryptomator-Volume.icns"
- --background "dist/mac/dmg/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 "dist/mac/dmg/resources/license.rtf"
- --icon ".background" 128 758
- --icon ".fseventsd" 320 758
- --icon ".VolumeIcon.icns" 512 758
- Cryptomator-${VERSION_NO}.dmg dmg
- env:
- VERSION_NO: ${{ needs.metadata.outputs.semVerNum }}
- - name: Install notarization credentials
- env:
- NOTARIZATION_KEYCHAIN_PROFILE: ${{ secrets.MACOS_NOTARIZATION_KEYCHAIN_PROFILE }}
- NOTARIZATION_APPLE_ID: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
- NOTARIZATION_PW: ${{ secrets.MACOS_NOTARIZATION_PW }}
- NOTARIZATION_TEAM_ID: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
- NOTARIZATION_TMP_KEYCHAIN_PW: ${{ secrets.MACOS_NOTARIZATION_TMP_KEYCHAIN_PW }}
- run: |
- # create temporary keychain
- KEYCHAIN_PATH=$RUNNER_TEMP/notarization.keychain-db
- security create-keychain -p "${NOTARIZATION_TMP_KEYCHAIN_PW}" ${KEYCHAIN_PATH}
- security set-keychain-settings -lut 900 ${KEYCHAIN_PATH}
- security unlock-keychain -p "${NOTARIZATION_TMP_KEYCHAIN_PW}" ${KEYCHAIN_PATH}
-
- # import credentials from secrets
- sudo xcode-select -s /Applications/Xcode_13.0.app
- xcrun notarytool store-credentials "${NOTARIZATION_KEYCHAIN_PROFILE}" --apple-id "${NOTARIZATION_APPLE_ID}" --password "${NOTARIZATION_PW}" --team-id "${NOTARIZATION_TEAM_ID}" --keychain "${KEYCHAIN_PATH}"
- - name: Notarize .dmg
- env:
- NOTARIZATION_KEYCHAIN_PROFILE: ${{ secrets.MACOS_NOTARIZATION_KEYCHAIN_PROFILE }}
- run: |
- KEYCHAIN_PATH=$RUNNER_TEMP/notarization.keychain-db
- sudo xcode-select -s /Applications/Xcode_13.0.app
- xcrun notarytool submit Cryptomator-*.dmg --keychain-profile "${NOTARIZATION_KEYCHAIN_PROFILE}" --keychain "${KEYCHAIN_PATH}" --wait
- xcrun stapler staple Cryptomator-*.dmg
- - name: Clean up notarization credentials
- if: ${{ always() }}
- run: security delete-keychain $RUNNER_TEMP/notarization.keychain-db
- - name: Add possible alpha/beta tags to installer name
- run: mv Cryptomator-*.dmg Cryptomator-${{ needs.metadata.outputs.semVerStr }}.dmg
- - name: Upload mac-dmg
- uses: actions/upload-artifact@v2
- with:
- name: mac-dmg
- path: Cryptomator-*.dmg
- if-no-files-found: error
-
-#
-# MSI package
-#
- win-msi:
- name: Build Cryptomator.msi
- runs-on: windows-latest
- needs: [appdir, metadata]
- steps:
- - uses: actions/checkout@v2
- - name: Download win-appdir
- uses: actions/download-artifact@v2
- with:
- name: win-appdir
- - name: Untar appdir.tar
- run: tar -xvf appdir.tar
- - uses: actions/setup-java@v2
- with:
- distribution: 'temurin'
- java-version: ${{ env.JAVA_VERSION }}
- - name: Patch Application Directory
- run: |
- cp dist/win/contrib/* appdir/Cryptomator
- - name: Fix permissions
- run: attrib -r appdir/Cryptomator/Cryptomator.exe
- shell: pwsh
- - name: Codesign
- uses: skymatic/code-sign-action@v1
- with:
- certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
- password: ${{ secrets.WIN_CODESIGN_P12_PW }}
- certificatesha1: FF52240075AD7D14AF25629FDF69635357C7D14B
- description: Cryptomator
- timestampUrl: 'http://timestamp.digicert.com'
- folder: appdir/Cryptomator
- recursive: true
- - name: Create MSI
- run: >
- ${JAVA_HOME}/bin/jpackage
- --verbose
- --type msi
- --win-upgrade-uuid bda45523-42b1-4cae-9354-a45475ed4775
- --app-image appdir/Cryptomator
- --dest installer
- --name Cryptomator
- --vendor "Skymatic GmbH"
- --copyright "(C) 2016 - 2022 Skymatic GmbH"
- --app-version "${{ needs.metadata.outputs.semVerNum }}"
- --win-menu
- --win-dir-chooser
- --win-shortcut-prompt
- --win-update-url "https:\\cryptomator.org"
- --win-menu-group Cryptomator
- --resource-dir dist/win/resources
- --license-file dist/win/resources/license.rtf
- --file-associations dist/win/resources/FAvaultFile.properties
- env:
- JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
- - name: Codesign MSI
- uses: skymatic/code-sign-action@v1
- with:
- certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
- password: ${{ secrets.WIN_CODESIGN_P12_PW }}
- certificatesha1: FF52240075AD7D14AF25629FDF69635357C7D14B
- description: Cryptomator Installer
- timestampUrl: 'http://timestamp.digicert.com'
- folder: installer
- - name: Add possible alpha/beta tags to installer name
- run: mv installer/Cryptomator-*.msi installer/Cryptomator-${{ needs.metadata.outputs.semVerStr }}-x64.msi
- - name: Upload win-msi
- uses: actions/upload-artifact@v2
- with:
- name: win-msi
- path: installer/*.msi
- if-no-files-found: error
-
-#
-# Release
-#
- release:
- name: Draft a release on Github
- runs-on: ubuntu-latest
- needs: [metadata,linux-appimage,mac-dmg,win-msi,ppa]
- if: startsWith(github.ref, 'refs/tags/') && github.repository == 'cryptomator/cryptomator'
- steps:
- - uses: actions/checkout@v2
- - name: Create tarball
- run: git archive --prefix="cryptomator-${{ needs.metadata.outputs.semVerStr }}/" -o "cryptomator-${{ needs.metadata.outputs.semVerStr }}.tar.gz" ${{ github.ref }}
- - name: Download linux appimage
- uses: actions/download-artifact@v2
- with:
- name: linux-appimage
- - name: Download macOS dmg
- uses: actions/download-artifact@v2
- with:
- name: mac-dmg
- - name: Download Windows msi
- uses: actions/download-artifact@v2
- with:
- name: win-msi
- - name: Create detached GPG signature for all release files with key 615D449FE6E6A235
- run: |
- echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
- for FILE in `find . -name "*.AppImage" -o -name "*.dmg" -o -name "*.msi" -o -name "*.zsync" -o -name "*.tar.gz"`; do
- echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a ${FILE}
- done
- env:
- GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
- GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- - name: Compute SHA256 checksums of release artifacts
- run: |
- SHA256_SUMS=`find . -name "*.AppImage" -o -name "*.dmg" -o -name "*.msi" -o -name "*.tar.gz" | xargs sha256sum`
- echo "SHA256_SUMS<> $GITHUB_ENV
- echo "${SHA256_SUMS}" >> $GITHUB_ENV
- echo "EOF" >> $GITHUB_ENV
- continue-on-error: true
- - name: Create release draft
- uses: softprops/action-gh-release@v1
- with:
- draft: true
- fail_on_unmatched_files: true
- discussion_category_name: releases
- token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
- files: |
- *.AppImage
- *.zsync
- *.asc
- *.dmg
- *.msi
- body: |-
- :construction: Work in Progress
- ## What's New
- ## Bugfixes
- ## Misc
-
- ---
-
- :scroll: A complete list of closed issues is available [here](LINK).
-
- ---
-
- :floppy_disk: SHA-256 checksums of release artifacts:
- ```
- ${{ env.SHA256_SUMS }}
- ```
diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml
new file mode 100644
index 000000000..f024d7347
--- /dev/null
+++ b/.github/workflows/win-exe.yml
@@ -0,0 +1,255 @@
+name: Build Windows Installer
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+env:
+ JAVA_VERSION: 17
+ WINFSP_MSI: https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ build-msi:
+ name: Build .msi Installer
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: 'maven'
+ - id: versions
+ name: Apply version information
+ run: |
+ if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
+ SEM_VER_STR=${GITHUB_REF##*/}
+ mvn versions:set -DnewVersion=${SEM_VER_STR}
+ else
+ SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
+ fi
+ SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
+ REVCOUNT=`git rev-list --count HEAD`
+ echo "::set-output name=semVerStr::${SEM_VER_STR}"
+ echo "::set-output name=semVerNum::${SEM_VER_NUM}"
+ echo "::set-output name=revNum::${REVCOUNT}"
+ - name: Validate Version
+ uses: skymatic/semver-validation-action@v1
+ with:
+ version: ${{ steps.versions.outputs.semVerStr }}
+ - name: Run maven
+ run: mvn -B clean package -Pdependency-check,win -DskipTests
+ - name: Patch target dir
+ run: |
+ cp LICENSE.txt target
+ cp dist/linux/launcher.sh target
+ cp target/cryptomator-*.jar target/mods
+ - name: Run jlink
+ run: >
+ ${JAVA_HOME}/bin/jlink
+ --verbose
+ --output runtime
+ --module-path "${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,jdk.management.jfr
+ --strip-native-commands
+ --no-header-files
+ --no-man-pages
+ --strip-debug
+ --compress=1
+ - name: Run jpackage
+ run: >
+ ${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 appdir
+ --name Cryptomator
+ --vendor "Skymatic GmbH"
+ --copyright "(C) 2016 - 2022 Skymatic GmbH"
+ --app-version "${{ steps.versions.outputs.semVerNum }}.${{ steps.versions.outputs.revNum }}"
+ --java-options "-Xss5m"
+ --java-options "-Xmx256m"
+ --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-${{ steps.versions.outputs.revNum }}\""
+ --resource-dir dist/win/resources
+ --icon dist/win/resources/Cryptomator.ico
+ - name: Patch Application Directory
+ run: |
+ cp dist/win/contrib/* appdir/Cryptomator
+ - name: Fix permissions
+ run: attrib -r appdir/Cryptomator/Cryptomator.exe
+ shell: pwsh
+ - name: Codesign
+ uses: skymatic/code-sign-action@v1
+ with:
+ certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
+ password: ${{ secrets.WIN_CODESIGN_P12_PW }}
+ certificatesha1: FF52240075AD7D14AF25629FDF69635357C7D14B
+ description: Cryptomator
+ timestampUrl: 'http://timestamp.digicert.com'
+ folder: appdir/Cryptomator
+ recursive: true
+ - name: Generate license
+ run: >
+ mvn -B license:add-third-party
+ "-Dlicense.thirdPartyFilename=license.rtf"
+ "-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
+ "-Dlicense.outputDirectory=dist/win/resources"
+ - name: Create MSI
+ run: >
+ ${JAVA_HOME}/bin/jpackage
+ --verbose
+ --type msi
+ --win-upgrade-uuid bda45523-42b1-4cae-9354-a45475ed4775
+ --app-image appdir/Cryptomator
+ --dest installer
+ --name Cryptomator
+ --vendor "Skymatic GmbH"
+ --copyright "(C) 2016 - 2022 Skymatic GmbH"
+ --app-version "${{ steps.versions.outputs.semVerNum }}"
+ --win-menu
+ --win-dir-chooser
+ --win-shortcut-prompt
+ --win-update-url "https:\\cryptomator.org"
+ --win-menu-group Cryptomator
+ --resource-dir dist/win/resources
+ --license-file dist/win/resources/license.rtf
+ --file-associations dist/win/resources/FAvaultFile.properties
+ env:
+ JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
+ - name: Codesign MSI
+ uses: skymatic/code-sign-action@v1
+ with:
+ certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
+ password: ${{ secrets.WIN_CODESIGN_P12_PW }}
+ certificatesha1: FF52240075AD7D14AF25629FDF69635357C7D14B
+ description: Cryptomator Installer
+ timestampUrl: 'http://timestamp.digicert.com'
+ folder: installer
+ - name: Add possible alpha/beta tags to installer name
+ run: mv installer/Cryptomator-*.msi Cryptomator-${{ steps.versions.outputs.semVerStr }}-x64.msi
+ - name: Create detached GPG signature with key 615D449FE6E6A235
+ run: |
+ echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
+ echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a Cryptomator-*.msi
+ env:
+ GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
+ GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: msi
+ path: |
+ Cryptomator-*.msi
+ Cryptomator-*.asc
+ if-no-files-found: error
+ - name: Publish .msi on GitHub Releases
+ if: startsWith(github.ref, 'refs/tags/')
+ uses: softprops/action-gh-release@v1
+ with:
+ fail_on_unmatched_files: true
+ token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+ files: |
+ *.msi
+ *.asc
+ outputs:
+ semVerNum: ${{ steps.versions.outputs.semVerNum }}
+ semVerStr: ${{ steps.versions.outputs.semVerStr }}
+ revNum: ${{ steps.versions.outputs.revNum }}
+
+ build-exe:
+ name: Build .exe installer
+ runs-on: windows-latest
+ needs: [build-msi]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Download .msi
+ uses: actions/download-artifact@v2
+ with:
+ name: msi
+ path: dist/win/bundle/resources
+ - name: Strip version info from msi file name
+ run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
+ - uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: 'maven'
+ - name: Generate license
+ run: >
+ mvn -B license:add-third-party
+ "-Dlicense.thirdPartyFilename=license.rtf"
+ "-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
+ "-Dlicense.outputDirectory=dist/win/bundle/resources"
+ - name: Download WinFsp
+ run:
+ curl --output dist/win/bundle/resources/winfsp.msi -L ${{ env.WINFSP_MSI }}
+ - name: Compile to wixObj file
+ run: >
+ "${WIX}/bin/candle.exe" dist/win/bundle/bundleWithWinfsp.wxs
+ -ext WixBalExtension
+ -out dist/win/bundle/
+ -dBundleVersion="${{ needs.build-msi.outputs.semVerNum }}.${{ needs.build-msi.outputs.revNum }}"
+ -dBundleVendor="Skymatic GmbH"
+ -dBundleCopyright="(C) 2016 - 2022 Skymatic GmbH"
+ -dAboutUrl="https://cryptomator.org"
+ -dHelpUrl="https://cryptomator.org/contact"
+ -dUpdateUrl="https://cryptomator.org/downloads/"
+ - name: Create executable with linker
+ run: >
+ "${WIX}/bin/light.exe" -b dist/win/ dist/win/bundle/bundleWithWinfsp.wixobj
+ -ext WixBalExtension
+ -out installer/Cryptomator.exe
+ - name: Codesign EXE
+ uses: skymatic/code-sign-action@v1
+ with:
+ certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
+ password: ${{ secrets.WIN_CODESIGN_P12_PW }}
+ certificatesha1: FF52240075AD7D14AF25629FDF69635357C7D14B
+ description: Cryptomator Installer
+ timestampUrl: 'http://timestamp.digicert.com'
+ folder: installer
+ - name: Add possible alpha/beta tags to installer name
+ run: mv installer/Cryptomator.exe Cryptomator-${{ needs.build-msi.outputs.semVerStr }}-x64.exe
+ - name: Create detached GPG signature with key 615D449FE6E6A235
+ run: |
+ echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
+ echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a Cryptomator-*.exe
+ env:
+ GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
+ GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: exe
+ path: |
+ Cryptomator-*.exe
+ Cryptomator-*.asc
+ if-no-files-found: error
+ - name: Publish .msi on GitHub Releases
+ if: startsWith(github.ref, 'refs/tags/')
+ uses: softprops/action-gh-release@v1
+ with:
+ fail_on_unmatched_files: true
+ token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+ files: |
+ Cryptomator-*.exe
+ Cryptomator-*.asc
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index be67207df..8e239b35e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,6 @@ pom.xml.versionsBackup
.idea/jarRepositories.xml
.idea/uiDesigner.xml
.idea/**/libraries/
-*.iml
\ No newline at end of file
+*.iml
+
+hs_err_pid*.log
\ No newline at end of file
diff --git a/dist/linux/appimage/build.sh b/dist/linux/appimage/build.sh
index 335532cba..6dd670df2 100755
--- a/dist/linux/appimage/build.sh
+++ b/dist/linux/appimage/build.sh
@@ -9,6 +9,7 @@ command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found."; exit 1; }
command -v curl >/dev/null 2>&1 || { echo >&2 "curl not found."; exit 1; }
VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
+SEMVER_STR=${VERSION}
# compile
mvn -B -f ../../../pom.xml clean package -DskipTests -Plinux
@@ -18,7 +19,7 @@ cp ../../../target/cryptomator-*.jar ../../../target/mods
${JAVA_HOME}/bin/jlink \
--output runtime \
--module-path "${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 \
+ --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,jdk.management.jfr \
--no-header-files \
--no-man-pages \
--strip-debug \
@@ -54,6 +55,12 @@ mv Cryptomator Cryptomator.AppDir
cp -r resources/AppDir/* Cryptomator.AppDir/
chmod +x Cryptomator.AppDir/lib/runtime/bin/java
envsubst '${REVISION_NO}' < resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
+cp ../common/org.cryptomator.Cryptomator256.png Cryptomator.AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png
+cp ../common/org.cryptomator.Cryptomator512.png Cryptomator.AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png
+cp ../common/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
+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
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/Cryptomator.svg
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/applications/.gitkeep b/dist/linux/appimage/resources/AppDir/usr/share/applications/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/256x256/apps/.gitkeep b/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/256x256/apps/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/512x512/apps/.gitkeep b/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/512x512/apps/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/scalable/apps/.gitkeep b/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/scalable/apps/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg b/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
deleted file mode 100644
index b2e12a3c3..000000000
--- a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/metainfo/.gitkeep b/dist/linux/appimage/resources/AppDir/usr/share/metainfo/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml b/dist/linux/appimage/resources/AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml
deleted file mode 100644
index ad4af6c70..000000000
--- a/dist/linux/appimage/resources/AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
- org.cryptomator.Cryptomator
- FSFAP
- GPL-3.0-or-later
- Cryptomator
- Multi-platform client-side encryption tool optimized for cloud storages
-
-
- Cryptomator offers multi-platform transparent client-side encryption of your files in the cloud.
-
-
- Features:
-
- Works with Dropbox, Google Drive, OneDrive, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
- Open Source means: No backdoors, control is better than trust
- Client-side: No accounts, no data shared with any online service
- Totally transparent: Just work on the virtual drive as if it were a USB flash drive
- AES encryption with 256-bit key length
- File names get encrypted
- Folder structure gets obfuscated
- Use as many vaults in your Dropbox as you want, each having individual passwords
- One thousand commits for the security of your data!! :tada:
-
-
-
- Privacy:
-
- 256-bit keys (unlimited strength policy bundled with native binaries)
- Scrypt key derivation
- Cryptographically secure random numbers for salts, IVs and the masterkey of course
- Sensitive data is wiped from the heap asap
- Lightweight: Complexity kills security
-
-
-
- Consistency:
-
- HMAC over file contents to recognize changed ciphertext before decryption
- I/O operations are transactional and atomic, if the filesystems support it
- Each file contains all information needed for decryption (except for the key of course), no common metadata means no Single Point of Failure
-
-
-
-
- Office
- Security
- FileTools
- Java
-
- http://cryptomator.org
- https://github.com/cryptomator/cryptomator/issues
- https://community.cryptomator.org/c/kb/faq
- https://community.cryptomator.org/
- https://cryptomator.org/
-
- none
- none
- none
- none
- mild
-
- Cryptomator
-
- cryptomator
-
- org.cryptomator.Cryptomator.desktop
-
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/mime/packages/.gitkeep b/dist/linux/appimage/resources/AppDir/usr/share/mime/packages/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/linux/debian/cryptomator-vault.xml b/dist/linux/common/application-vnd.cryptomator.vault.xml
similarity index 77%
rename from dist/linux/debian/cryptomator-vault.xml
rename to dist/linux/common/application-vnd.cryptomator.vault.xml
index eeb4bc537..3b602f230 100644
--- a/dist/linux/debian/cryptomator-vault.xml
+++ b/dist/linux/common/application-vnd.cryptomator.vault.xml
@@ -1,6 +1,6 @@
-
+
Cryptomator Vault Metadata
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop b/dist/linux/common/org.cryptomator.Cryptomator.desktop
similarity index 71%
rename from dist/linux/appimage/resources/AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop
rename to dist/linux/common/org.cryptomator.Cryptomator.desktop
index 3e1b34830..1872b9f38 100644
--- a/dist/linux/appimage/resources/AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop
+++ b/dist/linux/common/org.cryptomator.Cryptomator.desktop
@@ -6,5 +6,6 @@ Icon=org.cryptomator.Cryptomator
Terminal=false
Type=Application
Categories=Utility;Security;FileTools;
+StartupNotify=true
StartupWMClass=org.cryptomator.launcher.Cryptomator
-MimeType=application/vnd.cryptomator.encrypted;application/x-vnd.cryptomator.vault-metadata;
+MimeType=application/vnd.cryptomator.encrypted;application/vnd.cryptomator.vault;
diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
new file mode 100644
index 000000000..bdd0e178e
--- /dev/null
+++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
@@ -0,0 +1,71 @@
+
+
+
+ org.cryptomator.Cryptomator
+ FSFAP
+ GPL-3.0-or-later
+ Cryptomator
+ Multi-platform client-side encryption tool optimized for cloud storages
+
+
+
+ Cryptomator provides transparent, client-side encryption for your cloud. Protect your documents from unauthorized
+ access. Cryptomator is free and open source software, so you can rest assured there are no backdoors.
+
+
+ Cryptomator encrypts file contents and names using AES. Your passphrase is protected against bruteforcing attempts
+ using scrypt. Directory structures get obfuscated. The only thing which cannot be encrypted without breaking your
+ cloud synchronization is the modification date of your files.
+
+
+ Cryptomator is a free and open source software licensed under the GPLv3. This allows anyone to check our code. It
+ is impossible to introduce backdoors for third parties. Also we cannot hide vulnerabilities. And the best thing
+ is: There is no need to trust us, as you can control us!
+
+
+ Vendor lock-ins are impossible. Even if we decided to stop development: The source code is already cloned by
+ hundreds of other developers. As you don't need an account, you will never stand in front of locked doors.
+
+
+
+
+ Office
+ Security
+ FileTools
+
+
+ org.cryptomator.Cryptomator.desktop
+
+ cryptomator
+ application/vnd.cryptomator.vault
+ application/vnd.cryptomator.encrypted
+
+
+
+
+ Light theme
+ https://user-images.githubusercontent.com/11858409/156986109-6e58f59c-8b8c-4501-b33b-bb1e33007cea.png
+
+
+ Dark theme
+ https://user-images.githubusercontent.com/11858409/156986113-6c5d7801-86e0-4643-bc2f-aff9d95d3ce0.png
+
+
+
+ https://cryptomator.org/
+ https://github.com/cryptomator/cryptomator/issues/
+ https://cryptomator.org/donate
+ https://community.cryptomator.org/c/kb/faq
+ https://community.cryptomator.org/
+ https://translate.cryptomator.org
+
+ Skymatic GmbH
+
+
+ mild
+
+
+
+
+
+
diff --git a/dist/linux/debian/org.cryptomator.Cryptomator.svg b/dist/linux/common/org.cryptomator.Cryptomator.svg
similarity index 99%
rename from dist/linux/debian/org.cryptomator.Cryptomator.svg
rename to dist/linux/common/org.cryptomator.Cryptomator.svg
index 19d80d49c..c76d99fb9 100644
--- a/dist/linux/debian/org.cryptomator.Cryptomator.svg
+++ b/dist/linux/common/org.cryptomator.Cryptomator.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png b/dist/linux/common/org.cryptomator.Cryptomator256.png
similarity index 100%
rename from dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png
rename to dist/linux/common/org.cryptomator.Cryptomator256.png
diff --git a/dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png b/dist/linux/common/org.cryptomator.Cryptomator512.png
similarity index 100%
rename from dist/linux/appimage/resources/AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png
rename to dist/linux/common/org.cryptomator.Cryptomator512.png
diff --git a/dist/linux/debian/cryptomator.install b/dist/linux/debian/cryptomator.install
index 0d5e0b31c..d3ff8cf1f 100644
--- a/dist/linux/debian/cryptomator.install
+++ b/dist/linux/debian/cryptomator.install
@@ -1,7 +1,8 @@
cryptomator usr/lib
debian/cryptomator.sh usr/lib/cryptomator/bin
-debian/org.cryptomator.Cryptomator.desktop usr/share/applications
-debian/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps
-debian/org.cryptomator.Cryptomator.png usr/share/icons/hicolor/512x512/apps
-debian/org.cryptomator.Cryptomator.appdata.xml usr/share/metainfo
-debian/cryptomator-vault.xml usr/share/mime/packages
\ No newline at end of file
+common/org.cryptomator.Cryptomator.desktop usr/share/applications
+common/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps
+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
\ No newline at end of file
diff --git a/dist/linux/debian/org.cryptomator.Cryptomator.appdata.xml b/dist/linux/debian/org.cryptomator.Cryptomator.appdata.xml
deleted file mode 100644
index ad4af6c70..000000000
--- a/dist/linux/debian/org.cryptomator.Cryptomator.appdata.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
- org.cryptomator.Cryptomator
- FSFAP
- GPL-3.0-or-later
- Cryptomator
- Multi-platform client-side encryption tool optimized for cloud storages
-
-
- Cryptomator offers multi-platform transparent client-side encryption of your files in the cloud.
-
-
- Features:
-
- Works with Dropbox, Google Drive, OneDrive, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
- Open Source means: No backdoors, control is better than trust
- Client-side: No accounts, no data shared with any online service
- Totally transparent: Just work on the virtual drive as if it were a USB flash drive
- AES encryption with 256-bit key length
- File names get encrypted
- Folder structure gets obfuscated
- Use as many vaults in your Dropbox as you want, each having individual passwords
- One thousand commits for the security of your data!! :tada:
-
-
-
- Privacy:
-
- 256-bit keys (unlimited strength policy bundled with native binaries)
- Scrypt key derivation
- Cryptographically secure random numbers for salts, IVs and the masterkey of course
- Sensitive data is wiped from the heap asap
- Lightweight: Complexity kills security
-
-
-
- Consistency:
-
- HMAC over file contents to recognize changed ciphertext before decryption
- I/O operations are transactional and atomic, if the filesystems support it
- Each file contains all information needed for decryption (except for the key of course), no common metadata means no Single Point of Failure
-
-
-
-
- Office
- Security
- FileTools
- Java
-
- http://cryptomator.org
- https://github.com/cryptomator/cryptomator/issues
- https://community.cryptomator.org/c/kb/faq
- https://community.cryptomator.org/
- https://cryptomator.org/
-
- none
- none
- none
- none
- mild
-
- Cryptomator
-
- cryptomator
-
- org.cryptomator.Cryptomator.desktop
-
diff --git a/dist/linux/debian/org.cryptomator.Cryptomator.desktop b/dist/linux/debian/org.cryptomator.Cryptomator.desktop
deleted file mode 100644
index d8a5925bd..000000000
--- a/dist/linux/debian/org.cryptomator.Cryptomator.desktop
+++ /dev/null
@@ -1,11 +0,0 @@
-[Desktop Entry]
-Name=Cryptomator
-Version=${VERSION_STR}
-Comment=Cloud Storage Encryption Utility
-Exec=/usr/bin/cryptomator %f
-Icon=org.cryptomator.Cryptomator
-Terminal=false
-Type=Application
-Categories=Utility;Security;FileTools;
-StartupWMClass=org.cryptomator.launcher.Cryptomator
-MimeType=application/vnd.cryptomator.encrypted;application/x-vnd.cryptomator.vault-metadata;
\ No newline at end of file
diff --git a/dist/linux/debian/org.cryptomator.Cryptomator.png b/dist/linux/debian/org.cryptomator.Cryptomator.png
deleted file mode 100644
index 9c8635111..000000000
Binary files a/dist/linux/debian/org.cryptomator.Cryptomator.png and /dev/null differ
diff --git a/dist/linux/debian/postinst b/dist/linux/debian/postinst
index 2af574c6b..5668a5e29 100644
--- a/dist/linux/debian/postinst
+++ b/dist/linux/debian/postinst
@@ -24,7 +24,7 @@ case "$1" in
mkdir -p /usr/share/desktop-directories
fi
xdg-desktop-menu install --novendor /usr/share/applications/org.cryptomator.Cryptomator.desktop
- xdg-mime install /usr/share/mime/packages/cryptomator-vault.xml
+ xdg-mime install /usr/share/mime/packages/application-vnd.cryptomator.vault.xml
;;
abort-upgrade|abort-remove|abort-deconfigure)
diff --git a/dist/linux/debian/prerm b/dist/linux/debian/prerm
index cace6816e..41a54cf33 100644
--- a/dist/linux/debian/prerm
+++ b/dist/linux/debian/prerm
@@ -22,7 +22,7 @@ case "$1" in
echo Removing shortcut
xdg-desktop-menu uninstall --novendor /usr/share/applications/org.cryptomator.Cryptomator.desktop
- xdg-mime uninstall /usr/share/mime/packages/cryptomator-vault.xml
+ xdg-mime uninstall /usr/share/mime/packages/application-vnd.cryptomator.vault.xml
;;
failed-upgrade)
diff --git a/dist/linux/debian/rules b/dist/linux/debian/rules
index fc237107e..e4f824394 100755
--- a/dist/linux/debian/rules
+++ b/dist/linux/debian/rules
@@ -11,11 +11,14 @@ override_dh_auto_clean:
rm -rf runtime
rm -rf cryptomator
rm -rf debian/cryptomator
+ rm -rf resources
override_dh_auto_build:
+ mkdir resources
+ ln -s ../common/org.cryptomator.Cryptomator512.png resources/cryptomator.png
jlink \
--output runtime \
- --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 \
+ --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,jdk.management.jfr \
--no-header-files \
--no-man-pages \
--strip-debug \
@@ -39,8 +42,8 @@ override_dh_auto_build:
--java-options "-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\"" \
--java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=false" \
- --java-options "-Dcryptomator.buildNumber=\"ppa-${REVISION_NUM}\"" \
- --java-options "-Dcryptomator.appVersion=\"${VERSION_STR}\"" \
+ --java-options "-Dcryptomator.buildNumber=\"deb-${REVISION_NUM}\"" \
+ --java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\"" \
--app-version "${VERSION_NUM}.${REVISION_NUM}" \
--resource-dir resources \
--verbose
diff --git a/dist/linux/debian/source/include-binaries b/dist/linux/debian/source/include-binaries
index adc7cabd8..8b9254c65 100644
--- a/dist/linux/debian/source/include-binaries
+++ b/dist/linux/debian/source/include-binaries
@@ -1,2 +1,2 @@
-debian/org.cryptomator.Cryptomator.png
-resources/cryptomator.png
+common/org.cryptomator.Cryptomator256.png
+common/org.cryptomator.Cryptomator512.png
diff --git a/dist/mac/dmg/.gitignore b/dist/mac/dmg/.gitignore
index c186170c9..b8ef35283 100644
--- a/dist/mac/dmg/.gitignore
+++ b/dist/mac/dmg/.gitignore
@@ -1,4 +1,5 @@
# created during build
+Cryptomator.app/
runtime/
dmg/
-*.dmg
+*.dmg
\ No newline at end of file
diff --git a/dist/mac/dmg/build.sh b/dist/mac/dmg/build.sh
index ebec045bc..c90411acb 100755
--- a/dist/mac/dmg/build.sh
+++ b/dist/mac/dmg/build.sh
@@ -22,8 +22,8 @@ VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q
# 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; }
+command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found. Fix by 'brew install maven'."; exit 1; }
+command -v create-dmg >/dev/null 2>&1 || { echo >&2 "create-dmg not found. Fix by 'brew install create-dmg'."; 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
@@ -37,7 +37,7 @@ cp ../../../target/cryptomator-*.jar ../../../target/mods
${JAVA_HOME}/bin/jlink \
--output runtime \
--module-path "${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 \
+ --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,jdk.management.jfr \
--no-header-files \
--no-man-pages \
--strip-debug \
diff --git a/dist/win/.gitignore b/dist/win/.gitignore
index 2b66ddbed..9cce929df 100644
--- a/dist/win/.gitignore
+++ b/dist/win/.gitignore
@@ -1,3 +1,7 @@
runtime
Cryptomator
-installer
\ No newline at end of file
+installer
+*.wixobj
+*.pdb
+*.msi
+license.rtf
\ No newline at end of file
diff --git a/dist/win/build.ps1 b/dist/win/build.ps1
index eb33c2462..0b0e953bc 100644
--- a/dist/win/build.ps1
+++ b/dist/win/build.ps1
@@ -1,11 +1,14 @@
+# check parameters
+$clean = $args[0] -eq "fresh"
+
# check preconditions
-if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null)
-{
+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)
-{
+if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
+{
Write-Host "Unable to find mvn.cmd in your PATH (try: choco install maven)"
exit 1
}
@@ -21,21 +24,34 @@ Write-Output "`$revisionNo=$revisionNo"
Write-Output "`$buildDir=$buildDir"
Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
+$vendor = "Skymatic GmbH"
+$copyright = "(C) 2016 - 2022 Skymatic GmbH"
+
# compile
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin
Copy-Item "$buildDir\..\..\target\cryptomator-*.jar" -Destination "$buildDir\..\..\target\mods"
# add runtime
+$runtimeImagePath = '.\runtime'
+if ($clean -and (Test-Path -Path $runtimeImagePath)) {
+ Remove-Item -Path $runtimeImagePath -Force -Recurse
+}
+
& "$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 `
+ --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,jdk.management.jfr `
--no-header-files `
--no-man-pages `
--strip-debug `
--compress=1
+$appPath = '.\Cryptomator'
+if ($clean -and (Test-Path -Path $appPath)) {
+ Remove-Item -Path $appPath -Force -Recurse
+}
+
# create app dir
& "$Env:JAVA_HOME\bin\jpackage" `
--verbose `
@@ -46,8 +62,8 @@ Copy-Item "$buildDir\..\..\target\cryptomator-*.jar" -Destination "$buildDir\..\
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator `
--dest . `
--name Cryptomator `
- --vendor "Skymatic GmbH" `
- --copyright "(C) 2016 - 2022 Skymatic GmbH" `
+ --vendor $vendor `
+ --copyright $copyright `
--java-options "-Xss5m" `
--java-options "-Xmx256m" `
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
@@ -64,11 +80,21 @@ Copy-Item "$buildDir\..\..\target\cryptomator-*.jar" -Destination "$buildDir\..\
--resource-dir resources `
--icon resources/Cryptomator.ico
+#Create RTF license for msi
+&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
+ "-Dlicense.thirdPartyFilename=license.rtf" `
+ "-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl" `
+ "-Dlicense.outputDirectory=$buildDir\resources\"
+
# patch app dir
Copy-Item "contrib\*" -Destination "Cryptomator"
attrib -r "Cryptomator\Cryptomator.exe"
-# create .msi bundle
+$aboutUrl="https://cryptomator.org"
+$updateUrl="https://cryptomator.org/downloads/"
+$helpUrl="https://cryptomator.org/contact/"
+
+# create .msi
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
& "$Env:JAVA_HOME\bin\jpackage" `
--verbose `
@@ -77,14 +103,41 @@ $Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
--app-image Cryptomator `
--dest installer `
--name Cryptomator `
- --vendor "Skymatic GmbH" `
- --copyright "(C) 2016 - 2022 Skymatic GmbH" `
+ --vendor $vendor `
+ --copyright $copyright `
--app-version "$semVerNo" `
--win-menu `
--win-dir-chooser `
--win-shortcut-prompt `
- --win-update-url "https:\\cryptomator.org" `
+ --win-update-url $updateUrl `
--win-menu-group Cryptomator `
--resource-dir resources `
+ --about-url $aboutUrl `
--license-file resources/license.rtf `
--file-associations resources/FAvaultFile.properties
+
+#Create RTF license for bundle
+&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\"
+
+# download Winfsp
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$ProgressPreference = 'SilentlyContinue' # disables Invoke-WebRequest's progress bar, which slows down downloads to a few bytes/s
+$winfspMsiUrl = "https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi"
+Write-Output "Downloading ${winfspMsiUrl}..."
+Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default
+
+# copy MSI to bundle resources
+Copy-Item ".\installer\Cryptomator-*.msi" -Destination ".\bundle\resources\Cryptomator.msi"
+
+# create bundle including winfsp
+& "$env:WIX\bin\candle.exe" .\bundle\bundleWithWinfsp.wxs -ext WixBalExtension -out bundle\ `
+ -dBundleVersion="$semVerNo.$revisionNo" `
+ -dBundleVendor="$vendor" `
+ -dBundleCopyright="$copyright" `
+ -dAboutUrl="$aboutUrl" `
+ -dHelpUrl="$helpUrl" `
+ -dUpdateUrl="$updateUrl"
+& "$env:WIX\bin\light.exe" -b . .\bundle\BundlewithWinfsp.wixobj -ext WixBalExtension -out installer\CryptomatorBundle.exe
\ No newline at end of file
diff --git a/dist/win/bundle/bundleWithWinfsp.wxs b/dist/win/bundle/bundleWithWinfsp.wxs
new file mode 100644
index 000000000..91093df7d
--- /dev/null
+++ b/dist/win/bundle/bundleWithWinfsp.wxs
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/win/bundle/customBootstrapperTheme.wxl b/dist/win/bundle/customBootstrapperTheme.wxl
new file mode 100644
index 000000000..cc464ce9c
--- /dev/null
+++ b/dist/win/bundle/customBootstrapperTheme.wxl
@@ -0,0 +1,64 @@
+
+
+
+
+
+ [WixBundleName] Setup
+ [WixBundleName]
+
+ This Setup will install [WixBundleName] and additional dependencies on your computer.
+ Version [WixBundleVersion]
+ Are you sure you want to cancel?
+ Previous version
+
+ /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or
+ creates a complete local copy of the bundle in directory. Install is the default.
+
+/passive | /quiet - displays minimal UI with no prompts or displays no UI and
+ no prompts. By default UI and all prompts are displayed.
+
+/norestart - suppress any attempts to restart. By default UI will prompt before restart.
+/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.
+ &Close
+ [WixBundleName] <a href="#">license terms</a>.
+ I &agree to the license terms and conditions
+ &Options
+ &Install
+ &Close
+
+ Install location:
+ &Browse
+ &OK
+ &Cancel
+
+ Processing:
+ Initializing...
+ &Cancel
+
+ &Repair
+ &Uninstall
+ &Close
+
+
+
+
+ &Launch
+ You must restart your computer before you can use the software.
+ &Restart
+ &Close
+
+
+
+
+ One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>.
+ You must restart your computer to complete the rollback of the software.
+ &Restart
+ &Close
+
+ The following applications are using files that need to be updated:
+ Close the &applications and attempt to restart them.
+ &Do not close applications. A reboot will be required.
+ &OK
+ &Cancel
+ No action was taken as a system reboot is required.
+
diff --git a/dist/win/bundle/customBootstrapperTheme.xml b/dist/win/bundle/customBootstrapperTheme.xml
new file mode 100644
index 000000000..792f51a35
--- /dev/null
+++ b/dist/win/bundle/customBootstrapperTheme.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+ #(loc.Caption)
+ Segoe UI
+ Segoe UI
+ Segoe UI
+ Segoe UI
+ Segoe UI
+
+
+ #(loc.Title)
+
+
+
+ #(loc.Title)
+ #(loc.HelpHeader)
+ #(loc.HelpText)
+ #(loc.HelpCloseButton)
+
+
+ #(loc.Title)
+
+ #(loc.InstallHeader)
+ #(loc.InstallMessage)
+
+ #(loc.InstallAcceptCheckbox)
+ #(loc.InstallVersion)
+ #(loc.InstallInstallButton)
+ #(loc.InstallCloseButton)
+
+
+
+ #(loc.Title)
+ #(loc.FilesInUseHeader)
+ #(loc.FilesInUseLabel)
+ A
+
+ #(loc.FilesInUseCloseRadioButton)
+ #(loc.FilesInUseDontCloseRadioButton)
+
+ #(loc.FilesInUseOkButton)
+ #(loc.FilesInUseCancelButton)
+
+
+ #(loc.Title)
+
+ #(loc.ProgressHeader)
+ #(loc.ProgressLabel)
+ #(loc.OverallProgressPackageText)
+
+ #(loc.ProgressCancelButton)
+
+
+
+ #(loc.Title)
+ #(loc.ModifyHeader)
+ #(loc.ModifyRepairButton)
+ #(loc.ModifyUninstallButton)
+ #(loc.ModifyCloseButton)
+
+
+ #(loc.Title)
+
+ #(loc.SuccessHeader)
+ #(loc.SuccessInstallHeader)
+ #(loc.SuccessRepairHeader)
+ #(loc.SuccessUninstallHeader)
+ #(loc.SuccessLaunchButton)
+ #(loc.SuccessRestartText)
+ #(loc.SuccessRestartButton)
+ #(loc.SuccessCloseButton)
+
+
+ #(loc.Title)
+
+ #(loc.FailureHeader)
+ #(loc.FailureInstallHeader)
+ #(loc.FailureUninstallHeader)
+ #(loc.FailureRepairHeader)
+ #(loc.FailureHyperlinkLogText)
+
+ #(loc.FailureRestartText)
+ #(loc.FailureRestartButton)
+ #(loc.FailureCloseButton)
+
+
diff --git a/dist/win/bundle/resources/Cryptomator.ico b/dist/win/bundle/resources/Cryptomator.ico
new file mode 100644
index 000000000..7d1d8be88
Binary files /dev/null and b/dist/win/bundle/resources/Cryptomator.ico differ
diff --git a/dist/win/bundle/resources/licenseTemplate.ftl b/dist/win/bundle/resources/licenseTemplate.ftl
new file mode 100644
index 000000000..bd137a1a1
--- /dev/null
+++ b/dist/win/bundle/resources/licenseTemplate.ftl
@@ -0,0 +1,41 @@
+<#function artifactFormat p>
+ <#if p.name?index_of('Unnamed') > -1>
+ <#return p.artifactId + " (" + p.groupId + ":" + p.artifactId + ":" + p.version + " - {{\\field{\\*\\fldinst{HYPERLINK " + (p.url!"no url defined") + "}}{\\fldrslt{" + (p.url!"no url defined") + "\\ul0\\cf0}}}}\\f0\\fs16 ) ">
+ <#else>
+ <#return p.name + " (" + p.groupId + ":" + p.artifactId + ":" + p.version + " - {{\\field{\\*\\fldinst{HYPERLINK " + (p.url!"no url defined") + "}}{\\fldrslt{" + (p.url!"no url defined") + "\\ul0\\cf0}}}}\\f0\\fs16 ) ">
+ #if>
+#function>
+{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Arial;}}
+{\colortbl ;\red0\green0\blue255;}
+\viewkind4\uc1
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
+\par
+\b\'a9 2016 \endash 2022 Skymatic GmbH\b0\par
+\par
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
+\par
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\par
+\par
+You should have received a copy of the GNU General Public License along with this program. If not, see {{\field{\*\fldinst{HYPERLINK http://www.gnu.org/licenses/ }}{\fldrslt{http://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs16 .\par
+\par
+
+\b Cryptomator uses ${dependencyMap?size} third-party dependencies under the following licenses:\b0\par
+<#list licenseMap as e>
+<#assign license = e.getKey()/>
+<#assign projects = e.getValue()/>
+<#if projects?size > 0>
+\tab ${license}:\par
+<#list projects as project>
+\tab\tab- ${artifactFormat(project)}\par
+#list>
+#if>
+#list>
+\par
+\b Cryptomator uses other third-party assets under the following licenses:\b0\par
+\tab SIL OFL 1.1 License:\par
+\tab\tab - Font Awesome 5.12.0 ({{\field{\*\fldinst{HYPERLINK https://fontawesome.com/ }}{\fldrslt{https://fontawesome.com/\ul0\cf0}}}}\f0\fs16 )\b\par
+\par
+\b Cryptomator dynamically links to third-party libraries under the following license:\b0\par
+\tab Uncategorized License:\par
+\tab\tab - WinFsp - Windows File System Proxy, Copyright (C) Bill Zissimopoulos ({{\field{\*\fldinst{HYPERLINK https://github.com/billziss-gh/winfsp }}{\fldrslt{https://github.com/billziss-gh/winfsp\ul0\cf0}}}}\f0\fs16 )\b\par
+}
\ No newline at end of file
diff --git a/dist/win/bundle/resources/logo.png b/dist/win/bundle/resources/logo.png
new file mode 100644
index 000000000..fdfdd6235
Binary files /dev/null and b/dist/win/bundle/resources/logo.png differ
diff --git a/dist/win/bundle/resources/logoSide.png b/dist/win/bundle/resources/logoSide.png
new file mode 100644
index 000000000..e1629e8d6
Binary files /dev/null and b/dist/win/bundle/resources/logoSide.png differ
diff --git a/dist/win/resources/license.rtf b/dist/win/resources/license.rtf
deleted file mode 100644
index 28956ed42..000000000
--- a/dist/win/resources/license.rtf
+++ /dev/null
@@ -1,84 +0,0 @@
-{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Arial;}}
-{\colortbl ;\red0\green0\blue255;}
-{\*\generator Riched20 10.0.17134}\viewkind4\uc1
-\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
-\par
-\b\'a9 2016 \endash 2022 Skymatic GmbH\b0\par
-\par
-This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
-\par
-This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\par
-\par
-You should have received a copy of the GNU General Public License along with this program. If not, see {{\field{\*\fldinst{HYPERLINK http://www.gnu.org/licenses/ }}{\fldrslt{http://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs16 .\par
-\par
-\b Cryptomator uses 40 third-party dependencies under the following licenses:\b0\par
-\tab Apache License v2.0:\par
-\tab\tab - jffi (com.github.jnr:jffi:1.2.23 - {{\field{\*\fldinst{HYPERLINK http://github.com/jnr/jffi }}{\fldrslt{http://github.com/jnr/jffi\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - jnr-a64asm (com.github.jnr:jnr-a64asm:1.0.0 - {{\field{\*\fldinst{HYPERLINK http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm }}{\fldrslt{http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - jnr-constants (com.github.jnr:jnr-constants:0.9.15 - {{\field{\*\fldinst{HYPERLINK http://github.com/jnr/jnr-constants }}{\fldrslt{http://github.com/jnr/jnr-constants\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - jnr-ffi (com.github.jnr:jnr-ffi:2.1.12 - {{\field{\*\fldinst{HYPERLINK http://github.com/jnr/jnr-ffi }}{\fldrslt{http://github.com/jnr/jnr-ffi\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Gson (com.google.code.gson:gson:2.8.7 - {{\field{\*\fldinst{HYPERLINK https://github.com/google/gson/gson }}{\fldrslt{https://github.com/google/gson/gson\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Dagger (com.google.dagger:dagger:2.38.1 - {{\field{\*\fldinst{HYPERLINK https://github.com/google/dagger }}{\fldrslt{https://github.com/google/dagger\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - {{\field{\*\fldinst{HYPERLINK https://github.com/google/guava/failureaccess }}{\fldrslt{https://github.com/google/guava/failureaccess\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Guava: Google Core Libraries for Java (com.google.guava:guava:30.1.1-jre - {{\field{\*\fldinst{HYPERLINK https://github.com/google/guava/guava }}{\fldrslt{https://github.com/google/guava/guava\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Apache Commons CLI (commons-cli:commons-cli:1.4 - {{\field{\*\fldinst{HYPERLINK http://commons.apache.org/proper/commons-cli/ }}{\fldrslt{http://commons.apache.org/proper/commons-cli/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - javax.inject (javax.inject:javax.inject:1 - {{\field{\*\fldinst{HYPERLINK http://code.google.com/p/atinject/ }}{\fldrslt{http://code.google.com/p/atinject/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Java Native Access (net.java.dev.jna:jna:5.7.0 - {{\field{\*\fldinst{HYPERLINK https://github.com/java-native-access/jna }}{\fldrslt{https://github.com/java-native-access/jna\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Java Native Access Platform (net.java.dev.jna:jna-platform:5.7.0 - {{\field{\*\fldinst{HYPERLINK https://github.com/java-native-access/jna }}{\fldrslt{https://github.com/java-native-access/jna\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Apache Commons Lang (org.apache.commons:commons-lang3:3.12.0 - {{\field{\*\fldinst{HYPERLINK https://commons.apache.org/proper/commons-lang/ }}{\fldrslt{https://commons.apache.org/proper/commons-lang/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.14 - {{\field{\*\fldinst{HYPERLINK http://hc.apache.org/httpcomponents-core-ga }}{\fldrslt{http://hc.apache.org/httpcomponents-core-ga\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jackrabbit WebDAV Library (org.apache.jackrabbit:jackrabbit-webdav:2.21.5 - {{\field{\*\fldinst{HYPERLINK http://jackrabbit.apache.org/jackrabbit-webdav/ }}{\fldrslt{http://jackrabbit.apache.org/jackrabbit-webdav/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Http Utility (org.eclipse.jetty:jetty-http:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-http }}{\fldrslt{https://eclipse.org/jetty/jetty-http\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: IO Utility (org.eclipse.jetty:jetty-io:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-io }}{\fldrslt{https://eclipse.org/jetty/jetty-io\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Security (org.eclipse.jetty:jetty-security:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-security }}{\fldrslt{https://eclipse.org/jetty/jetty-security\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Server Core (org.eclipse.jetty:jetty-server:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-server }}{\fldrslt{https://eclipse.org/jetty/jetty-server\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-servlet }}{\fldrslt{https://eclipse.org/jetty/jetty-servlet\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Utilities (org.eclipse.jetty:jetty-util:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-util }}{\fldrslt{https://eclipse.org/jetty/jetty-util\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Servlet API and Schemas for JPMS and OSGi (org.eclipse.jetty.toolchain:jetty-servlet-api:4.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-servlet-api }}{\fldrslt{https://eclipse.org/jetty/jetty-servlet-api\ul0\cf0}}}}\f0\fs16 )\par
-\tab BSD:\par
-\tab\tab - asm (org.ow2.asm:asm:7.1 - {{\field{\*\fldinst{HYPERLINK http://asm.ow2.org/ }}{\fldrslt{http://asm.ow2.org/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - asm-analysis (org.ow2.asm:asm-analysis:7.1 - {{\field{\*\fldinst{HYPERLINK http://asm.ow2.org/ }}{\fldrslt{http://asm.ow2.org/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - asm-commons (org.ow2.asm:asm-commons:7.1 - {{\field{\*\fldinst{HYPERLINK http://asm.ow2.org/ }}{\fldrslt{http://asm.ow2.org/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - asm-tree (org.ow2.asm:asm-tree:7.1 - {{\field{\*\fldinst{HYPERLINK http://asm.ow2.org/ }}{\fldrslt{http://asm.ow2.org/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - asm-util (org.ow2.asm:asm-util:7.1 - {{\field{\*\fldinst{HYPERLINK http://asm.ow2.org/ }}{\fldrslt{http://asm.ow2.org/\ul0\cf0}}}}\f0\fs16 )\par
-\tab Eclipse Public License - Version 1.0:\par
-\tab\tab - Jetty :: Servlet API and Schemas for JPMS and OSGi (org.eclipse.jetty.toolchain:jetty-servlet-api:4.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-servlet-api }}{\fldrslt{https://eclipse.org/jetty/jetty-servlet-api\ul0\cf0}}}}\f0\fs16 )\par
-\tab Eclipse Public License - Version 2.0:\par
-\tab\tab - Jetty :: Http Utility (org.eclipse.jetty:jetty-http:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-http }}{\fldrslt{https://eclipse.org/jetty/jetty-http\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: IO Utility (org.eclipse.jetty:jetty-io:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-io }}{\fldrslt{https://eclipse.org/jetty/jetty-io\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Security (org.eclipse.jetty:jetty-security:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-security }}{\fldrslt{https://eclipse.org/jetty/jetty-security\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Server Core (org.eclipse.jetty:jetty-server:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-server }}{\fldrslt{https://eclipse.org/jetty/jetty-server\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-servlet }}{\fldrslt{https://eclipse.org/jetty/jetty-servlet\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Jetty :: Utilities (org.eclipse.jetty:jetty-util:10.0.6 - {{\field{\*\fldinst{HYPERLINK https://eclipse.org/jetty/jetty-util }}{\fldrslt{https://eclipse.org/jetty/jetty-util\ul0\cf0}}}}\f0\fs16 )\par
-\tab Eclipse Public License - v 1.0:\par
-\tab\tab - Logback Classic Module (ch.qos.logback:logback-classic:1.2.3 - {{\field{\*\fldinst{HYPERLINK http://logback.qos.ch/logback-classic }}{\fldrslt{http://logback.qos.ch/logback-classic\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Logback Core Module (ch.qos.logback:logback-core:1.2.3 - {{\field{\*\fldinst{HYPERLINK http://logback.qos.ch/logback-core }}{\fldrslt{http://logback.qos.ch/logback-core\ul0\cf0}}}}\f0\fs16 )\par
-\tab Eclipse Public License - v 2.0:\par
-\tab\tab - jnr-posix (com.github.jnr:jnr-posix:3.0.54 - {{\field{\*\fldinst{HYPERLINK http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix }}{\fldrslt{http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix\ul0\cf0}}}}\f0\fs16 )\par
-\tab GNU Lesser General Public License:\par
-\tab\tab - Logback Classic Module (ch.qos.logback:logback-classic:1.2.3 - {{\field{\*\fldinst{HYPERLINK http://logback.qos.ch/logback-classic }}{\fldrslt{http://logback.qos.ch/logback-classic\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Logback Core Module (ch.qos.logback:logback-core:1.2.3 - {{\field{\*\fldinst{HYPERLINK http://logback.qos.ch/logback-core }}{\fldrslt{http://logback.qos.ch/logback-core\ul0\cf0}}}}\f0\fs16 )\par
-\tab GPLv2:\par
-\tab\tab - jnr-posix (com.github.jnr:jnr-posix:3.0.54 - {{\field{\*\fldinst{HYPERLINK http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix }}{\fldrslt{http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix\ul0\cf0}}}}\f0\fs16 )\par
-\tab GPLv2+CE:\par
-\tab\tab - javafx-base (org.openjfx:javafx-base:16 - {{\field{\*\fldinst{HYPERLINK https://openjdk.java.net/projects/openjfx/javafx-base/ }}{\fldrslt{https://openjdk.java.net/projects/openjfx/javafx-base/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - javafx-controls (org.openjfx:javafx-controls:16 - {{\field{\*\fldinst{HYPERLINK https://openjdk.java.net/projects/openjfx/javafx-controls/ }}{\fldrslt{https://openjdk.java.net/projects/openjfx/javafx-controls/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - javafx-fxml (org.openjfx:javafx-fxml:16 - {{\field{\*\fldinst{HYPERLINK https://openjdk.java.net/projects/openjfx/javafx-fxml/ }}{\fldrslt{https://openjdk.java.net/projects/openjfx/javafx-fxml/\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - javafx-graphics (org.openjfx:javafx-graphics:16 - {{\field{\*\fldinst{HYPERLINK https://openjdk.java.net/projects/openjfx/javafx-graphics/ }}{\fldrslt{https://openjdk.java.net/projects/openjfx/javafx-graphics/\ul0\cf0}}}}\f0\fs16 )\par
-\tab LGPL 2.1:\par
-\tab\tab - jnr-posix (com.github.jnr:jnr-posix:3.0.54 - {{\field{\*\fldinst{HYPERLINK http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix }}{\fldrslt{http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Java Native Access (net.java.dev.jna:jna:5.7.0 - {{\field{\*\fldinst{HYPERLINK https://github.com/java-native-access/jna }}{\fldrslt{https://github.com/java-native-access/jna\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - Java Native Access Platform (net.java.dev.jna:jna-platform:5.7.0 - {{\field{\*\fldinst{HYPERLINK https://github.com/java-native-access/jna }}{\fldrslt{https://github.com/java-native-access/jna\ul0\cf0}}}}\f0\fs16 )\par
-\tab MIT License:\par
-\tab\tab - java jwt (com.auth0:java-jwt:3.18.1 - {{\field{\*\fldinst{HYPERLINK https://github.com/auth0/java-jwt }}{\fldrslt{https://github.com/auth0/java-jwt\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - jnr-x86asm (com.github.jnr:jnr-x86asm:1.0.2 - {{\field{\*\fldinst{HYPERLINK http://github.com/jnr/jnr-x86asm }}{\fldrslt{http://github.com/jnr/jnr-x86asm\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - jnr-fuse (com.github.serceman:jnr-fuse:0.5.5 - {{\field{\*\fldinst{HYPERLINK https://github.com/SerCeMan/jnr-fuse }}{\fldrslt{https://github.com/SerCeMan/jnr-fuse\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - zxcvbn4j (com.nulab-inc:zxcvbn:1.5.2 - {{\field{\*\fldinst{HYPERLINK https://github.com/nulab/zxcvbn4j }}{\fldrslt{https://github.com/nulab/zxcvbn4j\ul0\cf0}}}}\f0\fs16 )\par
-\tab\tab - SLF4J API Module (org.slf4j:slf4j-api:1.7.31 - {{\field{\*\fldinst{HYPERLINK http://www.slf4j.org }}{\fldrslt{http://www.slf4j.org\ul0\cf0}}}}\f0\fs16 )\par
-\tab The BSD 2-Clause License:\par
-\tab\tab - EasyBind (com.tobiasdiez:easybind:2.2 - {{\field{\*\fldinst{HYPERLINK https://github.com/tobiasdiez/EasyBind }}{\fldrslt{https://github.com/tobiasdiez/EasyBind\ul0\cf0}}}}\f0\fs16 )\par
-\par
-\b Cryptomator uses other third-party assets under the following licenses:\b0\par
-\tab SIL OFL 1.1 License:\par
-\tab\tab - Font Awesome 5.12.0 ({{\field{\*\fldinst{HYPERLINK https://fontawesome.com/ }}{\fldrslt{https://fontawesome.com/\ul0\cf0}}}}\f0\fs16 )\b\par
-}
diff --git a/dist/win/resources/licenseTemplate.ftl b/dist/win/resources/licenseTemplate.ftl
new file mode 100644
index 000000000..d442e6538
--- /dev/null
+++ b/dist/win/resources/licenseTemplate.ftl
@@ -0,0 +1,37 @@
+<#function artifactFormat p>
+ <#if p.name?index_of('Unnamed') > -1>
+ <#return p.artifactId + " (" + p.groupId + ":" + p.artifactId + ":" + p.version + " - {{\\field{\\*\\fldinst{HYPERLINK " + (p.url!"no url defined") + "}}{\\fldrslt{" + (p.url!"no url defined") + "\\ul0\\cf0}}}}\\f0\\fs16 ) ">
+ <#else>
+ <#return p.name + " (" + p.groupId + ":" + p.artifactId + ":" + p.version + " - {{\\field{\\*\\fldinst{HYPERLINK " + (p.url!"no url defined") + "}}{\\fldrslt{" + (p.url!"no url defined") + "\\ul0\\cf0}}}}\\f0\\fs16 ) ">
+ #if>
+#function>
+{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Arial;}}
+{\colortbl ;\red0\green0\blue255;}
+\viewkind4\uc1
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
+\par
+\b\'a9 2016 \endash 2022 Skymatic GmbH\b0\par
+\par
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
+\par
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\par
+\par
+You should have received a copy of the GNU General Public License along with this program. If not, see {{\field{\*\fldinst{HYPERLINK http://www.gnu.org/licenses/ }}{\fldrslt{http://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs16 .\par
+\par
+
+\b Cryptomator uses ${dependencyMap?size} third-party dependencies under the following licenses:\b0\par
+<#list licenseMap as e>
+<#assign license = e.getKey()/>
+<#assign projects = e.getValue()/>
+<#if projects?size > 0>
+\tab ${license}:\par
+<#list projects as project>
+\tab\tab- ${artifactFormat(project)}\par
+#list>
+#if>
+#list>
+\par
+\b Cryptomator uses other third-party assets under the following licenses:\b0\par
+\tab SIL OFL 1.1 License:\par
+\tab\tab - Font Awesome 5.12.0 ({{\field{\*\fldinst{HYPERLINK https://fontawesome.com/ }}{\fldrslt{https://fontawesome.com/\ul0\cf0}}}}\f0\fs16 )\b\par
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 6f0243597..469ab6398 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,9 +37,9 @@
1.2.6
- 17.0.1
+ 17.0.2
3.12.0
- 3.18.2
+ 3.18.3
2.2
31.0-jre
2.40.3
@@ -52,6 +52,10 @@
5.8.1
3.12.4
2.2
+
+
+ 7.0.0
+ 0.8.7
@@ -228,7 +232,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ 3.10.1
org.apache.maven.plugins
@@ -238,7 +242,7 @@
org.apache.maven.plugins
maven-dependency-plugin
- 3.2.0
+ 3.3.0
org.apache.maven.plugins
@@ -253,17 +257,17 @@
org.apache.maven.plugins
maven-jar-plugin
- 3.2.0
+ 3.2.2
org.jacoco
jacoco-maven-plugin
- 0.8.7
+ ${jacoco.version}
org.owasp
dependency-check-maven
- 6.3.1
+ ${dependency-check.version}
diff --git a/src/main/java/org/cryptomator/common/mountpoint/CustomDriveLetterChooser.java b/src/main/java/org/cryptomator/common/mountpoint/CustomDriveLetterChooser.java
index 1a42aa5ad..02f75d4a1 100644
--- a/src/main/java/org/cryptomator/common/mountpoint/CustomDriveLetterChooser.java
+++ b/src/main/java/org/cryptomator/common/mountpoint/CustomDriveLetterChooser.java
@@ -5,6 +5,9 @@ import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Volume;
import javax.inject.Inject;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
@@ -27,4 +30,13 @@ class CustomDriveLetterChooser implements MountPointChooser {
public Optional chooseMountPoint(Volume caller) {
return this.vaultSettings.getWinDriveLetter().map(letter -> letter.charAt(0) + ":\\").map(Paths::get);
}
+
+ @Override
+ public boolean prepare(Volume caller, Path driveLetter) throws InvalidMountPointException {
+ if (!Files.notExists(driveLetter, LinkOption.NOFOLLOW_LINKS)) {
+ //Drive already exists OR can't be determined
+ throw new InvalidMountPointException(new FileAlreadyExistsException(driveLetter.toString()));
+ }
+ return false;
+ }
}
diff --git a/src/main/java/org/cryptomator/common/mountpoint/CustomMountPointChooser.java b/src/main/java/org/cryptomator/common/mountpoint/CustomMountPointChooser.java
index 5f1a7fedd..80c5b067b 100644
--- a/src/main/java/org/cryptomator/common/mountpoint/CustomMountPointChooser.java
+++ b/src/main/java/org/cryptomator/common/mountpoint/CustomMountPointChooser.java
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Environment;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.settings.VolumeImpl;
+import org.cryptomator.common.vaults.MountPointRequirement;
import org.cryptomator.common.vaults.Volume;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -11,10 +12,10 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
-import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -22,6 +23,9 @@ import java.util.Optional;
class CustomMountPointChooser implements MountPointChooser {
+ private static final String HIDEAWAY_PREFIX = ".~$";
+ private static final String HIDEAWAY_SUFFIX = ".tmp";
+ private static final String WIN_HIDDEN = "dos:hidden";
private static final Logger LOG = LoggerFactory.getLogger(CustomMountPointChooser.class);
private final VaultSettings vaultSettings;
@@ -35,7 +39,6 @@ class CustomMountPointChooser implements MountPointChooser {
@Override
public boolean isApplicable(Volume caller) {
- //Disable if useExperimentalFuse is required (Win + Fuse), but set to false
return caller.getImplementationType() != VolumeImpl.FUSE || !SystemUtils.IS_OS_WINDOWS || environment.useExperimentalFuse();
}
@@ -47,49 +50,102 @@ class CustomMountPointChooser implements MountPointChooser {
@Override
public boolean prepare(Volume caller, Path mountPoint) throws InvalidMountPointException {
- switch (caller.getMountPointRequirement()) {
- case PARENT_NO_MOUNT_POINT -> prepareParentNoMountPoint(mountPoint);
- case EMPTY_MOUNT_POINT -> prepareEmptyMountPoint(mountPoint);
- case NONE -> {
- //Requirement "NONE" doesn't make any sense here.
- //No need to prepare/verify a Mountpoint without requiring one...
+ return switch (caller.getMountPointRequirement()) {
+ case PARENT_NO_MOUNT_POINT -> {
+ prepareParentNoMountPoint(mountPoint);
+ LOG.debug("Successfully checked custom mount point: {}", mountPoint);
+ yield true;
+ }
+ case EMPTY_MOUNT_POINT -> {
+ prepareEmptyMountPoint(mountPoint);
+ LOG.debug("Successfully checked custom mount point: {}", mountPoint);
+ yield false;
+ }
+ case NONE, UNUSED_ROOT_DIR, PARENT_OPT_MOUNT_POINT -> {
throw new InvalidMountPointException(new IllegalStateException("Illegal MountPointRequirement"));
}
- default -> {
- //Currently the case for "PARENT_OPT_MOUNT_POINT"
- throw new InvalidMountPointException(new IllegalStateException("Not implemented"));
- }
- }
- LOG.debug("Successfully checked custom mount point: {}", mountPoint);
- return false;
+ };
}
- private void prepareParentNoMountPoint(Path mountPoint) throws InvalidMountPointException {
- //This the case on Windows when using FUSE
- //See https://github.com/billziss-gh/winfsp/issues/320
- Path parent = mountPoint.getParent();
- if (!Files.isDirectory(parent)) {
- throw new InvalidMountPointException(new NotDirectoryException(parent.toString()));
- }
- //We must use #notExists() here because notExists =/= !exists (see docs)
- if (!Files.notExists(mountPoint, LinkOption.NOFOLLOW_LINKS)) {
- //File exists OR can't be determined
- throw new InvalidMountPointException(new FileAlreadyExistsException(mountPoint.toString()));
+ //This is case on Windows when using FUSE
+ //See https://github.com/billziss-gh/winfsp/issues/320
+ void prepareParentNoMountPoint(Path mountPoint) throws InvalidMountPointException {
+ Path hideaway = getHideaway(mountPoint);
+ var mpExists = Files.exists(mountPoint, LinkOption.NOFOLLOW_LINKS);
+ var hideExists = Files.exists(hideaway, LinkOption.NOFOLLOW_LINKS);
+
+ //TODO: possible improvement by just deleting an _empty_ hideaway
+ if (mpExists && hideExists) { //both resources exist (whatever type)
+ throw new InvalidMountPointException(new FileAlreadyExistsException(hideaway.toString()));
+ } else if (!mpExists && !hideExists) { //neither mountpoint nor hideaway exist
+ throw new InvalidMountPointException(new NoSuchFileException(mountPoint.toString()));
+ } else if (!mpExists) { //only hideaway exists
+ checkIsDirectory(hideaway);
+ LOG.info("Mountpoint {} for winfsp mount seems to be not properly cleaned up. Will be fixed on unmount.", mountPoint);
+ try {
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Files.setAttribute(hideaway, WIN_HIDDEN, true, LinkOption.NOFOLLOW_LINKS);
+ }
+ } catch (IOException e) {
+ throw new InvalidMountPointException(e);
+ }
+ } else { //only mountpoint exists
+ try {
+ checkIsDirectory(mountPoint);
+ checkIsEmpty(mountPoint);
+
+ Files.move(mountPoint, hideaway);
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Files.setAttribute(hideaway, WIN_HIDDEN, true, LinkOption.NOFOLLOW_LINKS);
+ }
+ } catch (IOException e) {
+ throw new InvalidMountPointException(e);
+ }
}
}
private void prepareEmptyMountPoint(Path mountPoint) throws InvalidMountPointException {
//This is the case for Windows when using Dokany and for Linux and Mac
- if (!Files.isDirectory(mountPoint)) {
- throw new InvalidMountPointException(new NotDirectoryException(mountPoint.toString()));
- }
- try (DirectoryStream ds = Files.newDirectoryStream(mountPoint)) {
- if (ds.iterator().hasNext()) {
- throw new InvalidMountPointException(new DirectoryNotEmptyException(mountPoint.toString()));
- }
+ checkIsDirectory(mountPoint);
+ try {
+ checkIsEmpty(mountPoint);
} catch (IOException exception) {
throw new InvalidMountPointException("IOException while checking folder content", exception);
}
}
+ @Override
+ public void cleanup(Volume caller, Path mountPoint) {
+ if (caller.getMountPointRequirement() == MountPointRequirement.PARENT_NO_MOUNT_POINT) {
+ Path hideaway = getHideaway(mountPoint);
+ try {
+ Files.move(hideaway, mountPoint);
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Files.setAttribute(mountPoint, WIN_HIDDEN, false);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to clean up mountpoint {} for Winfsp mounting.", mountPoint, e);
+ }
+ }
+ }
+
+ private void checkIsDirectory(Path toCheck) throws InvalidMountPointException {
+ if (!Files.isDirectory(toCheck, LinkOption.NOFOLLOW_LINKS)) {
+ throw new InvalidMountPointException(new NotDirectoryException(toCheck.toString()));
+ }
+ }
+
+ private void checkIsEmpty(Path toCheck) throws InvalidMountPointException, IOException {
+ try (var dirStream = Files.list(toCheck)) {
+ if (dirStream.findFirst().isPresent()) {
+ throw new InvalidMountPointException(new DirectoryNotEmptyException(toCheck.toString()));
+ }
+ }
+ }
+
+ //visible for testing
+ Path getHideaway(Path mountPoint) {
+ return mountPoint.resolveSibling(HIDEAWAY_PREFIX + mountPoint.getFileName().toString() + HIDEAWAY_SUFFIX);
+ }
+
}
diff --git a/src/main/java/org/cryptomator/common/mountpoint/TemporaryMountPointChooser.java b/src/main/java/org/cryptomator/common/mountpoint/TemporaryMountPointChooser.java
index eb1d8d0b1..bcda3d8f2 100644
--- a/src/main/java/org/cryptomator/common/mountpoint/TemporaryMountPointChooser.java
+++ b/src/main/java/org/cryptomator/common/mountpoint/TemporaryMountPointChooser.java
@@ -65,7 +65,7 @@ class TemporaryMountPointChooser implements MountPointChooser {
throw new InvalidMountPointException(new IllegalStateException("Illegal MountPointRequirement"));
}
default -> {
- //Currently the case for "PARENT_OPT_MOUNT_POINT"
+ //Currently the case for "UNUSED_ROOT_DIR, PARENT_OPT_MOUNT_POINT"
throw new InvalidMountPointException(new IllegalStateException("Not implemented"));
}
}
diff --git a/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java b/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java
index c998761d0..c08642073 100644
--- a/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java
+++ b/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java
@@ -86,7 +86,7 @@ public class DokanyVolume extends AbstractVolume {
@Override
public MountPointRequirement getMountPointRequirement() {
- return MountPointRequirement.EMPTY_MOUNT_POINT;
+ return this.vaultSettings.getWinDriveLetter().isPresent() ? MountPointRequirement.UNUSED_ROOT_DIR : MountPointRequirement.EMPTY_MOUNT_POINT;
}
public static boolean isSupportedStatic() {
diff --git a/src/main/java/org/cryptomator/common/vaults/FuseVolume.java b/src/main/java/org/cryptomator/common/vaults/FuseVolume.java
index a1579fdaf..0321cfa0f 100644
--- a/src/main/java/org/cryptomator/common/vaults/FuseVolume.java
+++ b/src/main/java/org/cryptomator/common/vaults/FuseVolume.java
@@ -4,6 +4,7 @@ import com.google.common.collect.Iterators;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.mountpoint.InvalidMountPointException;
import org.cryptomator.common.mountpoint.MountPointChooser;
+import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.settings.VolumeImpl;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.frontend.fuse.mount.EnvironmentVariables;
@@ -28,11 +29,14 @@ public class FuseVolume extends AbstractVolume {
private static final Logger LOG = LoggerFactory.getLogger(FuseVolume.class);
private static final Pattern NON_WHITESPACE_OR_QUOTED = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"); // Thanks to https://stackoverflow.com/a/366532
+ private final VaultSettings vaultSettings;
+
private Mount mount;
@Inject
- public FuseVolume(@Named("orderedMountPointChoosers") Iterable choosers) {
+ public FuseVolume(VaultSettings vaultSettings, @Named("orderedMountPointChoosers") Iterable choosers) {
super(choosers);
+ this.vaultSettings = vaultSettings;
}
@Override
@@ -50,7 +54,7 @@ public class FuseVolume extends AbstractVolume {
.withFileNameTranscoder(mounter.defaultFileNameTranscoder()) //
.build();
this.mount = mounter.mount(root, envVars, onExitAction);
- } catch ( FuseMountException | FuseNotSupportedException e) {
+ } catch (FuseMountException | FuseNotSupportedException e) {
throw new VolumeException("Unable to mount Filesystem", e);
}
}
@@ -119,7 +123,10 @@ public class FuseVolume extends AbstractVolume {
@Override
public MountPointRequirement getMountPointRequirement() {
- return SystemUtils.IS_OS_WINDOWS ? MountPointRequirement.PARENT_NO_MOUNT_POINT : MountPointRequirement.EMPTY_MOUNT_POINT;
+ if (!SystemUtils.IS_OS_WINDOWS) {
+ return MountPointRequirement.EMPTY_MOUNT_POINT;
+ }
+ return this.vaultSettings.getWinDriveLetter().isPresent() ? MountPointRequirement.UNUSED_ROOT_DIR : MountPointRequirement.PARENT_NO_MOUNT_POINT;
}
public static boolean isSupportedStatic() {
diff --git a/src/main/java/org/cryptomator/common/vaults/MountPointRequirement.java b/src/main/java/org/cryptomator/common/vaults/MountPointRequirement.java
index 84a798e59..deec61e1a 100644
--- a/src/main/java/org/cryptomator/common/vaults/MountPointRequirement.java
+++ b/src/main/java/org/cryptomator/common/vaults/MountPointRequirement.java
@@ -6,6 +6,11 @@ package org.cryptomator.common.vaults;
*/
public enum MountPointRequirement {
+ /**
+ * The Mountpoint needs to be a filesystem root and must not exist.
+ */
+ UNUSED_ROOT_DIR,
+
/**
* No Mountpoint on the local filesystem required. (e.g. WebDAV)
*/
diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java
index 35f2be069..1fd463432 100644
--- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java
+++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java
@@ -35,14 +35,13 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ResourceBundle;
-import java.util.UUID;
@AddVaultWizardScoped
public class CreateNewVaultLocationController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(CreateNewVaultLocationController.class);
private static final Path DEFAULT_CUSTOM_VAULT_PATH = Paths.get(System.getProperty("user.home"));
- private static final String TEMP_FILE_FORMAT = "cryptomator-%s.tmp";
+ private static final String TEMP_FILE_FORMAT = ".locationTest.cryptomator.tmp";
private final Stage window;
private final Lazy chooseNameScene;
@@ -112,7 +111,7 @@ public class CreateNewVaultLocationController implements FxController {
}
private boolean isActuallyWritable(Path p) {
- Path tmpFile = p.resolve(String.format(TEMP_FILE_FORMAT, UUID.randomUUID()));
+ Path tmpFile = p.resolve(TEMP_FILE_FORMAT);
try (var chan = Files.newByteChannel(tmpFile, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) {
return true;
} catch (IOException e) {
diff --git a/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java b/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java
index fd85db988..234bac65b 100644
--- a/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java
+++ b/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java
@@ -1,5 +1,6 @@
package org.cryptomator.ui.unlock;
+import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.MountPointRequirement;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
@@ -32,12 +33,24 @@ public class UnlockInvalidMountPointController implements FxController {
return vault.getVaultSettings().getCustomMountPath().orElse("AUTO");
}
- public boolean getMustExist() {
- MountPointRequirement requirement = vault.getVolume().orElseThrow(() -> new IllegalStateException("Invalid Mountpoint without a Volume?!")).getMountPointRequirement();
- assert requirement != MountPointRequirement.NONE; //An invalid MountPoint with no required MountPoint doesn't seem sensible
- assert requirement != MountPointRequirement.PARENT_OPT_MOUNT_POINT; //Not implemented anywhere (yet)
-
- return requirement == MountPointRequirement.EMPTY_MOUNT_POINT;
+ public boolean getNotExisting() {
+ return getMountPointRequirement() == MountPointRequirement.EMPTY_MOUNT_POINT;
}
-}
+ public boolean getExisting() {
+ return getMountPointRequirement() == MountPointRequirement.PARENT_NO_MOUNT_POINT;
+ }
+
+ public boolean getDriveLetterOccupied() {
+ return getMountPointRequirement() == MountPointRequirement.UNUSED_ROOT_DIR;
+ }
+
+ private MountPointRequirement getMountPointRequirement() {
+ var requirement = vault.getVolume().orElseThrow(() -> new IllegalStateException("Invalid Mountpoint without a Volume?!")).getMountPointRequirement();
+ assert requirement != MountPointRequirement.NONE; //An invalid MountPoint with no required MountPoint doesn't seem sensible
+ assert requirement != MountPointRequirement.PARENT_OPT_MOUNT_POINT; //Not implemented anywhere (yet)
+ assert requirement != MountPointRequirement.UNUSED_ROOT_DIR || SystemUtils.IS_OS_WINDOWS; //Not implemented anywhere, but on Windows
+
+ return requirement;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java b/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java
index 073258d80..6964c3c86 100644
--- a/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java
+++ b/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java
@@ -2,6 +2,7 @@ package org.cryptomator.ui.unlock;
import com.google.common.base.Throwables;
import dagger.Lazy;
+import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.mountpoint.InvalidMountPointException;
import org.cryptomator.common.vaults.MountPointRequirement;
import org.cryptomator.common.vaults.Vault;
@@ -79,9 +80,10 @@ public class UnlockWorkflow extends Task {
}
private void handleInvalidMountPoint(InvalidMountPointException impExc) {
- MountPointRequirement requirement = vault.getVolume().orElseThrow(() -> new IllegalStateException("Invalid Mountpoint without a Volume?!", impExc)).getMountPointRequirement();
+ var requirement = vault.getVolume().orElseThrow(() -> new IllegalStateException("Invalid Mountpoint without a Volume?!", impExc)).getMountPointRequirement();
assert requirement != MountPointRequirement.NONE; //An invalid MountPoint with no required MountPoint doesn't seem sensible
assert requirement != MountPointRequirement.PARENT_OPT_MOUNT_POINT; //Not implemented anywhere (yet)
+ assert requirement != MountPointRequirement.UNUSED_ROOT_DIR || SystemUtils.IS_OS_WINDOWS; //Not implemented anywhere, but on Windows
Throwable cause = impExc.getCause();
// TODO: apply https://openjdk.java.net/jeps/8213076 in future JDK versions
@@ -93,7 +95,11 @@ public class UnlockWorkflow extends Task {
}
showInvalidMountPointScene();
} else if (cause instanceof FileAlreadyExistsException) {
- LOG.error("Unlock failed. Mountpoint already exists: {}", cause.getMessage());
+ if (requirement == MountPointRequirement.UNUSED_ROOT_DIR) {
+ LOG.error("Unlock failed. Drive Letter already in use: {}", cause.getMessage());
+ } else {
+ LOG.error("Unlock failed. Mountpoint already exists: {}", cause.getMessage());
+ }
showInvalidMountPointScene();
} else if (cause instanceof DirectoryNotEmptyException) {
LOG.error("Unlock failed. Mountpoint not an empty directory: {}", cause.getMessage());
diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java
index 8739be791..3be38568d 100644
--- a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java
+++ b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java
@@ -11,9 +11,6 @@ import org.cryptomator.ui.common.FxController;
import javax.inject.Inject;
import javafx.beans.binding.Bindings;
-import javafx.beans.binding.BooleanBinding;
-import javafx.beans.property.BooleanProperty;
-import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
@@ -32,18 +29,15 @@ import java.nio.file.Path;
import java.util.ResourceBundle;
import java.util.Set;
-/**
- * TODO: if WebDav is selected on a windows system, custom mount directory is _not_ supported. This is currently not indicated/shown/etc in the ui
- */
@VaultOptionsScoped
public class MountOptionsController implements FxController {
private final Stage window;
private final Vault vault;
- private final BooleanProperty osIsWindows = new SimpleBooleanProperty(SystemUtils.IS_OS_WINDOWS);
- private final BooleanBinding webDavAndWindows;
+ private final VolumeImpl usedVolumeImpl;
private final WindowsDriveLetters windowsDriveLetters;
private final ResourceBundle resourceBundle;
+
public CheckBox readOnlyCheckbox;
public CheckBox customMountFlagsCheckbox;
public TextField mountFlags;
@@ -53,20 +47,13 @@ public class MountOptionsController implements FxController {
public RadioButton mountPointCustomDir;
public ChoiceBox driveLetterSelection;
- //FUSE + Windows -> Disable some (experimental) features for the user because they are unstable
- //Use argument Dfuse.experimental="true" to override
- private final BooleanBinding restrictToStableFuseOnWindows;
-
@Inject
MountOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, Settings settings, WindowsDriveLetters windowsDriveLetters, ResourceBundle resourceBundle, Environment environment) {
this.window = window;
this.vault = vault;
- this.webDavAndWindows = settings.preferredVolumeImpl().isEqualTo(VolumeImpl.WEBDAV).and(osIsWindows);
+ this.usedVolumeImpl = settings.preferredVolumeImpl().get();
this.windowsDriveLetters = windowsDriveLetters;
this.resourceBundle = resourceBundle;
-
- BooleanBinding isFuseOnWindows = settings.preferredVolumeImpl().isEqualTo(VolumeImpl.FUSE).and(osIsWindows);
- this.restrictToStableFuseOnWindows = isFuseOnWindows.and(new SimpleBooleanProperty(!environment.useExperimentalFuse())); //Is FUSE on Win and is NOT experimental fuse enabled
}
@FXML
@@ -74,10 +61,11 @@ public class MountOptionsController implements FxController {
// readonly:
readOnlyCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().usesReadOnlyMode());
- if (getRestrictToStableFuseOnWindows()) {
+ //TODO: support this feature on Windows
+ if (usedVolumeImpl == VolumeImpl.FUSE && isOsWindows()) {
readOnlyCheckbox.setSelected(false); // to prevent invalid states
+ readOnlyCheckbox.setDisable(true);
}
- readOnlyCheckbox.disableProperty().bind(customMountFlagsCheckbox.selectedProperty().or(restrictToStableFuseOnWindows));
// custom mount flags:
mountFlags.disableProperty().bind(customMountFlagsCheckbox.selectedProperty().not());
@@ -95,9 +83,7 @@ public class MountOptionsController implements FxController {
driveLetterSelection.setConverter(new WinDriveLetterLabelConverter(windowsDriveLetters, resourceBundle));
driveLetterSelection.setValue(vault.getVaultSettings().winDriveLetter().get());
- if (vault.getVaultSettings().useCustomMountPath().get()
- && vault.getVaultSettings().getCustomMountPath().isPresent()
- && !getRestrictToStableFuseOnWindows() /* to prevent invalid states */) {
+ if (vault.getVaultSettings().useCustomMountPath().get() && vault.getVaultSettings().getCustomMountPath().isPresent()) {
mountPoint.selectToggle(mountPointCustomDir);
} else if (!Strings.isNullOrEmpty(vault.getVaultSettings().winDriveLetter().get())) {
mountPoint.selectToggle(mountPointWinDriveLetter);
@@ -188,32 +174,28 @@ public class MountOptionsController implements FxController {
// Getter & Setter
- public BooleanProperty osIsWindowsProperty() {
- return osIsWindows;
+ public boolean isOsWindows() {
+ return SystemUtils.IS_OS_WINDOWS;
}
- public boolean getOsIsWindows() {
- return osIsWindows.get();
+ public boolean isCustomMountPointSupported() {
+ return !(usedVolumeImpl == VolumeImpl.WEBDAV && isOsWindows());
}
- public BooleanBinding webDavAndWindowsProperty() {
- return webDavAndWindows;
- }
-
- public boolean isWebDavAndWindows() {
- return webDavAndWindows.get();
+ public boolean isReadOnlySupported() {
+ return !(usedVolumeImpl == VolumeImpl.FUSE && isOsWindows());
}
public StringProperty customMountPathProperty() {
return vault.getVaultSettings().customMountPath();
}
+ public boolean isCustomMountOptionsSupported() {
+ return usedVolumeImpl != VolumeImpl.WEBDAV;
+ }
+
public String getCustomMountPath() {
return vault.getVaultSettings().customMountPath().get();
}
- public Boolean getRestrictToStableFuseOnWindows() {
- return restrictToStableFuseOnWindows.get();
- }
-
}
diff --git a/src/main/resources/fxml/unlock_invalid_mount_point.fxml b/src/main/resources/fxml/unlock_invalid_mount_point.fxml
index 253ff5704..062981304 100644
--- a/src/main/resources/fxml/unlock_invalid_mount_point.fxml
+++ b/src/main/resources/fxml/unlock_invalid_mount_point.fxml
@@ -29,8 +29,9 @@
-
-
+
+
+
diff --git a/src/main/resources/fxml/vault_options_mount.fxml b/src/main/resources/fxml/vault_options_mount.fxml
index a96784020..48b1fc7cd 100644
--- a/src/main/resources/fxml/vault_options_mount.fxml
+++ b/src/main/resources/fxml/vault_options_mount.fxml
@@ -24,7 +24,7 @@
-
+
@@ -38,19 +38,19 @@
-
+
-
-
+
+
-
+
diff --git a/src/main/resources/i18n/strings.properties b/src/main/resources/i18n/strings.properties
index 63e2bbecf..36932b877 100644
--- a/src/main/resources/i18n/strings.properties
+++ b/src/main/resources/i18n/strings.properties
@@ -116,6 +116,7 @@ unlock.error.heading=Unable to unlock vault
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Mount point "%s" is not a directory, not empty or does not exist.
unlock.error.invalidMountPoint.existing=Mount point "%s" already exists or parent folder is missing.
+unlock.error.invalidMountPoint.driveLetterOccupied=Drive Letter "%s" is already in use.
# Lock
## Force
diff --git a/src/main/resources/license/THIRD-PARTY.txt b/src/main/resources/license/THIRD-PARTY.txt
index ba4310dd5..9c9d92c7d 100644
--- a/src/main/resources/license/THIRD-PARTY.txt
+++ b/src/main/resources/license/THIRD-PARTY.txt
@@ -62,10 +62,10 @@ Cryptomator uses 40 third-party dependencies under the following licenses:
GPLv2:
- jnr-posix (com.github.jnr:jnr-posix:3.1.10 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
GPLv2+CE:
- - javafx-base (org.openjfx:javafx-base:17.0.1 - https://openjdk.java.net/projects/openjfx/javafx-base/)
- - javafx-controls (org.openjfx:javafx-controls:17.0.1 - https://openjdk.java.net/projects/openjfx/javafx-controls/)
- - javafx-fxml (org.openjfx:javafx-fxml:17.0.1 - https://openjdk.java.net/projects/openjfx/javafx-fxml/)
- - javafx-graphics (org.openjfx:javafx-graphics:17.0.1 - https://openjdk.java.net/projects/openjfx/javafx-graphics/)
+ - javafx-base (org.openjfx:javafx-base:17.0.2 - https://openjdk.java.net/projects/openjfx/javafx-base/)
+ - javafx-controls (org.openjfx:javafx-controls:17.0.2 - https://openjdk.java.net/projects/openjfx/javafx-controls/)
+ - javafx-fxml (org.openjfx:javafx-fxml:17.0.2 - https://openjdk.java.net/projects/openjfx/javafx-fxml/)
+ - javafx-graphics (org.openjfx:javafx-graphics:17.0.2 - https://openjdk.java.net/projects/openjfx/javafx-graphics/)
LGPL 2.1:
- jnr-posix (com.github.jnr:jnr-posix:3.1.10 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
LGPL-2.1-or-later:
diff --git a/src/test/java/org/cryptomator/common/mountpoint/CustomMountPointChooserTest.java b/src/test/java/org/cryptomator/common/mountpoint/CustomMountPointChooserTest.java
new file mode 100644
index 000000000..da2e0fde0
--- /dev/null
+++ b/src/test/java/org/cryptomator/common/mountpoint/CustomMountPointChooserTest.java
@@ -0,0 +1,187 @@
+package org.cryptomator.common.mountpoint;
+
+import org.cryptomator.common.Environment;
+import org.cryptomator.common.settings.VaultSettings;
+import org.cryptomator.common.vaults.MountPointRequirement;
+import org.cryptomator.common.vaults.Volume;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class CustomMountPointChooserTest {
+
+ //--- Mocks ---
+ VaultSettings vaultSettings;
+ Environment environment;
+ Volume volume;
+
+ CustomMountPointChooser customMpc;
+
+
+ @BeforeEach
+ public void init() {
+ this.volume = Mockito.mock(Volume.class);
+ this.vaultSettings = Mockito.mock(VaultSettings.class);
+ this.environment = Mockito.mock(Environment.class);
+ this.customMpc = new CustomMountPointChooser(vaultSettings, environment);
+ }
+
+ @Nested
+ public class WinfspPreperations {
+
+ @Test
+ @DisplayName("Hideaway name for PARENT_NO_MOUNTPOINT is not the same as mountpoint")
+ public void testGetHideaway() {
+ //prepare
+ Path mntPoint = Path.of("/foo/bar");
+ //execute
+ var hideaway = customMpc.getHideaway(mntPoint);
+ //eval
+ Assertions.assertNotEquals(hideaway.getFileName(), mntPoint.getFileName());
+ Assertions.assertEquals(hideaway.getParent(), mntPoint.getParent());
+ Assertions.assertTrue(hideaway.getFileName().toString().contains(mntPoint.getFileName().toString()));
+ }
+
+ @Test
+ @DisplayName("PARENT_NO_MOUNTPOINT preparations succeeds, if only mountpoint is present")
+ public void testPrepareParentNoMountpointOnlyMountpoint(@TempDir Path tmpDir) throws IOException {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ Files.createDirectory(mntPoint);
+
+ //execute
+ Assertions.assertDoesNotThrow(() -> customMpc.prepareParentNoMountPoint(mntPoint));
+
+ //evaluate
+ Assertions.assertTrue(Files.notExists(mntPoint));
+
+ Path hideaway = customMpc.getHideaway(mntPoint);
+ Assertions.assertTrue(Files.exists(hideaway));
+
+ if(OS.WINDOWS.isCurrentOs()) {
+ Assertions.assertTrue((Boolean) Files.getAttribute(hideaway, "dos:hidden"));
+ }
+ }
+
+ @Test
+ @DisplayName("PARENT_NO_MOUNTPOINT preparations fail, if only non-empty mountpoint is present")
+ public void testPrepareParentNoMountpointOnlyNonEmptyMountpoint(@TempDir Path tmpDir) throws IOException {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ Files.createDirectory(mntPoint);
+ Files.createFile(mntPoint.resolve("foo"));
+
+ //execute
+ Assertions.assertThrows(InvalidMountPointException.class, () -> customMpc.prepareParentNoMountPoint(mntPoint));
+
+ //evaluate
+ Assertions.assertTrue(Files.exists(mntPoint.resolve("foo")));
+ }
+
+ @Test
+ @DisplayName("PARENT_NO_MOUNTPOINT preparation succeeds, if for any reason only hideaway dir is present")
+ public void testPrepareParentNoMountpointOnlyHideaway(@TempDir Path tmpDir) throws IOException {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ var hideaway = customMpc.getHideaway(mntPoint);
+ Files.createDirectory(hideaway); //we explicitly do not set the file attributes here
+
+ //execute
+ Assertions.assertDoesNotThrow(() -> customMpc.prepareParentNoMountPoint(mntPoint));
+
+ //evaluate
+ Assertions.assertTrue(Files.exists(hideaway));
+
+ if(OS.WINDOWS.isCurrentOs()) {
+ Assertions.assertTrue((Boolean) Files.getAttribute(hideaway, "dos:hidden"));
+ }
+ }
+
+ @Test
+ @DisplayName("PARENT_NO_MOUNTPOINT preparation fails, if mountpoint and hideaway dirs are present")
+ public void testPrepareParentNoMountpointMountPointAndHideaway(@TempDir Path tmpDir) throws IOException {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ var hideaway = customMpc.getHideaway(mntPoint);
+ Files.createDirectory(hideaway); //we explicitly do not set the file attributes here
+ Files.createDirectory(mntPoint);
+
+ //execute
+ Assertions.assertThrows(InvalidMountPointException.class, () -> customMpc.prepareParentNoMountPoint(mntPoint));
+
+ //evaluate
+ Assertions.assertTrue(Files.exists(hideaway));
+ Assertions.assertTrue(Files.exists(mntPoint));
+
+ if(OS.WINDOWS.isCurrentOs()) {
+ Assertions.assertFalse((Boolean) Files.getAttribute(hideaway, "dos:hidden"));
+ }
+ }
+
+ @Test
+ @DisplayName("PARENT_NO_MOUNTPOINT preparation fails, if neither mountpoint nor hideaway dir is present")
+ public void testPrepareParentNoMountpointNothing(@TempDir Path tmpDir) {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ var hideaway = customMpc.getHideaway(mntPoint);
+
+ //execute
+ Assertions.assertThrows(InvalidMountPointException.class, () -> customMpc.prepareParentNoMountPoint(mntPoint));
+
+ //evaluate
+ Assertions.assertTrue(Files.notExists(hideaway));
+ Assertions.assertTrue(Files.notExists(mntPoint));
+ }
+
+ @Test
+ @DisplayName("Normal Cleanup for PARENT_NO_MOUNTPOINT")
+ public void testCleanupSuccess(@TempDir Path tmpDir) throws IOException {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ var hideaway = customMpc.getHideaway(mntPoint);
+
+ Files.createDirectory(hideaway);
+ Mockito.when(volume.getMountPointRequirement()).thenReturn(MountPointRequirement.PARENT_NO_MOUNT_POINT);
+
+ //execute
+ Assertions.assertDoesNotThrow(() -> customMpc.cleanup(volume, mntPoint));
+
+ //evaluate
+ Assertions.assertTrue(Files.exists(mntPoint));
+ Assertions.assertTrue(Files.notExists(hideaway));
+
+ if(OS.WINDOWS.isCurrentOs()) {
+ Assertions.assertFalse((Boolean) Files.getAttribute(mntPoint, "dos:hidden"));
+ }
+ }
+
+ @Test
+ @DisplayName("On IOException cleanup for PARENT_NO_MOUNTPOINT exits normally")
+ public void testCleanupIOFailure(@TempDir Path tmpDir) throws IOException {
+ //prepare
+ var mntPoint = tmpDir.resolve("mntPoint");
+ var hideaway = customMpc.getHideaway(mntPoint);
+
+ Files.createDirectory(hideaway);
+ Mockito.when(volume.getMountPointRequirement()).thenReturn(MountPointRequirement.PARENT_NO_MOUNT_POINT);
+ try (MockedStatic filesMock = Mockito.mockStatic(Files.class)) {
+ filesMock.when(() -> Files.move(Mockito.any(), Mockito.any(), Mockito.any())).thenThrow(new IOException("error"));
+ //execute
+ Assertions.assertDoesNotThrow(() -> customMpc.cleanup(volume, mntPoint));
+ }
+ }
+
+ }
+
+
+}
diff --git a/suppression.xml b/suppression.xml
index c747f92a7..ccd1a1cdf 100644
--- a/suppression.xml
+++ b/suppression.xml
@@ -25,4 +25,23 @@
org.eclipse.jetty.toolchain:jetty-servlet-api:4.0.6
.*
+
+
+
+ ^org\.cryptomator:.*$
+ cpe:/a:cryptomator:cryptomator
+ CVE-2022-25366
+
+
+
+
+ ^commons\-cli:commons\-cli:.*$
+ cpe:/a:apache:james
+
+ cpe:/a:spirit-project:spirit
+
\ No newline at end of file