Compare commits

..
Author SHA1 Message Date
JaniruTEC 2bad933c85 First prototype: Moved logic of "getCiphertextPath"
Moved logic of "getCiphertextPath" from Vault to VaultState
2023-07-21 17:09:07 +02:00
249 changed files with 2225 additions and 10198 deletions
+1 -3
View File
@@ -26,7 +26,6 @@ body:
Examples: Examples:
- Operating System: Windows 10 - Operating System: Windows 10
- Cryptomator: 1.5.16 - Cryptomator: 1.5.16
- OneDrive: 23.226
- LibreOffice: 7.1.4 - LibreOffice: 7.1.4
value: | value: |
- Operating System: - Operating System:
@@ -44,7 +43,6 @@ body:
- WinFsp (Local Drive) - WinFsp (Local Drive)
- FUSE-T - FUSE-T
- macFUSE - macFUSE
- FUSE
- WebDAV (Windows Explorer) - WebDAV (Windows Explorer)
- WebDAV (AppleScript) - WebDAV (AppleScript)
- WebDAV (gio) - WebDAV (gio)
@@ -97,4 +95,4 @@ body:
id: further-info id: further-info
attributes: attributes:
label: Anything else? label: Anything else?
description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue? description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue?
-54
View File
@@ -1,54 +0,0 @@
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "Etc/UTC"
ignore:
- dependency-name: "org.cryptomator:integrations-api"
versions: ["2.0.0-alpha1"]
groups:
java-test-dependencies:
patterns:
- "org.junit.jupiter:*"
- "org.mockito:*"
- "org.hamcrest:*"
- "com.google.jimfs:jimfs"
maven-build-plugins:
patterns:
- "org.apache.maven.plugins:*"
- "org.jacoco:jacoco-maven-plugin"
- "org.owasp:dependency-check-maven"
- "me.fabriciorby:maven-surefire-junit5-tree-reporter"
- "org.codehaus.mojo:license-maven-plugin"
javafx:
patterns:
- "org.openjfx:*"
java-production-dependencies:
patterns:
- "*"
exclude-patterns:
- "org.openjfx:*"
- "org.apache.maven.plugins:*"
- "org.jacoco:jacoco-maven-plugin"
- "org.owasp:dependency-check-maven"
- "me.fabriciorby:maven-surefire-junit5-tree-reporter"
- "org.codehaus.mojo:license-maven-plugin"
- "org.junit.jupiter:*"
- "org.mockito:*"
- "org.hamcrest:*"
- "com.google.jimfs:jimfs"
- package-ecosystem: "github-actions"
directory: "/" # even for `.github/workflows`
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
- "*"
labels:
- "misc:ci"
+32 -58
View File
@@ -10,8 +10,7 @@ on:
required: false required: false
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: '22.0.2+9'
jobs: jobs:
get-version: get-version:
@@ -21,71 +20,51 @@ jobs:
build: build:
name: Build AppImage name: Build AppImage
runs-on: ${{ matrix.os }} runs-on: ubuntu-latest
needs: [get-version] needs: [get-version]
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: 'd44bff3b94d5668fdee18a938d7b1269026d663d44765f02d29a9bdfd3fa1eb0'
- os: [self-hosted, Linux, ARM64]
appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: '3d5457136690c4f5bb9522d38b45218e045bdac13c24aa4c808c7c8d17d039c7'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: 'zulu'
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
check-latest: true java-package: 'jdk+fx'
cache: 'maven' cache: 'maven'
- name: Ensure major jfx version in pom equals in jdk
- name: Download OpenJFX jmods shell: pwsh
id: download-jmods
run: | run: |
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip $jfxPomVersion = (&mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) -split "\."
echo "${{ matrix.openjfx-sha }} openjfx-jmods.zip" | shasum -a256 --check $jfxJdkVersion = ((Get-Content -path "${env:JAVA_HOME}/lib/javafx.properties" | Where-Object {$_ -like 'javafx.version=*' }) -replace '.*=','') -split "\."
mkdir -p openjfx-jmods if ($jfxPomVersion[0] -ne $jfxJdkVersion[0]) {
unzip -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods Write-Error "Major part of JavaFX version in pom($($jfxPomVersion[0])) does not match the version in JDK($($jfxJdkVersion[0])) "
- name: Ensure major jfx version in pom and in jmods is the same
run: |
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION_AMD64 ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})"
exit 1 exit 1
fi }
- name: Set version - name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven - name: Run maven
run: mvn -B clean package -Plinux -DskipTests -Djavafx.platform=linux run: mvn -B clean package -Pdependency-check,linux -DskipTests
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here appimage)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" --module-path "${JAVA_HOME}/jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
--no-man-pages --no-man-pages
--strip-debug --strip-debug
--compress zip-0 --compress=1
- name: Prepare additional launcher
run: envsubst '${SEMVER_STR} ${REVISION_NUM}' < dist/linux/launcher-gtk2.properties > launcher-gtk2.properties
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
REVISION_NUM: ${{ needs.get-version.outputs.revNum }}
- name: Run jpackage - name: Run jpackage
run: > run: >
${JAVA_HOME}/bin/jpackage ${JAVA_HOME}/bin/jpackage
@@ -98,10 +77,10 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH" --copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" --java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
@@ -113,8 +92,7 @@ jobs:
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true" --java-options "-Dcryptomator.showTrayIcon=false"
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
--java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.get-version.outputs.revNum }}\"" --java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.get-version.outputs.revNum }}\""
--add-launcher Cryptomator-gtk2=launcher-gtk2.properties --add-launcher Cryptomator-gtk2=launcher-gtk2.properties
--resource-dir dist/linux/resources --resource-dir dist/linux/resources
@@ -125,10 +103,6 @@ jobs:
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.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.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.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
cp dist/linux/common/org.cryptomator.Cryptomator.tray.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray.svg
cp dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray-unlocked.svg
cp dist/linux/common/org.cryptomator.Cryptomator.tray.svg Cryptomator.AppDir/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg
cp dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg Cryptomator.AppDir/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.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.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/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 cp dist/linux/common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.xml
@@ -139,7 +113,7 @@ jobs:
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
- name: Download AppImageKit - name: Download AppImageKit
run: | run: |
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-${{ matrix.appimage-suffix }}.AppImage -o appimagetool.AppImage curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o appimagetool.AppImage
chmod +x appimagetool.AppImage chmod +x appimagetool.AppImage
./appimagetool.AppImage --appimage-extract ./appimagetool.AppImage --appimage-extract
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235 - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
@@ -151,25 +125,25 @@ jobs:
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Build AppImage - name: Build AppImage
run: > run: >
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.appimage-suffix }}.AppImage ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.get-version.outputs.semVerStr }}-x86_64.AppImage
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.appimage-suffix }}.AppImage.zsync' -u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
--sign --sign-key=615D449FE6E6A235 --sign-args="--batch --pinentry-mode loopback" --sign --sign-key=615D449FE6E6A235 --sign-args="--batch --pinentry-mode loopback"
- name: Create detached GPG signatures - name: Create detached GPG signatures
run: | 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
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: appimage-${{ matrix.appimage-suffix }} name: appimage
path: | path: |
cryptomator-*.AppImage cryptomator-*.AppImage
cryptomator-*.AppImage.zsync cryptomator-*.AppImage.zsync
cryptomator-*.asc cryptomator-*.asc
if-no-files-found: error if-no-files-found: error
- name: Publish AppImage on GitHub Releases - name: Publish AppImage on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
fail_on_unmatched_files: true fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
-40
View File
@@ -1,40 +0,0 @@
name: AntiVirus Whitelisting
on:
workflow_call:
inputs:
url:
description: "Url to the file to upload"
required: true
type: string
workflow_dispatch:
inputs:
url:
description: "Url to the file to upload"
required: true
type: string
jobs:
allowlist:
name: Anti Virus Allowlisting
runs-on: ubuntu-latest
steps:
- name: Download file
run: |
curl --remote-name ${{ inputs.url }} -L
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
port: 990
username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
- name: Upload to Avast
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
protocol: ftp
server: whitelisting.avast.com
port: 21
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
+8 -9
View File
@@ -6,8 +6,7 @@ on:
types: [labeled] types: [labeled]
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: 22
defaults: defaults:
run: run:
@@ -18,14 +17,14 @@ jobs:
name: Compile and Test name: Compile and Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: actions/setup-java@v4 - uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: 'zulu'
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
cache: 'maven' cache: 'maven'
- name: Cache SonarCloud packages - name: Cache SonarCloud packages
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: ~/.sonar/cache path: ~/.sonar/cache
key: ${{ runner.os }}-sonar key: ${{ runner.os }}-sonar
@@ -33,10 +32,10 @@ jobs:
- name: Build and Test - name: Build and Test
run: > run: >
xvfb-run xvfb-run
mvn -B verify -Djavafx.platform=linux mvn -B verify
jacoco:report jacoco:report
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
-Pcoverage -Pcoverage,dependency-check
-Dsonar.projectKey=cryptomator_cryptomator -Dsonar.projectKey=cryptomator_cryptomator
-Dsonar.organization=cryptomator -Dsonar.organization=cryptomator
-Dsonar.host.url=https://sonarcloud.io -Dsonar.host.url=https://sonarcloud.io
@@ -45,7 +44,7 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Draft a release - name: Draft a release
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
draft: true draft: true
discussion_category_name: releases discussion_category_name: releases
-64
View File
@@ -1,64 +0,0 @@
name: Checks JDK version for minor updates
on:
schedule:
- cron: '0 0 1 * *' # run once a month at the first day of month
env:
JDK_VERSION: '22.0.1+8'
JDK_VENDOR: zulu
jobs:
jdk-current:
name: Check out current version
runs-on: ubuntu-latest
outputs:
jdk-date: ${{ steps.get-data.outputs.jdk-date}}
steps:
- uses: actions/setup-java@v4
with:
java-version: ${{ env.JDK_VERSION }}
distribution: ${{ env.JDK_VENDOR }}
check-latest: false
- name: Read JAVA_VERSION_DATE and store in env variable
id: get-data
run: |
date=$(cat ${JAVA_HOME}/release | grep "JAVA_VERSION_DATE=\"" | awk -F'=' '{print $2}' | tr -d '"')
echo "jdk-date=${date}" >> "$GITHUB_OUTPUT"
jdk-latest:
name: Checkout latest jdk version
runs-on: ubuntu-latest
outputs:
jdk-date: ${{ steps.get-data.outputs.jdk-date}}
jdk-version: ${{ steps.get-data.outputs.jdk-version}}
steps:
- uses: actions/setup-java@v4
with:
java-version: 21
distribution: ${{ env.JDK_VENDOR }}
check-latest: true
- name: Read JAVA_VERSION_DATE and store in env variable
id: get-data
run: |
date=$(cat ${JAVA_HOME}/release | grep "JAVA_VERSION_DATE=\"" | awk -F'=' '{print $2}' | tr -d '"')
echo "jdk-date=${date}" >> "$GITHUB_OUTPUT"
version=$(cat ${JAVA_HOME}/release | grep "JAVA_RUNTIME_VERSION=\"" | awk -F'=' '{print $2}' | tr -d '"')
echo "jdk-version=${version}" >> "$GITHUB_OUTPUT"
notify:
name: Notifies for jdk update
runs-on: ubuntu-latest
needs: [jdk-current, jdk-latest]
if: ${{ needs.jdk-latest.outputs.jdk-date }} > ${{ needs.jdk-current.outputs.jdk-date }}
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "JDK update available"
SLACK_MESSAGE: "Cryptomator-CI JDK can be upgraded to ${{ needs.jdk-latest.outputs.jdk-version }}. See https://github.com/cryptomator/cryptomator/wiki/How-to-update-the-build-JDK for instructions."
SLACK_FOOTER: false
MSG_MINIMAL: true
+13 -21
View File
@@ -16,21 +16,16 @@ on:
type: boolean type: boolean
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: '22.0.2+9' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-x64_bin-jmods.zip'
COFFEELIBS_JDK: 22 OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-aarch64_bin-jmods.zip'
COFFEELIBS_JDK_VERSION: '22.0.2+9-0ppa1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'd44bff3b94d5668fdee18a938d7b1269026d663d44765f02d29a9bdfd3fa1eb0'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '3d5457136690c4f5bb9522d38b45218e045bdac13c24aa4c808c7c8d17d039c7'
jobs: jobs:
build: build:
name: Build Debian Package name: Build Debian Package
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- id: versions - id: versions
name: Get version information name: Get version information
run: | run: |
@@ -44,25 +39,22 @@ jobs:
run: | run: |
sudo add-apt-repository ppa:coffeelibs/openjdk sudo add-apt-repository ppa:coffeelibs/openjdk
sudo apt-get update sudo apt-get update
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.COFFEELIBS_JDK }}=${{ env.COFFEELIBS_JDK_VERSION }} sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.JAVA_VERSION }} libgtk2.0-0
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: 'zulu'
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
check-latest: true
cache: 'maven' cache: 'maven'
- name: Run maven - name: Run maven
run: mvn -B clean package -Plinux -Djavafx.platform=linux -DskipTests run: mvn -B clean package -Pdependency-check,linux -DskipTests
- name: Download OpenJFX jmods - name: Download OpenJFX jmods
id: download-jmods id: download-jmods
run: | run: |
curl -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip curl -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip
echo "${{ env.OPENJFX_JMODS_AMD64_HASH }} openjfx-amd64.zip" | shasum -a256 --check
mkdir -p jmods/amd64 mkdir -p jmods/amd64
unzip -j openjfx-amd64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/amd64 unzip -j openjfx-amd64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/amd64
curl -L ${{ env.OPENJFX_JMODS_AARCH64 }} -o openjfx-aarch64.zip curl -L ${{ env.OPENJFX_JMODS_AARCH64 }} -o openjfx-aarch64.zip
echo "${{ env.OPENJFX_JMODS_AARCH64_HASH }} openjfx-aarch64.zip" | shasum -a256 --check
mkdir -p jmods/aarch64 mkdir -p jmods/aarch64
unzip -j openjfx-aarch64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/aarch64 unzip -j openjfx-aarch64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/aarch64
- name: Ensure major jfx version in pom and in jmods is the same - name: Ensure major jfx version in pom and in jmods is the same
@@ -99,8 +91,7 @@ jobs:
run: | run: |
cp -r dist/linux/debian/ pkgdir cp -r dist/linux/debian/ pkgdir
export RFC2822_TIMESTAMP=`date --rfc-2822` export RFC2822_TIMESTAMP=`date --rfc-2822`
export DISABLE_UPDATE_CHECK=${{ inputs.dput }} envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM}' < dist/linux/debian/rules > pkgdir/debian/rules
envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM} ${DISABLE_UPDATE_CHECK}' < dist/linux/debian/rules > pkgdir/debian/rules
envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog
find . -name "*.jar" >> pkgdir/debian/source/include-binaries find . -name "*.jar" >> pkgdir/debian/source/include-binaries
mv pkgdir cryptomator_${{ inputs.ppaver }} mv pkgdir cryptomator_${{ inputs.ppaver }}
@@ -128,7 +119,7 @@ jobs:
run: | run: |
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: linux-deb-package name: linux-deb-package
path: | path: |
@@ -142,11 +133,12 @@ jobs:
- name: Publish on PPA - name: Publish on PPA
if: inputs.dput if: inputs.dput
run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes
# If ref is a tag, also upload to GitHub Releases: # If ref is a tag, also upload to GitHub Releases:
- name: Publish Debian package on GitHub Releases - name: Publish Debian package on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && inputs.dput if: startsWith(github.ref, 'refs/tags/')
env: env:
GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
run: | run: |
artifacts=$(ls | grep cryptomator*.deb) artifacts=$(ls | grep cryptomator*.deb)
gh release upload ${{ github.ref_name }} $artifacts gh release upload ${{ github.ref_name }} $artifacts
-18
View File
@@ -1,18 +0,0 @@
name: OWASP Maven Dependency Check
on:
schedule:
- cron: '0 8 * * 0'
workflow_dispatch:
jobs:
check-dependencies:
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@v1
with:
runner-os: 'ubuntu-latest'
java-distribution: 'temurin'
java-version: 22
check-command: 'mvn -B validate -Pdependency-check -Djavafx.platform=linux'
secrets:
nvd-api-key: ${{ secrets.NVD_API_KEY }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
steps: steps:
- name: Get download count of latest releases - name: Get download count of latest releases
id: get-stats id: get-stats
uses: actions/github-script@v7 uses: actions/github-script@v6
with: with:
script: | script: |
const query = `query($owner:String!, $name:String!) { const query = `query($owner:String!, $name:String!) {
+4 -10
View File
@@ -2,7 +2,7 @@ name: Update Error Database
on: on:
discussion: discussion:
types: [created, edited, deleted, category_changed, answered, unanswered] types: [created, edited, category_changed, answered, unanswered]
discussion_comment: discussion_comment:
types: [created, edited, deleted] types: [created, edited, deleted]
@@ -12,9 +12,8 @@ jobs:
if: github.event.discussion.category.name == 'Errors' if: github.event.discussion.category.name == 'Errors'
steps: steps:
- name: Query Discussion Data - name: Query Discussion Data
if: github.event_name == 'discussion_comment' || github.event_name == 'discussion' && github.event.action != 'deleted'
id: query-data id: query-data
uses: actions/github-script@v7 uses: actions/github-script@v6
with: with:
script: | script: |
const query = `query ($owner: String!, $name: String!, $discussionNumber: Int!) { const query = `query ($owner: String!, $name: String!, $discussionNumber: Int!) {
@@ -48,13 +47,8 @@ jobs:
- name: Merge Error Code Data - name: Merge Error Code Data
run: | run: |
jq -c '.' ${{ steps.get-gist.outputs.file }} > original.json jq -c '.' ${{ steps.get-gist.outputs.file }} > original.json
if [ ! -z "$DISCUSSION" ] echo $DISCUSSION | jq -c '.repository.discussion | .comments = .comments.totalCount | {(.id|tostring) : .}' > new.json
then jq -s '.[0] * .[1]' original.json new.json > merged.json
echo $DISCUSSION | jq -c '.repository.discussion | .comments = .comments.totalCount | {(.id|tostring) : .}' > new.json
jq -s '.[0] * .[1]' original.json new.json > merged.json
else
cat original.json | jq 'del(.[] | select(.url=="https://github.com/cryptomator/cryptomator/discussions/${{ github.event.discussion.number }}"))' > merged.json
fi
env: env:
DISCUSSION: ${{ steps.query-data.outputs.result }} DISCUSSION: ${{ steps.query-data.outputs.result }}
- name: Patch Gist - name: Patch Gist
-88
View File
@@ -1,88 +0,0 @@
name: Create PR for flathub
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag'
required: true
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.tag }}
tarball:
name: Determines tarball url and compute checksum
runs-on: ubuntu-latest
needs: [get-version]
if: github.event_name == 'workflow_dispatch' || needs.get-version.outputs.versionType == 'stable'
outputs:
url: ${{ steps.url.outputs.url}}
sha512: ${{ steps.sha512.outputs.sha512}}
steps:
- name: Determine tarball url
id: url
run: |
URL="";
if [[ -n "${{ inputs.tag }}" ]]; then
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ inputs.tag }}.tar.gz"
else
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz"
fi
echo "url=${URL}" >> "$GITHUB_OUTPUT"
- name: Download source tarball and compute checksum
id: sha512
run: |
curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
echo "sha512=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
flathub:
name: Create PR for flathub
runs-on: ubuntu-latest
needs: [tarball, get-version]
env:
FLATHUB_PR_URL: tbd
steps:
- uses: actions/checkout@v4
with:
repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
- name: Update build file
run: |
sed -i -e 's/VERSION: [0-9]\+\.[0-9]\+\.[0-9]\+.*/VERSION: ${{ needs.get-version.outputs.semVerStr }}/g' org.cryptomator.Cryptomator.yaml
sed -i -e 's/sha512: [0-9A-Za-z_\+-]\{128\} #CRYPTOMATOR/sha512: ${{ needs.tarball.outputs.sha512 }} #CRYPTOMATOR/g' org.cryptomator.Cryptomator.yaml
sed -i -e 's;url: https://github.com/cryptomator/cryptomator/archive/refs/tags/[^[:blank:]]\+;url: ${{ needs.tarball.outputs.url }};g' org.cryptomator.Cryptomator.yaml
- name: Commit and push
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
git config push.autoSetupRemote true
git stage .
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
git push
- name: Create pull request
run: |
printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update maven dependencies\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
if: github.event_name == 'release'
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "Flathub release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
SLACK_MESSAGE: "See <${{ env.FLATHUB_PR_URL }}|PR> on how to proceed.>."
SLACK_FOOTER: false
MSG_MINIMAL: true
+9 -8
View File
@@ -22,8 +22,9 @@ on:
value: ${{ jobs.determine-version.outputs.type }} value: ${{ jobs.determine-version.outputs.type }}
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: 22 JAVA_DIST: 'temurin'
JAVA_CACHE: 'maven'
jobs: jobs:
determine-version: determine-version:
@@ -35,22 +36,22 @@ jobs:
revNum: ${{ steps.versions.outputs.revNum }} revNum: ${{ steps.versions.outputs.revNum }}
type: ${{ steps.versions.outputs.type}} type: ${{ steps.versions.outputs.type}}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
cache: 'maven' cache: ${{ env.JAVA_CACHE }}
- id: versions - id: versions
name: Get version information name: Get version information
run: | run: |
if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
SEM_VER_STR=${GITHUB_REF##*/} SEM_VER_STR=${GITHUB_REF##*/}
elif [[ "${{ inputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+.* ]]; then elif [[ "${{ inputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+.* ]]; then
SEM_VER_STR="${{ inputs.version }}" SEM_VER_STR="${{ github.event.inputs.version }}"
else else
SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout` SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
fi fi
@@ -71,6 +72,6 @@ jobs:
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
echo "type=${TYPE}" >> $GITHUB_OUTPUT echo "type=${TYPE}" >> $GITHUB_OUTPUT
- name: Validate Version - name: Validate Version
uses: skymatic/semver-validation-action@v3 uses: skymatic/semver-validation-action@v2
with: with:
version: ${{ steps.versions.outputs.semVerStr }} version: ${{ steps.versions.outputs.semVerStr }}
+27 -54
View File
@@ -8,15 +8,9 @@ on:
version: version:
description: 'Version' description: 'Version'
required: false required: false
notarize:
description: 'Notarize'
required: true
default: false
type: boolean
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: '22.0.2+9'
jobs: jobs:
get-version: get-version:
@@ -32,71 +26,56 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: macos-12 - os: macos-11
architecture: x64 architecture: x64
output-suffix: x64 output-suffix: x64
xcode-path: '/Applications/Xcode_13.2.1.app' xcode-path: '/Applications/Xcode_13.2.1.app'
fuse-lib: macFUSE fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '115cb08bb59d880cfff6e51e0bf0dcc45785ed9d456b8b8425597b04da6ab3d4'
- os: [self-hosted, macOS, ARM64] - os: [self-hosted, macOS, ARM64]
architecture: aarch64 architecture: aarch64
output-suffix: arm64 output-suffix: arm64
xcode-path: '/Applications/Xcode_13.2.1.app' xcode-path: '/Applications/Xcode_13.2.1.app'
fuse-lib: FUSE-T fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: '813c6748f7c99cb7a579d48b48a087b4682b1fad1fc1a4fe5f9b21cf872b15a7'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: 'zulu'
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
java-package: 'jdk+fx'
architecture: ${{ matrix.architecture }} architecture: ${{ matrix.architecture }}
check-latest: true
cache: 'maven' cache: 'maven'
- name: Download OpenJFX jmods - name: Ensure major jfx version in pom equals in jdk
id: download-jmods if: ${{ !contains(matrix.os, 'self-hosted') }}
shell: pwsh
run: | run: |
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip $jfxPomVersion = (&mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) -split "\."
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check $jfxJdkVersion = ((Get-Content -path "${env:JAVA_HOME}/lib/javafx.properties" | Where-Object {$_ -like 'javafx.version=*' }) -replace '.*=','') -split "\."
mkdir -p openjfx-jmods/ if ($jfxPomVersion[0] -ne $jfxJdkVersion[0]) {
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods Write-Error "Major part of JavaFX version in pom($($jfxPomVersion[0])) does not match the version in JDK($($jfxJdkVersion[0])) "
- name: Ensure major jfx version in pom and in jmods is the same
run: |
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ "${POM_JFX_VERSION}" -ne "${JMOD_VERSION}" ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != jmod version (${JMOD_VERSION})"
exit 1 exit 1
fi }
- name: Set version - name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven - name: Run maven
run: mvn -B -Djavafx.platform=mac clean package -Pmac -DskipTests run: mvn -B clean package -Pdependency-check,mac -DskipTests
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here dmg)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" --module-path "${JAVA_HOME}/jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
--no-man-pages --no-man-pages
--strip-debug --strip-debug
--compress zip-0 --compress=1
- name: Run jpackage - name: Run jpackage
run: > run: >
${JAVA_HOME}/bin/jpackage ${JAVA_HOME}/bin/jpackage
@@ -109,7 +88,7 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH" --copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac" --java-options "--enable-native-access=org.cryptomator.jfuse.mac"
@@ -137,14 +116,12 @@ jobs:
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/ 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_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
env: env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }} VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }} REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Generate license for dmg - name: Generate license for dmg
run: > run: >
mvn -B -Djavafx.platform=mac license:add-third-party mvn -B license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf -Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources -Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl -Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
@@ -177,7 +154,7 @@ jobs:
run: | run: |
echo "Codesigning jdk files..." echo "Codesigning jdk files..."
find Cryptomator.app/Contents/runtime/Contents/Home/lib/ -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \; find Cryptomator.app/Contents/runtime/Contents/Home/lib/ -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
find Cryptomator.app/Contents/runtime/Contents/Home/lib/ \( -name 'jspawnhelper' -o -name 'pauseengine' -o -name 'simengine' \) -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \; find Cryptomator.app/Contents/runtime/Contents/Home/lib/ -name 'jspawnhelper' -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
echo "Codesigning jar contents..." echo "Codesigning jar contents..."
find Cryptomator.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \; 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 for JAR_PATH in `find Cryptomator.app -name "*.jar"`; do
@@ -196,12 +173,9 @@ jobs:
fi fi
done done
echo "Codesigning Cryptomator.app..." echo "Codesigning Cryptomator.app..."
sed -i '' "s|###APP_IDENTIFIER_PREFIX###|${TEAM_IDENTIFIER}.|g" dist/mac/Cryptomator.entitlements
sed -i '' "s|###TEAM_IDENTIFIER###|${TEAM_IDENTIFIER}|g" dist/mac/Cryptomator.entitlements
codesign --force --deep --entitlements dist/mac/Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app codesign --force --deep --entitlements dist/mac/Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app
env: env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }} CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
TEAM_IDENTIFIER: ${{ secrets.MACOS_TEAM_IDENTIFIER }}
- name: Prepare .dmg contents - name: Prepare .dmg contents
run: | run: |
mkdir dmg mkdir dmg
@@ -228,12 +202,13 @@ jobs:
--app-drop-link 512 245 --app-drop-link 512 245
--eula "dist/mac/dmg/resources/license.rtf" --eula "dist/mac/dmg/resources/license.rtf"
--icon ".background" 128 758 --icon ".background" 128 758
--icon ".fseventsd" 320 758
--icon ".VolumeIcon.icns" 512 758 --icon ".VolumeIcon.icns" 512 758
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env: env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }} VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
- name: Notarize .dmg - name: Notarize .dmg
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize if: startsWith(github.ref, 'refs/tags/')
uses: cocoalibs/xcode-notarization-action@v1 uses: cocoalibs/xcode-notarization-action@v1
with: with:
app-path: 'Cryptomator-*.dmg' app-path: 'Cryptomator-*.dmg'
@@ -255,16 +230,14 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true continue-on-error: true
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: dmg-${{ matrix.output-suffix }} name: dmg-${{ matrix.output-suffix }}
path: | path: Cryptomator-*.dmg
Cryptomator-*.dmg
Cryptomator-*.asc
if-no-files-found: error if-no-files-found: error
- name: Publish dmg on GitHub Releases - name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
fail_on_unmatched_files: true fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
issues: write issues: write
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v8
with: with:
days-before-stale: 14 days-before-stale: 14
days-before-close: 0 days-before-close: 0
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Publish asc on GitHub Releases - name: Publish asc on GitHub Releases
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
fail_on_unmatched_files: true fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
+5 -6
View File
@@ -4,8 +4,7 @@ on:
pull_request: pull_request:
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: 22
defaults: defaults:
run: run:
@@ -17,11 +16,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: actions/setup-java@v4 - uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: 'zulu'
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
cache: 'maven' cache: 'maven'
- name: Build and Test - name: Build and Test
run: xvfb-run mvn -B clean install jacoco:report -Pcoverage -Djavafx.platform=linux run: xvfb-run mvn -B clean install jacoco:report -Pcoverage,dependency-check
+7 -29
View File
@@ -6,26 +6,19 @@ on:
- 'release/**' - 'release/**'
- 'hotfix/**' - 'hotfix/**'
env:
JAVA_VERSION: 20
defaults: defaults:
run: run:
shell: bash shell: bash
env:
JAVA_DIST: 'zulu'
JAVA_VERSION: 22
jobs: jobs:
check-preconditions: release-check-precondition:
name: Validate commits pushed to release/hotfix branch to fulfill release requirements name: Validate commits pushed to release/hotfix branch to fulfill release requirements
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- id: validate-pom-version - id: validate-pom-version
name: Validate POM version name: Validate POM version
run: | run: |
@@ -44,22 +37,7 @@ jobs:
fi fi
- name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file - name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file
run: | run: |
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\">" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\"/>" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml" echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml"
exit 1 exit 1
fi fi
- name: Cache NVD DB
uses: actions/cache@v4
with:
path: ~/.m2/repository/org/owasp/dependency-check-data/
key: dependency-check-${{ github.run_id }}
restore-keys: |
dependency-check
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5
- name: Run org.owasp:dependency-check plugin
id: dependency-check
continue-on-error: true
run: mvn -B verify -Pdependency-check -DskipTests -Djavafx.platform=linux
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
issues: write issues: write
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v8
with: with:
days-before-stale: 365 days-before-stale: 365
days-before-close: 90 days-before-close: 90
+90 -131
View File
@@ -10,17 +10,15 @@ on:
required: false required: false
isDebug: isDebug:
description: 'Build debug version with console output' description: 'Build debug version with console output'
type: boolean type: boolean
default: false
env: env:
JAVA_DIST: 'zulu' JAVA_VERSION: 20
JAVA_VERSION: '22.0.2+9' JAVA_DIST: 'temurin'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/22.0.2/openjfx-22.0.2_windows-x64_bin-jmods.zip' JAVA_CACHE: 'maven'
OPENJFX_JMODS_AMD64_HASH: 'f9376d200f5c5b85327d575c1ec1482e6455f19916577f7e2fc9be2f48bb29b6' JFX_JMODS_URL: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_windows-x64_bin-jmods.zip'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi' JFX_JMODS_HASH: 'D00767334C43B8832B5CF10267D34CA8F563D187C4655B73EB6020DD79C054B5'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
defaults: defaults:
run: run:
@@ -40,23 +38,20 @@ jobs:
LOOPBACK_ALIAS: 'cryptomator-vault' LOOPBACK_ALIAS: 'cryptomator-vault'
WIN_CONSOLE_FLAG: '' WIN_CONSOLE_FLAG: ''
steps: steps:
- name: Upgrade WIX to latest version - uses: actions/checkout@v3
run: choco install wixtoolset --version 3.14.1
shell: pwsh
- uses: actions/checkout@v4
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
check-latest: true java-package: 'jdk'
cache: 'maven' cache: ${{ env.JAVA_CACHE }}
- name: Download and extract JavaFX jmods from Gluon - name: Download and extract JavaFX jmods from Gluon
#In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip #In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip
run: | run: |
curl --output jfxjmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}" curl --output jfxjmods.zip -L "${{ env.JFX_JMODS_URL }}"
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) { if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.equals("${{ env.JFX_JMODS_HASH }}")) {
throw "Wrong checksum of JMOD archive downloaded from ${{ env.OPENJFX_JMODS_AMD64 }}."; throw "Wrong checksum of JMOD archive downloaded from ${{ env.JFX_JMODS_URL }}.";
} }
Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent} Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
@@ -77,24 +72,23 @@ jobs:
- name: Set version - name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven - name: Run maven
run: mvn -B clean package -Pwin -DskipTests -Djavafx.platform=win run: mvn -B clean package -Pdependency-check,win -DskipTests
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here msi)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "jfxjmods;${JAVA_HOME}/jmods" --module-path "jfxjmods;${JAVA_HOME}/jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
--no-man-pages --no-man-pages
--strip-debug --strip-debug
--compress zip-0 --compress=1
- name: Change win-console flag if debug is active - name: Change win-console flag if debug is active
if: ${{ inputs.isDebug }} if: ${{ inputs.isDebug }}
run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV
@@ -110,10 +104,10 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH" --copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" --java-options "--enable-native-access=org.cryptomator.jfuse.win"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
@@ -150,56 +144,26 @@ jobs:
- name: Fix permissions - name: Fix permissions
run: attrib -r appdir/Cryptomator/Cryptomator.exe run: attrib -r appdir/Cryptomator/Cryptomator.exe
shell: pwsh shell: pwsh
- name: Extract jars with DLLs for Codesigning - name: Extract integrations DLL for code signing
shell: pwsh shell: pwsh
run: | run: gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --extract integrations.dll }
Add-Type -AssemblyName "System.io.compression.filesystem"
$jarFolder = Resolve-Path ".\appdir\Cryptomator\app\mods"
$jarExtractDir = New-Item -Path ".\appdir\jar-extract" -ItemType Directory
#for all jars inspect
Get-ChildItem -Path $jarFolder -Filter "*.jar" | ForEach-Object {
$jar = [Io.compression.zipfile]::OpenRead($_.FullName)
if (@($jar.Entries | Where-Object {$_.Name.ToString().EndsWith(".dll")} | Select-Object -First 1).Count -gt 0) {
#jars containing dlls extract
Set-Location $jarExtractDir
Expand-Archive -Path $_.FullName
}
$jar.Dispose()
}
- name: Extract wixhelper.dll for Codesigning #see https://github.com/cryptomator/cryptomator/issues/3130
shell: pwsh
run: |
New-Item -Path appdir/jpackage-jmod -ItemType Directory
& $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
- name: Codesign - name: Codesign
uses: skymatic/code-sign-action@v3 uses: skymatic/code-sign-action@v2
with: with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }} password: ${{ secrets.WIN_CODESIGN_P12_PW }}
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
description: Cryptomator description: Cryptomator
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: appdir folder: appdir/Cryptomator
recursive: true recursive: true
- name: Replace DLLs inside jars with signed ones - name: Repack signed DLL into jar
shell: pwsh shell: pwsh
run: | run: |
$jarExtractDir = Resolve-Path ".\appdir\jar-extract" gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --update integrations.dll; Remove-Item integrations.dll}
$jarFolder = Resolve-Path ".\appdir\Cryptomator\app\mods"
Get-ChildItem -Path $jarExtractDir | ForEach-Object {
$jarName = $_.Name
$jarFile = "${jarFolder}\${jarName}.jar"
Set-Location $_
Get-ChildItem -Path $_ -Recurse -File "*.dll" | ForEach-Object {
# update jar with signed dll
jar --file="$jarFile" --update $(Resolve-Path -Relative -Path $_)
}
}
- name: Generate license for MSI - name: Generate license for MSI
run: > run: >
mvn -B license:add-third-party "-Djavafx.platform=win" mvn -B license:add-third-party
"-Dlicense.thirdPartyFilename=license.rtf" "-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.outputDirectory=dist/win/resources" "-Dlicense.outputDirectory=dist/win/resources"
"-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl" "-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
@@ -218,21 +182,20 @@ jobs:
--dest installer --dest installer
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2024 Skymatic GmbH" --copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
--win-menu --win-menu
--win-dir-chooser --win-dir-chooser
--win-shortcut-prompt --win-shortcut-prompt
--win-update-url "https:\\cryptomator.org\downloads" --win-update-url "https:\\cryptomator.org"
--win-menu-group Cryptomator --win-menu-group Cryptomator
--resource-dir dist/win/resources --resource-dir dist/win/resources
--license-file dist/win/resources/license.rtf --license-file dist/win/resources/license.rtf
--file-associations dist/win/resources/FAvaultFile.properties --file-associations dist/win/resources/FAvaultFile.properties
env: env:
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
- name: Codesign MSI - name: Codesign MSI
uses: skymatic/code-sign-action@v3 uses: skymatic/code-sign-action@v2
with: with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }} password: ${{ secrets.WIN_CODESIGN_P12_PW }}
@@ -250,36 +213,44 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: msi name: msi
path: | path: |
Cryptomator-*.msi Cryptomator-*.msi
Cryptomator-*.asc Cryptomator-*.asc
if-no-files-found: error 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
build-exe: build-exe:
name: Build .exe installer name: Build .exe installer
runs-on: windows-latest runs-on: windows-latest
needs: [get-version, build-msi] needs: [get-version, build-msi]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Download .msi - name: Download .msi
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: msi name: msi
path: dist/win/bundle/resources path: dist/win/bundle/resources
- name: Strip version info from msi file name - name: Strip version info from msi file name
run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
- uses: actions/setup-java@v4 - uses: actions/setup-java@v3
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
check-latest: true cache: ${{ env.JAVA_CACHE }}
cache: 'maven'
- name: Generate license for exe - name: Generate license for exe
run: > run: >
mvn -B license:add-third-party "-Djavafx.platform=win" mvn -B license:add-third-party
"-Dlicense.thirdPartyFilename=license.rtf" "-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl" "-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
"-Dlicense.outputDirectory=dist/win/bundle/resources" "-Dlicense.outputDirectory=dist/win/bundle/resources"
@@ -290,11 +261,8 @@ jobs:
shell: pwsh shell: pwsh
- name: Download WinFsp - name: Download WinFsp
run: | run: |
curl --output dist/win/bundle/resources/winfsp.msi -L ${{ env.WINFSP_MSI }} $winfspUrl = (Select-String -Path ".\dist\win\bundle\resources\winFspMetaData.wxi" -Pattern '<\?define BundledWinFspDownloadLink="(.+)".*?>').Matches.Groups[1].Value
shell: pwsh curl --output dist/win/bundle/resources/winfsp.msi -L $winfspUrl
- name: Download Legacy-WinFsp uninstaller
run: |
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
shell: pwsh shell: pwsh
- name: Compile to wixObj file - name: Compile to wixObj file
run: > run: >
@@ -304,7 +272,7 @@ jobs:
-out dist/win/bundle/ -out dist/win/bundle/
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" -dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
-dBundleVendor="Skymatic GmbH" -dBundleVendor="Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2024 Skymatic GmbH" -dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
-dAboutUrl="https://cryptomator.org" -dAboutUrl="https://cryptomator.org"
-dHelpUrl="https://cryptomator.org/contact" -dHelpUrl="https://cryptomator.org/contact"
-dUpdateUrl="https://cryptomator.org/downloads/" -dUpdateUrl="https://cryptomator.org/downloads/"
@@ -320,7 +288,7 @@ jobs:
-ib installer/unsigned/Cryptomator-Installer.exe -ib installer/unsigned/Cryptomator-Installer.exe
-o tmp/engine.exe -o tmp/engine.exe
- name: Codesign burn engine - name: Codesign burn engine
uses: skymatic/code-sign-action@v3 uses: skymatic/code-sign-action@v2
with: with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }} password: ${{ secrets.WIN_CODESIGN_P12_PW }}
@@ -334,7 +302,7 @@ jobs:
-ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe -ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe
-o installer/Cryptomator-Installer.exe -o installer/Cryptomator-Installer.exe
- name: Codesign EXE - name: Codesign EXE
uses: skymatic/code-sign-action@v3 uses: skymatic/code-sign-action@v2
with: with:
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
password: ${{ secrets.WIN_CODESIGN_P12_PW }} password: ${{ secrets.WIN_CODESIGN_P12_PW }}
@@ -352,68 +320,59 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: exe name: exe
path: | path: |
Cryptomator-*.exe Cryptomator-*.exe
Cryptomator-*.asc Cryptomator-*.asc
if-no-files-found: error if-no-files-found: error
publish:
name: Publish installers to the github release
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
runs-on: ubuntu-latest
needs: [build-msi, build-exe]
outputs:
download-url-msi: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-exe: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }}
steps:
- name: Download installers
uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Publish .msi on GitHub Releases - name: Publish .msi on GitHub Releases
id: publish if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
with: with:
fail_on_unmatched_files: true fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
# do not change ordering of filelist, required for correct job output
files: | files: |
*.msi Cryptomator-*.exe
*.exe Cryptomator-*.asc
*.asc
allowlist-msi: allowlist:
uses: ./.github/workflows/av-whitelist.yml name: Anti Virus Allowlisting
needs: [publish] if: startsWith(github.ref, 'refs/tags/')
with:
url: ${{ needs.publish.outputs.download-url-msi }}
secrets: inherit
allowlist-exe:
uses: ./.github/workflows/av-whitelist.yml
needs: [publish]
with:
url: ${{ needs.publish.outputs.download-url-exe }}
secrets: inherit
notify-winget:
name: Notify for winget-release
if: needs.get-version.outputs.versionType == 'stable'
needs: [publish, get-version]
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build-msi, build-exe]
steps: steps:
- name: Slack Notification - name: Download .msi
uses: rtCamp/action-slack-notify@v2 uses: actions/download-artifact@v3
env: with:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} name: msi
SLACK_USERNAME: 'Cryptobot' path: msi
SLACK_ICON: false - name: Download .exe
SLACK_ICON_EMOJI: ':bot:' uses: actions/download-artifact@v3
SLACK_CHANNEL: 'cryptomator-desktop' with:
SLACK_TITLE: "MSI of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." name: exe
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml| release to winget>." path: exe
SLACK_FOOTER: false - name: Collect files
MSG_MINIMAL: true run: |
mkdir files
cp msi/*.msi files
cp exe/*.exe files
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@4.3.3
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
port: 990
username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
local-dir: files/
- name: Upload to Avast
uses: SamKirkland/FTP-Deploy-Action@4.3.0
with:
protocol: ftp
server: whitelisting.avast.com
port: 21
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
local-dir: files/
-27
View File
@@ -1,27 +0,0 @@
name: Publish MSI to winget-pkgs
on:
workflow_dispatch:
inputs:
tag:
description: 'Release tag'
required: true
jobs:
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Sync winget-pkgs fork
run: |
gh repo sync cryptomator/winget-pkgs -b master --force
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
- name: Submit package
uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: Cryptomator.Cryptomator
version: ${{ inputs.tag }}
release-tag: ${{ inputs.tag }}
installers-regex: '\.msi$'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+15 -12
View File
@@ -14,29 +14,32 @@
<option name="dagger.fastInit" value="enabled" /> <option name="dagger.fastInit" value="enabled" />
<option name="dagger.formatGeneratedSource" value="enabled" /> <option name="dagger.formatGeneratedSource" value="enabled" />
<processorPath useClasspath="false"> <processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.49/dagger-compiler-2.49.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.45/dagger-compiler-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.49/dagger-2.49.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.45/dagger-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" /> <entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.49/dagger-spi-2.49.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-producers/2.45/dagger-producers-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/1.9.20-1.0.14/symbol-processing-api-1.9.20-1.0.14.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.0/kotlin-stdlib-jdk8-1.9.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.20/kotlin-stdlib-1.9.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.0/kotlin-stdlib-jdk7-1.9.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar" /> <entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.7.1/error_prone_annotations-2.7.1.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.7.1/error_prone_annotations-2.7.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.45/dagger-spi-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/1.7.0-1.0.6/symbol-processing-api-1.7.0-1.0.6.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.7.0/kotlin-stdlib-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.0/kotlin-stdlib-common-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" /> <entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.0/kotlin-stdlib-jdk8-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.0/kotlin-stdlib-jdk7-1.7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" /> <entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" /> <entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-metadata-jvm/0.5.0/kotlinx-metadata-jvm-0.5.0.jar" />
</processorPath> </processorPath>
<module name="cryptomator" /> <module name="cryptomator" />
</profile> </profile>
+1 -1
View File
@@ -8,7 +8,7 @@
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" project-jdk-name="22" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_20_PREVIEW" project-jdk-name="20" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -5,7 +5,7 @@
</envs> </envs>
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" /> <option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+4 -3
View File
@@ -30,8 +30,9 @@ Cryptomator is provided free of charge as an open-source project despite the hig
<table> <table>
<tbody> <tbody>
<tr> <tr>
<td><a href="https://mowcapital.com/"><img src="https://cryptomator.org/img/sponsors/mowcapital.svg" alt="Mow Capital" height="28"></a></td> <td><a href="https://mowcapital.com/"><img src="https://cryptomator.org/img/sponsors/mowcapital.svg" alt="Mow Capital" height="40"></a></td>
<td><a href="https://www.route4me.com/"><img src="https://cryptomator.org/img/sponsors/route4me.svg" alt="Route4Me" height="56"></a></td> <td><a href="https://www.easeus.com/"><img src="https://cryptomator.org/img/sponsors/easeus.png" alt="EaseUS" height="40"></a></td>
<td><a href="https://www.hassmann-it-forensik.de/"><img src="https://cryptomator.org/img/sponsors/hassmannitforensik.png" alt="Hassmann IT-Forensik" height="40"></a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -84,7 +85,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies ### Dependencies
* JDK 22 (e.g. temurin, zulu) * JDK 19 (e.g. temurin)
* Maven 3 * Maven 3
### Run Maven ### Run Maven
+1 -3
View File
@@ -1,6 +1,4 @@
# downloaded/created during build # created during build
openjfx-jmods.zip
*.jmod
Cryptomator.AppDir Cryptomator.AppDir
*.AppImage *.AppImage
*.AppImage.zsync *.AppImage.zsync
+16 -51
View File
@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
set -e
cd $(dirname $0) cd $(dirname $0)
REVISION_NO=`git rev-list --count HEAD` REVISION_NO=`git rev-list --count HEAD`
@@ -8,62 +7,32 @@ REVISION_NO=`git rev-list --count HEAD`
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi 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 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; } command -v curl >/dev/null 2>&1 || { echo >&2 "curl not found."; exit 1; }
command -v unzip >/dev/null 2>&1 || { echo >&2 "unzip not found."; exit 1; }
VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout) VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
SEMVER_STR=${VERSION} SEMVER_STR=${VERSION}
CPU_ARCH=$(uname -p)
if [[ ! "${CPU_ARCH}" =~ x86_64|aarch64 ]]; then echo "Platform ${CPU_ARCH} not supported"; exit 1; fi
mvn -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR} mvn -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR}
# compile # compile
mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests -Djavafx.platform=linux mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
cp ../../../LICENSE.txt ../../../target cp ../../../LICENSE.txt ../../../target
cp ../launcher.sh ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods cp ../../../target/cryptomator-*.jar ../../../target/mods
JAVAFX_VERSION=22.0.2
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='d44bff3b94d5668fdee18a938d7b1269026d663d44765f02d29a9bdfd3fa1eb0'
if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='3d5457136690c4f5bb9522d38b45218e045bdac13c24aa4c808c7c8d17d039c7'
fi
# download javaFX jmods
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_linux-${JAVAFX_ARCH}_bin-jmods.zip"
curl -L ${JAVAFX_JMODS_URL} -o openjfx-jmods.zip
echo "${JAVAFX_JMODS_SHA256} openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods
unzip -o -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
JMOD_VERSION=$(jmod describe ./openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout -B -f ../../../pom.xml)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})"
exit 1
fi
# add runtime # add runtime
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--verbose \ --verbose \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" \ --module-path "${JAVA_HOME}/jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \ --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \ --strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
--strip-debug \ --strip-debug \
--compress zip-0 --compress=1
# create app dir # create app dir
envsubst '${SEMVER_STR} ${REVISION_NUM}' < ../launcher-gtk2.properties > launcher-gtk2.properties
${JAVA_HOME}/bin/jpackage \ ${JAVA_HOME}/bin/jpackage \
--verbose \ --verbose \
--type app-image \ --type app-image \
@@ -75,8 +44,8 @@ ${JAVA_HOME}/bin/jpackage \
--name Cryptomator \ --name Cryptomator \
--vendor "Skymatic GmbH" \ --vendor "Skymatic GmbH" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \ --java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \
--copyright "(C) 2016 - 2024 Skymatic GmbH" \ --copyright "(C) 2016 - 2023 Skymatic GmbH" \
--java-options "-Xss5m" \ --java-options "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--app-version "${VERSION}.${REVISION_NO}" \ --app-version "${VERSION}.${REVISION_NO}" \
@@ -88,9 +57,9 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \ --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \ --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \ --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \ --java-options "-Dcryptomator.showTrayIcon=false" \
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\"" \
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \ --java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
--add-launcher cryptomator-gtk2=launcher-gtk2.properties \
--resource-dir ../resources --resource-dir ../resources
# transform AppDir # transform AppDir
@@ -100,10 +69,6 @@ envsubst '${REVISION_NO}' < resources/AppDir/bin/cryptomator.sh > Cryptomator.Ap
cp ../common/org.cryptomator.Cryptomator256.png Cryptomator.AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png 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.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.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
cp ../common/org.cryptomator.Cryptomator.tray.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray.svg
cp ../common/org.cryptomator.Cryptomator.tray-unlocked.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray-unlocked.svg
cp ../common/org.cryptomator.Cryptomator.tray.svg Cryptomator.AppDir/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg
cp ../common/org.cryptomator.Cryptomator.tray-unlocked.svg Cryptomator.AppDir/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.svg
cp ../common/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop 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/org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.metainfo.xml
cp ../common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.xml cp ../common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.xml
@@ -114,17 +79,17 @@ ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.App
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
# load AppImageTool # load AppImageTool
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-${CPU_ARCH}.AppImage -o /tmp/appimagetool.AppImage curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o /tmp/appimagetool.AppImage
chmod +x /tmp/appimagetool.AppImage chmod +x /tmp/appimagetool.AppImage
# create AppImage # create AppImage
/tmp/appimagetool.AppImage \ /tmp/appimagetool.AppImage \
Cryptomator.AppDir \ Cryptomator.AppDir \
cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage \ cryptomator-${SEMVER_STR}-x86_64.AppImage \
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${CPU_ARCH}.AppImage.zsync' -u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
echo "" echo ""
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage" echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-x86_64.AppImage"
echo ""
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir runtime squashfs-root openjfx-jmods; rm /tmp/appimagetool.AppImage openjfx-jmods.zip"
echo "" echo ""
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir jni runtime squashfs-root; rm launcher-gtk2.properties /tmp/appimagetool.AppImage"
echo ""
+35 -123
View File
@@ -5,27 +5,26 @@
<metadata_license>FSFAP</metadata_license> <metadata_license>FSFAP</metadata_license>
<project_license>GPL-3.0-or-later</project_license> <project_license>GPL-3.0-or-later</project_license>
<name>Cryptomator</name> <name>Cryptomator</name>
<summary>Encryption made easy and optimized for the cloud</summary> <summary>Multi-platform client-side encryption tool optimized for cloud storages</summary>
<description> <description>
<p> <p>
Cryptomator provides easy-to-use, transparent, client-side encryption for your cloud. Cryptomator provides transparent, client-side encryption for your cloud. Protect your documents from unauthorized
It protects your documents from unauthorized access and prying eyes, while you will still be able to view and edit your documents locally. access. Cryptomator is free and open source software, so you can rest assured there are no backdoors.
By not requiring any registration or account and performing all encryption locally, it gives you back control over your data and ensures your privacy.
Cryptomator is offered for all major platforms (including Android and iOS).
</p> </p>
<p> <p>
Cryptomator encrypts file contents and names using the widespread industry standard AES. Cryptomator encrypts file contents and names using AES. Your passphrase is protected against bruteforcing attempts
Your passphrase is protected against brute forcing attempts using scrypt. using scrypt. Directory structures get obfuscated. The only thing which cannot be encrypted without breaking your
Additionally, directory structures get obfuscated. cloud synchronization is the modification date of your files.
For more info about the Cryptomator encryption scheme, check out the online documentation.
</p> </p>
<p> <p>
Cryptomator is a free and open-source software licensed under the GPLv3. Cryptomator is a free and open source software licensed under the GPLv3. This allows anyone to check our code. It
This allows anyone to check our code. is impossible to introduce backdoors for third parties. Also we cannot hide vulnerabilities. And the best thing
Thus, it is impossible to introduce backdoors for third parties or to hide vulnerabilities, so you do not need to trust Cryptomator. is: There is no need to trust us, as you can control us!
Also, vendor lock-ins are impossible. </p>
Even if we decided to stop development: The source code is already cloned by hundreds of other developers and development can be picked up by others. <p>
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.
</p> </p>
</description> </description>
@@ -43,7 +42,7 @@
</provides> </provides>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot>
<caption>Light theme</caption> <caption>Light theme</caption>
<image>https://user-images.githubusercontent.com/11858409/156986109-6e58f59c-8b8c-4501-b33b-bb1e33007cea.png</image> <image>https://user-images.githubusercontent.com/11858409/156986109-6e58f59c-8b8c-4501-b33b-bb1e33007cea.png</image>
</screenshot> </screenshot>
@@ -53,125 +52,38 @@
</screenshot> </screenshot>
</screenshots> </screenshots>
<branding>
<color type="primary" scheme_preference="light">#EBF5EB</color>
<color type="primary" scheme_preference="dark">#2F4858</color>
</branding>
<url type="homepage">https://cryptomator.org/</url> <url type="homepage">https://cryptomator.org/</url>
<url type="bugtracker">https://github.com/cryptomator/cryptomator/issues/</url> <url type="bugtracker">https://github.com/cryptomator/cryptomator/issues/</url>
<url type="donation">https://cryptomator.org/donate</url> <url type="donation">https://cryptomator.org/donate</url>
<url type="faq">https://community.cryptomator.org/c/kb/faq</url> <url type="faq">https://community.cryptomator.org/c/kb/faq</url>
<url type="help">https://docs.cryptomator.org/</url> <url type="help">https://community.cryptomator.org/</url>
<url type="translate">https://translate.cryptomator.org</url> <url type="translate">https://translate.cryptomator.org</url>
<developer id="de.skymatic"> <developer_name>Skymatic GmbH</developer_name>
<name>Skymatic GmbH</name>
</developer>
<content_rating type="oars-1.1"> <content_rating type="oars-1.1">
<content_attribute id="social-info">mild</content_attribute> <!-- update checker connects to https://api.cryptomator.org/updates/latestVersion.json --> <content_attribute id="social-info">mild</content_attribute> <!-- update checker connects to https://api.cryptomator.org/updates/latestVersion.json -->
</content_rating> </content_rating>
<releases> <releases>
<release date="2024-09-17" version="1.14.0"> <release date="2023-06-07" version="1.9.1"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.14.0</url> <release date="2023-05-30" version="1.9.0"/>
</release> <release date="2023-04-25" version="1.8.0"/>
<release date="2024-06-26" version="1.13.0"> <release date="2023-04-07" version="1.7.5"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.13.0</url> <release date="2023-04-05" version="1.7.4"/>
</release> <release date="2023-03-15" version="1.7.3"/>
<release date="2024-03-27" version="1.12.4"> <release date="2023-03-07" version="1.7.2"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.4</url> <release date="2023-03-03" version="1.7.1"/>
</release> <release date="2023-03-01" version="1.7.0"/>
<release date="2024-02-27" version="1.12.3"> <release date="2022-12-14" version="1.6.17"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.3</url> <release date="2022-12-06" version="1.6.16"/>
</release> <release date="2022-10-06" version="1.6.15"/>
<release date="2024-02-09" version="1.12.2"> <release date="2022-08-31" version="1.6.14"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.2</url> <release date="2022-07-27" version="1.6.12"/>
</release> <release date="2022-07-26" version="1.6.11"/>
<release date="2024-02-07" version="1.12.1"> <release date="2022-05-03" version="1.6.10"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.1</url> <release date="2022-04-27" version="1.6.9"/>
</release> <release date="2022-03-30" version="1.6.8"/>
<release date="2024-02-06" version="1.12.0"> <release date="2021-12-16" version="1.6.5"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.0</url>
</release>
<release date="2023-12-05" version="1.11.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.11.1</url>
</release>
<release date="2023-11-08" version="1.11.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.11.0</url>
</release>
<release date="2023-09-20" version="1.10.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.10.1</url>
</release>
<release date="2023-09-11" version="1.10.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.10.0</url>
</release>
<release date="2023-08-11" version="1.9.4">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.4</url>
</release>
<release date="2023-08-07" version="1.9.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.3</url>
</release>
<release date="2023-07-24" version="1.9.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.2</url>
</release>
<release date="2023-06-07" version="1.9.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.1</url>
</release>
<release date="2023-05-30" version="1.9.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.9.0</url>
</release>
<release date="2023-04-25" version="1.8.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.8.0</url>
</release>
<release date="2023-04-07" version="1.7.5">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.5</url>
</release>
<release date="2023-04-05" version="1.7.4">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.4</url>
</release>
<release date="2023-03-15" version="1.7.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.3</url>
</release>
<release date="2023-03-07" version="1.7.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.2</url>
</release>
<release date="2023-03-03" version="1.7.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.1</url>
</release>
<release date="2023-03-01" version="1.7.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.7.0</url>
</release>
<release date="2022-12-14" version="1.6.17">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.17</url>
</release>
<release date="2022-12-06" version="1.6.16">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.16</url>
</release>
<release date="2022-10-06" version="1.6.15">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.15</url>
</release>
<release date="2022-08-31" version="1.6.14">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.14</url>
</release>
<release date="2022-07-27" version="1.6.12">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.12</url>
</release>
<release date="2022-07-26" version="1.6.11">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.11</url>
</release>
<release date="2022-05-03" version="1.6.10">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.10</url>
</release>
<release date="2022-04-27" version="1.6.9">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.9</url>
</release>
<release date="2022-03-30" version="1.6.8">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.8</url>
</release>
<release date="2021-12-16" version="1.6.5">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.6.5</url>
</release>
</releases> </releases>
</component> </component>
@@ -1,12 +0,0 @@
<svg height="16" viewBox="0 0 42 42" width="16" xmlns="http://www.w3.org/2000/svg">
<style
id="current-color-scheme" type="text/css">
.ColorScheme-Text {
color:#232629;
}
</style>
<g fill-rule="evenodd" style="fill:#f2f2f2;fill-opacity:1" class="ColorScheme-Text" fill="currentColor">
<path d="m15.591 35.824c-.019.009-.936.775-1.458 1.208a.418.418 0 0 1 -.627-.111 9.322 9.322 0 0 1 -.3-5.974 15.843 15.843 0 0 0 2.894 2.043c.051 1.03-.161 2.644-.509 2.834zm6.409-6.824h-2l.5-5a2 2 0 1 1 1 0zm-14.544-3.241.744-1.366a1.579 1.579 0 0 0 -.019-1.557l.653-1.2c.2.014-.03-.113.165-.14.051-.217-.051-.336 0-.5a3.269 3.269 0 0 0 0-1.5 7.151 7.151 0 0 1 0-3 2.366 2.366 0 0 0 -2.378 1.448 2.409 2.409 0 0 0 .229 2.661l-.7 1.278a1.779 1.779 0 0 0 -1.317.891l-.741 1.372a1.577 1.577 0 0 0 -.019 1.487 3.028 3.028 0 0 0 -2.746 1.525 2.648 2.648 0 0 0 .044 2.631.748.748 0 0 0 .981.266.656.656 0 0 0 .284-.92 1.37 1.37 0 0 1 -.023-1.361 1.6 1.6 0 0 1 2.079-.63 1.408 1.408 0 0 1 .672 1.95 1.546 1.546 0 0 1 -1.2.78.688.688 0 0 0 -.636.749.707.707 0 0 0 .717.6.789.789 0 0 0 .082 0 2.989 2.989 0 0 0 2.322-1.513 2.669 2.669 0 0 0 -.377-3.084 1.767 1.767 0 0 0 1.184-.867zm13.544-10.759a13.013 13.013 0 0 1 5-1 21.6 21.6 0 0 1 4.5.5 9.312 9.312 0 0 0 -9.5-8.5c-5.794 0-9.176 4-9.5 8.5a21.858 21.858 0 0 1 4.5-.5 12.819 12.819 0 0 1 5 1zm3.5-5c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2zm-7 0c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2zm14.473 6a8.067 8.067 0 0 0 -8.08 8v2.141a3.891 3.891 0 0 0 -2.893 3.734v5.125a23.166 23.166 0 0 1 -4.174-1.623 7.857 7.857 0 0 1 -.027.878 3.263 3.263 0 0 1 -.729 2.074l-1.794 1.483a.379.379 0 0 1 -.276.188h-4c-1.324 0-2.346-1.336-2.653-3.343a7.058 7.058 0 0 1 .234-3.18 3.477 3.477 0 0 1 1.636-2.157 1.868 1.868 0 0 1 .783-.32h1.5a8.035 8.035 0 0 1 -1.5-5 11.1 11.1 0 0 1 .5-3 2.519 2.519 0 0 0 0-1.5 13.272 13.272 0 0 1 -.5-3.5c6.687-1.936 11 0 11 0s4.319-1.955 11 0"/>
<path d="m39 28h-10v-4a3.13 3.13 0 0 1 3-3 3.087 3.087 0 0 1 3 3v1a1.034 1.034 0 0 0 1 1h1a1.034 1.034 0 0 0 1-1v-1a6 6 0 0 0 -12 0v4h-1a2.073 2.073 0 0 0 -2 2v6a2.073 2.073 0 0 0 2 2h14a2.073 2.073 0 0 0 2-2v-6a2.073 2.073 0 0 0 -2-2zm-5.391 5.94a1.609 1.609 0 0 1 -3.217 0v-1.876a1.609 1.609 0 0 1 3.217 0z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@@ -1,8 +0,0 @@
<svg height="16" viewBox="0 0 42 42" width="16" xmlns="http://www.w3.org/2000/svg">
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text {
color:#232629;
}
</style>
<path d="m32.66 29.319a1.432 1.432 0 0 0 -.66-.319h-1.5a8.125 8.125 0 0 0 1.5-5 11.027 11.027 0 0 0 -.5-3 2.519 2.519 0 0 1 0-1.5 12.987 12.987 0 0 0 .5-3.5c-6.681-1.955-11 0-11 0s-4.313-1.936-11 0a13.272 13.272 0 0 0 .5 3.5 2.519 2.519 0 0 1 0 1.5 11.1 11.1 0 0 0 -.5 3 8.035 8.035 0 0 0 1.5 5h-1.5a1.868 1.868 0 0 0 -.783.319 3.477 3.477 0 0 0 -1.636 2.157 7.058 7.058 0 0 0 -.234 3.18c.307 2.008 1.329 3.344 2.653 3.344h4a.379.379 0 0 0 .277-.187l1.793-1.483a3.263 3.263 0 0 0 .729-2.074 7.857 7.857 0 0 0 .027-.878 23.166 23.166 0 0 0 4.174 1.622 24.4 24.4 0 0 0 4.051-1.614 7.848 7.848 0 0 0 .027.869 3.263 3.263 0 0 0 .729 2.074l1.793 1.484a.61.61 0 0 0 .4.187h4c1.324 0 2.223-1.336 2.529-3.343a7.057 7.057 0 0 0 -.234-3.18 3.477 3.477 0 0 0 -1.635-2.158zm-17.069 6.5c-.019.009-.936.775-1.458 1.208a.418.418 0 0 1 -.627-.111 9.322 9.322 0 0 1 -.3-5.974 15.843 15.843 0 0 0 2.894 2.048c.051 1.03-.161 2.644-.509 2.834zm6.409-6.819h-2l.5-5a2 2 0 1 1 1 0zm6.38 7.921a.418.418 0 0 1 -.627.111c-.522-.433-1.439-1.2-1.458-1.208-.348-.189-.56-1.8-.505-2.828a15.84 15.84 0 0 0 2.9-2.037 9.322 9.322 0 0 1 -.31 5.962zm-20.924-11.162.744-1.366a1.579 1.579 0 0 0 -.019-1.557l.653-1.2c.2.014-.03-.113.165-.14.051-.217-.051-.336 0-.5a3.269 3.269 0 0 0 0-1.5 7.151 7.151 0 0 1 0-3 2.366 2.366 0 0 0 -2.378 1.448 2.409 2.409 0 0 0 .229 2.661l-.7 1.278a1.779 1.779 0 0 0 -1.317.891l-.741 1.372a1.577 1.577 0 0 0 -.019 1.487 3.028 3.028 0 0 0 -2.746 1.525 2.648 2.648 0 0 0 .044 2.631.748.748 0 0 0 .981.266.656.656 0 0 0 .284-.92 1.37 1.37 0 0 1 -.023-1.361 1.6 1.6 0 0 1 2.079-.63 1.408 1.408 0 0 1 .672 1.95 1.546 1.546 0 0 1 -1.2.78.688.688 0 0 0 -.636.749.707.707 0 0 0 .717.6.789.789 0 0 0 .082 0 2.989 2.989 0 0 0 2.322-1.513 2.669 2.669 0 0 0 -.377-3.084 1.767 1.767 0 0 0 1.184-.867zm33.217 1.2a3.021 3.021 0 0 0 -2.658-1.525 1.574 1.574 0 0 0 -.107-1.283l-.745-1.367a1.779 1.779 0 0 0 -1.317-.891l-.7-1.278a2.409 2.409 0 0 0 .229-2.661 2.283 2.283 0 0 0 -2.375-1.454 7.039 7.039 0 0 1 0 3 3.272 3.272 0 0 0 0 1.5c.047.152-.047.3 0 .5.227.04-.069.156.165.14l.653 1.2a1.579 1.579 0 0 0 -.019 1.557l.745 1.367a1.753 1.753 0 0 0 1.045.832 2.66 2.66 0 0 0 -.238 2.916 2.989 2.989 0 0 0 2.326 1.509.79.79 0 0 0 .082 0 .707.707 0 0 0 .717-.6.688.688 0 0 0 -.636-.749 1.546 1.546 0 0 1 -1.2-.78 1.408 1.408 0 0 1 .672-1.95 1.628 1.628 0 0 1 1.179-.089 1.512 1.512 0 0 1 .9.719 1.37 1.37 0 0 1 -.023 1.361.656.656 0 0 0 .284.92.748.748 0 0 0 .981-.266 2.648 2.648 0 0 0 .04-2.633zm-19.673-11.959a13.013 13.013 0 0 1 5-1 21.6 21.6 0 0 1 4.5.5 9.312 9.312 0 0 0 -9.5-8.5c-5.794 0-9.176 4-9.5 8.5a21.858 21.858 0 0 1 4.5-.5 12.819 12.819 0 0 1 5 1zm3.5-5c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2zm-7 0c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2z" fill-rule="evenodd" style="fill:#f2f2f2;fill-opacity:1" class="ColorScheme-Text" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

+1 -1
View File
@@ -2,7 +2,7 @@ Source: cryptomator
Maintainer: Cryptobot <releases@cryptomator.org> Maintainer: Cryptobot <releases@cryptomator.org>
Section: utils Section: utils
Priority: optional Priority: optional
Build-Depends: debhelper (>=10), coffeelibs-jdk-22 (>= 22.0.1+8-0ppa1), libgtk-3-0, libxxf86vm1, libgl1 Build-Depends: debhelper (>=10), coffeelibs-jdk-20, libgtk2.0-0, libgtk-3-0, libxxf86vm1, libgl1
Standards-Version: 4.5.0 Standards-Version: 4.5.0
Homepage: https://cryptomator.org Homepage: https://cryptomator.org
Vcs-Git: https://github.com/cryptomator/cryptomator.git Vcs-Git: https://github.com/cryptomator/cryptomator.git
+2 -2
View File
@@ -4,11 +4,11 @@ Upstream-Contact: Cryptomator <info@cryptomator.org>
Source: https://cryptomator.org Source: https://cryptomator.org
Files: * Files: *
Copyright: 2016-2024 Skymatic GmbH Copyright: 2016-2023 Skymatic GmbH
License: GPL-3+ License: GPL-3+
Files: debian/org.cryptomator.Cryptomator.appdata.xml Files: debian/org.cryptomator.Cryptomator.appdata.xml
Copyright: 2016-2024 Skymatic GmbH Copyright: 2016-2023 Skymatic GmbH
License: FSFAP License: FSFAP
License: GPL-3+ License: GPL-3+
-2
View File
@@ -1,8 +1,6 @@
cryptomator usr/lib cryptomator usr/lib
common/org.cryptomator.Cryptomator.desktop usr/share/applications common/org.cryptomator.Cryptomator.desktop usr/share/applications
common/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps common/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps
common/org.cryptomator.Cryptomator.tray.svg usr/share/icons/hicolor/scalable/apps
common/org.cryptomator.Cryptomator.tray-unlocked.svg usr/share/icons/hicolor/scalable/apps
common/org.cryptomator.Cryptomator256.png usr/share/icons/hicolor/256x256/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.Cryptomator512.png usr/share/icons/hicolor/512x512/apps
common/org.cryptomator.Cryptomator.metainfo.xml usr/share/metainfo common/org.cryptomator.Cryptomator.metainfo.xml usr/share/metainfo
-2
View File
@@ -1,3 +1 @@
usr/lib/cryptomator/bin/cryptomator usr/bin/cryptomator usr/lib/cryptomator/bin/cryptomator usr/bin/cryptomator
usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray.svg usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg
usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray-unlocked.svg usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.svg
+6 -10
View File
@@ -4,7 +4,7 @@
# Uncomment this to turn on verbose mode. # Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1 #export DH_VERBOSE=1
JAVA_HOME = /usr/lib/jvm/java-22-coffeelibs JAVA_HOME = /usr/lib/jvm/java-20-coffeelibs
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH) DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
ifeq ($(DEB_BUILD_ARCH),amd64) ifeq ($(DEB_BUILD_ARCH),amd64)
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
@@ -24,16 +24,15 @@ override_dh_auto_clean:
override_dh_auto_build: override_dh_auto_build:
mkdir resources mkdir resources
ln -s ../common/org.cryptomator.Cryptomator512.png resources/cryptomator.png ln -s ../common/org.cryptomator.Cryptomator512.png resources/cryptomator.png
# Remark: no compression is applied for improved build compression later (here deb)
$(JAVA_HOME)/bin/jlink \ $(JAVA_HOME)/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JMODS_PATH}" \ --module-path "${JMODS_PATH}" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \ --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \ --strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
--strip-debug \ --strip-debug \
--compress zip-0 --compress=2
$(JAVA_HOME)/bin/jpackage \ $(JAVA_HOME)/bin/jpackage \
--type app-image \ --type app-image \
--runtime-image runtime \ --runtime-image runtime \
@@ -44,8 +43,8 @@ override_dh_auto_build:
--name cryptomator \ --name cryptomator \
--vendor "Skymatic GmbH" \ --vendor "Skymatic GmbH" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \ --java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \
--copyright "(C) 2016 - 2024 Skymatic GmbH" \ --copyright "(C) 2016 - 2023 Skymatic GmbH" \
--java-options "-Xss5m" \ --java-options "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \ --java-options "-Dfile.encoding=\"utf-8\"" \
@@ -56,12 +55,9 @@ override_dh_auto_build:
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \ --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \ --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \ --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \ --java-options "-Dcryptomator.showTrayIcon=false" \
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"/usr/share/icons/hicolor/symbolic/apps\"" \
--java-options "-Dcryptomator.buildNumber=\"deb-${REVISION_NUM}\"" \ --java-options "-Dcryptomator.buildNumber=\"deb-${REVISION_NUM}\"" \
--java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\"" \ --java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\"" \
--java-options "-Dcryptomator.disableUpdateCheck=\"${DISABLE_UPDATE_CHECK}\"" \
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
--app-version "${VERSION_NUM}.${REVISION_NUM}" \ --app-version "${VERSION_NUM}.${REVISION_NUM}" \
--resource-dir resources \ --resource-dir resources \
--verbose --verbose
+14
View File
@@ -0,0 +1,14 @@
java-options=-Xss5m \
-Xmx256m \
--enable-preview \
--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64 \
-Dfile.encoding=\"utf-8\" \
-Dcryptomator.appVersion=\"${SEMVER_STR}\" \
-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\" \
-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\" \
-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\" \
-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\" \
-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\" \
-Dcryptomator.showTrayIcon=false \
-Dcryptomator.buildNumber=\"appimage-${REVISION_NUM}\" \
-Djdk.gtk.version=2
-1
View File
@@ -1 +0,0 @@
embedded.provisionprofile
-8
View File
@@ -2,10 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.application-identifier</key>
<string>###APP_IDENTIFIER_PREFIX###org.cryptomator</string>
<key>com.apple.developer.team-identifier</key>
<string>###TEAM_IDENTIFIER###</string>
<key>com.apple.security.cs.allow-jit</key> <key>com.apple.security.cs.allow-jit</key>
<true/> <true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key> <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
@@ -14,9 +10,5 @@
<true/> <true/>
<key>com.apple.security.cs.disable-library-validation</key> <key>com.apple.security.cs.disable-library-validation</key>
<true/> <true/>
<key>keychain-access-groups</key>
<array>
<string>###APP_IDENTIFIER_PREFIX###org.cryptomator</string>
</array>
</dict> </dict>
</plist> </plist>
+2 -5
View File
@@ -1,9 +1,6 @@
# downloaded/created during build # created during build
Cryptomator.app/ Cryptomator.app/
runtime/ runtime/
dmg/ dmg/
*.dmg *.dmg
license.rtf license.rtf
openjfx-jmods.zip
*.jmod
Cryptomator.entitlements
+11 -51
View File
@@ -1,15 +1,12 @@
#!/bin/bash #!/bin/bash
# parse options # parse options
usage() { echo "Usage: $0 [-s <codesign-identity>] [-t <team-identifier>]" 1>&2; exit 1; } usage() { echo "Usage: $0 [-s <codesign-identity>]" 1>&2; exit 1; }
while getopts ":s:t:" o; do while getopts ":s:" o; do
case "${o}" in case "${o}" in
s) s)
CODESIGN_IDENTITY=${OPTARG} CODESIGN_IDENTITY=${OPTARG}
;; ;;
t)
TEAM_IDENTIFIER=${OPTARG}
;;
*) *)
usage usage
;; ;;
@@ -24,7 +21,7 @@ rm -rf runtime dmg *.app *.dmg
# set variables # set variables
APP_NAME="Cryptomator" APP_NAME="Cryptomator"
VENDOR="Skymatic GmbH" VENDOR="Skymatic GmbH"
COPYRIGHT_YEARS="2016 - 2024" COPYRIGHT_YEARS="2016 - 2023"
PACKAGE_IDENTIFIER="org.cryptomator" PACKAGE_IDENTIFIER="org.cryptomator"
MAIN_JAR_GLOB="cryptomator-*.jar" MAIN_JAR_GLOB="cryptomator-*.jar"
MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator" MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
@@ -32,18 +29,6 @@ REVISION_NO=`git rev-list --count HEAD`
VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'` VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
FUSE_LIB="FUSE-T" FUSE_LIB="FUSE-T"
JAVAFX_VERSION=22.0.2
JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="813c6748f7c99cb7a579d48b48a087b4682b1fad1fc1a4fe5f9b21cf872b15a7"
else
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="115cb08bb59d880cfff6e51e0bf0dcc45785ed9d456b8b8425597b04da6ab3d4"
fi
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
# check preconditions # check preconditions
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi 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. Fix by 'brew install maven'."; exit 1; } command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found. Fix by 'brew install maven'."; exit 1; }
@@ -53,38 +38,20 @@ if [ -n "${CODESIGN_IDENTITY}" ]; then
if [[ ! `security find-identity -v -p codesigning | grep -w "${CODESIGN_IDENTITY}"` ]]; then echo "Given codesign identity is invalid."; exit 1; fi if [[ ! `security find-identity -v -p codesigning | grep -w "${CODESIGN_IDENTITY}"` ]]; then echo "Given codesign identity is invalid."; exit 1; fi
fi fi
# download and check jmods
curl -L ${JAVAFX_JMODS_URL} -o openjfx-jmods.zip
echo "${JAVAFX_JMODS_SHA256} openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods/
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn -f../../../pom.xml help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ "${POM_JFX_VERSION}" -ne "${JMOD_VERSION}" ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != jmod version (${JMOD_VERSION})"
exit 1
fi
# compile # compile
mvn -B -Djavafx.platform=mac -f../../../pom.xml clean package -DskipTests -Pmac mvn -B -f../../../pom.xml clean package -DskipTests -Pmac
cp ../../../LICENSE.txt ../../../target
cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
# add runtime # add runtime
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" \ --module-path "${JAVA_HOME}/jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,java.compiler \ --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \ --strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
--strip-debug \ --strip-debug \
--compress zip-0 --compress=1
# create app dir # create app dir
${JAVA_HOME}/bin/jpackage \ ${JAVA_HOME}/bin/jpackage \
@@ -124,10 +91,9 @@ ${JAVA_HOME}/bin/jpackage \
cp ../resources/${APP_NAME}-Vault.icns ${APP_NAME}.app/Contents/Resources/ cp ../resources/${APP_NAME}-Vault.icns ${APP_NAME}.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/Contents/Info.plist sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
# generate license # generate license
mvn -B -Djavafx.platform=mac -f../../../pom.xml license:add-third-party \ mvn -B -f../../../pom.xml license:add-third-party \
-Dlicense.thirdPartyFilename=license.rtf \ -Dlicense.thirdPartyFilename=license.rtf \
-Dlicense.outputDirectory=dist/mac/dmg/resources \ -Dlicense.outputDirectory=dist/mac/dmg/resources \
-Dlicense.fileTemplate=resources/licenseTemplate.ftl \ -Dlicense.fileTemplate=resources/licenseTemplate.ftl \
@@ -137,11 +103,7 @@ mvn -B -Djavafx.platform=mac -f../../../pom.xml license:add-third-party \
-Dlicense.licenseMergesUrl=file://$(pwd)/../../../license/merges -Dlicense.licenseMergesUrl=file://$(pwd)/../../../license/merges
# codesign # codesign
if [ -n "${CODESIGN_IDENTITY}" ] && [ -n "${TEAM_IDENTIFIER}" ]; then if [ -n "${CODESIGN_IDENTITY}" ]; then
echo "Codesigning jdk files..."
find ${APP_NAME}.app/Contents/runtime/Contents/Home/lib/ -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
find ${APP_NAME}.app/Contents/runtime/Contents/Home/lib/ -name 'jspawnhelper' -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
echo "Codesigning jar contents..."
find ${APP_NAME}.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \; find ${APP_NAME}.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
for JAR_PATH in `find ${APP_NAME}.app -name "*.jar"`; do for JAR_PATH in `find ${APP_NAME}.app -name "*.jar"`; do
if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
@@ -159,10 +121,7 @@ if [ -n "${CODESIGN_IDENTITY}" ] && [ -n "${TEAM_IDENTIFIER}" ]; then
fi fi
done done
echo "Codesigning ${APP_NAME}.app..." echo "Codesigning ${APP_NAME}.app..."
cp ../${APP_NAME}.entitlements . codesign --force --deep --entitlements ../${APP_NAME}.entitlements -o runtime -s ${CODESIGN_IDENTITY} ${APP_NAME}.app
sed -i '' "s|###APP_IDENTIFIER_PREFIX###|${TEAM_IDENTIFIER}.|g" ${APP_NAME}.entitlements
sed -i '' "s|###TEAM_IDENTIFIER###|${TEAM_IDENTIFIER}|g" ${APP_NAME}.entitlements
codesign --force --deep --entitlements ${APP_NAME}.entitlements -o runtime -s ${CODESIGN_IDENTITY} ${APP_NAME}.app
fi fi
# prepare dmg contents # prepare dmg contents
@@ -185,5 +144,6 @@ create-dmg \
--app-drop-link 512 245 \ --app-drop-link 512 245 \
--eula "resources/license.rtf" \ --eula "resources/license.rtf" \
--icon ".background" 128 758 \ --icon ".background" 128 758 \
--icon ".fseventsd" 320 758 \
--icon ".VolumeIcon.icns" 512 758 \ --icon ".VolumeIcon.icns" 512 758 \
${APP_NAME}-${VERSION_NO}.dmg dmg ${APP_NAME}-${VERSION_NO}.dmg dmg
+1 -1
View File
@@ -17,7 +17,7 @@
\f1\b0 \ \f1\b0 \
\ \
\f0\b \'a9 2016 \'96 2024 Skymatic GmbH \f0\b \'a9 2016 \'96 2023 Skymatic GmbH
\f1\b0 \ \f1\b0 \
\ \
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.\ 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.\
Binary file not shown.
+1 -1
View File
@@ -3,7 +3,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>11</string> <string>10.13.0</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleAllowMixedLocalizations</key> <key>CFBundleAllowMixedLocalizations</key>
-3
View File
@@ -4,7 +4,4 @@ installer
*.wixobj *.wixobj
*.pdb *.pdb
*.msi *.msi
*.exe
*.jmod
resources/jfxJmods.zip
license.rtf license.rtf
+1 -1
View File
@@ -11,7 +11,7 @@ SET HELP_URL="https://cryptomator.org/contact/"
SET MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator" SET MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
SET LOOPBACK_ALIAS="cryptomator-vault" SET LOOPBACK_ALIAS="cryptomator-vault"
powershell -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^ powershell -NoLogo -ExecutionPolicy Unrestricted -Command .\build.ps1^
-AppName %APPNAME%^ -AppName %APPNAME%^
-MainJarGlob "%MAIN_JAR_GLOB%"^ -MainJarGlob "%MAIN_JAR_GLOB%"^
-ModuleAndMainClass "%MODULE_AND_MAIN_CLASS%"^ -ModuleAndMainClass "%MODULE_AND_MAIN_CLASS%"^
+20 -30
View File
@@ -41,7 +41,7 @@ Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
$copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor" $copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor"
# compile # compile
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin "-Djavafx.platform=win" &mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin
Copy-Item "$buildDir\..\..\target\$MainJarGlob.jar" -Destination "$buildDir\..\..\target\mods" Copy-Item "$buildDir\..\..\target\$MainJarGlob.jar" -Destination "$buildDir\..\..\target\mods"
# add runtime # add runtime
@@ -51,36 +51,32 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
} }
## download jfx jmods ## download jfx jmods
$javaFxVersion='22.0.2' $jfxJmodsChecksum = 'd00767334c43b8832b5cf10267d34ca8f563d187c4655b73eb6020dd79c054b5'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip" $jfxJmodsZip = '.\resources\jfxJmods.zip'
$javaFxJmodsSHA256 = 'f9376d200f5c5b85327d575c1ec1482e6455f19916577f7e2fc9be2f48bb29b6' if( !(Test-Path -Path $jfxJmodsZip) ) {
$javaFxJmods = '.\resources\jfxJmods.zip' $jmodsUrl = "https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_windows-x64_bin-jmods.zip"
if( !(Test-Path -Path $javaFxJmods) ) { Write-Output "Downloading ${jmodsUrl}..."
Write-Output "Downloading ${javaFxJmodsUrl}..." Invoke-WebRequest $jmodsUrl -OutFile $jfxJmodsZip # redirects are followed by default
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
} }
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash $jmodsChecksumActual = $(Get-FileHash -Path $jfxJmodsZip -Algorithm SHA256).Hash
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) { if( $jmodsChecksumActual -ne $jfxJmodsChecksum ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256 Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $jfxJmodsChecksum, actual: $jmodsChecksumActual"
, actual: $jmodsChecksumActual" exit 1;
exit 1;
} }
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\" Expand-Archive -Force -Path $jfxJmodsZip -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods"
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
## create custom runtime
& "$Env:JAVA_HOME\bin\jlink" ` & "$Env:JAVA_HOME\bin\jlink" `
--verbose ` --verbose `
--output runtime ` --output runtime `
--module-path "$Env:JAVA_HOME/jmods;$buildDir/resources/javafx-jmods" ` --module-path "$Env:JAVA_HOME/jmods;$buildDir/resources/javafx-jmods-20.0.1" `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml ` --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--strip-native-commands ` --strip-native-commands `
--no-header-files ` --no-header-files `
--no-man-pages ` --no-man-pages `
--strip-debug ` --strip-debug `
--compress "zip-0" #do not compress to have improved msi compression --compress=1
$appPath = ".\$AppName" $appPath = ".\$AppName"
if ($clean -and (Test-Path -Path $appPath)) { if ($clean -and (Test-Path -Path $appPath)) {
@@ -100,7 +96,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
--vendor $Vendor ` --vendor $Vendor `
--copyright $copyright ` --copyright $copyright `
--java-options "--enable-preview" ` --java-options "--enable-preview" `
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" ` --java-options "--enable-native-access=org.cryptomator.jfuse.win" `
--java-options "-Xss5m" ` --java-options "-Xss5m" `
--java-options "-Xmx256m" ` --java-options "-Xmx256m" `
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" ` --java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
@@ -122,7 +118,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
--icon resources/$AppName.ico --icon resources/$AppName.ico
#Create RTF license for msi #Create RTF license for msi
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" ` &mvn -B -f $buildDir/../../pom.xml license:add-third-party `
"-Dlicense.thirdPartyFilename=license.rtf" ` "-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl" ` "-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\resources\" ` "-Dlicense.outputDirectory=$buildDir\resources\" `
@@ -145,7 +141,6 @@ try {
# create .msi # create .msi
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources" $Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
$Env:JP_WIXHELPER_DIR = "."
& "$Env:JAVA_HOME\bin\jpackage" ` & "$Env:JAVA_HOME\bin\jpackage" `
--verbose ` --verbose `
--type msi ` --type msi `
@@ -167,7 +162,7 @@ $Env:JP_WIXHELPER_DIR = "."
--file-associations resources/FAvaultFile.properties --file-associations resources/FAvaultFile.properties
#Create RTF license for bundle #Create RTF license for bundle
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" ` &mvn -B -f $buildDir/../../pom.xml license:add-third-party `
"-Dlicense.thirdPartyFilename=license.rtf" ` "-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl" ` "-Dlicense.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\bundle\resources\" ` "-Dlicense.outputDirectory=$buildDir\bundle\resources\" `
@@ -177,15 +172,10 @@ $Env:JP_WIXHELPER_DIR = "."
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges" "-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges"
# download Winfsp # download Winfsp
$winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi' $winfspMsiUrl= (Select-String -Path ".\bundle\resources\winFspMetaData.wxi" -Pattern '<\?define BundledWinFspDownloadLink="(.+)".*?>').Matches.Groups[1].Value
Write-Output "Downloading ${winfspMsiUrl}..." Write-Output "Downloading ${winfspMsiUrl}..."
Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default
# download legacy-winfsp uninstaller
$winfspUninstaller= 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
Write-Output "Downloading ${winfspUninstaller}..."
Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninstaller.exe" # redirects are followed by default
# copy MSI to bundle resources # copy MSI to bundle resources
Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi" Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi"
+20 -25
View File
@@ -1,6 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html--> <!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html-->
<!-- Attributes explicitly not used: <!-- Attributes explicitly not used:
@@ -11,10 +10,21 @@
AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico"> AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico">
<!-- detect outdated WinFsp installations --> <!-- detect outdated WinFsp installations -->
<?include "resources\winFspMetaData.wxi" ?>
<util:ProductSearch <util:ProductSearch
Variable="InstalledLegacyWinFspVersion" Variable="InstalledWinFspVersion"
Result="version" Result="version"
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"/> UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"
/>
<!-- Note: The bundle engine takes the Message format literaly -->
<bal:Condition Message=
"The WinFsp driver used by Cryptomator is outdated and must be removed before the installation.
1. Open the view of installed apps
2. Search for &quot;WinFsp&quot;
3. Uninstall the listed application
4. Reboot your device
5. Restart this installer">(InstalledWinFspVersion = v0.0.0.0) OR ($(var.BundledWinFspVersion) &lt;= InstalledWinFspVersion)</bal:Condition>
<!-- for definition of the standard themes, see https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/--> <!-- for definition of the standard themes, see https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/-->
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense"> <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
@@ -26,41 +36,26 @@
SuppressOptionsUI="yes" SuppressOptionsUI="yes"
ThemeFile="bundle\customBootstrapperTheme.xml" ThemeFile="bundle\customBootstrapperTheme.xml"
LocalizationFile="bundle\customBootstrapperTheme.wxl" LocalizationFile="bundle\customBootstrapperTheme.wxl"
LogoFile="bundle\resources\logo.png"/> LogoFile="bundle\resources\logo.png"
/>
<Payload SourceFile="bundle\resources\logoSide.png" /> <Payload SourceFile="bundle\resources\logoSide.png" />
</BootstrapperApplicationRef> </BootstrapperApplicationRef>
<Chain> <Chain>
<ExePackage Cache="yes" PerMachine="yes" Permanent="no"
SourceFile="resources\winfsp-uninstaller.exe"
DisplayName="Removing outdated WinFsp Driver"
Description="Executable to remove old winfsp"
DetectCondition="false"
InstallCondition="(InstalledLegacyWinFspVersion &lt;&gt; v0.0.0.0) AND ((WixBundleAction = 7) OR (WixBundleAction = 5))">
<CommandLine Condition="WixBundleUILevel &lt;= 3" InstallArgument="-q -l &quot;[WixBundleLog].winfsp-uninstaller.log&quot;" RepairArgument="-q" UninstallArgument="-s" />
<!-- XML allows line breaks in attributes, hence keep the line breaks here -->
<CommandLine Condition="WixBundleUILevel &gt; 3" InstallArgument="-l &quot;[WixBundleLog].winfsp-uninstaller.log&quot; -t &quot;Cryptomator Installer&quot; -m &quot;Cryptomator requires a newer version of the WinFsp driver. The installer will now uninstall WinFsp, possibly reboot, and afterwards proceed with the installation.
Do you want to continue?&quot;" RepairArgument="-q" UninstallArgument="-s" />
<ExitCode Behavior="success" Value="0"/>
<ExitCode Behavior="success" Value="1"/>
<ExitCode Behavior="error" Value="2"/>
<ExitCode Behavior="error" Value="3"/>
<ExitCode Behavior="forceReboot" Value="4"/>
<ExitCode Behavior="success" Value="5"/>
</ExePackage>
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/msipackage.html--> <!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/msipackage.html-->
<MsiPackage <MsiPackage
SourceFile="resources\Cryptomator.msi" SourceFile="resources\Cryptomator.msi"
CacheId="cryptomator-bundle-cryptomator" CacheId="cryptomator-bundle-cryptomator"
DisplayInternalUI="no" DisplayInternalUI="no"
Visible="no"/> Visible="no"
/>
<MsiPackage <MsiPackage
SourceFile="resources\winfsp.msi" SourceFile="resources\winfsp.msi"
CacheId="cryptomator-bundle-winfsp" CacheId="cryptomator-bundle-winfsp"
Visible="yes" Visible="yes"
DisplayInternalUI="no" DisplayInternalUI="no"
Permanent="yes"/> Vital="no"
Permanent="yes"
/>
</Chain> </Chain>
</Bundle> </Bundle>
</Wix> </Wix>
+1 -1
View File
@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0 \vieww12000\viewh15840\viewkind0
\pard\tx283\tx567\tx850\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 \pard\tx283\tx567\tx850\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 \par
\b\'a9 2016 \'96 2024 Skymatic GmbH \b0\par \b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\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 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 \par
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- A version number MUST be prefixed with letter "v", otherwise it is considered a normal string -->
<?define BundledWinFspVersion="v1.12.22339" ?>
<?define BundledWinFspDownloadLink="https://github.com/winfsp/winfsp/releases/download/v1.12.22339/winfsp-1.12.22339.msi" ?> <!-- Only used by external build scripts -->
</Include>
+1 -1
View File
@@ -3,5 +3,5 @@
::REPLACE ME ::REPLACE ME
cd %~dp0 cd %~dp0
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command .\patchWebDAV.ps1^ powershell -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -Command .\patchWebDAV.ps1^
-LoopbackAlias %LOOPBACK_ALIAS% -LoopbackAlias %LOOPBACK_ALIAS%
+5
View File
@@ -0,0 +1,5 @@
@echo off
:: see comments in file ./version170-migrate-settings.ps1
cd %~dp0
powershell -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -Command .\version170-migrate-settings.ps1
+35
View File
@@ -0,0 +1,35 @@
# This script migrates Cryptomator settings for all local users on Windows in case the users uses custom directories as mountpoint
# See also https://github.com/cryptomator/cryptomator/pull/2654.
#
# TODO: This script should be evaluated in a yearly interval if it is still needed and if not, should be removed
#
#Requires -RunAsAdministrator
#Get all active, local user profiles
$profileList = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
Get-ChildItem $profileList | ForEach-Object {
$profilePath = $_.GetValue("ProfileImagePath")
$settingsPath = "$profilePath\AppData\Roaming\Cryptomator\settings.json"
if(!(Test-Path -Path $settingsPath -PathType Leaf)) {
#No settings file, nothing to do.
return;
}
$settings = Get-Content -Path $settingsPath | ConvertFrom-Json
if($settings.preferredVolumeImpl -ne "FUSE") {
#Fuse not used, nothing to do
return;
}
#check if customMountPoints are used
$atLeastOneCustomPath = $false;
foreach ($vault in $settings.directories){
$atLeastOneCustomPath = $atLeastOneCustomPath -or ($vault.useCustomMountPath -eq "True")
}
#if so, use WinFsp Local Drive
if( $atLeastOneCustomPath ) {
Add-Member -Force -InputObject $settings -Name "mountService" -Value "org.cryptomator.frontend.fuse.mount.WinFspMountProvider" -MemberType NoteProperty
$newSettings = $settings | Select-Object * -ExcludeProperty "preferredVolumeImpl"
ConvertTo-Json $newSettings | Set-Content -Path $settingsPath
}
}
+1 -1
View File
@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0 \vieww12000\viewh15840\viewkind0
\pard\tx283\tx567\tx850\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 \pard\tx283\tx567\tx850\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 \par
\b\'a9 2016 \'96 2024 Skymatic GmbH \b0\par \b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\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 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 \par
+6 -6
View File
@@ -70,7 +70,7 @@
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" /> <CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
<?endif?> <?endif?>
<Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll"/> <Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
<CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" /> <CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" />
<?ifndef SkipCryptomatorLegacyCheck ?> <?ifndef SkipCryptomatorLegacyCheck ?>
@@ -132,12 +132,11 @@
<CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" /> <CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
<?endif?> <?endif?>
<Property Id="WixQuietExec64CmdTimeout" Value="20" />
<!-- Note for custom actions: Immediate CAs run BEFORE the files are installed, hence if you depend on installed files, the CAs must be deferred.-->
<!-- WebDAV patches --> <!-- WebDAV patches -->
<SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot;" <CustomAction Id="PatchWebDAV" Impersonate="no" ExeCommand="[INSTALLDIR]patchWebDAV.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" />
Sequence="execute" Before="PatchWebDAV" />
<CustomAction Id="PatchWebDAV" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/> <!-- Special Settings migration for 1.7.0,. Should be removed eventually, for more info, see ../contrib/version170-migrate-settings.ps1-->
<CustomAction Id="V170MigrateSettings" Impersonate="no" ExeCommand="[INSTALLDIR]version170-migrate-settings.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" />
<!-- Running App detection and exit --> <!-- Running App detection and exit -->
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/> <Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
@@ -190,6 +189,7 @@
<RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications --> <RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications -->
<Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom> <Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
</InstallExecuteSequence> </InstallExecuteSequence>
<InstallUISequence> <InstallUISequence>
+41 -70
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId> <artifactId>cryptomator</artifactId>
<version>1.14.0</version> <version>1.10.0-SNAPSHOT</version>
<name>Cryptomator Desktop App</name> <name>Cryptomator Desktop App</name>
<organization> <organization>
@@ -26,60 +26,49 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>22</project.jdk.version> <project.jdk.version>20</project.jdk.version>
<!-- Group IDs of jars that need to stay on the class path for now --> <!-- Group IDs of jars that need to stay on the class path for now -->
<!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) --> <!-- Once hypfvieh, swiesend, purejava and integrations-linux have module-info, remove them-->
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds> <nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
<!-- cryptomator dependencies --> <!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.7.0</cryptomator.cryptofs.version> <cryptomator.cryptofs.version>2.6.6</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.4.0</cryptomator.integrations.version> <cryptomator.integrations.version>1.2.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.3.0</cryptomator.integrations.win.version> <cryptomator.integrations.win.version>1.2.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.2.4</cryptomator.integrations.mac.version> <cryptomator.integrations.mac.version>1.2.0</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.5.0</cryptomator.integrations.linux.version> <cryptomator.integrations.linux.version>1.2.1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.0.0</cryptomator.fuse.version> <cryptomator.fuse.version>3.0.0</cryptomator.fuse.version>
<cryptomator.webdav.version>2.0.6</cryptomator.webdav.version> <cryptomator.dokany.version>2.0.0</cryptomator.dokany.version>
<cryptomator.webdav.version>2.0.3</cryptomator.webdav.version>
<!-- 3rd party dependencies --> <!-- 3rd party dependencies -->
<commons-lang3.version>3.16.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<dagger.version>2.51.1</dagger.version> <dagger.version>2.45</dagger.version>
<easybind.version>2.2</easybind.version> <easybind.version>2.2</easybind.version>
<guava.version>33.3.0-jre</guava.version> <guava.version>32.0.1-jre</guava.version>
<jackson.version>2.17.2</jackson.version> <jackson.version>2.15.2</jackson.version>
<javafx.version>22.0.2</javafx.version> <javafx.version>20.0.1</javafx.version>
<jwt.version>4.4.0</jwt.version> <jwt.version>4.4.0</jwt.version>
<nimbus-jose.version>9.37.3</nimbus-jose.version> <nimbus-jose.version>9.31</nimbus-jose.version>
<logback.version>1.5.7</logback.version> <logback.version>1.4.7</logback.version>
<slf4j.version>2.0.16</slf4j.version> <slf4j.version>2.0.7</slf4j.version>
<tinyoauth2.version>0.8.0</tinyoauth2.version> <tinyoauth2.version>0.5.1</tinyoauth2.version>
<zxcvbn.version>1.9.0</zxcvbn.version> <zxcvbn.version>1.7.0</zxcvbn.version>
<!-- test dependencies --> <!-- test dependencies -->
<junit.jupiter.version>5.11.0</junit.jupiter.version> <junit.jupiter.version>5.9.3</junit.jupiter.version>
<mockito.version>5.12.0</mockito.version> <mockito.version>5.3.1</mockito.version>
<hamcrest.version>3.0</hamcrest.version> <hamcrest.version>2.2</hamcrest.version>
<!-- build-time dependencies --> <!-- build-time dependencies -->
<jetbrains.annotations.version>24.1.0</jetbrains.annotations.version> <jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
<dependency-check.version>10.0.3</dependency-check.version> <dependency-check.version>8.1.2</dependency-check.version>
<jacoco.version>0.8.12</jacoco.version> <jacoco.version>0.8.9</jacoco.version>
<license-generator.version>2.4.0</license-generator.version>
<junit-tree-reporter.version>1.3.0</junit-tree-reporter.version>
<mvn-compiler.version>3.13.0</mvn-compiler.version>
<mvn-resources.version>3.3.1</mvn-resources.version>
<mvn-dependency.version>3.7.1</mvn-dependency.version>
<mvn-surefire.version>3.4.0</mvn-surefire.version>
<mvn-jar.version>3.4.2</mvn-jar.version>
</properties> </properties>
<dependencies> <dependencies>
<!-- Cryptomator Libs --> <!-- Cryptomator Libs -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId>
<version>2.2.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId> <artifactId>cryptofs</artifactId>
@@ -90,6 +79,11 @@
<artifactId>fuse-nio-adapter</artifactId> <artifactId>fuse-nio-adapter</artifactId>
<version>${cryptomator.fuse.version}</version> <version>${cryptomator.fuse.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>dokany-nio-adapter</artifactId>
<version>${cryptomator.dokany.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter</artifactId> <artifactId>webdav-nio-adapter</artifactId>
@@ -163,18 +157,11 @@
<artifactId>nimbus-jose-jwt</artifactId> <artifactId>nimbus-jose-jwt</artifactId>
<version>${nimbus-jose.version}</version> <version>${nimbus-jose.version}</version>
</dependency> </dependency>
<!-- Jackson -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version> <version>${jackson.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- EasyBind --> <!-- EasyBind -->
<dependency> <dependency>
@@ -253,7 +240,7 @@
<dependency> <dependency>
<groupId>com.google.jimfs</groupId> <groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId> <artifactId>jimfs</artifactId>
<version>1.3.0</version> <version>1.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@@ -271,32 +258,32 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>${mvn-compiler.version}</version> <version>3.10.1</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId> <artifactId>maven-resources-plugin</artifactId>
<version>${mvn-resources.version}</version> <version>3.3.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>${mvn-dependency.version}</version> <version>3.3.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${mvn-surefire.version}</version> <version>3.0.0-M7</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId> <artifactId>license-maven-plugin</artifactId>
<version>${license-generator.version}</version> <version>2.0.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>${mvn-jar.version}</version> <version>3.3.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
@@ -345,22 +332,8 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>me.fabriciorby</groupId>
<artifactId>maven-surefire-junit5-tree-reporter</artifactId>
<version>${junit-tree-reporter.version}</version>
</dependency>
</dependencies>
<configuration> <configuration>
<argLine>--enable-preview</argLine> <argLine>--enable-preview</argLine>
<reportFormat>plain</reportFormat>
<consoleOutputReporter>
<disable>true</disable>
</consoleOutputReporter>
<statelessTestsetInfoReporter
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
</statelessTestsetInfoReporter>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@@ -466,19 +439,17 @@
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<configuration> <configuration>
<nvdValidForHours>24</nvdValidForHours> <cveValidForHours>24</cveValidForHours>
<failBuildOnCVSS>0</failBuildOnCVSS> <failBuildOnCVSS>0</failBuildOnCVSS>
<skipTestScope>true</skipTestScope> <skipTestScope>true</skipTestScope>
<detail>true</detail> <detail>true</detail>
<suppressionFile>suppression.xml</suppressionFile> <suppressionFile>suppression.xml</suppressionFile>
<nvdApiKeyEnvironmentVariable>NVD_API_KEY</nvdApiKeyEnvironmentVariable>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>check</goal> <goal>check</goal>
</goals> </goals>
<phase>validate</phase>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
+2 -2
View File
@@ -21,6 +21,7 @@ open module org.cryptomator.desktop {
requires org.cryptomator.cryptolib; requires org.cryptomator.cryptolib;
requires org.cryptomator.cryptofs; requires org.cryptomator.cryptofs;
requires org.cryptomator.frontend.dokany;
requires org.cryptomator.frontend.fuse; requires org.cryptomator.frontend.fuse;
requires org.cryptomator.frontend.webdav; requires org.cryptomator.frontend.webdav;
requires org.cryptomator.integrations.api; requires org.cryptomator.integrations.api;
@@ -31,18 +32,17 @@ open module org.cryptomator.desktop {
requires javafx.graphics; requires javafx.graphics;
requires javafx.controls; requires javafx.controls;
requires javafx.fxml; requires javafx.fxml;
requires jdk.crypto.ec;
// 3rd party: // 3rd party:
requires ch.qos.logback.classic; requires ch.qos.logback.classic;
requires ch.qos.logback.core; requires ch.qos.logback.core;
requires com.auth0.jwt; requires com.auth0.jwt;
requires com.google.common; requires com.google.common;
requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.datatype.jsr310;
requires com.nimbusds.jose.jwt; requires com.nimbusds.jose.jwt;
requires com.nulabinc.zxcvbn; requires com.nulabinc.zxcvbn;
requires com.tobiasdiez.easybind; requires com.tobiasdiez.easybind;
requires dagger; requires dagger;
requires java.compiler;
requires io.github.coffeelibs.tinyoauth2client; requires io.github.coffeelibs.tinyoauth2client;
requires org.slf4j; requires org.slf4j;
requires org.apache.commons.lang3; requires org.apache.commons.lang3;
@@ -5,8 +5,10 @@
*******************************************************************************/ *******************************************************************************/
package org.cryptomator.common; package org.cryptomator.common;
import com.tobiasdiez.easybind.EasyBind;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.keychain.KeychainModule; import org.cryptomator.common.keychain.KeychainModule;
import org.cryptomator.common.mount.MountModule; import org.cryptomator.common.mount.MountModule;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
@@ -20,6 +22,8 @@ import org.slf4j.LoggerFactory;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Comparator; import java.util.Comparator;
@@ -132,4 +136,13 @@ public abstract class CommonsModule {
LOG.error("Uncaught exception in " + thread.getName(), throwable); LOG.error("Uncaught exception in " + thread.getName(), throwable);
} }
@Provides
@Singleton
static ObservableValue<InetSocketAddress> provideServerSocketAddressBinding(Settings settings) {
return settings.port.map(port -> {
String host = SystemUtils.IS_OS_WINDOWS ? "127.0.0.1" : "localhost";
return InetSocketAddress.createUnresolved(host, settings.port.intValue());
});
}
} }
@@ -2,7 +2,6 @@ package org.cryptomator.common;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -32,7 +31,6 @@ public class Environment {
private static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber"; private static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir"; private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon"; private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
private static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
private Environment() {} private Environment() {}
@@ -45,16 +43,15 @@ public class Environment {
logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME); logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME); logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME); logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
logCryptomatorSystemProperty(LOG_DIR_PROP_NAME); logCryptomatorSystemProperty(LOG_DIR_PROP_NAME);
logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME); logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME);
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
logCryptomatorSystemProperty(MOUNTPOINT_DIR_PROP_NAME); logCryptomatorSystemProperty(MOUNTPOINT_DIR_PROP_NAME);
logCryptomatorSystemProperty(MIN_PW_LENGTH_PROP_NAME); logCryptomatorSystemProperty(MIN_PW_LENGTH_PROP_NAME);
logCryptomatorSystemProperty(APP_VERSION_PROP_NAME); logCryptomatorSystemProperty(APP_VERSION_PROP_NAME);
logCryptomatorSystemProperty(BUILD_NUMBER_PROP_NAME); logCryptomatorSystemProperty(BUILD_NUMBER_PROP_NAME);
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME); logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
logCryptomatorSystemProperty(DISABLE_UPDATE_CHECK_PROP_NAME); logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
} }
public static Environment getInstance() { public static Environment getInstance() {
@@ -77,6 +74,10 @@ public class Environment {
return getPaths(SETTINGS_PATH_PROP_NAME); return getPaths(SETTINGS_PATH_PROP_NAME);
} }
public Stream<Path> getP12Path() {
return getPaths(P12_PATH_PROP_NAME);
}
public Stream<Path> getIpcSocketPath() { public Stream<Path> getIpcSocketPath() {
return getPaths(IPC_SOCKET_PATH_PROP_NAME); return getPaths(IPC_SOCKET_PATH_PROP_NAME);
} }
@@ -85,10 +86,6 @@ public class Environment {
return getPaths(KEYCHAIN_PATHS_PROP_NAME); return getPaths(KEYCHAIN_PATHS_PROP_NAME);
} }
public Stream<Path> getP12Path() {
return getPaths(P12_PATH_PROP_NAME);
}
public Optional<Path> getLogDir() { public Optional<Path> getLogDir() {
return getPath(LOG_DIR_PROP_NAME); return getPath(LOG_DIR_PROP_NAME);
} }
@@ -97,12 +94,12 @@ public class Environment {
return Optional.ofNullable(System.getProperty(LOOPBACK_ALIAS_PROP_NAME)); return Optional.ofNullable(System.getProperty(LOOPBACK_ALIAS_PROP_NAME));
} }
public Optional<Path> getMountPointsDir() { public Optional<Path> getPluginDir() {
return getPath(MOUNTPOINT_DIR_PROP_NAME); return getPath(PLUGIN_DIR_PROP_NAME);
} }
public int getMinPwLength() { public Optional<Path> getMountPointsDir() {
return Integer.getInteger(MIN_PW_LENGTH_PROP_NAME, DEFAULT_MIN_PW_LENGTH); return getPath(MOUNTPOINT_DIR_PROP_NAME);
} }
/** /**
@@ -118,24 +115,20 @@ public class Environment {
return Optional.ofNullable(System.getProperty(BUILD_NUMBER_PROP_NAME)); return Optional.ofNullable(System.getProperty(BUILD_NUMBER_PROP_NAME));
} }
public Optional<Path> getPluginDir() { public int getMinPwLength() {
return getPath(PLUGIN_DIR_PROP_NAME); return Integer.getInteger(MIN_PW_LENGTH_PROP_NAME, DEFAULT_MIN_PW_LENGTH);
} }
public boolean showTrayIcon() { public boolean showTrayIcon() {
return Boolean.getBoolean(TRAY_ICON_PROP_NAME); return Boolean.getBoolean(TRAY_ICON_PROP_NAME);
} }
public boolean disableUpdateCheck() {
return Boolean.getBoolean(DISABLE_UPDATE_CHECK_PROP_NAME);
}
private Optional<Path> getPath(String propertyName) { private Optional<Path> getPath(String propertyName) {
String value = System.getProperty(propertyName); String value = System.getProperty(propertyName);
return Optional.ofNullable(value).map(Paths::get); return Optional.ofNullable(value).map(Paths::get);
} }
@VisibleForTesting // visible for testing
Stream<Path> getPaths(String propertyName) { Stream<Path> getPaths(String propertyName) {
Stream<String> rawSettingsPaths = getRawList(propertyName, System.getProperty("path.separator").charAt(0)); Stream<String> rawSettingsPaths = getRawList(propertyName, System.getProperty("path.separator").charAt(0));
return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Path::of); return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Path::of);
@@ -3,7 +3,6 @@ package org.cryptomator.common;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import org.jetbrains.annotations.VisibleForTesting;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
@@ -115,7 +114,7 @@ public class ErrorCode {
* @param bottomFrames Other stack frames, potentially forming the bottom of the stack of <code>allFrames</code> * @param bottomFrames Other stack frames, potentially forming the bottom of the stack of <code>allFrames</code>
* @return The number of additional frames in <code>allFrames</code>. In most cases this should be equal to the difference in size. * @return The number of additional frames in <code>allFrames</code>. In most cases this should be equal to the difference in size.
*/ */
@VisibleForTesting // visible for testing
static int countTopmostFrames(StackTraceElement[] allFrames, StackTraceElement[] bottomFrames) { static int countTopmostFrames(StackTraceElement[] allFrames, StackTraceElement[] bottomFrames) {
if (allFrames.length < bottomFrames.length) { if (allFrames.length < bottomFrames.length) {
// if frames had been stacked on top of bottomFrames, allFrames would be larger // if frames had been stacked on top of bottomFrames, allFrames would be larger
@@ -125,7 +124,7 @@ public class ErrorCode {
} }
} }
@VisibleForTesting // visible for testing
static <T> int commonSuffixLength(T[] set, T[] subset) { static <T> int commonSuffixLength(T[] set, T[] subset) {
Preconditions.checkArgument(set.length >= subset.length); Preconditions.checkArgument(set.length >= subset.length);
// iterate items backwards as long as they are identical // iterate items backwards as long as they are identical
@@ -5,7 +5,6 @@ import org.slf4j.LoggerFactory;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class SubstitutingProperties extends PropertiesDecorator { public class SubstitutingProperties extends PropertiesDecorator {
@@ -59,7 +58,7 @@ public class SubstitutingProperties extends PropertiesDecorator {
LoggerFactory.getLogger(SubstitutingProperties.class).warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src); LoggerFactory.getLogger(SubstitutingProperties.class).warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src);
return ""; return "";
} else { } else {
return Matcher.quoteReplacement(val); return val.replace("\\", "\\\\");
} }
} }
@@ -44,7 +44,7 @@ public class KeychainManager implements KeychainAccessProvider {
} }
@Override @Override
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean ignored) throws KeychainAccessException { public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
getKeychainOrFail().storePassphrase(key, displayName, passphrase); getKeychainOrFail().storePassphrase(key, displayName, passphrase);
setPassphraseStored(key, true); setPassphraseStored(key, true);
} }
@@ -62,7 +62,7 @@ public final class OneDriveWindowsLocationPresetsProvider implements LocationPre
ProcessBuilder command = new ProcessBuilder(args); ProcessBuilder command = new ProcessBuilder(args);
Process p = command.start(); Process p = command.start();
waitForSuccess(p, 3, "`reg query`"); waitForSuccess(p, 3, "`reg query`");
return p.inputReader(StandardCharsets.ISO_8859_1).lines().filter(outputFilter); return p.inputReader(StandardCharsets.UTF_8).lines().filter(outputFilter);
} }
@@ -83,8 +83,8 @@ public final class OneDriveWindowsLocationPresetsProvider implements LocationPre
throw new TimeoutException(cmdDescription + " timed out after " + timeoutSeconds + "s"); throw new TimeoutException(cmdDescription + " timed out after " + timeoutSeconds + "s");
} }
if (process.exitValue() != 0) { if (process.exitValue() != 0) {
@SuppressWarnings("resource") var stdout = process.inputReader(StandardCharsets.ISO_8859_1).lines().collect(Collectors.joining("\n")); @SuppressWarnings("resource") var stdout = process.inputReader(StandardCharsets.UTF_8).lines().collect(Collectors.joining("\n"));
@SuppressWarnings("resource") var stderr = process.errorReader(StandardCharsets.ISO_8859_1).lines().collect(Collectors.joining("\n")); @SuppressWarnings("resource") var stderr = process.errorReader(StandardCharsets.UTF_8).lines().collect(Collectors.joining("\n"));
throw new CommandFailedException(cmdDescription, process.exitValue(), stdout, stderr); throw new CommandFailedException(cmdDescription, process.exitValue(), stdout, stderr);
} }
} }
@@ -0,0 +1,6 @@
package org.cryptomator.common.mount;
import org.cryptomator.integrations.mount.MountService;
public record ActualMountService(MountService service, boolean isDesired) {
}
@@ -1,14 +0,0 @@
package org.cryptomator.common.mount;
import org.cryptomator.integrations.mount.MountFailedException;
/**
* Thrown by {@link Mounter} to indicate that the selected mount service can not be used
* due to incompatibilities with a different mount service that is already in use.
*/
public class ConflictingMountServiceException extends MountFailedException {
public ConflictingMountServiceException(String msg) {
super(msg);
}
}
@@ -1,17 +0,0 @@
package org.cryptomator.common.mount;
import java.nio.file.Path;
public class HideawayNotDirectoryException extends IllegalMountPointException {
private final Path hideaway;
public HideawayNotDirectoryException(Path path, Path hideaway) {
super(path, "Existing hideaway (" + hideaway.toString() + ") for mountpoint is not a directory: " + path.toString());
this.hideaway = hideaway;
}
public Path getHideaway() {
return hideaway;
}
}
@@ -1,25 +1,9 @@
package org.cryptomator.common.mount; package org.cryptomator.common.mount;
import java.nio.file.Path;
/**
* Indicates that validation or preparation of a mountpoint failed due to a configuration error or an invalid system state.<br>
* Instances of this exception are usually caught and displayed to the user in an appropriate fashion, e.g. by {@link org.cryptomator.ui.unlock.UnlockInvalidMountPointController UnlockInvalidMountPointController.}
*/
public class IllegalMountPointException extends IllegalArgumentException { public class IllegalMountPointException extends IllegalArgumentException {
private final Path mountpoint; public IllegalMountPointException(String msg) {
public IllegalMountPointException(Path mountpoint) {
this(mountpoint, "The provided mountpoint has a problem: " + mountpoint.toString());
}
public IllegalMountPointException(Path mountpoint, String msg) {
super(msg); super(msg);
this.mountpoint = mountpoint;
} }
public Path getMountpoint() { }
return mountpoint;
}
}
@@ -4,18 +4,21 @@ import dagger.Module;
import dagger.Provides; import dagger.Provides;
import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.ObservableUtil;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.Mount;
import org.cryptomator.integrations.mount.MountService; import org.cryptomator.integrations.mount.MountService;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.ConcurrentHashMap;
@Module @Module
public class MountModule { public class MountModule {
private static final AtomicReference<MountService> formerSelectedMountService = new AtomicReference<>(null);
private static final List<String> problematicFuseMountServices = List.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", "org.cryptomator.frontend.fuse.mount.FuseTMountProvider");
@Provides @Provides
@Singleton @Singleton
static List<MountService> provideSupportedMountServices() { static List<MountService> provideSupportedMountServices() {
@@ -24,18 +27,46 @@ public class MountModule {
@Provides @Provides
@Singleton @Singleton
static ObservableValue<MountService> provideDefaultMountService(List<MountService> mountProviders, Settings settings) { @Named("FUPFMS")
var fallbackProvider = mountProviders.stream().findFirst().get(); //there should always be a mount provider, at least webDAV static AtomicReference<MountService> provideFirstUsedProblematicFuseMountService() {
return ObservableUtil.mapWithDefault(settings.mountService, // return new AtomicReference<>(null);
serviceName -> mountProviders.stream().filter(s -> s.getClass().getName().equals(serviceName)).findFirst().orElse(fallbackProvider), //
fallbackProvider);
} }
@Provides @Provides
@Singleton @Singleton
@Named("usedMountServices") static ObservableValue<ActualMountService> provideMountService(Settings settings, List<MountService> serviceImpls, @Named("FUPFMS") AtomicReference<MountService> fupfms) {
static Set<MountService> provideSetOfUsedMountServices() { var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
return ConcurrentHashMap.newKeySet();
var observableMountService = ObservableUtil.mapWithDefault(settings.mountService, //
desiredServiceImpl -> { //
var serviceFromSettings = serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny(); //
var targetedService = serviceFromSettings.orElse(fallbackProvider);
return applyWorkaroundForProblematicFuse(targetedService, serviceFromSettings.isPresent(), fupfms);
}, //
() -> { //
return applyWorkaroundForProblematicFuse(fallbackProvider, true, fupfms);
});
return observableMountService;
} }
} //see https://github.com/cryptomator/cryptomator/issues/2786
private synchronized static ActualMountService applyWorkaroundForProblematicFuse(MountService targetedService, boolean isDesired, AtomicReference<MountService> firstUsedProblematicFuseMountService) {
//set the first used problematic fuse service if applicable
var targetIsProblematicFuse = isProblematicFuseService(targetedService);
if (targetIsProblematicFuse && firstUsedProblematicFuseMountService.get() == null) {
firstUsedProblematicFuseMountService.set(targetedService);
}
//do not use the targeted mount service and fallback to former one, if the service is problematic _and_ not the first problematic one used.
if (targetIsProblematicFuse && !firstUsedProblematicFuseMountService.get().equals(targetedService)) {
return new ActualMountService(formerSelectedMountService.get(), false);
} else {
formerSelectedMountService.set(targetedService);
return new ActualMountService(targetedService, isDesired);
}
}
public static boolean isProblematicFuseService(MountService service) {
return problematicFuseMountServices.contains(service.getClass().getName());
}
}
@@ -1,10 +0,0 @@
package org.cryptomator.common.mount;
import java.nio.file.Path;
public class MountPointCleanupFailedException extends IllegalMountPointException {
public MountPointCleanupFailedException(Path path) {
super(path, "Mountpoint could not be cleared: " + path.toString());
}
}
@@ -1,10 +1,8 @@
package org.cryptomator.common.mount; package org.cryptomator.common.mount;
import java.nio.file.Path;
public class MountPointInUseException extends IllegalMountPointException { public class MountPointInUseException extends IllegalMountPointException {
public MountPointInUseException(Path path) { public MountPointInUseException(String msg) {
super(path); super(msg);
} }
} }
@@ -1,10 +0,0 @@
package org.cryptomator.common.mount;
import java.nio.file.Path;
public class MountPointNotEmptyDirectoryException extends IllegalMountPointException {
public MountPointNotEmptyDirectoryException(Path path, String msg) {
super(path, msg);
}
}
@@ -1,14 +0,0 @@
package org.cryptomator.common.mount;
import java.nio.file.Path;
public class MountPointNotExistingException extends IllegalMountPointException {
public MountPointNotExistingException(Path path, String msg) {
super(path, msg);
}
public MountPointNotExistingException(Path path) {
super(path, "Mountpoint does not exist: " + path);
}
}
@@ -0,0 +1,8 @@
package org.cryptomator.common.mount;
public class MountPointNotExistsException extends IllegalMountPointException {
public MountPointNotExistsException(String msg) {
super(msg);
}
}
@@ -1,10 +1,8 @@
package org.cryptomator.common.mount; package org.cryptomator.common.mount;
import java.nio.file.Path;
public class MountPointNotSupportedException extends IllegalMountPointException { public class MountPointNotSupportedException extends IllegalMountPointException {
public MountPointNotSupportedException(Path path, String msg) { public MountPointNotSupportedException(String msg) {
super(path, msg); super(msg);
} }
} }
@@ -0,0 +1,12 @@
package org.cryptomator.common.mount;
public class MountPointPreparationException extends RuntimeException {
public MountPointPreparationException(String msg) {
super(msg);
}
public MountPointPreparationException(Throwable cause) {
super(cause);
}
}
@@ -1,16 +1,17 @@
package org.cryptomator.common.mount; package org.cryptomator.common.mount;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.LinkOption; import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
public final class MountWithinParentUtil { public final class MountWithinParentUtil {
@@ -21,33 +22,31 @@ public final class MountWithinParentUtil {
private MountWithinParentUtil() {} private MountWithinParentUtil() {}
static void prepareParentNoMountPoint(Path mountPoint) throws IllegalMountPointException, IOException { static void prepareParentNoMountPoint(Path mountPoint) throws MountPointPreparationException {
Path hideaway = getHideaway(mountPoint); Path hideaway = getHideaway(mountPoint);
var mpState = getMountPointState(mountPoint); var mpExists = Files.exists(mountPoint, LinkOption.NOFOLLOW_LINKS);
var hideExists = Files.exists(hideaway, LinkOption.NOFOLLOW_LINKS); var hideExists = Files.exists(hideaway, LinkOption.NOFOLLOW_LINKS);
if (mpState == MountPointState.BROKEN_JUNCTION) { //TODO: possible improvement by just deleting an _empty_ hideaway
LOG.info("Mountpoint \"{}\" is still a junction. Deleting it.", mountPoint); if (mpExists && hideExists) { //both resources exist (whatever type)
Files.delete(mountPoint); //Throws if mountPoint is also a non-empty folder throw new MountPointPreparationException(new FileAlreadyExistsException(hideaway.toString()));
mpState = MountPointState.NOT_EXISTING; } else if (!mpExists && !hideExists) { //neither mountpoint nor hideaway exist
} throw new MountPointPreparationException(new NoSuchFileException(mountPoint.toString()));
} else if (!mpExists) { //only hideaway exists
if (mpState == MountPointState.NOT_EXISTING && !hideExists) { //neither mountpoint nor hideaway exist checkIsDirectory(hideaway);
throw new MountPointNotExistingException(mountPoint);
} else if (mpState == MountPointState.NOT_EXISTING) { //only hideaway exists
checkIsHideawayDirectory(mountPoint, hideaway);
LOG.info("Mountpoint {} seems to be not properly cleaned up. Will be fixed on unmount.", mountPoint); LOG.info("Mountpoint {} seems to be not properly cleaned up. Will be fixed on unmount.", mountPoint);
if (SystemUtils.IS_OS_WINDOWS) {
Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS);
}
} else {
assert mpState == MountPointState.EMPTY_DIR;
try { try {
if (hideExists) { //... with hideaway if (SystemUtils.IS_OS_WINDOWS) {
removeResidualHideaway(mountPoint, hideaway); Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS);
} }
} catch (IOException e) {
throw new MountPointPreparationException(e);
}
} else { //only mountpoint exists
try {
checkIsDirectory(mountPoint);
checkIsEmpty(mountPoint);
//... (now) without hideaway
Files.move(mountPoint, hideaway); Files.move(mountPoint, hideaway);
if (SystemUtils.IS_OS_WINDOWS) { if (SystemUtils.IS_OS_WINDOWS) {
Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS); Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS);
@@ -55,66 +54,30 @@ public final class MountWithinParentUtil {
int attempts = 0; int attempts = 0;
while (!Files.notExists(mountPoint)) { while (!Files.notExists(mountPoint)) {
if (attempts >= 10) { if (attempts >= 10) {
throw new MountPointCleanupFailedException(mountPoint); throw new MountPointPreparationException("Path " + mountPoint + " could not be cleared");
} }
Thread.sleep(1000); Thread.sleep(1000);
attempts++; attempts++;
} }
} catch (IOException e) {
throw new MountPointPreparationException(e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw new RuntimeException(e); throw new MountPointPreparationException(e);
} }
} }
} }
@VisibleForTesting
static MountPointState getMountPointState(Path path) throws IOException, IllegalMountPointException {
if (Files.notExists(path, LinkOption.NOFOLLOW_LINKS)) {
return MountPointState.NOT_EXISTING;
}
if (!Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS).isOther()) {
checkIsMountPointDirectory(path);
checkIsMountPointEmpty(path);
return MountPointState.EMPTY_DIR;
}
if (Files.exists(path /* FOLLOW_LINKS */)) { //Both junction and target exist
throw new MountPointInUseException(path);
}
return MountPointState.BROKEN_JUNCTION;
}
@VisibleForTesting
enum MountPointState {
NOT_EXISTING,
EMPTY_DIR,
BROKEN_JUNCTION;
}
@VisibleForTesting
static void removeResidualHideaway(Path mountPoint, Path hideaway) throws IOException {
checkIsHideawayDirectory(mountPoint, hideaway);
Files.delete(hideaway); //Fails if not empty
}
static void cleanup(Path mountPoint) { static void cleanup(Path mountPoint) {
Path hideaway = getHideaway(mountPoint); Path hideaway = getHideaway(mountPoint);
try { try {
waitForMountpointRestoration(mountPoint); waitForMountpointRestoration(mountPoint);
if (Files.notExists(hideaway, LinkOption.NOFOLLOW_LINKS)) {
LOG.error("Unable to restore hidden directory to mountpoint \"{}\": Directory does not exist.", mountPoint);
return;
}
Files.move(hideaway, mountPoint); Files.move(hideaway, mountPoint);
if (SystemUtils.IS_OS_WINDOWS) { if (SystemUtils.IS_OS_WINDOWS) {
Files.setAttribute(mountPoint, WIN_HIDDEN_ATTR, false); Files.setAttribute(mountPoint, WIN_HIDDEN_ATTR, false);
} }
} catch (IOException e) { } catch (IOException e) {
LOG.error("Unable to restore hidden directory to mountpoint \"{}\".", mountPoint, e); LOG.error("Unable to restore hidden directory to mountpoint {}.", mountPoint, e);
} }
} }
@@ -136,27 +99,21 @@ public final class MountWithinParentUtil {
} }
} }
private static void checkIsMountPointDirectory(Path toCheck) throws IllegalMountPointException { private static void checkIsDirectory(Path toCheck) throws MountPointPreparationException {
if (!Files.isDirectory(toCheck, LinkOption.NOFOLLOW_LINKS)) { if (!Files.isDirectory(toCheck, LinkOption.NOFOLLOW_LINKS)) {
throw new MountPointNotEmptyDirectoryException(toCheck, "Mountpoint is not a directory: " + toCheck); throw new MountPointPreparationException(new NotDirectoryException(toCheck.toString()));
} }
} }
private static void checkIsHideawayDirectory(Path mountPoint, Path hideawayToCheck) { private static void checkIsEmpty(Path toCheck) throws MountPointPreparationException, IOException {
if (!Files.isDirectory(hideawayToCheck, LinkOption.NOFOLLOW_LINKS)) {
throw new HideawayNotDirectoryException(mountPoint, hideawayToCheck);
}
}
private static void checkIsMountPointEmpty(Path toCheck) throws IllegalMountPointException, IOException {
try (var dirStream = Files.list(toCheck)) { try (var dirStream = Files.list(toCheck)) {
if (dirStream.findFirst().isPresent()) { if (dirStream.findFirst().isPresent()) {
throw new MountPointNotEmptyDirectoryException(toCheck, "Mountpoint directory is not empty: " + toCheck); throw new MountPointPreparationException(new DirectoryNotEmptyException(toCheck.toString()));
} }
} }
} }
@VisibleForTesting //visible for testing
static Path getHideaway(Path mountPoint) { static Path getHideaway(Path mountPoint) {
return mountPoint.resolveSibling(HIDEAWAY_PREFIX + mountPoint.getFileName().toString() + HIDEAWAY_SUFFIX); return mountPoint.resolveSibling(HIDEAWAY_PREFIX + mountPoint.getFileName().toString() + HIDEAWAY_SUFFIX);
} }
@@ -7,19 +7,13 @@ import org.cryptomator.integrations.mount.Mount;
import org.cryptomator.integrations.mount.MountBuilder; import org.cryptomator.integrations.mount.MountBuilder;
import org.cryptomator.integrations.mount.MountFailedException; import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.MountService; import org.cryptomator.integrations.mount.MountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER; import static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR; import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR;
@@ -30,41 +24,24 @@ import static org.cryptomator.integrations.mount.MountCapability.UNMOUNT_FORCED;
@Singleton @Singleton
public class Mounter { public class Mounter {
private static final Logger LOG = LoggerFactory.getLogger(Mounter.class);
// mount providers (key) can not be used if any of the conflicting mount providers (values) are already in use
private static final Map<String, Set<String>> CONFLICTING_MOUNT_SERVICES = Map.of(
"org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", Set.of("org.cryptomator.frontend.fuse.mount.FuseTMountProvider"),
"org.cryptomator.frontend.fuse.mount.FuseTMountProvider", Set.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider")
);
private final Environment env;
private final Settings settings; private final Settings settings;
private final Environment env;
private final WindowsDriveLetters driveLetters; private final WindowsDriveLetters driveLetters;
private final List<MountService> mountProviders; private final ObservableValue<ActualMountService> mountServiceObservable;
private final Set<MountService> usedMountServices;
private final ObservableValue<MountService> defaultMountService;
@Inject @Inject
public Mounter(Environment env, // public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue<ActualMountService> mountServiceObservable) {
Settings settings, //
WindowsDriveLetters driveLetters, //
List<MountService> mountProviders, //
@Named("usedMountServices") Set<MountService> usedMountServices, //
ObservableValue<MountService> defaultMountService) {
this.env = env;
this.settings = settings; this.settings = settings;
this.env = env;
this.driveLetters = driveLetters; this.driveLetters = driveLetters;
this.mountProviders = mountProviders; this.mountServiceObservable = mountServiceObservable;
this.usedMountServices = usedMountServices;
this.defaultMountService = defaultMountService;
} }
private class SettledMounter { private class SettledMounter {
private final MountService service; private MountService service;
private final MountBuilder builder; private MountBuilder builder;
private final VaultSettings vaultSettings; private VaultSettings vaultSettings;
public SettledMounter(MountService service, MountBuilder builder, VaultSettings vaultSettings) { public SettledMounter(MountService service, MountBuilder builder, VaultSettings vaultSettings) {
this.service = service; this.service = service;
@@ -76,13 +53,8 @@ public class Mounter {
for (var capability : service.capabilities()) { for (var capability : service.capabilities()) {
switch (capability) { switch (capability) {
case FILE_SYSTEM_NAME -> builder.setFileSystemName("cryptoFs"); case FILE_SYSTEM_NAME -> builder.setFileSystemName("cryptoFs");
case LOOPBACK_PORT -> { case LOOPBACK_PORT ->
if (vaultSettings.mountService.getValue() == null) { builder.setLoopbackPort(settings.port.get()); //TODO: move port from settings to vaultsettings (see https://github.com/cryptomator/cryptomator/tree/feature/mount-setting-per-vault)
builder.setLoopbackPort(settings.port.get());
} else {
builder.setLoopbackPort(vaultSettings.port.get());
}
}
case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName); case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName);
case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode.get()); case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode.get());
case MOUNT_FLAGS -> { case MOUNT_FLAGS -> {
@@ -127,11 +99,13 @@ public class Mounter {
var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\"); var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\");
if (mpIsDriveLetter) { if (mpIsDriveLetter) {
if (driveLetters.getOccupied().contains(userChosenMountPoint)) { if (driveLetters.getOccupied().contains(userChosenMountPoint)) {
throw new MountPointInUseException(userChosenMountPoint); throw new MountPointInUseException(userChosenMountPoint.toString());
} }
} else if (canMountToParent && !canMountToDir) { } else if (canMountToParent && !canMountToDir) {
MountWithinParentUtil.prepareParentNoMountPoint(userChosenMountPoint); MountWithinParentUtil.prepareParentNoMountPoint(userChosenMountPoint);
cleanup = () -> MountWithinParentUtil.cleanup(userChosenMountPoint); cleanup = () -> {
MountWithinParentUtil.cleanup(userChosenMountPoint);
};
} }
try { try {
builder.setMountpoint(userChosenMountPoint); builder.setMountpoint(userChosenMountPoint);
@@ -141,13 +115,13 @@ public class Mounter {
|| (!canMountToParent && !mpIsDriveLetter) // || (!canMountToParent && !mpIsDriveLetter) //
|| (!canMountToDir && !canMountToParent && !canMountToSystem && !canMountToDriveLetter); || (!canMountToDir && !canMountToParent && !canMountToSystem && !canMountToDriveLetter);
if (configNotSupported) { if (configNotSupported) {
throw new MountPointNotSupportedException(userChosenMountPoint, e.getMessage()); throw new MountPointNotSupportedException(e.getMessage());
} else if (canMountToDir && !canMountToParent && !Files.exists(userChosenMountPoint)) { } else if (canMountToDir && !canMountToParent && !Files.exists(userChosenMountPoint)) {
//mountpoint must exist //mountpoint must exist
throw new MountPointNotExistingException(userChosenMountPoint, e.getMessage()); throw new MountPointNotExistsException(e.getMessage());
} else { } else {
//TODO: add specific exception for !canMountToDir && canMountToParent && !Files.notExists(userChosenMountPoint) //TODO: add specific exception for !canMountToDir && canMountToParent && !Files.notExists(userChosenMountPoint)
throw new IllegalMountPointException(userChosenMountPoint, e.getMessage()); throw new IllegalMountPointException(e.getMessage());
} }
} }
} }
@@ -157,26 +131,13 @@ public class Mounter {
} }
public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException { public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException {
var mountService = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defaultMountService.getValue()); var mountService = this.mountServiceObservable.getValue().service();
if (isConflictingMountService(mountService)) {
var msg = STR."\{mountService.getClass()} unavailable due to conflict with either of \{CONFLICTING_MOUNT_SERVICES.get(mountService.getClass().getName())}";
throw new ConflictingMountServiceException(msg);
}
usedMountServices.add(mountService);
var builder = mountService.forFileSystem(cryptoFsRoot); var builder = mountService.forFileSystem(cryptoFsRoot);
var internal = new SettledMounter(mountService, builder, vaultSettings); // FIXME: no need for an inner class var internal = new SettledMounter(mountService, builder, vaultSettings);
var cleanup = internal.prepare(); var cleanup = internal.prepare();
return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup); return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup);
} }
public boolean isConflictingMountService(MountService service) {
var conflictingServices = CONFLICTING_MOUNT_SERVICES.getOrDefault(service.getClass().getName(), Set.of());
return usedMountServices.stream().map(MountService::getClass).map(Class::getName).anyMatch(conflictingServices::contains);
}
public record MountHandle(Mount mountObj, boolean supportsUnmountForced, Runnable specialCleanup) { public record MountHandle(Mount mountObj, boolean supportsUnmountForced, Runnable specialCleanup) {
} }
@@ -25,7 +25,6 @@ import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.geometry.NodeOrientation; import javafx.geometry.NodeOrientation;
import java.time.Instant;
import java.util.function.Consumer; import java.util.function.Consumer;
public class Settings { public class Settings {
@@ -37,21 +36,16 @@ public class Settings {
static final boolean DEFAULT_START_HIDDEN = false; static final boolean DEFAULT_START_HIDDEN = false;
static final boolean DEFAULT_AUTO_CLOSE_VAULTS = false; static final boolean DEFAULT_AUTO_CLOSE_VAULTS = false;
static final boolean DEFAULT_USE_KEYCHAIN = true; static final boolean DEFAULT_USE_KEYCHAIN = true;
static final boolean DEFAULT_USE_QUICKACCESS = true;
static final int DEFAULT_PORT = 42427; static final int DEFAULT_PORT = 42427;
static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3; static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
static final boolean DEFAULT_DEBUG_MODE = false; static final boolean DEFAULT_DEBUG_MODE = false;
static final UiTheme DEFAULT_THEME = UiTheme.LIGHT; static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
@Deprecated // to be changed to "whatever is available" eventually @Deprecated // to be changed to "whatever is available" eventually
static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : // static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : "org.cryptomator.linux.keychain.SecretServiceKeychainAccess";
SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : //
"org.cryptomator.linux.keychain.SecretServiceKeychainAccess";
static final String DEFAULT_QUICKACCESS_SERVICE = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.quickaccess.ExplorerQuickAccessService" : //
SystemUtils.IS_OS_LINUX ? "org.cryptomator.linux.quickaccess.NautilusBookmarks" : null;
static final String DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT.name(); static final String DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT.name();
static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false; static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
public static final Instant DEFAULT_TIMESTAMP = Instant.parse("2000-01-01T00:00:00Z"); static final String DEFAULT_LAST_UPDATE_CHECK = "2000-01-01";
public final ObservableList<VaultSettings> directories; public final ObservableList<VaultSettings> directories;
public final BooleanProperty askedForUpdateCheck; public final BooleanProperty askedForUpdateCheck;
public final BooleanProperty checkForUpdates; public final BooleanProperty checkForUpdates;
@@ -63,8 +57,6 @@ public class Settings {
public final BooleanProperty debugMode; public final BooleanProperty debugMode;
public final ObjectProperty<UiTheme> theme; public final ObjectProperty<UiTheme> theme;
public final StringProperty keychainProvider; public final StringProperty keychainProvider;
public final BooleanProperty useQuickAccess;
public final StringProperty quickAccessService;
public final ObjectProperty<NodeOrientation> userInterfaceOrientation; public final ObjectProperty<NodeOrientation> userInterfaceOrientation;
public final StringProperty licenseKey; public final StringProperty licenseKey;
public final BooleanProperty showMinimizeButton; public final BooleanProperty showMinimizeButton;
@@ -73,9 +65,10 @@ public class Settings {
public final IntegerProperty windowYPosition; public final IntegerProperty windowYPosition;
public final IntegerProperty windowWidth; public final IntegerProperty windowWidth;
public final IntegerProperty windowHeight; public final IntegerProperty windowHeight;
public final StringProperty displayConfiguration;
public final StringProperty language; public final StringProperty language;
public final StringProperty mountService; public final StringProperty mountService;
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck; public final StringProperty lastUpdateCheck;
private Consumer<Settings> saveCmd; private Consumer<Settings> saveCmd;
@@ -97,7 +90,6 @@ public class Settings {
this.startHidden = new SimpleBooleanProperty(this, "startHidden", json.startHidden); this.startHidden = new SimpleBooleanProperty(this, "startHidden", json.startHidden);
this.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults); this.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults);
this.useKeychain = new SimpleBooleanProperty(this, "useKeychain", json.useKeychain); this.useKeychain = new SimpleBooleanProperty(this, "useKeychain", json.useKeychain);
this.useQuickAccess = new SimpleBooleanProperty(this, "addToQuickAccess", json.useQuickAccess);
this.port = new SimpleIntegerProperty(this, "webDavPort", json.port); this.port = new SimpleIntegerProperty(this, "webDavPort", json.port);
this.numTrayNotifications = new SimpleIntegerProperty(this, "numTrayNotifications", json.numTrayNotifications); this.numTrayNotifications = new SimpleIntegerProperty(this, "numTrayNotifications", json.numTrayNotifications);
this.debugMode = new SimpleBooleanProperty(this, "debugMode", json.debugMode); this.debugMode = new SimpleBooleanProperty(this, "debugMode", json.debugMode);
@@ -111,10 +103,10 @@ public class Settings {
this.windowYPosition = new SimpleIntegerProperty(this, "windowYPosition", json.windowYPosition); this.windowYPosition = new SimpleIntegerProperty(this, "windowYPosition", json.windowYPosition);
this.windowWidth = new SimpleIntegerProperty(this, "windowWidth", json.windowWidth); this.windowWidth = new SimpleIntegerProperty(this, "windowWidth", json.windowWidth);
this.windowHeight = new SimpleIntegerProperty(this, "windowHeight", json.windowHeight); this.windowHeight = new SimpleIntegerProperty(this, "windowHeight", json.windowHeight);
this.displayConfiguration = new SimpleStringProperty(this, "displayConfiguration", json.displayConfiguration);
this.language = new SimpleStringProperty(this, "language", json.language); this.language = new SimpleStringProperty(this, "language", json.language);
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService); this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
this.quickAccessService = new SimpleStringProperty(this, "quickAccessService", json.quickAccessService); this.lastUpdateCheck = new SimpleStringProperty(this, "lastUpdateCheck", json.lastUpdateCheck);
this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList()); this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
@@ -126,7 +118,6 @@ public class Settings {
startHidden.addListener(this::somethingChanged); startHidden.addListener(this::somethingChanged);
autoCloseVaults.addListener(this::somethingChanged); autoCloseVaults.addListener(this::somethingChanged);
useKeychain.addListener(this::somethingChanged); useKeychain.addListener(this::somethingChanged);
useQuickAccess.addListener(this::somethingChanged);
port.addListener(this::somethingChanged); port.addListener(this::somethingChanged);
numTrayNotifications.addListener(this::somethingChanged); numTrayNotifications.addListener(this::somethingChanged);
debugMode.addListener(this::somethingChanged); debugMode.addListener(this::somethingChanged);
@@ -140,10 +131,10 @@ public class Settings {
windowYPosition.addListener(this::somethingChanged); windowYPosition.addListener(this::somethingChanged);
windowWidth.addListener(this::somethingChanged); windowWidth.addListener(this::somethingChanged);
windowHeight.addListener(this::somethingChanged); windowHeight.addListener(this::somethingChanged);
displayConfiguration.addListener(this::somethingChanged);
language.addListener(this::somethingChanged); language.addListener(this::somethingChanged);
mountService.addListener(this::somethingChanged); mountService.addListener(this::somethingChanged);
quickAccessService.addListener(this::somethingChanged); lastUpdateCheck.addListener(this::somethingChanged);
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@@ -182,7 +173,6 @@ public class Settings {
json.startHidden = startHidden.get(); json.startHidden = startHidden.get();
json.autoCloseVaults = autoCloseVaults.get(); json.autoCloseVaults = autoCloseVaults.get();
json.useKeychain = useKeychain.get(); json.useKeychain = useKeychain.get();
json.useQuickAccess = useQuickAccess.get();
json.port = port.get(); json.port = port.get();
json.numTrayNotifications = numTrayNotifications.get(); json.numTrayNotifications = numTrayNotifications.get();
json.debugMode = debugMode.get(); json.debugMode = debugMode.get();
@@ -196,10 +186,10 @@ public class Settings {
json.windowYPosition = windowYPosition.get(); json.windowYPosition = windowYPosition.get();
json.windowWidth = windowWidth.get(); json.windowWidth = windowWidth.get();
json.windowHeight = windowHeight.get(); json.windowHeight = windowHeight.get();
json.displayConfiguration = displayConfiguration.get();
json.language = language.get(); json.language = language.get();
json.mountService = mountService.get(); json.mountService = mountService.get();
json.quickAccessService = quickAccessService.get(); json.lastUpdateCheck = lastUpdateCheck.get();
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
return json; return json;
} }
@@ -1,11 +1,9 @@
package org.cryptomator.common.settings; package org.cryptomator.common.settings;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
import java.util.List; import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@@ -33,6 +31,9 @@ class SettingsJson {
@JsonProperty("theme") @JsonProperty("theme")
UiTheme theme = Settings.DEFAULT_THEME; UiTheme theme = Settings.DEFAULT_THEME;
@JsonProperty("displayConfiguration")
String displayConfiguration;
@JsonProperty("keychainProvider") @JsonProperty("keychainProvider")
String keychainProvider = Settings.DEFAULT_KEYCHAIN_PROVIDER; String keychainProvider = Settings.DEFAULT_KEYCHAIN_PROVIDER;
@@ -82,13 +83,7 @@ class SettingsJson {
@JsonProperty(value = "preferredVolumeImpl", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233 @JsonProperty(value = "preferredVolumeImpl", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233
String preferredVolumeImpl; String preferredVolumeImpl;
@JsonProperty("lastSuccessfulUpdateCheck") @JsonProperty("lastUpdateCheck")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC") String lastUpdateCheck = Settings.DEFAULT_LAST_UPDATE_CHECK;
Instant lastSuccessfulUpdateCheck = Settings.DEFAULT_TIMESTAMP;
@JsonProperty("useQuickAccess")
boolean useQuickAccess = Settings.DEFAULT_USE_QUICKACCESS;
@JsonProperty("quickAccessService")
String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE;
} }
@@ -10,7 +10,6 @@ package org.cryptomator.common.settings;
import com.fasterxml.jackson.core.JacksonException; import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import org.cryptomator.common.Environment; import org.cryptomator.common.Environment;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -37,7 +36,7 @@ import java.util.stream.Stream;
@Singleton @Singleton
public class SettingsProvider implements Supplier<Settings> { public class SettingsProvider implements Supplier<Settings> {
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true).registerModule(new JavaTimeModule()); private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true);
private static final Logger LOG = LoggerFactory.getLogger(SettingsProvider.class); private static final Logger LOG = LoggerFactory.getLogger(SettingsProvider.class);
private static final long SAVE_DELAY_MS = 1000; private static final long SAVE_DELAY_MS = 1000;
@@ -58,10 +57,7 @@ public class SettingsProvider implements Supplier<Settings> {
} }
private Settings load() { private Settings load() {
Settings settings = env.getSettingsPath() // Settings settings = env.getSettingsPath().flatMap(this::tryLoad).findFirst().orElseGet(() -> Settings.create(env));
.flatMap(this::tryLoad) //
.findFirst() //
.orElseGet(() -> Settings.create(env));
settings.setSaveCmd(this::scheduleSave); settings.setSaveCmd(this::scheduleSave);
return settings; return settings;
} }
@@ -8,7 +8,7 @@ package org.cryptomator.common.settings;
import com.google.common.base.CharMatcher; import com.google.common.base.CharMatcher;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.io.BaseEncoding; import com.google.common.io.BaseEncoding;
import org.jetbrains.annotations.VisibleForTesting; import org.apache.commons.lang3.SystemUtils;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
@@ -39,7 +39,6 @@ public class VaultSettings {
static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK; static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false; static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false;
static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60; static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60;
static final int DEFAULT_PORT = 42427;
private static final Random RNG = new Random(); private static final Random RNG = new Random();
@@ -56,8 +55,6 @@ public class VaultSettings {
public final IntegerProperty autoLockIdleSeconds; public final IntegerProperty autoLockIdleSeconds;
public final ObjectProperty<Path> mountPoint; public final ObjectProperty<Path> mountPoint;
public final StringExpression mountName; public final StringExpression mountName;
public final StringProperty mountService;
public final IntegerProperty port;
VaultSettings(VaultSettingsJson json) { VaultSettings(VaultSettingsJson json) {
this.id = json.id; this.id = json.id;
@@ -72,8 +69,6 @@ public class VaultSettings {
this.autoLockWhenIdle = new SimpleBooleanProperty(this, "autoLockWhenIdle", json.autoLockWhenIdle); this.autoLockWhenIdle = new SimpleBooleanProperty(this, "autoLockWhenIdle", json.autoLockWhenIdle);
this.autoLockIdleSeconds = new SimpleIntegerProperty(this, "autoLockIdleSeconds", json.autoLockIdleSeconds); this.autoLockIdleSeconds = new SimpleIntegerProperty(this, "autoLockIdleSeconds", json.autoLockIdleSeconds);
this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint)); this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint));
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
this.port = new SimpleIntegerProperty(this, "port", json.port);
// mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318 // mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318
this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> { this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> {
final String name; final String name;
@@ -99,7 +94,7 @@ public class VaultSettings {
} }
Observable[] observables() { Observable[] observables() {
return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService}; return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode};
} }
public static VaultSettings withRandomId() { public static VaultSettings withRandomId() {
@@ -128,12 +123,10 @@ public class VaultSettings {
json.autoLockWhenIdle = autoLockWhenIdle.get(); json.autoLockWhenIdle = autoLockWhenIdle.get();
json.autoLockIdleSeconds = autoLockIdleSeconds.get(); json.autoLockIdleSeconds = autoLockIdleSeconds.get();
json.mountPoint = mountPoint.map(Path::toString).getValue(); json.mountPoint = mountPoint.map(Path::toString).getValue();
json.mountService = mountService.get();
json.port = port.get();
return json; return json;
} }
@VisibleForTesting //visible for testing
static String normalizeDisplayName(String original) { static String normalizeDisplayName(String original) {
if (original.isBlank() || ".".equals(original) || "..".equals(original)) { if (original.isBlank() || ".".equals(original) || "..".equals(original)) {
return "_"; return "_";
@@ -45,12 +45,6 @@ class VaultSettingsJson {
@JsonProperty("autoLockIdleSeconds") @JsonProperty("autoLockIdleSeconds")
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS; int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
@JsonProperty("mountService")
String mountService;
@JsonProperty("port")
int port = VaultSettings.DEFAULT_PORT;
@Deprecated(since = "1.7.0") @Deprecated(since = "1.7.0")
@JsonProperty(value = "winDriveLetter", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233 @JsonProperty(value = "winDriveLetter", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233
String winDriveLetter; String winDriveLetter;
@@ -11,7 +11,7 @@ package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants; import org.cryptomator.common.Constants;
import org.cryptomator.common.mount.Mounter; import org.cryptomator.common.mount.Mounter;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem; import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties; import org.cryptomator.cryptofs.CryptoFileSystemProperties;
@@ -24,9 +24,6 @@ import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.cryptomator.integrations.mount.MountFailedException; import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.Mountpoint; import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException; import org.cryptomator.integrations.mount.UnmountFailedException;
import org.cryptomator.integrations.quickaccess.QuickAccessService;
import org.cryptomator.integrations.quickaccess.QuickAccessServiceException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -58,7 +55,6 @@ public class Vault {
private final VaultSettings vaultSettings; private final VaultSettings vaultSettings;
private final AtomicReference<CryptoFileSystem> cryptoFileSystem; private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final AtomicReference<QuickAccessService.QuickAccessEntry> quickAccessEntry;
private final VaultState state; private final VaultState state;
private final ObjectProperty<Exception> lastKnownException; private final ObjectProperty<Exception> lastKnownException;
private final VaultConfigCache configCache; private final VaultConfigCache configCache;
@@ -72,19 +68,12 @@ public class Vault {
private final BooleanBinding unknownError; private final BooleanBinding unknownError;
private final ObjectBinding<Mountpoint> mountPoint; private final ObjectBinding<Mountpoint> mountPoint;
private final Mounter mounter; private final Mounter mounter;
private final Settings settings;
private final BooleanProperty showingStats; private final BooleanProperty showingStats;
private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null); private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@Inject @Inject
Vault(VaultSettings vaultSettings, // Vault(VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats, WindowsDriveLetters windowsDriveLetters, Mounter mounter) {
VaultConfigCache configCache, //
AtomicReference<CryptoFileSystem> cryptoFileSystem, //
VaultState state, //
@Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
VaultStats stats, //
Mounter mounter, Settings settings) {
this.vaultSettings = vaultSettings; this.vaultSettings = vaultSettings;
this.configCache = configCache; this.configCache = configCache;
this.cryptoFileSystem = cryptoFileSystem; this.cryptoFileSystem = cryptoFileSystem;
@@ -100,9 +89,7 @@ public class Vault {
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state); this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state); this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
this.mounter = mounter; this.mounter = mounter;
this.settings = settings;
this.showingStats = new SimpleBooleanProperty(false); this.showingStats = new SimpleBooleanProperty(false);
this.quickAccessEntry = new AtomicReference<>(null);
} }
// ****************************************************************************** // ******************************************************************************
@@ -162,9 +149,6 @@ public class Vault {
var rootPath = fs.getRootDirectories().iterator().next(); var rootPath = fs.getRootDirectories().iterator().next();
var mountHandle = mounter.mount(vaultSettings, rootPath); var mountHandle = mounter.mount(vaultSettings, rootPath);
success = this.mountHandle.compareAndSet(null, mountHandle); success = this.mountHandle.compareAndSet(null, mountHandle);
if (settings.useQuickAccess.getValue()) {
addToQuickAccess();
}
} finally { } finally {
if (!success) { if (!success) {
destroyCryptoFileSystem(); destroyCryptoFileSystem();
@@ -189,7 +173,6 @@ public class Vault {
mountHandle.mountObj().close(); mountHandle.mountObj().close();
mountHandle.specialCleanup().run(); mountHandle.specialCleanup().run();
} finally { } finally {
removeFromQuickAccess();
destroyCryptoFileSystem(); destroyCryptoFileSystem();
} }
@@ -197,52 +180,6 @@ public class Vault {
LOG.info("Locked vault '{}'", getDisplayName()); LOG.info("Locked vault '{}'", getDisplayName());
} }
private synchronized void addToQuickAccess() {
if (quickAccessEntry.get() != null) {
//we don't throw an exception since we don't wanna block unlocking
LOG.warn("Vault already added to quick access area. Will be removed on next lock operation.");
return;
}
QuickAccessService.get() //
.filter(s -> s.getClass().getName().equals(settings.quickAccessService.getValue())) //
.findFirst() //
.ifPresentOrElse( //
this::addToQuickAccessInternal, //
() -> LOG.warn("Unable to add Vault to quick access area: Desired implementation not available.") //
);
}
private void addToQuickAccessInternal(@NotNull QuickAccessService s) {
if (getMountPoint() instanceof Mountpoint.WithPath mp) {
try {
var entry = s.add(mp.path(), getDisplayName());
quickAccessEntry.set(entry);
} catch (QuickAccessServiceException e) {
LOG.error("Adding vault to quick access area failed", e);
}
} else {
LOG.warn("Unable to add vault to quick access area: Vault is not mounted to local system path.");
}
}
private synchronized void removeFromQuickAccess() {
if (quickAccessEntry.get() == null) {
LOG.debug("Removing vault from quick access area: Entry not found, nothing to do.");
return;
}
removeFromQuickAccessInternal();
}
private void removeFromQuickAccessInternal() {
try {
quickAccessEntry.get().remove();
quickAccessEntry.set(null);
} catch (QuickAccessServiceException e) {
LOG.error("Removing vault from quick access area failed", e);
}
}
// ****************************************************************************** // ******************************************************************************
// Observable Properties // Observable Properties
// ******************************************************************************* // *******************************************************************************
@@ -377,6 +314,10 @@ public class Vault {
return vaultSettings.path.get(); return vaultSettings.path.get();
} }
CryptoFileSystem getCryptoFileSystem() {
return cryptoFileSystem.get();
}
/** /**
* Gets from the cleartext path its ciphertext counterpart. * Gets from the cleartext path its ciphertext counterpart.
* *
@@ -385,23 +326,7 @@ public class Vault {
* @throws IllegalStateException if the vault is not unlocked * @throws IllegalStateException if the vault is not unlocked
*/ */
public Path getCiphertextPath(Path cleartextPath) throws IOException { public Path getCiphertextPath(Path cleartextPath) throws IOException {
if (!state.getValue().equals(VaultState.Value.UNLOCKED)) { return state.get().getCiphertextPath(this, cleartextPath);
throw new IllegalStateException("Vault is not unlocked");
}
var fs = cryptoFileSystem.get();
var osPathSeparator = cleartextPath.getFileSystem().getSeparator();
var cryptoFsPathSeparator = fs.getSeparator();
if (getMountPoint() instanceof Mountpoint.WithPath mp) {
var absoluteCryptoFsPath = cryptoFsPathSeparator + mp.path().relativize(cleartextPath).toString();
if (!cryptoFsPathSeparator.equals(osPathSeparator)) {
absoluteCryptoFsPath = absoluteCryptoFsPath.replace(osPathSeparator, cryptoFsPathSeparator);
}
var cryptoPath = fs.getPath(absoluteCryptoFsPath);
return fs.getCiphertextPath(cryptoPath);
} else {
throw new UnsupportedOperationException("URI mount points not supported.");
}
} }
public VaultConfigCache getVaultConfigCache() { public VaultConfigCache getVaultConfigCache() {
@@ -8,13 +8,11 @@
*******************************************************************************/ *******************************************************************************/
package org.cryptomator.common.vaults; package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystemProvider; import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.DirStructure; import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.cryptofs.migration.Migrators; import org.cryptomator.cryptofs.migration.Migrators;
import org.cryptomator.integrations.mount.MountService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -26,7 +24,6 @@ import java.nio.file.Files;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@@ -41,21 +38,14 @@ public class VaultListManager {
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class); private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
private final AutoLocker autoLocker; private final AutoLocker autoLocker;
private final List<MountService> mountServices;
private final VaultComponent.Factory vaultComponentFactory; private final VaultComponent.Factory vaultComponentFactory;
private final ObservableList<Vault> vaultList; private final ObservableList<Vault> vaultList;
private final String defaultVaultName; private final String defaultVaultName;
@Inject @Inject
public VaultListManager(ObservableList<Vault> vaultList, // public VaultListManager(ObservableList<Vault> vaultList, AutoLocker autoLocker, VaultComponent.Factory vaultComponentFactory, ResourceBundle resourceBundle, Settings settings) {
AutoLocker autoLocker, //
List<MountService> mountServices,
VaultComponent.Factory vaultComponentFactory,
ResourceBundle resourceBundle,
Settings settings) {
this.vaultList = vaultList; this.vaultList = vaultList;
this.autoLocker = autoLocker; this.autoLocker = autoLocker;
this.mountServices = mountServices;
this.vaultComponentFactory = vaultComponentFactory; this.vaultComponentFactory = vaultComponentFactory;
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName"); this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
@@ -86,15 +76,6 @@ public class VaultListManager {
} else { } else {
vaultSettings.displayName.set(defaultVaultName); vaultSettings.displayName.set(defaultVaultName);
} }
//due to https://github.com/cryptomator/cryptomator/issues/2880#issuecomment-1680313498
var nameOfWinfspLocalMounter = "org.cryptomator.frontend.fuse.mount.WinFspMountProvider";
if (SystemUtils.IS_OS_WINDOWS //
&& vaultSettings.path.get().toString().contains("Dropbox") //
&& mountServices.stream().anyMatch(s -> s.getClass().getName().equals(nameOfWinfspLocalMounter))) {
vaultSettings.mountService.setValue(nameOfWinfspLocalMounter);
}
return vaultSettings; return vaultSettings;
} }
@@ -1,6 +1,7 @@
package org.cryptomator.common.vaults; package org.cryptomator.common.vaults;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import org.cryptomator.integrations.mount.Mountpoint;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -8,6 +9,8 @@ import javax.inject.Inject;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ObservableObjectValue; import javafx.beans.value.ObservableObjectValue;
import javafx.beans.value.ObservableValueBase; import javafx.beans.value.ObservableValueBase;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
@@ -43,12 +46,40 @@ public class VaultState extends ObservableValueBase<VaultState.Value> implements
/** /**
* Vault is unlocked * Vault is unlocked
*/ */
UNLOCKED, UNLOCKED {
/**
* Gets from the cleartext path its ciphertext counterpart.
*
* @return Local os path to the ciphertext resource
* @throws IOException if an I/O error occurs
* @throws IllegalStateException if the vault is not unlocked
*/
Path getCiphertextPath(Vault vault, Path cleartextPath) throws IOException {
var fs = vault.getCryptoFileSystem();
var osPathSeparator = cleartextPath.getFileSystem().getSeparator();
var cryptoFsPathSeparator = fs.getSeparator();
if (vault.getMountPoint() instanceof Mountpoint.WithPath mp) {
var absoluteCryptoFsPath = cryptoFsPathSeparator + mp.path().relativize(cleartextPath).toString();
if (!cryptoFsPathSeparator.equals(osPathSeparator)) {
absoluteCryptoFsPath = absoluteCryptoFsPath.replace(osPathSeparator, cryptoFsPathSeparator);
}
var cryptoPath = fs.getPath(absoluteCryptoFsPath);
return fs.getCiphertextPath(cryptoPath);
} else {
throw new UnsupportedOperationException("URI mount points not supported.");
}
}
},
/** /**
* Unknown state due to preceding unrecoverable exceptions. * Unknown state due to preceding unrecoverable exceptions.
*/ */
ERROR; ERROR;
Path getCiphertextPath(Vault vault, Path cleartextPath) throws IOException {
throw new IllegalStateException("Vault is not unlocked");
}
} }
private final AtomicReference<Value> value; private final AtomicReference<Value> value;
@@ -6,7 +6,6 @@
*******************************************************************************/ *******************************************************************************/
package org.cryptomator.launcher; package org.cryptomator.launcher;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -49,7 +48,7 @@ class FileOpenRequestHandler {
handleLaunchArgs(FileSystems.getDefault(), args); handleLaunchArgs(FileSystems.getDefault(), args);
} }
@VisibleForTesting // visible for testing
void handleLaunchArgs(FileSystem fs, List<String> args) { void handleLaunchArgs(FileSystem fs, List<String> args) {
Collection<Path> pathsToOpen = args.stream().map(str -> { Collection<Path> pathsToOpen = args.stream().map(str -> {
try { try {
@@ -5,7 +5,6 @@ import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.Configurator; import ch.qos.logback.classic.spi.Configurator;
import ch.qos.logback.classic.spi.ConfiguratorRank;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender; import ch.qos.logback.core.Appender;
import ch.qos.logback.core.ConsoleAppender; import ch.qos.logback.core.ConsoleAppender;
@@ -20,7 +19,6 @@ import org.cryptomator.common.Environment;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Map; import java.util.Map;
@ConfiguratorRank(ConfiguratorRank.CUSTOM_NORMAL_PRIORITY)
public class LogbackConfigurator extends ContextAwareBase implements Configurator { public class LogbackConfigurator extends ContextAwareBase implements Configurator {
private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"; private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
@@ -45,8 +45,9 @@ public abstract class AddVaultModule {
@Provides @Provides
@AddVaultWizardWindow @AddVaultWizardWindow
@AddVaultWizardScoped @AddVaultWizardScoped
static Stage provideStage(StageFactory factory, @PrimaryStage Stage primaryStage) { static Stage provideStage(StageFactory factory, @PrimaryStage Stage primaryStage, ResourceBundle resourceBundle) {
Stage stage = factory.create(); Stage stage = factory.create();
stage.setTitle(resourceBundle.getString("addvaultwizard.title"));
stage.setResizable(false); stage.setResizable(false);
stage.initModality(Modality.WINDOW_MODAL); stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(primaryStage); stage.initOwner(primaryStage);
@@ -89,6 +90,13 @@ public abstract class AddVaultModule {
// ------------------ // ------------------
@Provides
@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
@AddVaultWizardScoped
static Scene provideWelcomeScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_WELCOME);
}
@Provides @Provides
@FxmlScene(FxmlFile.ADDVAULT_EXISTING) @FxmlScene(FxmlFile.ADDVAULT_EXISTING)
@AddVaultWizardScoped @AddVaultWizardScoped
@@ -140,6 +148,11 @@ public abstract class AddVaultModule {
// ------------------ // ------------------
@Binds
@IntoMap
@FxControllerKey(AddVaultWelcomeController.class)
abstract FxController bindWelcomeController(AddVaultWelcomeController controller);
@Binds @Binds
@IntoMap @IntoMap
@FxControllerKey(ChooseExistingVaultController.class) @FxControllerKey(ChooseExistingVaultController.class)
@@ -0,0 +1,38 @@
package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.scene.Scene;
import javafx.stage.Stage;
@AddVaultWizardScoped
public class AddVaultWelcomeController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(AddVaultWelcomeController.class);
private final Stage window;
private final Lazy<Scene> chooseExistingVaultScene;
private final Lazy<Scene> createNewVaultScene;
@Inject
AddVaultWelcomeController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_EXISTING) Lazy<Scene> chooseExistingVaultScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> createNewVaultScene) {
this.window = window;
this.chooseExistingVaultScene = chooseExistingVaultScene;
this.createNewVaultScene = createNewVaultScene;
}
public void createNewVault() {
LOG.debug("AddVaultWelcomeController.createNewVault()");
window.setScene(createNewVaultScene.get());
}
public void chooseExistingVault() {
LOG.debug("AddVaultWelcomeController.chooseExistingVault()");
window.setScene(chooseExistingVaultScene.get());
}
}
@@ -12,7 +12,6 @@ import org.cryptomator.ui.common.FxmlScene;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.util.ResourceBundle;
@AddVaultWizardScoped @AddVaultWizardScoped
@Subcomponent(modules = {AddVaultModule.class}) @Subcomponent(modules = {AddVaultModule.class})
@@ -21,23 +20,12 @@ public interface AddVaultWizardComponent {
@AddVaultWizardWindow @AddVaultWizardWindow
Stage window(); Stage window();
@FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) @FxmlScene(FxmlFile.ADDVAULT_WELCOME)
Lazy<Scene> sceneNew(); Lazy<Scene> scene();
@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
Lazy<Scene> sceneExisting();
default void showAddNewVaultWizard(ResourceBundle resourceBundle) { default void showAddVaultWizard() {
Stage stage = window(); Stage stage = window();
stage.setScene(sceneNew().get()); stage.setScene(scene().get());
stage.setTitle(resourceBundle.getString("addvaultwizard.new.title"));
stage.sizeToScene();
stage.show();
}
default void showAddExistingVaultWizard(ResourceBundle resourceBundle) {
Stage stage = window();
stage.setScene(sceneExisting().get());
stage.setTitle(resourceBundle.getString("addvaultwizard.existing.title"));
stage.sizeToScene(); stage.sizeToScene();
stage.show(); stage.show();
} }
@@ -35,6 +35,7 @@ public class ChooseExistingVaultController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(ChooseExistingVaultController.class); private static final Logger LOG = LoggerFactory.getLogger(ChooseExistingVaultController.class);
private final Stage window; private final Stage window;
private final Lazy<Scene> welcomeScene;
private final Lazy<Scene> successScene; private final Lazy<Scene> successScene;
private final FxApplicationWindows appWindows; private final FxApplicationWindows appWindows;
private final ObjectProperty<Path> vaultPath; private final ObjectProperty<Path> vaultPath;
@@ -44,15 +45,9 @@ public class ChooseExistingVaultController implements FxController {
private final ObservableValue<Image> screenshot; private final ObservableValue<Image> screenshot;
@Inject @Inject
ChooseExistingVaultController(@AddVaultWizardWindow Stage window, // ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, FxApplicationWindows appWindows, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, VaultListManager vaultListManager, ResourceBundle resourceBundle, FxApplicationStyle applicationStyle) {
@FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, //
FxApplicationWindows appWindows, //
ObjectProperty<Path> vaultPath, //
@AddVaultWizardWindow ObjectProperty<Vault> vault, //
VaultListManager vaultListManager, //
ResourceBundle resourceBundle, //
FxApplicationStyle applicationStyle) {
this.window = window; this.window = window;
this.welcomeScene = welcomeScene;
this.successScene = successScene; this.successScene = successScene;
this.appWindows = appWindows; this.appWindows = appWindows;
this.vaultPath = vaultPath; this.vaultPath = vaultPath;
@@ -75,6 +70,11 @@ public class ChooseExistingVaultController implements FxController {
return new Image((Objects.requireNonNull(getClass().getResource(imageResourcePath)).toString())); return new Image((Objects.requireNonNull(getClass().getResource(imageResourcePath)).toString()));
} }
@FXML
public void back() {
window.setScene(welcomeScene.get());
}
@FXML @FXML
public void chooseFileAndNext() { public void chooseFileAndNext() {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
@@ -13,37 +13,31 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.RadioButton; import javafx.scene.control.RadioButton;
import javafx.scene.control.Toggle; import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup; import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.Comparator;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.concurrent.ExecutorService;
@AddVaultWizardScoped @AddVaultWizardScoped
public class CreateNewVaultLocationController implements FxController { public class CreateNewVaultLocationController implements FxController {
@@ -55,23 +49,19 @@ public class CreateNewVaultLocationController implements FxController {
private final Stage window; private final Stage window;
private final Lazy<Scene> chooseNameScene; private final Lazy<Scene> chooseNameScene;
private final Lazy<Scene> chooseExpertSettingsScene; private final Lazy<Scene> chooseExpertSettingsScene;
private final List<RadioButton> locationPresetBtns;
private final ObjectProperty<Path> vaultPath; private final ObjectProperty<Path> vaultPath;
private final StringProperty vaultName; private final StringProperty vaultName;
private final ExecutorService backgroundExecutor;
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
private final ObservableValue<VaultPathStatus> vaultPathStatus; private final ObservableValue<VaultPathStatus> vaultPathStatus;
private final ObservableValue<Boolean> validVaultPath; private final ObservableValue<Boolean> validVaultPath;
private final BooleanProperty usePresetPath; private final BooleanProperty usePresetPath;
private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false);
private final ObservableList<Node> radioButtons;
private final ObservableList<Node> sortedRadioButtons;
private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH; private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
//FXML //FXML
public ToggleGroup locationPresetsToggler; public ToggleGroup locationPresetsToggler;
public VBox radioButtonVBox; public VBox radioButtonVBox;
public HBox customLocationRadioBtn;
public RadioButton customRadioButton; public RadioButton customRadioButton;
public Label locationStatusLabel; public Label locationStatusLabel;
public FontAwesome5IconView goodLocation; public FontAwesome5IconView goodLocation;
@@ -83,20 +73,25 @@ public class CreateNewVaultLocationController implements FxController {
@FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, // @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, //
ObjectProperty<Path> vaultPath, // ObjectProperty<Path> vaultPath, //
@Named("vaultName") StringProperty vaultName, // @Named("vaultName") StringProperty vaultName, //
ExecutorService backgroundExecutor, ResourceBundle resourceBundle) { ResourceBundle resourceBundle) {
this.window = window; this.window = window;
this.chooseNameScene = chooseNameScene; this.chooseNameScene = chooseNameScene;
this.chooseExpertSettingsScene = chooseExpertSettingsScene; this.chooseExpertSettingsScene = chooseExpertSettingsScene;
this.vaultPath = vaultPath; this.vaultPath = vaultPath;
this.vaultName = vaultName; this.vaultName = vaultName;
this.backgroundExecutor = backgroundExecutor;
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
this.vaultPathStatus = ObservableUtil.mapWithDefault(vaultPath, this::validatePath, new VaultPathStatus(false, "error.message")); this.vaultPathStatus = ObservableUtil.mapWithDefault(vaultPath, this::validatePath, new VaultPathStatus(false, "error.message"));
this.validVaultPath = ObservableUtil.mapWithDefault(vaultPathStatus, VaultPathStatus::valid, false); this.validVaultPath = ObservableUtil.mapWithDefault(vaultPathStatus, VaultPathStatus::valid, false);
this.vaultPathStatus.addListener(this::updateStatusLabel); this.vaultPathStatus.addListener(this::updateStatusLabel);
this.usePresetPath = new SimpleBooleanProperty(); this.usePresetPath = new SimpleBooleanProperty();
this.radioButtons = FXCollections.observableArrayList(); this.locationPresetBtns = LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
this.sortedRadioButtons = radioButtons.sorted(this::compareLocationPresets); .flatMap(LocationPresetsProvider::getLocations) //
.sorted(Comparator.comparing(LocationPreset::name)) //
.map(preset -> { //
var btn = new RadioButton(preset.name());
btn.setUserData(preset.path());
return btn;
}).toList();
} }
private VaultPathStatus validatePath(Path p) throws NullPointerException { private VaultPathStatus validatePath(Path p) throws NullPointerException {
@@ -142,45 +137,12 @@ public class CreateNewVaultLocationController implements FxController {
@FXML @FXML
public void initialize() { public void initialize() {
var task = backgroundExecutor.submit(this::loadLocationPresets); radioButtonVBox.getChildren().addAll(1, locationPresetBtns); //first item is the list header
window.addEventHandler(WindowEvent.WINDOW_HIDING, _ -> task.cancel(true)); locationPresetsToggler.getToggles().addAll(locationPresetBtns);
locationPresetsToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation); locationPresetsToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation);
usePresetPath.bind(locationPresetsToggler.selectedToggleProperty().isNotEqualTo(customRadioButton)); usePresetPath.bind(locationPresetsToggler.selectedToggleProperty().isNotEqualTo(customRadioButton));
radioButtons.add(customLocationRadioBtn);
Bindings.bindContent(radioButtonVBox.getChildren(), sortedRadioButtons); //to prevent garbage collection of the binding, we bind explicitly to the sorted list
} }
private void loadLocationPresets() {
Platform.runLater(() -> loadingPresetLocations.set(true));
try {
LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
.flatMap(LocationPresetsProvider::getLocations) //we do not use sorted(), because it evaluates the stream elements, blocking until all elements are gathered
.forEach(this::createRadioButtonFor);
} finally {
Platform.runLater(() -> loadingPresetLocations.set(false));
}
}
private void createRadioButtonFor(LocationPreset preset) {
Platform.runLater(() -> {
var btn = new RadioButton(preset.name());
btn.setUserData(preset.path());
radioButtons.add(btn);
locationPresetsToggler.getToggles().add(btn);
});
}
private int compareLocationPresets(Node left, Node right) {
if (customLocationRadioBtn.getId().equals(left.getId())) {
return 1;
} else if (customLocationRadioBtn.getId().equals(right.getId())) {
return -1;
} else {
return ((RadioButton) left).getText().compareToIgnoreCase(((RadioButton) right).getText());
}
}
private void togglePredefinedLocation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) { private void togglePredefinedLocation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
var storagePath = Optional.ofNullable((Path) newValue.getUserData()).orElse(customVaultPath); var storagePath = Optional.ofNullable((Path) newValue.getUserData()).orElse(customVaultPath);
vaultPath.set(storagePath.resolve(vaultName.get())); vaultPath.set(storagePath.resolve(vaultName.get()));
@@ -235,15 +197,7 @@ public class CreateNewVaultLocationController implements FxController {
} }
public boolean isValidVaultPath() { public boolean isValidVaultPath() {
return Boolean.TRUE.equals(validVaultPath.getValue()); return validVaultPath.getValue();
}
public boolean isLoadingPresetLocations() {
return loadingPresetLocations.getValue();
}
public BooleanProperty loadingPresetLocationsProperty() {
return loadingPresetLocations;
} }
public BooleanProperty usePresetPathProperty() { public BooleanProperty usePresetPathProperty() {
@@ -17,6 +17,7 @@ import javafx.scene.Scene;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ResourceBundle;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@AddVaultWizardScoped @AddVaultWizardScoped
@@ -26,17 +27,16 @@ public class CreateNewVaultNameController implements FxController {
public TextField textField; public TextField textField;
private final Stage window; private final Stage window;
private final Lazy<Scene> welcomeScene;
private final Lazy<Scene> chooseLocationScene; private final Lazy<Scene> chooseLocationScene;
private final ObjectProperty<Path> vaultPath; private final ObjectProperty<Path> vaultPath;
private final StringProperty vaultName; private final StringProperty vaultName;
private final BooleanBinding validVaultName; private final BooleanBinding validVaultName;
@Inject @Inject
CreateNewVaultNameController(@AddVaultWizardWindow Stage window, // CreateNewVaultNameController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
@FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, //
ObjectProperty<Path> vaultPath, //
@Named("vaultName") StringProperty vaultName) {
this.window = window; this.window = window;
this.welcomeScene = welcomeScene;
this.chooseLocationScene = chooseLocationScene; this.chooseLocationScene = chooseLocationScene;
this.vaultPath = vaultPath; this.vaultPath = vaultPath;
this.vaultName = vaultName; this.vaultName = vaultName;
@@ -58,6 +58,11 @@ public class CreateNewVaultNameController implements FxController {
} }
} }
@FXML
public void back() {
window.setScene(welcomeScene.get());
}
@FXML @FXML
public void next() { public void next() {
window.setScene(chooseLocationScene.get()); window.setScene(chooseLocationScene.get());
@@ -1,7 +1,5 @@
package org.cryptomator.ui.addvaultwizard; package org.cryptomator.ui.addvaultwizard;
import org.jetbrains.annotations.VisibleForTesting;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@@ -53,7 +51,7 @@ public class ReadmeGenerator {
resourceBundle.getString("addvault.new.readme.accessLocation.4"))); resourceBundle.getString("addvault.new.readme.accessLocation.4")));
} }
@VisibleForTesting // visible for testing
String createDocument(Iterable<String> paragraphs) { String createDocument(Iterable<String> paragraphs) {
StringBuilder sb = new StringBuilder(RTF_HEADER); StringBuilder sb = new StringBuilder(RTF_HEADER);
for (String p : paragraphs) { for (String p : paragraphs) {
@@ -65,7 +63,7 @@ public class ReadmeGenerator {
return sb.toString(); return sb.toString();
} }
@VisibleForTesting // visible for testing
String escapeNonAsciiChars(CharSequence input) { String escapeNonAsciiChars(CharSequence input) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
appendEscaped(sb, input); appendEscaped(sb, input);
@@ -8,11 +8,11 @@ public enum FxmlFile {
ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), // ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), //
ADDVAULT_NEW_RECOVERYKEY("/fxml/addvault_new_recoverykey.fxml"), // ADDVAULT_NEW_RECOVERYKEY("/fxml/addvault_new_recoverykey.fxml"), //
ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), // ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), //
ADDVAULT_WELCOME("/fxml/addvault_welcome.fxml"), //
CHANGEPASSWORD("/fxml/changepassword.fxml"), // CHANGEPASSWORD("/fxml/changepassword.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), // CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), // CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_SUCCESS("/fxml/convertvault_hubtopassword_success.fxml"), // CONVERTVAULT_HUBTOPASSWORD_SUCCESS("/fxml/convertvault_hubtopassword_success.fxml"), //
DOKANY_SUPPORT_END("/fxml/dokany_support_end.fxml"), //
ERROR("/fxml/error.fxml"), // ERROR("/fxml/error.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), // FORGET_PASSWORD("/fxml/forget_password.fxml"), //
HEALTH_START("/fxml/health_start.fxml"), // HEALTH_START("/fxml/health_start.fxml"), //
@@ -21,14 +21,10 @@ public enum FxmlFile {
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), // HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), // HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), // HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
HUB_LEGACY_REGISTER_DEVICE("/fxml/hub_legacy_register_device.fxml"), //
HUB_LEGACY_REGISTER_SUCCESS("/fxml/hub_legacy_register_success.fxml"), //
HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), //
HUB_REGISTER_DEVICE_ALREADY_EXISTS("/fxml/hub_register_device_already_exists.fxml"), //
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"), //
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), // HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), //
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"),
HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), // HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), //
HUB_REQUIRE_ACCOUNT_INIT("/fxml/hub_require_account_init.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), // LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), // LOCK_FAILED("/fxml/lock_failed.fxml"), //
MAIN_WINDOW("/fxml/main_window.fxml"), // MAIN_WINDOW("/fxml/main_window.fxml"), //
@@ -46,10 +42,8 @@ public enum FxmlFile {
RECOVERYKEY_RESET_PASSWORD_SUCCESS("/fxml/recoverykey_reset_password_success.fxml"), // RECOVERYKEY_RESET_PASSWORD_SUCCESS("/fxml/recoverykey_reset_password_success.fxml"), //
RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), // RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), //
REMOVE_VAULT("/fxml/remove_vault.fxml"), // REMOVE_VAULT("/fxml/remove_vault.fxml"), //
SHARE_VAULT("/fxml/share_vault.fxml"), //
UPDATE_REMINDER("/fxml/update_reminder.fxml"), // UPDATE_REMINDER("/fxml/update_reminder.fxml"), //
UNLOCK_ENTER_PASSWORD("/fxml/unlock_enter_password.fxml"), UNLOCK_ENTER_PASSWORD("/fxml/unlock_enter_password.fxml"),
UNLOCK_REQUIRES_RESTART("/fxml/unlock_requires_restart.fxml"), //
UNLOCK_INVALID_MOUNT_POINT("/fxml/unlock_invalid_mount_point.fxml"), // UNLOCK_INVALID_MOUNT_POINT("/fxml/unlock_invalid_mount_point.fxml"), //
UNLOCK_SELECT_MASTERKEYFILE("/fxml/unlock_select_masterkeyfile.fxml"), // UNLOCK_SELECT_MASTERKEYFILE("/fxml/unlock_select_masterkeyfile.fxml"), //
UNLOCK_SUCCESS("/fxml/unlock_success.fxml"), // UNLOCK_SUCCESS("/fxml/unlock_success.fxml"), //
@@ -47,14 +47,12 @@ public enum FontAwesome5Icon {
QUESTION_CIRCLE("\uf059"), // QUESTION_CIRCLE("\uf059"), //
REDO("\uF01E"), // REDO("\uF01E"), //
SEARCH("\uF002"), // SEARCH("\uF002"), //
SHARE("\uF064"), //
SPINNER("\uF110"), // SPINNER("\uF110"), //
STETHOSCOPE("\uF0f1"), // STETHOSCOPE("\uF0f1"), //
SYNC("\uF021"), // SYNC("\uF021"), //
TIMES("\uF00D"), // TIMES("\uF00D"), //
TRASH("\uF1F8"), // TRASH("\uF1F8"), //
UNLINK("\uf127"), // UNLINK("\uf127"), //
USER_COG("\uf4fe"), //
WRENCH("\uF0AD"), // WRENCH("\uF0AD"), //
WINDOW_MINIMIZE("\uF2D1"), // WINDOW_MINIMIZE("\uF2D1"), //
; ;
@@ -16,7 +16,6 @@ import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.recoverykey.RecoveryKeyFactory; import org.cryptomator.ui.recoverykey.RecoveryKeyFactory;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -117,7 +116,7 @@ public class HubToPasswordConvertController implements FxController {
}, Platform::runLater); // }, Platform::runLater); //
} }
@VisibleForTesting //visible for testing
void convertInternal() throws CompletionException, IllegalArgumentException { void convertInternal() throws CompletionException, IllegalArgumentException {
var passphrase = newPasswordController.getNewPassword(); var passphrase = newPasswordController.getNewPassword();
var vaultPath = vault.getPath(); var vaultPath = vault.getPath();
@@ -142,7 +141,7 @@ public class HubToPasswordConvertController implements FxController {
} }
} }
@VisibleForTesting //visible for testing
void backupHubConfig(Path hubConfigPath) throws IOException { void backupHubConfig(Path hubConfigPath) throws IOException {
byte[] hubConfigBytes = Files.readAllBytes(hubConfigPath); byte[] hubConfigBytes = Files.readAllBytes(hubConfigPath);
Path backupPath = hubConfigPath.resolveSibling(VAULTCONFIG_FILENAME + BackupHelper.generateFileIdSuffix(hubConfigBytes) + MASTERKEY_BACKUP_SUFFIX); Path backupPath = hubConfigPath.resolveSibling(VAULTCONFIG_FILENAME + BackupHelper.generateFileIdSuffix(hubConfigBytes) + MASTERKEY_BACKUP_SUFFIX);
@@ -150,7 +149,7 @@ public class HubToPasswordConvertController implements FxController {
LOG.debug("Successfully created hub config backup {}", backupPath.getFileName()); LOG.debug("Successfully created hub config backup {}", backupPath.getFileName());
} }
@VisibleForTesting //visible for testing
Path createPasswordConfig(Path passwordConfigPath, Path masterkeyFile, Passphrase passphrase) throws IOException, MasterkeyLoadingFailedException { Path createPasswordConfig(Path passwordConfigPath, Path masterkeyFile, Passphrase passphrase) throws IOException, MasterkeyLoadingFailedException {
var unverifiedVaultConfig = vault.getVaultConfigCache().get(); var unverifiedVaultConfig = vault.getVaultConfigCache().get();
try (var masterkey = masterkeyFileAccess.load(masterkeyFile, passphrase)) { try (var masterkey = masterkeyFileAccess.load(masterkeyFile, passphrase)) {

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