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
345 changed files with 4444 additions and 18840 deletions
+1 -5
View File
@@ -3,7 +3,7 @@
## Did you find a bug? ## Did you find a bug?
- Ensure you're running the latest version of Cryptomator. - Ensure you're running the latest version of Cryptomator.
- Ensure the bug is related to the desktop version of Cryptomator. Bugs concerning the Cryptomator iOS and Android app can be reported on the [Cryptomator for iOS issues list](https://github.com/cryptomator/ios/issues) and [Cryptomator for Android issues list](https://github.com/cryptomator/android/issues) respectively. - Ensure the bug is related to the desktop version of Cryptomator. Bugs concerning the Cryptomator iOS and Android app can be reported on the [Cryptomator for iOS issues list](https://github.com/cryptomator/cryptomator-ios/issues) and [Cryptomator for Android issues list](https://github.com/cryptomator/cryptomator-android/issues) respectively.
- Ensure the bug was not [already reported](https://github.com/cryptomator/cryptomator/issues). You can also check out our [FAQ](https://community.cryptomator.org/c/kb/faq). - Ensure the bug was not [already reported](https://github.com/cryptomator/cryptomator/issues). You can also check out our [FAQ](https://community.cryptomator.org/c/kb/faq).
- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator/issues/new/choose). - If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator/issues/new/choose).
@@ -16,10 +16,6 @@
- Suggest your change by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new/choose) and start writing code. - Suggest your change by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new/choose) and start writing code.
## Do you intend to add a new translation or change an existing one?
Translations are not managed directly in this repository. Instead, we use [Crowdin](https://translate.cryptomator.org/), which automatically synchronizes translations with this repository. If you want to help us with translations, please visit our translation project on Crowdin.
## Code of Conduct ## Code of Conduct
Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md). Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md).
+8 -10
View File
@@ -1,14 +1,7 @@
name: Bug Report name: Bug Report
description: Create a report to help us improve description: Create a report to help us improve
type: "Bug" labels: ["type:bug"]
body: body:
- type: input
id: summary
attributes:
label: Summary
placeholder: Please summarize your problem.
validations:
required: true
- type: checkboxes - type: checkboxes
id: terms id: terms
attributes: attributes:
@@ -18,6 +11,13 @@ body:
required: true required: true
- label: I agree to follow this project's [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md) - label: I agree to follow this project's [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md)
required: true required: true
- type: input
id: summary
attributes:
label: Summary
placeholder: Please summarize your problem.
validations:
required: true
- type: textarea - type: textarea
id: software-versions id: software-versions
attributes: attributes:
@@ -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)
+8 -8
View File
@@ -1,14 +1,7 @@
name: Feature Request name: Feature Request
description: Suggest an idea for this project description: Suggest an idea for this project
type: "Feature" labels: ["type:feature-request"]
body: body:
- type: input
id: summary
attributes:
label: Summary
placeholder: Please summarize your feature request.
validations:
required: true
- type: checkboxes - type: checkboxes
id: terms id: terms
attributes: attributes:
@@ -18,6 +11,13 @@ body:
required: true required: true
- label: I agree to follow this project's [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md) - label: I agree to follow this project's [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md)
required: true required: true
- type: input
id: summary
attributes:
label: Summary
placeholder: Please summarize your feature request.
validations:
required: true
- type: textarea - type: textarea
id: motivation id: motivation
attributes: attributes:
-58
View File
@@ -1,58 +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"]
- dependency-name: "jakarta.inject:jakarta.inject-api"
versions: ["2.0.1.MR"]
- dependency-name: "org.openjfx:*"
update-types: ["version-update:semver-major"]
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"
+37 -79
View File
@@ -8,100 +8,63 @@ on:
version: version:
description: 'Version' description: 'Version'
required: false required: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/appimage.yml'
- 'dist/linux/appimage/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
env: env:
JAVA_DIST: 'temurin' JAVA_VERSION: 20
JAVA_VERSION: '24.0.1+9'
jobs: jobs:
get-version: get-version:
uses: ./.github/workflows/get-version.yml uses: ./.github/workflows/get-version.yml
with: with:
version: ${{ inputs.version }} #okay if not defined version: ${{ inputs.version }}
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/24.0.1/openjfx-24.0.1_linux-x64_bin-jmods.zip'
openjfx-sha: '425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
- os: ubuntu-24.04-arm
appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-aarch64_bin-jmods.zip'
openjfx-sha: '7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
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 ]; 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 with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- 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 "${{ steps.jep-493-check.outputs.jmod_paths }}" --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
@@ -114,10 +77,10 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 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=javafx.graphics,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 }}\""
@@ -129,10 +92,9 @@ 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 }}\""
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" --add-launcher Cryptomator-gtk2=launcher-gtk2.properties
--resource-dir dist/linux/resources --resource-dir dist/linux/resources
- name: Patch Cryptomator.AppDir - name: Patch Cryptomator.AppDir
run: | run: |
@@ -141,21 +103,17 @@ 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
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/Cryptomator.svg
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/org.cryptomator.Cryptomator.desktop ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml
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/appimagetool/releases/download/continuous/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
@@ -167,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 --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 }}
-88
View File
@@ -1,88 +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
avast:
description: "Upload to Avast"
required: false
type: boolean
default: false
kaspersky:
description: "Upload to Kaspersky"
required: false
type: boolean
default: false
jobs:
download-file:
name: Downloads the file into the VM
runs-on: ubuntu-latest
outputs:
fileName: ${{ steps.extractName.outputs.fileName}}
steps:
- name: Extract file name
id: extractName
run: |
url="${{ inputs.url }}"
echo "fileName=${url##*/}" >> $GITHUB_OUTPUT
- name: Download file
run: curl --remote-name ${{ inputs.url }} -L -o ${{steps.extractName.outputs.fileName}}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.extractName.outputs.fileName }}
path: ${{ steps.extractName.outputs.fileName }}
if-no-files-found: error
allowlist-kaspersky:
name: Anti Virus Allowlisting Kaspersky
runs-on: ubuntu-latest
needs: download-file
if: github.event_name == 'workflow_call' || inputs.kaspersky
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- 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 }}
local-dir: ./upload/
allowlist-avast:
name: Anti Virus Allowlisting Avast
runs-on: ubuntu-latest
needs: download-file
if: github.event_name == 'workflow_call' || inputs.avast
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Avast
uses: wlixcc/SFTP-Deploy-Action@v1.2.5
with:
server: whitelisting.avast.com
port: 22
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
ssh_private_key: ''
sftp_only: true
local_path: './upload/*'
remote_path: '/data'
+11 -31
View File
@@ -2,16 +2,11 @@ name: Build
on: on:
push: push:
paths:
- '.github/workflows/build.yml'
- 'pom.xml'
- 'src/**'
pull_request_target: pull_request_target:
types: [labeled] types: [labeled]
env: env:
JAVA_DIST: 'temurin' JAVA_VERSION: 20
JAVA_VERSION: 24
defaults: defaults:
run: run:
@@ -22,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
@@ -37,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
@@ -49,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
@@ -57,25 +52,10 @@ jobs:
generate_release_notes: true generate_release_notes: true
body: |- body: |-
:construction: Work in Progress :construction: Work in Progress
### What's New 🎉
### Bugfixes 🐛
### Other Changes 📎
---
TODO FULL CHANGELOG
📜 List of closed issues is available [here](TODO)
---
⏳ Please be patient, the builds are still [running](https://github.com/cryptomator/cryptomator/actions). New versions of Cryptomator can be found here in a few moments. ⏳ ⏳ Please be patient, the builds are still [running](https://github.com/cryptomator/cryptomator/actions). New versions of Cryptomator can be found here in a few moments. ⏳
<!-- Don't forget to include the
💾 SHA-256 checksums of release artifacts:
```
```
-->
As usual, the GPG signatures can be checked using [our public key `5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a). As usual, the GPG signatures can be checked using [our public key `5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
---
<!-- Don't forget to include the 💾 SHA-256 checksums of release artifacts: -->
-83
View File
@@ -1,83 +0,0 @@
name: Check JDK for non-major updates
on:
schedule:
- cron: '0 0 1 * *' # run once a month at the first day of month
workflow_dispatch:
env:
JDK_VERSION: '24.0.1+9'
JDK_VENDOR: temurin
RUNTIME_VERSION_HELPER: >
public class Test {
public static void main(String[] args) {
System.out.println(Runtime.version());
}
}
jobs:
check-version:
name: Checkout latest jdk version
runs-on: ubuntu-latest
env:
JDK_MAJOR_VERSION: 'toBeFilled'
steps:
- name: Determine current major version
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,20) >> "$env:GITHUB_ENV"
shell: pwsh
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JDK_MAJOR_VERSION}}
distribution: ${{ env.JDK_VENDOR }}
check-latest: true
- name: Determine if update is available
id: determine
shell: pwsh
run: |
$latestVersion = 0,0,0,0 #INTERIM, UPDATE, PATCH and BUILD
$currentVersion = 0,0,0,0
# Get the latest JDK runtime version
"${env:RUNTIME_VERSION_HELPER}" | Set-Content -Path "GetRuntimeVersion.java"
$latestVersionString = & java GetRuntimeVersion.java
$runtimeVersionAndBuild = $latestVersionString.Split('+')
if($runtimeVersionAndBuild.Length -eq 2) {
$latestVersion[3]=$runtimeVersionAndBuild[1];
}
$tmp=$runtimeVersionAndBuild[0].Split('.')
for($i=0;$i -lt $latestVersion.Length; $i++) {
$latestVersion[$i]=$tmp[$i+1];
}
# Get the current JDK version
$runtimeVersionAndBuild = '${{ env.JDK_VERSION}}'.Split('+')
if($runtimeVersionAndBuild.Length -eq 2) {
$currentVersion[3]=$runtimeVersionAndBuild[1];
}
$tmp=$runtimeVersionAndBuild[0].Split('.')
for($i=0;$i -lt $currentVersion.Length; $i++) {
$currentVersion[$i]=$tmp[$i+1];
}
# compare
for($i=0; $i -lt $currentVersion.Length ; $i++) {
if($latestVersion[$i] -gt $currentVersion[$i]){
echo 'UPDATE_AVAILABLE=true' >> "$env:GITHUB_OUTPUT"
echo "LATEST_JDK_VERSION='${latestVersionString}'" >> "$env:GITHUB_OUTPUT"
return 0;
}
}
- name: Notify
if: steps.determine.outputs.UPDATE_AVAILABLE == 'true'
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 ${{ steps.determine.outputs.LATEST_JDK_VERSION }}. Check the Nextcloud collective for instructions."
SLACK_FOOTER: false
MSG_MINIMAL: true
+31 -51
View File
@@ -5,75 +5,56 @@ on:
inputs: inputs:
semver: semver:
description: 'SemVer String (e.g. 1.7.0-beta1)' description: 'SemVer String (e.g. 1.7.0-beta1)'
required: true
ppaver: ppaver:
description: 'Base PPA Version String (e.g. 1.6.16+1.7.0~beta1) without -0ppa1' description: 'Base PPA Version String (e.g. 1.6.16+1.7.0~beta1) without -0ppa1'
required: true
dput: dput:
description: 'Upload to PPA' description: 'Upload to PPA'
required: true required: true
default: false default: false
type: boolean type: boolean
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/debian.yml'
- 'dist/linux/debian/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
env: env:
JAVA_DIST: 'temurin' JAVA_VERSION: 20
JAVA_VERSION: '24.0.1+9' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-x64_bin-jmods.zip'
COFFEELIBS_JDK: 24 OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-aarch64_bin-jmods.zip'
COFFEELIBS_JDK_VERSION: '24.0.1+9-0ppa3'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
jobs: jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.semver }} #okay if not defined
build: build:
name: Build Debian Package name: Build Debian Package
runs-on: ubuntu-22.04 runs-on: ubuntu-20.04
needs: [get-version]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- id: deb-version - id: versions
name: Determine deb-version name: Get version information
run: | run: |
if [ -n "${{inputs.ppaver}}" ]; then SEM_VER_STR="${{ inputs.semver }}"
echo "debVersion=${{inputs.ppaver }}" >> "$GITHUB_OUTPUT" SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
else REVCOUNT=`git rev-list --count HEAD`
echo "debVersion=${{needs.get-version.outputs.semVerStr}}" >> "$GITHUB_OUTPUT" echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT
fi echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
- name: Install build tools - name: Install build tools
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
@@ -105,21 +86,20 @@ jobs:
cp -r jmods pkgdir cp -r jmods pkgdir
cp -r dist/linux/common/ pkgdir cp -r dist/linux/common/ pkgdir
cp target/cryptomator-*.jar pkgdir/mods cp target/cryptomator-*.jar pkgdir/mods
tar -cJf cryptomator_${{ steps.deb-version.outputs.debVersion }}.orig.tar.xz -C pkgdir . tar -cJf cryptomator_${{ inputs.ppaver }}.orig.tar.xz -C pkgdir .
- name: Patch and rename pkgdir - name: Patch and rename pkgdir
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_${{ steps.deb-version.outputs.debVersion }} mv pkgdir cryptomator_${{ inputs.ppaver }}
env: env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }} SEMVER_STR: ${{ steps.versions.outputs.semVerStr }}
VERSION_NUM: ${{ needs.get-version.outputs.semVerNum }} VERSION_NUM: ${{ steps.versions.outputs.semVerNum }}
REVISION_NUM: ${{ needs.get-version.outputs.revNum }} REVISION_NUM: ${{ steps.versions.outputs.revNum }}
PPA_VERSION: ${{ steps.deb-version.outputs.debVersion }}-0ppa1 PPA_VERSION: ${{ inputs.ppaver }}-0ppa1
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235 - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
run: | run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -129,18 +109,17 @@ jobs:
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: debuild - name: debuild
run: | run: |
(sleep 8m; gpg --batch --quiet --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign README.md) &
debuild -S -sa -d debuild -S -sa -d
debuild -b -sa -d debuild -b -sa -d
env: env:
DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback
DEBSIGN_KEYID: 615D449FE6E6A235 DEBSIGN_KEYID: 615D449FE6E6A235
working-directory: cryptomator_${{ steps.deb-version.outputs.debVersion }} working-directory: cryptomator_${{ inputs.ppaver }}
- 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_*_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: |
@@ -152,11 +131,12 @@ jobs:
cryptomator_*_amd64.deb cryptomator_*_amd64.deb
cryptomator_*.asc cryptomator_*.asc
- name: Publish on PPA - name: Publish on PPA
if: inputs.dput && inputs.ppaver != '' 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: |
-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: 24
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
+7 -6
View File
@@ -22,8 +22,9 @@ on:
value: ${{ jobs.determine-version.outputs.type }} value: ${{ jobs.determine-version.outputs.type }}
env: env:
JAVA_VERSION: 20
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: 24 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 }}
-281
View File
@@ -1,281 +0,0 @@
name: Build macOS .dmg for x64
#######################################
# STOP! DO NOT EDIT THIS FILE!
#
# It is a copy of mac-dmg.yml with tiny adjustements (mainly lines 42 to 47)
# It was made necessary, since Github does not offer free macos intel runners for macos 15 and above.
#
#######################################
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version'
required: false
notarize:
description: 'Notarize'
required: true
default: false
type: boolean
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '24.0.1+9'
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }}
build-arm:
name: Build Cryptomator.app for ${{ matrix.output-suffix }}
runs-on: ${{ matrix.os }}
needs: [get-version]
strategy:
fail-fast: false
matrix:
include:
- os: macos-15-large
architecture: x64
output-suffix: x64
fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_osx-x64_bin-jmods.zip'
openjfx-sha: '6e62a426d43c168a488521f904a523f3dd6ee2cf103e08136f2fd465c828a105'
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
architecture: ${{ matrix.architecture }}
check-latest: true
cache: 'maven'
- name: Download OpenJFX jmods
id: download-jmods
run: |
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
mkdir -p openjfx-jmods/
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
- 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
fi
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven
run: mvn -B -Djavafx.platform=mac clean package -Pmac -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- name: Run jlink
#Remark: no compression is applied for improved build compression later (here dmg)
run: >
${JAVA_HOME}/bin/jlink
--verbose
--output runtime
--module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands
--no-header-files
--no-man-pages
--strip-debug
--compress zip-0
- name: Run jpackage
run: >
${JAVA_HOME}/bin/jpackage
--verbose
--type app-image
--runtime-image runtime
--input target/libs
--module-path target/mods
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--mac-package-identifier org.cryptomator
--resource-dir dist/mac/resources
- name: Patch Cryptomator.app
run: |
mv appdir/Cryptomator.app Cryptomator.app
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Generate license for dmg
run: >
mvn -B -Djavafx.platform=mac license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
-Dlicense.includedScopes=compile
-Dlicense.excludedGroups=^org\.cryptomator
-Dlicense.failOnMissing=true
-Dlicense.licenseMergesUrl=file://${{ github.workspace }}/license/merges
- name: Install codesign certificate
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
KEYCHAIN_PATH=$RUNNER_TEMP/codesign.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$CODESIGN_P12_BASE64" | base64 --decode --output $CERTIFICATE_PATH
# create temporary keychain
security create-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
security set-keychain-settings -lut 900 $KEYCHAIN_PATH
security unlock-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$CODESIGN_P12_PW" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
env:
CODESIGN_P12_BASE64: ${{ secrets.MACOS_CODESIGN_P12_BASE64 }}
CODESIGN_P12_PW: ${{ secrets.MACOS_CODESIGN_P12_PW }}
CODESIGN_TMP_KEYCHAIN_PW: ${{ secrets.MACOS_CODESIGN_TMP_KEYCHAIN_PW }}
- name: Codesign
run: |
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 'jspawnhelper' -o -name 'pauseengine' -o -name 'simengine' \) -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
echo "Codesigning jar contents..."
find Cryptomator.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
for JAR_PATH in `find Cryptomator.app -name "*.jar"`; do
if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
JAR_FILENAME=$(basename ${JAR_PATH})
OUTPUT_PATH=${JAR_PATH%.*}
echo "Codesigning libs in ${JAR_FILENAME}..."
unzip -q ${JAR_PATH} -d ${OUTPUT_PATH}
find ${OUTPUT_PATH} -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
find ${OUTPUT_PATH} -name '*.jnilib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
rm ${JAR_PATH}
pushd ${OUTPUT_PATH} > /dev/null
zip -qr ../${JAR_FILENAME} *
popd > /dev/null
rm -r ${OUTPUT_PATH}
fi
done
echo "Codesigning Cryptomator.app..."
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
env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
TEAM_IDENTIFIER: ${{ secrets.MACOS_TEAM_IDENTIFIER }}
- name: Prepare .dmg contents
run: |
mkdir dmg
mv Cryptomator.app dmg
cp dist/mac/dmg/resources/${{ matrix.fuse-lib }}.webloc dmg
ls -l dmg
- name: Install create-dmg
run: |
brew install create-dmg
create-dmg --help
- name: Create .dmg
run: >
create-dmg
--volname Cryptomator
--volicon "dist/mac/dmg/resources/Cryptomator-Volume.icns"
--background "dist/mac/dmg/resources/Cryptomator-${{ matrix.fuse-lib }}-background.tiff"
--window-pos 400 100
--window-size 640 694
--icon-size 128
--icon "Cryptomator.app" 128 245
--hide-extension "Cryptomator.app"
--icon "${{ matrix.fuse-lib }}.webloc" 320 501
--hide-extension "${{ matrix.fuse-lib }}.webloc"
--app-drop-link 512 245
--eula "dist/mac/dmg/resources/license.rtf"
--icon ".background" 128 758
--icon ".VolumeIcon.icns" 512 758
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
- name: Notarize .dmg
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
uses: cocoalibs/xcode-notarization-action@v1
with:
app-path: 'Cryptomator-*.dmg'
apple-id: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
password: ${{ secrets.MACOS_NOTARIZATION_PW }}
team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
xcode-path: '/Applications/Xcode_16.app'
- name: Add possible alpha/beta tags to installer name
run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a Cryptomator-*.dmg
env:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Clean up codesign certificate
if: ${{ always() }}
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dmg-${{ matrix.output-suffix }}
path: |
Cryptomator-*.dmg
Cryptomator-*.asc
if-no-files-found: error
- name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
Cryptomator-*.dmg
Cryptomator-*.asc
+36 -69
View File
@@ -1,4 +1,4 @@
name: Build macOS .dmg for arm64 name: Build macOS .dmg
on: on:
release: release:
@@ -8,21 +8,9 @@ on:
version: version:
description: 'Version' description: 'Version'
required: false required: false
notarize:
description: 'Notarize'
required: true
default: false
type: boolean
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/mac-dmg.yml'
- 'dist/mac/**'
env: env:
JAVA_DIST: 'temurin' JAVA_VERSION: 20
JAVA_VERSION: '24.0.1+9'
jobs: jobs:
get-version: get-version:
@@ -38,71 +26,56 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: macos-15 - os: macos-11
architecture: x64
output-suffix: x64
xcode-path: '/Applications/Xcode_13.2.1.app'
fuse-lib: macFUSE
- os: [self-hosted, macOS, ARM64]
architecture: aarch64 architecture: aarch64
output-suffix: arm64 output-suffix: arm64
xcode-path: '/Applications/Xcode_13.2.1.app'
fuse-lib: FUSE-T fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_osx-aarch64_bin-jmods.zip'
openjfx-sha: 'b5a94a13077507003fa852512bfa33f4fb680bc8076d8002e4227a84c85171d4'
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 with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- 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 "${{ steps.jep-493-check.outputs.jmod_paths }}" --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
@@ -115,10 +88,10 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 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=javafx.graphics,org.cryptomator.jfuse.mac" --java-options "--enable-native-access=org.cryptomator.jfuse.mac"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Dfile.encoding=\"utf-8\""
@@ -143,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
@@ -183,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
@@ -202,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
@@ -234,19 +202,20 @@ 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'
apple-id: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }} apple-id: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
password: ${{ secrets.MACOS_NOTARIZATION_PW }} password: ${{ secrets.MACOS_NOTARIZATION_PW }}
team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }} team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
xcode-path: '/Applications/Xcode_16.app' xcode-path: ${{ matrix.xcode-path }}
- name: Add possible alpha/beta tags to installer name - name: Add possible alpha/beta tags to installer name
run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg
- name: Create detached GPG signature with key 615D449FE6E6A235 - name: Create detached GPG signature with key 615D449FE6E6A235
@@ -261,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 }}
+6 -6
View File
@@ -4,8 +4,7 @@ on:
pull_request: pull_request:
env: env:
JAVA_DIST: 'temurin' JAVA_VERSION: 20
JAVA_VERSION: 24
defaults: defaults:
run: run:
@@ -15,12 +14,13 @@ jobs:
test: test:
name: Compile and Test name: Compile and Test
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]')"
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
+6 -28
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: 'temurin'
JAVA_VERSION: 23
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
+132 -235
View File
@@ -11,20 +11,14 @@ on:
isDebug: isDebug:
description: 'Build debug version with console output' description: 'Build debug version with console output'
type: boolean type: boolean
default: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/win-exe.yml'
- 'dist/win/**'
env: env:
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_windows-x64_bin-jmods.zip' JAVA_VERSION: 20
OPENJFX_JMODS_AMD64_HASH: 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f' JAVA_DIST: 'temurin'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi' JAVA_CACHE: 'maven'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe' JFX_JMODS_URL: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_windows-x64_bin-jmods.zip'
JFX_JMODS_HASH: 'D00767334C43B8832B5CF10267D34CA8F563D187C4655B73EB6020DD79C054B5'
defaults: defaults:
run: run:
@@ -38,54 +32,33 @@ jobs:
build-msi: build-msi:
name: Build .msi Installer name: Build .msi Installer
runs-on: ${{ matrix.os }} runs-on: windows-latest
needs: [ get-version ] needs: [get-version]
strategy:
matrix:
include:
- arch: x64
os: windows-latest
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
- arch: arm64
os: windows-11-arm
java-dist: 'liberica'
java-version: '24.0.1+11'
java-package: 'jdk+fx' #This is needed, as liberica contains JFX 24 Jmods for Windows ARM64
env: env:
LOOPBACK_ALIAS: 'cryptomator-vault' LOOPBACK_ALIAS: 'cryptomator-vault'
WIN_CONSOLE_FLAG: '' WIN_CONSOLE_FLAG: ''
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: ${{ matrix.java-dist }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ matrix.java-version }} java-version: ${{ env.JAVA_VERSION }}
java-package: ${{ matrix.java-package }} java-package: 'jdk'
check-latest: true cache: ${{ env.JAVA_CACHE }}
cache: 'maven'
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version 6.0.0
wix.exe extension add WixToolset.UI.wixext/6.0.0 --global
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
- name: Download and extract JavaFX jmods from Gluon - name: Download and extract JavaFX jmods from Gluon
if: matrix.arch == 'x64'
#In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip #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 openjfx-jmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}" curl --output jfxjmods.zip -L "${{ env.JFX_JMODS_URL }}"
if(!(Get-FileHash -Path openjfx-jmods.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 openjfx-jmods.zip -DestinationPath openjfx-jmods Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
Get-ChildItem -Path openjfx-jmods -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}
shell: pwsh shell: pwsh
- 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
if: matrix.arch == 'x64'
run: | run: |
JMOD_VERSION_AMD64=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1) JMOD_VERSION_AMD64=$(jmod describe jfxjmods/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@} JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@}
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*} JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
@@ -97,34 +70,25 @@ jobs:
exit 1 exit 1
fi 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 -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 with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! $(${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"); then
JMOD_PATHS="${JAVA_HOME}/jmods;${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- 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 "${{ steps.jep-493-check.outputs.jmod_paths }}" --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.crypto.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.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
@@ -140,10 +104,10 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 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=javafx.graphics,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 }}\""
@@ -160,7 +124,6 @@ jobs:
--java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\"" --java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\"" --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\""
--java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\"" --java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\""
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
--java-options "-Djavafx.verbose=${{ inputs.isDebug }}" --java-options "-Djavafx.verbose=${{ inputs.isDebug }}"
--resource-dir dist/win/resources --resource-dir dist/win/resources
--icon dist/win/resources/Cryptomator.ico --icon dist/win/resources/Cryptomator.ico
@@ -181,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"
@@ -249,21 +182,20 @@ jobs:
--dest installer --dest installer
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 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 }}
@@ -271,8 +203,8 @@ jobs:
description: Cryptomator Installer description: Cryptomator Installer
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: installer folder: installer
- name: Add possible alpha/beta tags and architecture to installer name - name: Add possible alpha/beta tags to installer name
run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.msi
- name: Create detached GPG signature with key 615D449FE6E6A235 - name: Create detached GPG signature with key 615D449FE6E6A235
run: | run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -281,58 +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-${{ matrix.arch }} 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: ${{ matrix.os }} runs-on: windows-latest
needs: [ get-version, build-msi ] needs: [get-version, build-msi]
strategy:
matrix:
include:
- arch: x64
os: windows-latest
executable-suffix: x64
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
- arch: arm64
os: windows-11-arm
executable-suffix: arm64
java-dist: 'liberica'
java-version: '24.0.1+11'
java-package: 'jdk+fx' #This is needed, as liberica contains JFX 24 Jmods for Windows ARM64
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version 6.0.0
wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
- name: Download .msi - name: Download .msi
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: msi-${{ matrix.arch }} 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
- name: Setup Java - uses: actions/setup-java@v3
uses: actions/setup-java@v4
with: with:
distribution: ${{ matrix.java-dist }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ matrix.java-version }} java-version: ${{ env.JAVA_VERSION }}
java-package: ${{ matrix.java-package }} cache: ${{ env.JAVA_CACHE }}
check-latest: true
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"
@@ -343,32 +261,34 @@ 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
curl --output dist/win/bundle/resources/winfsp.msi -L $winfspUrl
shell: pwsh shell: pwsh
- name: Download Legacy-WinFsp uninstaller - name: Compile to wixObj file
run: |
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
shell: pwsh
- name: Create Wix Burn bundle
working-directory: dist/win
run: > run: >
wix build "${WIX}/bin/candle.exe" dist/win/bundle/bundleWithWinfsp.wxs
-define BundleName="Cryptomator" -ext WixBalExtension
-define BundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}" -ext WixUtilExtension
-define BundleVendor="Skymatic GmbH" -out dist/win/bundle/
-define BundleCopyright="(C) 2016 - 2025 Skymatic GmbH" -dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
-define AboutUrl="https://cryptomator.org" -dBundleVendor="Skymatic GmbH"
-define HelpUrl="https://cryptomator.org/contact" -dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
-define UpdateUrl="https://cryptomator.org/downloads/" -dAboutUrl="https://cryptomator.org"
-ext "WixToolset.Util.wixext" -dHelpUrl="https://cryptomator.org/contact"
-ext "WixToolset.BootstrapperApplications.wixext" -dUpdateUrl="https://cryptomator.org/downloads/"
./bundle/bundleWithWinfsp.wxs - name: Create executable with linker
-out "../../installer/unsigned/Cryptomator-Installer.exe" run: >
"${WIX}/bin/light.exe" -b dist/win/ dist/win/bundle/bundleWithWinfsp.wixobj
-ext WixBalExtension
-ext WixUtilExtension
-out installer/unsigned/Cryptomator-Installer.exe
- name: Detach burn engine in preparation to sign - name: Detach burn engine in preparation to sign
run: > run: >
wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe "${WIX}/bin/insignia.exe"
-ib installer/unsigned/Cryptomator-Installer.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 }}
@@ -377,10 +297,12 @@ jobs:
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: tmp folder: tmp
- name: Reattach signed burn engine to installer - name: Reattach signed burn engine to installer
run: > run : >
wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe "${WIX}/bin/insignia.exe"
-ab tmp/engine.exe installer/unsigned/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 }}
@@ -389,7 +311,7 @@ jobs:
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: installer folder: installer
- name: Add possible alpha/beta tags to installer name - name: Add possible alpha/beta tags to installer name
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.exe
- name: Create detached GPG signature with key 615D449FE6E6A235 - name: Create detached GPG signature with key 615D449FE6E6A235
run: | run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -398,84 +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-${{ matrix.executable-suffix }} name: exe
path: | path: |
Cryptomator-*.exe Cryptomator-*.exe
Cryptomator-*.asc Cryptomator-*.asc
if-no-files-found: error if-no-files-found: error
- name: Publish .msi on GitHub Releases
publish: if: startsWith(github.ref, 'refs/tags/')
name: Publish installers to the github release uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
runs-on: ubuntu-latest
needs: [ build-msi, build-exe ]
outputs:
download-url-msi-x64: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-msi-arm64: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }}
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
download-url-exe-arm64: ${{ fromJSON(steps.publish.outputs.assets)[3].browser_download_url }}
steps:
- name: Download installers
uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Publish installers on GitHub Releases
id: publish
uses: softprops/action-gh-release@v2
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-x64: 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-x64 }}
secrets: inherit
allowlist-msi-arm64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish ]
with:
url: ${{ needs.publish.outputs.download-url-msi-arm64 }}
secrets: inherit
allowlist-exe-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-x64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe-x64 }}
secrets: inherit
allowlist-exe-arm64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-arm64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe-arm64 }}
secrets: inherit
notify-winget:
name: Notify for winget-release
if: needs.get-version.outputs.versionType == 'stable'
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 packages 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 them 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@main
with:
identifier: Cryptomator.Cryptomator
version: ${{ inputs.tag }}
release-tag: ${{ inputs.tag }}
installers-regex: '-x64\.msi$'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+21 -20
View File
@@ -14,31 +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.55/dagger-compiler-2.55.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.55/dagger-2.55.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.45/dagger-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" /> <entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-producers/2.45/dagger-producers-2.45.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.55/dagger-spi-2.55.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.0.21-1.0.28/symbol-processing-api-2.0.21-1.0.28.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.21/kotlin-stdlib-2.0.21.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.41.0/checker-qual-3.41.0.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" /> <entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.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$/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-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/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>
@@ -46,7 +47,7 @@
</component> </component>
<component name="JavacSettings"> <component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE"> <option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled" /> <module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled --enable-preview" />
</option> </option>
</component> </component>
</project> </project>
+1 -1
View File
@@ -8,7 +8,7 @@
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="24" 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,javafx.graphics" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -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,javafx.graphics" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -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.integrationsWin.windowsHelloKeychainPaths=&quot;@{appdata}/Cryptomator/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator/windowsHelloKeychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.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.integrationsWin.windowsHelloKeychainPaths=&quot;@{appdata}/Cryptomator-Dev/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/windowsHelloKeychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.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/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" /> <option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -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>
+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,javafx.graphics" /> <option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/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>
+17 -10
View File
@@ -1,9 +1,9 @@
[![cryptomator](cryptomator.png)](https://cryptomator.org/) [![cryptomator](cryptomator.png)](https://cryptomator.org/)
[![Build](https://github.com/cryptomator/cryptomator/workflows/Build/badge.svg)](https://github.com/cryptomator/cryptomator/actions/workflows/build.yml?query=branch%3Adevelop) [![Build](https://github.com/cryptomator/cryptomator/workflows/Build/badge.svg)](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild)
[![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptomator/badge.svg)](https://snyk.io/test/github/cryptomator/cryptomator) [![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptomator/badge.svg)](https://snyk.io/test/github/cryptomator/cryptomator)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cryptomator_cryptomator&metric=alert_status)](https://sonarcloud.io/dashboard?id=cryptomator_cryptomator) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cryptomator_cryptomator&metric=alert_status)](https://sonarcloud.io/dashboard?id=cryptomator_cryptomator)
[![Mastodon](https://img.shields.io/mastodon/follow/176112?domain=mastodon.online&style=flat)](https://mastodon.online/@cryptomator) [![Twitter](https://img.shields.io/badge/twitter-@Cryptomator-blue.svg?style=flat)](http://twitter.com/Cryptomator)
[![Crowdin](https://badges.crowdin.net/cryptomator/localized.svg)](https://translate.cryptomator.org/) [![Crowdin](https://badges.crowdin.net/cryptomator/localized.svg)](https://translate.cryptomator.org/)
[![Latest Release](https://img.shields.io/github/release/cryptomator/cryptomator.svg)](https://github.com/cryptomator/cryptomator/releases/latest) [![Latest Release](https://img.shields.io/github/release/cryptomator/cryptomator.svg)](https://github.com/cryptomator/cryptomator/releases/latest)
[![Community](https://img.shields.io/badge/help-Community-orange.svg)](https://community.cryptomator.org) [![Community](https://img.shields.io/badge/help-Community-orange.svg)](https://community.cryptomator.org)
@@ -17,24 +17,31 @@ Cryptomator is provided free of charge as an open-source project despite the hig
### Gold Sponsors ### Gold Sponsors
Become our Gold Sponsor and showcase your brand to a targeted audience! Please contact us if you are interested. <table>
<tbody>
<tr>
<td><a href="https://www.gee-whiz.de/"><img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="80"></a></td>
</tr>
</tbody>
</table>
### Silver Sponsors ### Silver Sponsors
<table> <table>
<tbody> <tbody>
<tr> <tr>
<td><a href="https://www.gee-whiz.de/"><img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="56"></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>
### Special Shoutout ### Special Shoutout
Continuous integration hosting for ARM64 builds is provided by [MacStadium](https://www.macstadium.com/company/opensource). Continuous integration hosting for ARM64 builds is provided by [MacStadium](https://www.macstadium.com/opensource).
<a href="https://www.macstadium.com/company/opensource"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="MacStadium" height="100"></a> <a href="https://www.macstadium.com/opensource"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="MacStadium" height="100"></a>
--- ---
@@ -54,7 +61,7 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator
- File names get encrypted - File names get encrypted
- Folder structure gets obfuscated - Folder structure gets obfuscated
- Use as many vaults in your Dropbox as you want, each having individual passwords - Use as many vaults in your Dropbox as you want, each having individual passwords
- More than Five thousand commits for the security of your data!! :tada: - Four thousand commits for the security of your data!! :tada:
### Privacy ### Privacy
@@ -72,13 +79,13 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator
### Security Architecture ### Security Architecture
For more information on the security details visit [cryptomator.org](https://docs.cryptomator.org/security/architecture/). For more information on the security details visit [cryptomator.org](https://docs.cryptomator.org/en/latest/security/architecture/).
## Building ## Building
### Dependencies ### Dependencies
* JDK 24 (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
+18 -60
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,68 +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=24.0.1 # add runtime
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
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
# create runtime
## check for JEP 493
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
## create runtime image
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--verbose \ --verbose \
--output runtime \ --output runtime \
--module-path "${JMOD_PATHS}" \ --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 \
@@ -81,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=javafx.graphics,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 - 2025 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}" \
@@ -94,10 +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}\"" \
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \ --add-launcher cryptomator-gtk2=launcher-gtk2.properties \
--resource-dir ../resources --resource-dir ../resources
# transform AppDir # transform AppDir
@@ -107,31 +69,27 @@ 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
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/Cryptomator.svg
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/org.cryptomator.Cryptomator.desktop ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml
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/appimagetool/releases/download/continuous/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 ""
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir runtime squashfs-root openjfx-jmods; rm /tmp/appimagetool.AppImage openjfx-jmods.zip" echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir jni runtime squashfs-root; rm launcher-gtk2.properties /tmp/appimagetool.AppImage"
echo "" echo ""
+40 -161
View File
@@ -1,36 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2018 Armin Schrenk <armin.schrenk@zoho.eu> -->
<component type="desktop-application"> <component type="desktop-application">
<id>org.cryptomator.Cryptomator</id> <id>org.cryptomator.Cryptomator</id>
<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 for your cloud made easy</summary> <summary>Multi-platform client-side encryption tool optimized for cloud storages</summary>
<keywords>
<keyword>encryption</keyword>
<keyword>security</keyword>
<keyword>privacy</keyword>
</keywords>
<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>
@@ -48,163 +42,48 @@
</provides> </provides>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot>
<caption>Encrypts your data, protects your privacy</caption> <caption>Light theme</caption>
<image>https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlockDialog_light.png</image> <image>https://user-images.githubusercontent.com/11858409/156986109-6e58f59c-8b8c-4501-b33b-bb1e33007cea.png</image>
</screenshot> </screenshot>
<screenshot> <screenshot>
<caption>Dark theme available</caption> <caption>Dark theme</caption>
<image>https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_dark.png</image> <image>https://user-images.githubusercontent.com/11858409/156986113-6c5d7801-86e0-4643-bc2f-aff9d95d3ce0.png</image>
</screenshot>
<screenshot>
<caption>Easy to use - work on encrypted files as if they were not</caption>
<image>https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_light.png</image>
</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="2025-05-15" version="1.16.2"> <release date="2023-06-07" version="1.9.1"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.2</url> <release date="2023-05-30" version="1.9.0"/>
</release> <release date="2023-04-25" version="1.8.0"/>
<release date="2025-04-30" version="1.16.1"> <release date="2023-04-07" version="1.7.5"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.1</url> <release date="2023-04-05" version="1.7.4"/>
</release> <release date="2023-03-15" version="1.7.3"/>
<release date="2025-04-29" version="1.16.0"> <release date="2023-03-07" version="1.7.2"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.0</url> <release date="2023-03-03" version="1.7.1"/>
</release> <release date="2023-03-01" version="1.7.0"/>
<release date="2025-04-09" version="1.15.3"> <release date="2022-12-14" version="1.6.17"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.3</url> <release date="2022-12-06" version="1.6.16"/>
</release> <release date="2022-10-06" version="1.6.15"/>
<release date="2025-04-04" version="1.15.2"> <release date="2022-08-31" version="1.6.14"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.2</url> <release date="2022-07-27" version="1.6.12"/>
</release> <release date="2022-07-26" version="1.6.11"/>
<release date="2025-02-05" version="1.15.1"> <release date="2022-05-03" version="1.6.10"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.1</url> <release date="2022-04-27" version="1.6.9"/>
</release> <release date="2022-03-30" version="1.6.8"/>
<release date="2025-02-03" version="1.15.0"> <release date="2021-12-16" version="1.6.5"/>
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.0</url>
</release>
<release date="2024-11-19" version="1.14.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.14.2</url>
</release>
<release date="2024-09-17" version="1.14.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.14.0</url>
</release>
<release date="2024-06-26" version="1.13.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.13.0</url>
</release>
<release date="2024-03-27" version="1.12.4">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.4</url>
</release>
<release date="2024-02-27" version="1.12.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.3</url>
</release>
<release date="2024-02-09" version="1.12.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.2</url>
</release>
<release date="2024-02-07" version="1.12.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.12.1</url>
</release>
<release date="2024-02-06" version="1.12.0">
<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,16 +0,0 @@
<svg height="16" viewBox="0 0 42 42" width="16" xmlns="http://www.w3.org/2000/svg">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text {
color:#222222;
}
.ColorScheme-Highlight {
color:#49B04A;
}
</style>
</defs>
<g fill-rule="evenodd">
<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" class="ColorScheme-Text" fill="currentColor"/>
<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" class="ColorScheme-Highlight" fill="currentColor"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

-10
View File
@@ -1,10 +0,0 @@
<svg height="16" viewBox="0 0 42 42" width="16" xmlns="http://www.w3.org/2000/svg">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text {
color:#222222;
}
</style>
</defs>
<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" class="ColorScheme-Text" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

+1 -1
View File
@@ -1,4 +1,4 @@
cryptomator (${PPA_VERSION}) jammy; urgency=low cryptomator (${PPA_VERSION}) focal; urgency=low
* Full changelog can be found on https://github.com/cryptomator/cryptomator/releases * Full changelog can be found on https://github.com/cryptomator/cryptomator/releases
+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-24 (>= 24.0.1+9-0ppa3), 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-2025 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-2025 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 -11
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-24-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=javafx.graphics,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 - 2025 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,13 +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\"" \
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
--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>
+1 -4
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
+13 -59
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 - 2025" 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=24.0.1
JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="b5a94a13077507003fa852512bfa33f4fb680bc8076d8002e4227a84c85171d4"
else
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="6e62a426d43c168a488521f904a523f3dd6ee2cf103e08136f2fd465c828a105"
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,44 +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
# create runtime # add runtime
## check for JEP 493
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
## create custom runtime
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JMOD_PATHS}" \ --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 \
@@ -106,7 +67,7 @@ ${JAVA_HOME}/bin/jpackage \
--copyright "(C) ${COPYRIGHT_YEARS} ${VENDOR}" \ --copyright "(C) ${COPYRIGHT_YEARS} ${VENDOR}" \
--app-version "${VERSION_NO}" \ --app-version "${VERSION_NO}" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac" \ --java-options "--enable-native-access=org.cryptomator.jfuse.mac" \
--java-options "-Xss5m" \ --java-options "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \ --java-options "-Dfile.encoding=\"utf-8\"" \
@@ -130,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 \
@@ -143,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
@@ -165,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
@@ -191,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 2025 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"
pwsh -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%"^
+31 -105
View File
@@ -18,32 +18,14 @@ $ProgressPreference = 'SilentlyContinue' # disables Invoke-WebRequest's progress
# check preconditions # check preconditions
if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null) if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null)
{ {
Write-Error "Unable to find git.exe in your PATH (try: choco install git)" Write-Host "Unable to find git.exe in your PATH (try: choco install git)"
exit 1 exit 1
} }
if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null) if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
{ {
Write-Error "Unable to find mvn.cmd in your PATH (try: choco install maven)" Write-Host "Unable to find mvn.cmd in your PATH (try: choco install maven)"
exit 1 exit 1
} }
if ((Get-Command 'wix' -ErrorAction SilentlyContinue) -eq $null)
{
Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.0)'
exit 1
}
$wixExtensions = & wix.exe extension list --global | Out-String
if ($wixExtensions -notmatch 'WixToolset.UI.wixext') {
Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.0 --global)'
exit 1
}
if ($wixExtensions -notmatch 'WixToolset.Util.wixext') {
Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.0 --global)'
exit 1
}
if ($wixExtensions -notmatch 'WixToolset.BootstrapperApplications.wixext') {
Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global)'
exit 1
}
$buildDir = Split-Path -Parent $PSCommandPath $buildDir = Split-Path -Parent $PSCommandPath
$version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout) $version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout)
@@ -59,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
@@ -68,71 +50,33 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
Remove-Item -Path $runtimeImagePath -Force -Recurse Remove-Item -Path $runtimeImagePath -Force -Recurse
} }
## download jfx jmods for X64, while they are part of the Arm64 JDK ## download jfx jmods
$archCode = (Get-CimInstance Win32_Processor).Architecture $jfxJmodsChecksum = 'd00767334c43b8832b5cf10267d34ca8f563d187c4655b73eb6020dd79c054b5'
$archName = switch ($archCode) { $jfxJmodsZip = '.\resources\jfxJmods.zip'
9 { "x64 (AMD64)" } if( !(Test-Path -Path $jfxJmodsZip) ) {
12 { "ARM64" } $jmodsUrl = "https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_windows-x64_bin-jmods.zip"
default { "WMI Win32_Processor.Architecture code ($archCode)" } Write-Output "Downloading ${jmodsUrl}..."
Invoke-WebRequest $jmodsUrl -OutFile $jfxJmodsZip # redirects are followed by default
} }
switch ($archName) { $jmodsChecksumActual = $(Get-FileHash -Path $jfxJmodsZip -Algorithm SHA256).Hash
'ARM64' { if( $jmodsChecksumActual -ne $jfxJmodsChecksum ) {
$javafxBaseJmod = Join-Path $Env:JAVA_HOME "jmods\javafx.base.jmod" Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $jfxJmodsChecksum, actual: $jmodsChecksumActual"
if (!(Test-Path $javafxBaseJmod)) { exit 1;
Write-Error "JavaFX module not found in JDK. Please ensure full JDK (including jmods) is installed."
exit 1
}
$jmodPaths = "$Env:JAVA_HOME/jmods"
}
'x64 (AMD64)' {
$javaFxVersion='24.0.1'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
Write-Output "Downloading ${javaFxJmodsUrl}..."
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
}
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash.ToLower()
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256
, actual: $jmodsChecksumActual"
exit 1;
}
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods" -ErrorAction Ignore
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
$jmodPaths="$buildDir/resources/javafx-jmods";
}
default {
Write-Error "Unsupported architecture: $arch"
exit 1
}
} }
Expand-Archive -Force -Path $jfxJmodsZip -DestinationPath ".\resources\"
## create custom runtime
### check for JEP 493
if ((& "$Env:JAVA_HOME\bin\jlink" --help | Select-String -Pattern "Linking from run-time image enabled" -SimpleMatch | Measure-Object).Count -eq 0 ) {
$jmodPaths="$Env:JAVA_HOME/jmods;" + $jmodPaths;
}
### create runtime
& "$Env:JAVA_HOME\bin\jlink" ` & "$Env:JAVA_HOME\bin\jlink" `
--verbose ` --verbose `
--output runtime ` --output runtime `
--module-path $jmodPaths ` --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,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml ` --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.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 and use msi compression --compress=1
$appPath = ".\$AppName" $appPath = ".\$AppName"
if ($clean -and (Test-Path -Path $appPath)) { if ($clean -and (Test-Path -Path $appPath)) {
@@ -152,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=javafx.graphics,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`"" `
@@ -168,14 +112,13 @@ if ($clean -and (Test-Path -Path $appPath)) {
--java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" ` --java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" `
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" ` --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" `
--java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" ` --java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" `
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`"" `
--java-options "-Dcryptomator.showTrayIcon=true" ` --java-options "-Dcryptomator.showTrayIcon=true" `
--java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" ` --java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" `
--resource-dir resources ` --resource-dir resources `
--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\" `
@@ -198,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 `
@@ -219,13 +161,8 @@ $Env:JP_WIXHELPER_DIR = "."
--about-url $AboutUrl ` --about-url $AboutUrl `
--file-associations resources/FAvaultFile.properties --file-associations resources/FAvaultFile.properties
if ($LASTEXITCODE -ne 0) {
Write-Error "jpackage MSI failed with exit code $LASTEXITCODE"
return 1;
}
#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\" `
@@ -235,30 +172,19 @@ if ($LASTEXITCODE -ne 0) {
"-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" -Force Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi"
# create bundle including winfsp # create bundle including winfsp
& wix build ` & "$env:WIX\bin\candle.exe" .\bundle\bundleWithWinfsp.wxs -ext WixBalExtension -ext WixUtilextension -out bundle\ `
-define BundleName="$AppName" ` -dBundleVersion="$semVerNo.$revisionNo" `
-define BundleVersion="$semVerNo.$revisionNo" ` -dBundleVendor="$Vendor" `
-define BundleVendor="$Vendor" ` -dBundleCopyright="$copyright" `
-define BundleCopyright="$copyright" ` -dAboutUrl="$AboutUrl" `
-define AboutUrl="$AboutUrl" ` -dHelpUrl="$HelpUrl" `
-define HelpUrl="$HelpUrl" ` -dUpdateUrl="$UpdateUrl"
-define UpdateUrl="$UpdateUrl" ` & "$env:WIX\bin\light.exe" -b . .\bundle\BundlewithWinfsp.wixobj -ext WixBalExtension -ext WixUtilextension -out installer\$AppName-Installer.exe
-ext "WixToolset.Util.wixext" `
-ext "WixToolset.BootstrapperApplications.wixext" `
.\bundle\bundleWithWinfsp.wxs `
-out "installer\$AppName-Installer.exe"
Write-Output "Created EXE installer .\installer\$AppName-Installer.exe"
+57 -44
View File
@@ -1,48 +1,61 @@
<!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/--> <?xml version="1.0"?>
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<ns0:Bundle Name="$(var.BundleName)" <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">
UpgradeCode="29eea626-2e5b-4449-b5f8-4602925ddf7b" <!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html-->
Version="$(var.BundleVersion)" <!-- Attributes explicitly not used:
Manufacturer="$(var.BundleVendor)" Condition - the single msi files have their own install conditions, no need to copy them here
AboutUrl="$(var.AboutUrl)" -->
HelpUrl="$(var.HelpUrl)"
UpdateUrl="$(var.UpdateUrl)" <Bundle Name="Cryptomator" UpgradeCode="29eea626-2e5b-4449-b5f8-4602925ddf7b" Version="$(var.BundleVersion)" Manufacturer="$(var.BundleVendor)"
Copyright="$(var.BundleCopyright)" AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico">
IconSourceFile="bundle\resources\Cryptomator.ico">
<!-- detect outdated WinFsp installations --> <!-- detect outdated WinFsp installations -->
<util:ProductSearch Variable="InstalledLegacyWinFspVersion" Result="version" UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B" /> <?include "resources\winFspMetaData.wxi" ?>
<util:ProductSearch
Variable="InstalledWinFspVersion"
Result="version"
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.
<ns0:BootstrapperApplication> 1. Open the view of installed apps
<bal:WixStandardBootstrapperApplication LicenseFile="bundle\resources\license.rtf" ShowVersion="yes" 2. Search for &quot;WinFsp&quot;
SuppressOptionsUI="yes" 3. Uninstall the listed application
Theme="rtfLargeLicense" 4. Reboot your device
ThemeFile="bundle\resources\customBootstrapperTheme.xml" 5. Restart this installer">(InstalledWinFspVersion = v0.0.0.0) OR ($(var.BundledWinFspVersion) &lt;= InstalledWinFspVersion)</bal:Condition>
LocalizationFile="bundle\resources\customBootstrapperTheme.wxl"
LogoSideFile="bundle\resources\logoSide.png"
LogoFile="bundle\resources\logo.png"
LaunchTarget="[ProgramFiles64Folder]\$(var.BundleName)\$(var.BundleName).exe" />
<ns0:Payload SourceFile="bundle\resources\logoSide.png"/>
<!-- Required due to https://github.com/wixtoolset/issues/issues/8104 -->
<ns0:Payload Name="Cryptobot.ico" SourceFile="bundle\resources\Cryptomator.ico"/>
</ns0:BootstrapperApplication>
<ns0:Chain> <!-- for definition of the standard themes, see https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/-->
<ns0:ExePackage Cache="keep" PerMachine="yes" Permanent="no" SourceFile="bundle\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))" UninstallArguments=""> <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
<ns0:CommandLine Condition="WixBundleUILevel &lt;= 3" InstallArgument="-q -l &quot;[WixBundleLog].winfsp-uninstaller.log&quot;" RepairArgument="-q" UninstallArgument="-s" /> <!-- see https://wixtoolset.org/documentation/manual/v3/xsd/bal/wixstandardbootstrapperapplication.html -->
<!-- XML allows line breaks in attributes, hence keep the line breaks here --> <!-- Possible Attributes: LaunchTarget -->
<ns0: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. <bal:WixStandardBootstrapperApplication
LicenseFile="bundle\resources\license.rtf"
Do you want to continue?&quot;" RepairArgument="-q" UninstallArgument="-s" /> ShowVersion="yes"
<ns0:ExitCode Behavior="success" Value="0" /> SuppressOptionsUI="yes"
<ns0:ExitCode Behavior="success" Value="1" /> ThemeFile="bundle\customBootstrapperTheme.xml"
<ns0:ExitCode Behavior="error" Value="2" /> LocalizationFile="bundle\customBootstrapperTheme.wxl"
<ns0:ExitCode Behavior="error" Value="3" /> LogoFile="bundle\resources\logo.png"
<ns0:ExitCode Behavior="forceReboot" Value="4" /> />
<ns0:ExitCode Behavior="success" Value="5" /> <Payload SourceFile="bundle\resources\logoSide.png" />
</ns0:ExePackage> </BootstrapperApplicationRef>
<ns0:MsiPackage SourceFile="bundle\resources\Cryptomator.msi" CacheId="cryptomator-bundle-cryptomator" Visible="no" /> <Chain>
<ns0:MsiPackage SourceFile="bundle\resources\winfsp.msi" CacheId="cryptomator-bundle-winfsp" Visible="yes" Permanent="yes" /> <!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/msipackage.html-->
</ns0:Chain> <MsiPackage
</ns0:Bundle> SourceFile="resources\Cryptomator.msi"
</ns0:Wix> CacheId="cryptomator-bundle-cryptomator"
DisplayInternalUI="no"
Visible="no"
/>
<MsiPackage
SourceFile="resources\winfsp.msi"
CacheId="cryptomator-bundle-winfsp"
Visible="yes"
DisplayInternalUI="no"
Vital="no"
Permanent="yes"
/>
</Chain>
</Bundle>
</Wix>
+64
View File
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="Caption">[WixBundleName] Setup</String>
<String Id="Title">[WixBundleName]</String>
<String Id="InstallHeader">Welcome</String>
<String Id="InstallMessage">This Setup will install [WixBundleName] and additional dependencies on your computer.</String>
<String Id="InstallVersion">Version [WixBundleVersion]</String>
<String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
<String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String>
<String Id="HelpHeader">Setup Help</String>
<String Id="HelpText">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or
creates a complete local copy of the bundle in directory. Install is the default.
/passive | /quiet - displays minimal UI with no prompts or displays no UI and
no prompts. By default UI and all prompts are displayed.
/norestart - suppress any attempts to restart. By default UI will prompt before restart.
/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>
<String Id="HelpCloseButton">&amp;Close</String>
<String Id="InstallLicenseLinkText">[WixBundleName] &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
<String Id="InstallOptionsButton">&amp;Options</String>
<String Id="InstallInstallButton">&amp;Install</String>
<String Id="InstallCloseButton">&amp;Close</String>
<String Id="OptionsHeader">Setup Options</String>
<String Id="OptionsLocationLabel">Install location:</String>
<String Id="OptionsBrowseButton">&amp;Browse</String>
<String Id="OptionsOkButton">&amp;OK</String>
<String Id="OptionsCancelButton">&amp;Cancel</String>
<String Id="ProgressHeader">Setup Progress</String>
<String Id="ProgressLabel">Processing:</String>
<String Id="OverallProgressPackageText">Initializing...</String>
<String Id="ProgressCancelButton">&amp;Cancel</String>
<String Id="ModifyHeader">Modify Setup</String>
<String Id="ModifyRepairButton">&amp;Repair</String>
<String Id="ModifyUninstallButton">&amp;Uninstall</String>
<String Id="ModifyCloseButton">&amp;Close</String>
<String Id="SuccessRepairHeader">Repair Successfully Completed</String>
<String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String>
<String Id="SuccessInstallHeader">Installation Successfully Completed</String>
<String Id="SuccessHeader">Setup Successful</String>
<String Id="SuccessLaunchButton">&amp;Launch</String>
<String Id="SuccessRestartText">You must restart your computer before you can use the software.</String>
<String Id="SuccessRestartButton">&amp;Restart</String>
<String Id="SuccessCloseButton">&amp;Close</String>
<String Id="FailureHeader">Setup Failed</String>
<String Id="FailureInstallHeader">Setup Failed</String>
<String Id="FailureUninstallHeader">Uninstall Failed</String>
<String Id="FailureRepairHeader">Repair Failed</String>
<String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
<String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
<String Id="FailureRestartButton">&amp;Restart</String>
<String Id="FailureCloseButton">&amp;Close</String>
<String Id="FilesInUseHeader">Files In Use</String>
<String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String>
<String Id="FilesInUseCloseRadioButton">Close the &amp;applications and attempt to restart them.</String>
<String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
<String Id="FilesInUseOkButton">&amp;OK</String>
<String Id="FilesInUseCancelButton">&amp;Cancel</String>
<String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
</WixLocalization>
+91
View File
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<!-- adjusted theme based on https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/HyperlinkSidebarTheme.xml -->
<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">
<Window Width="600" Height="450" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window>
<Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font>
<Font Id="5" Height="-12" Weight="700" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Page Name="Help">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text>
<Text X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text>
<Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button>
</Page>
<Page Name="Install">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text X="185" Y="50" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.InstallHeader)</Text>
<Text X="185" Y="91" Width="-11" Height="64" FontId="3" DisablePrefix="yes">#(loc.InstallMessage)</Text>
<Richedit Name="EulaRichedit" X="185" Y="131" Width="-12" Height="-65" HexStyle="0x00800000" TabStop="yes" FontId="0" />
<Checkbox Name="EulaAcceptCheckbox" X="185" Y="-46" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Text Name="InstallVersion" X="185" Y="-11" Width="-11" Height="17" FontId="3" DisablePrefix="yes" HideWhenDisabled="yes">#(loc.InstallVersion)</Text>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
<Page Name="FilesInUse">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FilesInUseHeader)</Text>
<Text X="11" Y="121" Width="-11" Height="34" FontId="3" DisablePrefix="yes">#(loc.FilesInUseLabel)</Text>
<Text Name="FilesInUseText" X="11" Y="150" Width="-11" Height="-86" FontId="3" DisablePrefix="yes" HexStyle="0x0000000C">A</Text>
<Button Name="FilesInUseCloseRadioButton" X="11" Y="-60" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseCloseRadioButton)</Button>
<Button Name="FilesInUseDontCloseRadioButton" X="11" Y="-40" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseDontCloseRadioButton)</Button>
<Button Name="FilesInUseOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FilesInUseOkButton)</Button>
<Button Name="FilesInUseCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FilesInUseCancelButton)</Button>
</Page>
<Page Name="Progress">
<Text X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text>
<Text X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text>
<Text Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button>
</Page>
<Page Name="Success">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text Name="SuccessHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text>
<Text Name="SuccessInstallHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text>
<Text Name="SuccessRepairHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text>
<Text Name="SuccessUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Text Name="SuccessRestartText" X="185" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button>
</Page>
<Page Name="Failure">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text Name="FailureHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text>
<Text Name="FailureInstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text>
<Text Name="FailureUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text>
<Text Name="FailureRepairHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text>
<Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="185" Y="-80" Width="-11" Height="140" FontId="5" TabStop="yes" HideWhenDisabled="yes" />
<Text Name="FailureRestartText" X="185" Y="-57" Width="-11" Height="80" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button>
</Page>
</Theme>
-68
View File
@@ -1,68 +0,0 @@
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://wixtoolset.org/schemas/v4/wxl">
<String Id="Caption" Value="[WixBundleName] Setup" />
<String Id="Title" Value="[WixBundleName]" />
<String Id="InstallHeader" Value="Welcome" />
<String Id="InstallMessage" Value="Setup will install [WixBundleName] on your computer." />
<String Id="InstallVersion" Value="Version [WixBundleVersion]" />
<String Id="CheckingForUpdatesLabel" Value="Checking for updates" />
<String Id="UpdateButton" Value="&amp;Update to version [WixStdBAUpdateAvailable]" />
<String Id="InstallVersion" Value="Version [WixBundleVersion]" />
<String Id="ConfirmCancelMessage" Value="Are you sure you want to cancel?" />
<String Id="ExecuteUpgradeRelatedBundleMessage" Value="Previous version" />
<String Id="HelpHeader" Value="Setup Help" />
<String Id="HelpText" Value="/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or&#xA; creates a complete local copy of the bundle in directory. Install is the default.&#xA;&#xA;/passive | /quiet - displays minimal UI with no prompts or displays no UI and&#xA; no prompts. By default UI and all prompts are displayed.&#xA;&#xA;/norestart - suppress any attempts to restart. By default UI will prompt before restart.&#xA;/log log.txt - logs to a specific file. By default a log file is created in %TEMP%." />
<String Id="HelpCloseButton" Value="&amp;Close" />
<String Id="InstallAcceptCheckbox" Value="I &amp;agree to the license terms and conditions" />
<String Id="InstallOptionsButton" Value="&amp;Options" />
<String Id="InstallInstallButton" Value="&amp;Install" />
<String Id="InstallCancelButton" Value="&amp;Cancel" />
<String Id="OptionsHeader" Value="Setup Options" />
<String Id="OptionsLocationLabel" Value="Install location:" />
<String Id="OptionsBrowseButton" Value="&amp;Browse" />
<String Id="OptionsOkButton" Value="&amp;OK" />
<String Id="OptionsCancelButton" Value="&amp;Cancel" />
<String Id="ProgressHeader" Value="Setup Progress" />
<String Id="ProgressLabel" Value="Processing:" />
<String Id="OverallProgressPackageText" Value="Initializing..." />
<String Id="ProgressCancelButton" Value="&amp;Cancel" />
<String Id="ModifyHeader" Value="Modify Setup" />
<String Id="ModifyRepairButton" Value="&amp;Repair" />
<String Id="ModifyUninstallButton" Value="&amp;Uninstall" />
<String Id="ModifyCancelButton" Value="&amp;Cancel" />
<String Id="SuccessHeader" Value="Setup Successful" />
<String Id="SuccessCacheHeader" Value="Cache Successfully Completed" />
<String Id="SuccessInstallHeader" Value="Installation Successfully Completed" />
<String Id="SuccessLayoutHeader" Value="Layout Successfully Completed" />
<String Id="SuccessModifyHeader" Value="Modify Successfully Completed" />
<String Id="SuccessRepairHeader" Value="Repair Successfully Completed" />
<String Id="SuccessUninstallHeader" Value="Uninstall Successfully Completed" />
<String Id="SuccessUnsafeUninstallHeader" Value="Uninstall Successfully Completed" />
<String Id="SuccessLaunchButton" Value="&amp;Launch" />
<String Id="SuccessRestartText" Value="You must restart your computer before you can use the software." />
<String Id="SuccessUninstallRestartText" Value="You must restart your computer to complete the removal of the software." />
<String Id="SuccessRestartButton" Value="&amp;Restart" />
<String Id="SuccessCloseButton" Value="&amp;Close" />
<String Id="FailureHeader" Value="Setup Failed" />
<String Id="FailureCacheHeader" Value="Cache Failed" />
<String Id="FailureInstallHeader" Value="Setup Failed" />
<String Id="FailureLayoutHeader" Value="Layout Failed" />
<String Id="FailureModifyHeader" Value="Modify Failed" />
<String Id="FailureRepairHeader" Value="Repair Failed" />
<String Id="FailureUninstallHeader" Value="Uninstall Failed" />
<String Id="FailureUnsafeUninstallHeader" Value="Uninstall Failed" />
<String Id="FailureHyperlinkLogText" Value="One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href=&quot;#&quot;&gt;log file&lt;/a&gt;." />
<String Id="FailureRestartText" Value="You must restart your computer to complete the rollback of the software." />
<String Id="FailureRestartButton" Value="&amp;Restart" />
<String Id="FailureCloseButton" Value="&amp;Close" />
<String Id="FilesInUseTitle" Value="Files In Use" />
<String Id="FilesInUseLabel" Value="The following applications are using files that need to be updated:" />
<String Id="FilesInUseNetfxCloseRadioButton" Value="Close the &amp;applications." />
<String Id="FilesInUseCloseRadioButton" Value="Close the &amp;applications and attempt to restart them." />
<String Id="FilesInUseDontCloseRadioButton" Value="&amp;Do not close applications. A reboot will be required." />
<String Id="FilesInUseRetryButton" Value="&amp;Retry" />
<String Id="FilesInUseIgnoreButton" Value="&amp;Ignore" />
<String Id="FilesInUseExitButton" Value="E&amp;xit" />
</WixLocalization>
-133
View File
@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
<Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
<Window Width="600" Height="450" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)" IconFile="Cryptobot.ico">
<Page Name="Help">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
<Label X="11" Y="121" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
<Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.HelpCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Loading">
<Label X="185" Y="50" Width="-11" Height="30" FontId="2" DisablePrefix="yes" Visible="no" Name="CheckingForUpdatesLabel" />
</Page>
<Page Name="Install">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.InstallHeader)</Label>
<Label X="185" Y="50" Width="-11" Height="64" FontId="3" DisablePrefix="yes">
<Text Condition="WixStdBASuppressOptionsUI">#(loc.InstallMessage)</Text>
<Text Condition="NOT WixStdBASuppressOptionsUI">#(loc.InstallMessageOptions)</Text>
</Label>
<Richedit Name="EulaRichedit" X="185" Y="91" Width="-12" Height="-64" HexStyle="0x00800000" TabStop="yes" FontId="0" />
<Checkbox Name="EulaAcceptCheckbox" X="185" Y="-39" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="InstallUpdateButton" X="11" Y="-11" Width="200" Height="23" TabStop="yes" FontId="0" EnableCondition="WixStdBAUpdateAvailable" HideWhenDisabled="yes">#(loc.UpdateButton)</Button>
<Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" VisibleCondition="NOT WixStdBASuppressOptionsUI">
<Text>#(loc.InstallOptionsButton)</Text>
<ChangePageAction Page="Options" />
</Button>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.InstallCancelButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Options">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Label>
<Label X="11" Y="121" Width="-11" Height="17" FontId="3">#(loc.OptionsLocationLabel)</Label>
<Editbox Name="InstallFolder" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
<Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">
<Text>#(loc.OptionsBrowseButton)</Text>
<BrowseDirectoryAction VariableName="InstallFolder" />
</Button>
<Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.OptionsOkButton)</Text>
<ChangePageAction Page="Install" />
</Button>
<Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.OptionsCancelButton)</Text>
<ChangePageAction Page="Install" Cancel="yes" />
</Button>
</Page>
<Page Name="Progress">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
<Label X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
<Label Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Label>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Label>
<Label Name="InstallVersion" X="11" Y="-11" Width="-11" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="ModifyUpdateButton" X="11" Y="-11" Width="200" Height="23" TabStop="yes" FontId="0" EnableCondition="WixStdBAUpdateAvailable" HideWhenDisabled="yes">#(loc.UpdateButton)</Button>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.ModifyCancelButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Success">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">
<Text>#(loc.SuccessHeader)</Text>
<Text Condition="WixBundleAction = 2">#(loc.SuccessLayoutHeader)</Text>
<Text Condition="WixBundleAction = 3">#(loc.SuccessUnsafeUninstallHeader)</Text>
<Text Condition="WixBundleAction = 4">#(loc.SuccessUninstallHeader)</Text>
<Text Condition="WixBundleAction = 5">#(loc.SuccessCacheHeader)</Text>
<Text Condition="WixBundleAction = 6">#(loc.SuccessInstallHeader)</Text>
<Text Condition="WixBundleAction = 7">#(loc.SuccessModifyHeader)</Text>
<Text Condition="WixBundleAction = 8">#(loc.SuccessRepairHeader)</Text>
</Label>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Label X="185" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">
<Text>#(loc.SuccessRestartText)</Text>
<Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallRestartText)</Text>
</Label>
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.SuccessCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Failure">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">
<Text>#(loc.FailureHeader)</Text>
<Text Condition="WixBundleAction = 2">#(loc.FailureLayoutHeader)</Text>
<Text Condition="WixBundleAction = 3">#(loc.FailureUnsafeUninstallHeader)</Text>
<Text Condition="WixBundleAction = 4">#(loc.FailureUninstallHeader)</Text>
<Text Condition="WixBundleAction = 5">#(loc.FailureCacheHeader)</Text>
<Text Condition="WixBundleAction = 6">#(loc.FailureInstallHeader)</Text>
<Text Condition="WixBundleAction = 7">#(loc.FailureModifyHeader)</Text>
<Text Condition="WixBundleAction = 8">#(loc.FailureRepairHeader)</Text>
</Label>
<Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="185" Y="-115" Width="-11" Height="80" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Label X="185" Y="-57" Width="-11" Height="80" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.FailureCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
</Window>
</Theme>
+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 2025 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>
Vendored Executable
BIN
View File
Binary file not shown.
+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 -2
View File
@@ -6,8 +6,7 @@ java ^
-Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^ -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^
-Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^ -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^
-Dcryptomator.mountPointsDir="~/Cryptomator" ^ -Dcryptomator.mountPointsDir="~/Cryptomator" ^
-Dcryptomator.integrationsWin.keychainPaths="~/AppData/Roaming/Cryptomator/keychain.json" ^ -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" ^
-Dcryptomator.integrationsWin.windowsHelloKeychainPaths="~/AppData/Roaming/Cryptomator/windowsHelloKeychain.json" ^
-Xss20m ^ -Xss20m ^
-Xmx512m ^ -Xmx512m ^
--enable-preview ` --enable-preview `
+109
View File
@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Include>
<Fragment>
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/WixUI_InstallDir.wxs with custom exit dialog-->
<UI Id="CustomWizard">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="InstallDir" />
<DialogRef Id="BrowseDlg" />
<DialogRef Id="DiskCostDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<!-- custom end dialogs -->
<Publish Dialog="MyExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
<Publish Dialog="MyFatalErrorDlg" Control="Finish" Event="EndDialog" Value="Return" Order="998">1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg">NOT Installed</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">LicenseAccepted = "1"</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1">NOT Installed</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
<Property Id="ARPNOMODIFY" Value="1" />
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/ExitDialog.wxs with adjustments-->
<Dialog Id="MyExitDialog" Width="370" Height="270" Title="!(loc.ExitDialog_Title)">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.ExitDialogBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogDescription)" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogTitle)" />
<!-- TODO: localize? -->
<Control Id="Suggestion" Type="Text" X="135" Y="100" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
<Text>We recommend for the best user experience to download and install the following third party Windows driver:</Text>
</Control>
<Control Id="WinFsp" Type="Hyperlink" X="140" Y="125" Width="220" Height="60" Transparent="yes">
<Text><![CDATA[WinFsp (<a href="https://winfsp.dev/">Homepage</a>)]]></Text>
</Control>
</Dialog>
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/FatalError.wxs with adjustments-->
<Dialog Id="MyFatalErrorDlg" Width="370" Height="270" Title="!(loc.FatalError_Title)">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)">
<Publish Event="EndDialog" Value="Exit">1</Publish>
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.FatalErrorBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.FatalErrorTitle)" />
<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="80" Transparent="yes" NoPrefix="yes" Text="!(loc.FatalErrorDescription1) !(loc.FatalErrorDescription2)" />
<Control Id="DescriptionReason1" Type="Text" X="135" Y="160" Width="220" Height="20" Transparent="yes" NoPrefix="yes" Hidden="yes" >
<Text>Reason:</Text>
<Condition Action="show">FOUNDRUNNINGAPP</Condition>
</Control>
<Control Id="DescriptionReason2" Type="Text" X="135" Y="170" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Hidden="yes" >
<Text>Application to update was still running during installation.</Text>
<Condition Action="show">FOUNDRUNNINGAPP</Condition>
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="MyExitDialog" Overridable="yes" OnExit="success"/>
<Show Dialog="MyFatalErrorDlg" Overridable="yes" OnExit="error"/>
</InstallUISequence>
<AdminUISequence>
<Show Dialog="MyExitDialog" Overridable="yes" OnExit="success"/>
<Show Dialog="MyFatalErrorDlg" Overridable="yes" OnExit="error"/>
</AdminUISequence>
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Include>
+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 2025 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
+116 -106
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" > <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<?ifdef JpIsSystemWide ?> <?ifdef JpIsSystemWide ?>
<?define JpInstallScope="perMachine"?> <?define JpInstallScope="perMachine"?>
@@ -29,165 +30,174 @@
<?include $(var.JpConfigDir)/overrides.wxi ?> <?include $(var.JpConfigDir)/overrides.wxi ?>
<ns0:Package <Product
Name="$(var.JpAppName)" Id="$(var.JpProductCode)"
Language="$(var.JpProductLanguage)" Name="$(var.JpAppName)"
Version="$(var.JpAppVersion)" Language="$(var.JpProductLanguage)"
Manufacturer="$(var.JpAppVendor)" Version="$(var.JpAppVersion)"
UpgradeCode="$(var.JpProductUpgradeCode)" Manufacturer="$(var.JpAppVendor)"
InstallerVersion="$(var.JpInstallerVersion)" UpgradeCode="$(var.JpProductUpgradeCode)">
Compressed="$(var.JpCompressedMsi)"
ProductCode="$(var.JpProductCode)"
Scope="$(var.JpInstallScope)">
<ns0:SummaryInformation Manufacturer="$(var.JpAppVendor)" Description="$(var.JpAppDescription)"/> <Package
<ns0:Media Id="1" Cabinet="Data.cab" EmbedCab="yes" /> Description="$(var.JpAppDescription)"
Manufacturer="$(var.JpAppVendor)"
InstallerVersion="$(var.JpInstallerVersion)"
Compressed="$(var.JpCompressedMsi)"
InstallScope="$(var.JpInstallScope)" Platform="x64"
/>
<Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
<ns0:Upgrade Id="$(var.JpProductUpgradeCode)"> <Upgrade Id="$(var.JpProductUpgradeCode)">
<ns0:UpgradeVersion <UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectUpgrade)" OnlyDetect="$(var.JpUpgradeVersionOnlyDetectUpgrade)"
Property="JP_UPGRADABLE_FOUND" Property="JP_UPGRADABLE_FOUND"
Maximum="$(var.JpAppVersion)" Maximum="$(var.JpAppVersion)"
MigrateFeatures="yes" MigrateFeatures="yes"
IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)"/> <!-- TODO in earlier versions, this was set to yes--> IncludeMaximum="yes" /> <!-- TODO: check if this needs to be set to yes-->
<ns0:UpgradeVersion <UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)" OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)"
Property="JP_DOWNGRADABLE_FOUND" Property="JP_DOWNGRADABLE_FOUND"
Minimum="$(var.JpAppVersion)" Minimum="$(var.JpAppVersion)"
MigrateFeatures="yes" MigrateFeatures="yes"
IncludeMinimum="$(var.JpUpgradeVersionOnlyDetectDowngrade)" /> IncludeMinimum="$(var.JpUpgradeVersionOnlyDetectDowngrade)" />
</ns0:Upgrade> </Upgrade>
<?ifndef JpAllowUpgrades ?> <?ifndef JpAllowUpgrades ?>
<ns0:CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" /> <CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" />
<?endif?> <?endif?>
<?ifndef JpAllowDowngrades ?> <?ifndef JpAllowDowngrades ?>
<ns0:CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" /> <CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
<?endif?> <?endif?>
<!-- TODO: how does this work again? --> <Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
<ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll" /> <CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" />
<ns0:CustomAction Id="JpFindRelatedProducts" BinaryRef="JpCaDll" DllEntry="FindRelatedProductsEx" />
<?ifndef SkipCryptomatorLegacyCheck ?> <?ifndef SkipCryptomatorLegacyCheck ?>
<!-- Block installation if innosetup entry of Cryptomator is found --> <!-- Block installation if innosetup entry of Cryptomator is found -->
<ns0:Property Id="OLDEXEINSTALLER"> <Property Id="OLDEXEINSTALLER">
<ns0:RegistrySearch Id="InnoSetupInstallation" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Cryptomator_is1" Type="raw" Name="DisplayName" /> <RegistrySearch Id="InnoSetupInstallation" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Cryptomator_is1" Type="raw" Name="DisplayName" />
</ns0:Property> </Property>
<!-- TODO: localize --> <!-- TODO: localize -->
<ns0:Launch Message="A lower version of [ProductName] is already installed. Uninstall it first and then start the setup again. Setup will now exit." Condition="Installed OR NOT OLDEXEINSTALLER" /> <Condition Message="A lower version of [ProductName] is already installed. Uninstall it first and then start the setup again. Setup will now exit.">
<![CDATA[Installed OR NOT OLDEXEINSTALLER]]>
</Condition>
<?endif?> <?endif?>
<!-- Cryptomator uses UNIX Sockets, which are supported starting with Windows 10 v1803--> <!-- Cryptomator uses UNIX Sockets, which are supported starting with Windows 10 v1803-->
<ns0:Property Id="WINDOWSBUILDNUMBER" Secure="yes"> <Property Id="WINDOWSBUILDNUMBER" Secure="yes">
<ns0:RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" /> <RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" />
</ns0:Property> </Property>
<ns0:Launch Message="This application requires Windows 10 version 1803 (build 17134) or newer." Condition="Installed OR (WINDOWSBUILDNUMBER >= 17134)" /> <Condition Message="This application requires Windows 10 version 1803 (build 17134) or newer.">
<![CDATA[Installed OR (WINDOWSBUILDNUMBER >= 17134)]]>
</Condition>
<!-- Non-Opening ProgID --> <!-- Non-Opening ProgID -->
<ns0:DirectoryRef Id="INSTALLDIR"> <DirectoryRef Id="INSTALLDIR">
<ns0:Component Bitness="always64" Id="nonStartingProgID" > <Component Win64="yes" Id="nonStartingProgID" >
<ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/> <File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"></File>
<ns0:ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0"> <ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0">
<ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)"> <Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
<ns0:MIME ContentType="$(var.ProgIdContentType)" Default="yes"/> <MIME ContentType="$(var.ProgIdContentType)" Default="yes"></MIME>
</ns0:Extension> </Extension>
<ns0:Extension Id="c9s" Advertise="no" ContentType="$(var.ProgIdContentType)"/> <Extension Id="c9s" Advertise="no" ContentType="$(var.ProgIdContentType)"/>
</ns0:ProgId> </ProgId>
</ns0:Component> </Component>
</ns0:DirectoryRef> </DirectoryRef>
<!-- Standard required root --> <!-- Standard required root -->
<Directory Id="TARGETDIR" Name="SourceDir"/>
<ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1"> <Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
<ns0:ComponentGroupRef Id="Shortcuts"/> <ComponentGroupRef Id="Shortcuts"/>
<ns0:ComponentGroupRef Id="Files"/> <ComponentGroupRef Id="Files"/>
<ns0:ComponentGroupRef Id="FileAssociations"/> <ComponentGroupRef Id="FileAssociations"/>
<!-- Ref to additional ProgIDs --> <!-- Ref to additional ProgIDs -->
<ns0:ComponentRef Id="nonStartingProgID" /> <ComponentRef Id="nonStartingProgID" />
</ns0:Feature> </Feature>
<ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" /> <CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<ns0:CustomAction Id="JpSetARPCOMMENTS" Property="ARPCOMMENTS" Value="$(var.JpAppDescription)" /> <CustomAction Id="JpSetARPCOMMENTS" Property="ARPCOMMENTS" Value="$(var.JpAppDescription)" />
<ns0:CustomAction Id="JpSetARPCONTACT" Property="ARPCONTACT" Value="$(var.JpAppVendor)" /> <CustomAction Id="JpSetARPCONTACT" Property="ARPCONTACT" Value="$(var.JpAppVendor)" />
<ns0:CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" /> <CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" />
<?ifdef JpHelpURL ?> <?ifdef JpHelpURL ?>
<ns0:CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" /> <CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" />
<?endif?> <?endif?>
<?ifdef JpAboutURL ?> <?ifdef JpAboutURL ?>
<ns0:CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" /> <CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" />
<?endif?> <?endif?>
<?ifdef JpUpdateURL ?> <?ifdef JpUpdateURL ?>
<ns0:CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" /> <CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
<?endif?> <?endif?>
<ns0: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 -->
<ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot;" Sequence="execute" Before="PatchWebDAV" /> <CustomAction Id="PatchWebDAV" Impersonate="no" ExeCommand="[INSTALLDIR]patchWebDAV.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" />
<ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" 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 -->
<ns0:Property Id="FOUNDRUNNINGAPP" Admin="yes"/> <Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<util:CloseApplication <util:CloseApplication
Target="$(var.CloseApplicationTarget)" Target="$(var.CloseApplicationTarget)"
Id="Close$(var.JpAppName)" Id="Close$(var.JpAppName)"
CloseMessage="no" CloseMessage="no"
RebootPrompt="no" RebootPrompt="no"
PromptToContinue="yes" PromptToContinue="yes"
Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue." Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue."
Property="FOUNDRUNNINGAPP" Property="FOUNDRUNNINGAPP"
/> >
<ns0:CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/> </util:CloseApplication>
<CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
<?ifdef JpIcon ?> <?ifdef JpIcon ?>
<ns0:Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/> <Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
<ns0:Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/> <Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
<?endif?> <?endif?>
<ns0:UIRef Id="JpUI"/> <UIRef Id="JpUI"/>
<ns0:InstallExecuteSequence> <InstallExecuteSequence>
<ns0:Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize">Not Installed</Custom>
<ns0:Custom Action="JpSetARPCOMMENTS" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPCOMMENTS" After="CostFinalize">Not Installed</Custom>
<ns0:Custom Action="JpSetARPCONTACT" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPCONTACT" After="CostFinalize">Not Installed</Custom>
<ns0:Custom Action="JpSetARPSIZE" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPSIZE" After="CostFinalize">Not Installed</Custom>
<?ifdef JpHelpURL ?> <?ifdef JpHelpURL ?>
<ns0:Custom Action="JpSetARPHELPLINK" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPHELPLINK" After="CostFinalize">Not Installed</Custom>
<?endif?> <?endif?>
<?ifdef JpAboutURL ?> <?ifdef JpAboutURL ?>
<ns0:Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize">Not Installed</Custom>
<?endif?> <?endif?>
<?ifdef JpUpdateURL ?> <?ifdef JpUpdateURL ?>
<ns0:Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize" Condition="Not Installed" /> <Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize">Not Installed</Custom>
<?endif?> <?endif?>
<?ifndef JpAllowUpgrades ?> <?ifndef JpAllowUpgrades ?>
<ns0:Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts" Condition="JP_UPGRADABLE_FOUND"/> <Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts">JP_UPGRADABLE_FOUND</Custom>
<?endif?> <?endif?>
<?ifndef JpAllowDowngrades ?> <?ifndef JpAllowDowngrades ?>
<ns0:Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts" Condition="JP_DOWNGRADABLE_FOUND" /> <Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts">JP_DOWNGRADABLE_FOUND</Custom>
<?endif?> <?endif?>
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/> <Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
<!-- Check and fail if Cryptomator is running --> <!-- Check and fail if Cryptomator is running -->
<ns0:Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="InstallValidate" /> <Custom Action="WixCloseApplications" Before="InstallValidate"></Custom>
<ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" /> <Custom Action="FailOnRunningApp" After="WixCloseApplications" >FOUNDRUNNINGAPP</Custom>
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* --> <RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications -->
<!-- Skip action on uninstall -->
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
<ns0:Custom Action="PatchWebDAV" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
</ns0:InstallExecuteSequence>
<ns0:InstallUISequence> <Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/> <Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
</ns0:InstallUISequence> </InstallExecuteSequence>
<ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" /> <InstallUISequence>
<ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" /> <Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
</ns0:Package> </InstallUISequence>
</ns0:Wix>
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
</Product>
</Wix>
+1 -1
View File
@@ -47,4 +47,4 @@ Legacy Installation settings:
- SkipCryptomatorLegacyCheck - SkipCryptomatorLegacyCheck
Should be defined to disable checking for the inno setup installation of Cryptomator and undefined, to enable it. Should be defined to disable checking for the inno setup installation of Cryptomator and undefined, to enable it.
--> -->
<ns0:Include xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs"></ns0:Include> <Include/>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR"></Property>
<WixVariable Id="WixUILicenseRtf" Value="$(var.JpLicenseRtf)"></WixVariable>
<UI Id="JpUI">
<UIRef Id="CustomWizard" />
<DialogRef Id="InstallDirNotEmptyDlg"></DialogRef>
<Publish Dialog="ShortcutPromptDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg">1</Publish>
<Publish Dialog="ShortcutPromptDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ShortcutPromptDlg" Order="6">NOT Installed</Publish>
<UIRef Id="CustomWizard" />
</UI>
</Fragment>
<?include $(env.JP_WIXWIZARD_RESOURCES)\customWizard.wxi ?>
</Wix>
+72 -112
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.17.0-SNAPSHOT</version> <version>1.10.0-SNAPSHOT</version>
<name>Cryptomator Desktop App</name> <name>Cryptomator Desktop App</name>
<organization> <organization>
@@ -26,73 +26,49 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>24</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.9.0</cryptomator.cryptofs.version> <cryptomator.cryptofs.version>2.6.6</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.6.0</cryptomator.integrations.version> <cryptomator.integrations.version>1.2.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.5.0</cryptomator.integrations.win.version> <cryptomator.integrations.win.version>1.2.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.4.0</cryptomator.integrations.mac.version> <cryptomator.integrations.mac.version>1.2.0</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.6.0</cryptomator.integrations.linux.version> <cryptomator.integrations.linux.version>1.2.1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.0.5</cryptomator.fuse.version> <cryptomator.fuse.version>3.0.0</cryptomator.fuse.version>
<cryptomator.webdav.version>2.0.10</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.17.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<dagger.version>2.56.1</dagger.version> <dagger.version>2.45</dagger.version>
<easybind.version>2.2</easybind.version> <easybind.version>2.2</easybind.version>
<jackson.version>2.18.3</jackson.version> <guava.version>32.0.1-jre</guava.version>
<javafx.version>24.0.1</javafx.version> <jackson.version>2.15.2</jackson.version>
<jwt.version>4.5.0</jwt.version> <javafx.version>20.0.1</javafx.version>
<nimbus-jose.version>9.37.3</nimbus-jose.version> <jwt.version>4.4.0</jwt.version>
<logback.version>1.5.18</logback.version> <nimbus-jose.version>9.31</nimbus-jose.version>
<slf4j.version>2.0.17</slf4j.version> <logback.version>1.4.7</logback.version>
<tinyoauth2.version>0.8.1</tinyoauth2.version> <slf4j.version>2.0.7</slf4j.version>
<zxcvbn.version>1.9.0</zxcvbn.version> <tinyoauth2.version>0.5.1</tinyoauth2.version>
<zxcvbn.version>1.7.0</zxcvbn.version>
<!-- test dependencies --> <!-- test dependencies -->
<junit.jupiter.version>5.12.2</junit.jupiter.version> <junit.jupiter.version>5.9.3</junit.jupiter.version>
<mockito.version>5.17.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>26.0.2</jetbrains.annotations.version> <jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
<dependency-check.version>12.1.1</dependency-check.version> <dependency-check.version>8.1.2</dependency-check.version>
<jacoco.version>0.8.13</jacoco.version> <jacoco.version>0.8.9</jacoco.version>
<license-generator.version>2.5.0</license-generator.version>
<junit-tree-reporter.version>1.4.0</junit-tree-reporter.version>
<mvn-compiler.version>3.14.0</mvn-compiler.version>
<mvn-resources.version>3.3.1</mvn-resources.version>
<mvn-dependency.version>3.8.1</mvn-dependency.version>
<mvn-surefire.version>3.5.3</mvn-surefire.version>
<mvn-jar.version>3.4.2</mvn-jar.version>
<!-- Property used by surefire to determine jacoco engine -->
<surefire.jacoco.args></surefire.jacoco.args>
</properties> </properties>
<!-- TODO: Remove once webdav version 2.0.11 is released -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter-servlet</artifactId>
<version>1.2.9</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<!-- Cryptomator Libs --> <!-- Cryptomator Libs -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId>
<version>2.2.1</version>
</dependency>
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId> <artifactId>cryptofs</artifactId>
@@ -103,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>
@@ -170,30 +151,17 @@
<groupId>com.auth0</groupId> <groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId> <artifactId>java-jwt</artifactId>
<version>${jwt.version}</version> <version>${jwt.version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.nimbusds</groupId> <groupId>com.nimbusds</groupId>
<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>
@@ -210,23 +178,40 @@
</dependency> </dependency>
<!-- Google --> <!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
<exclusions>
<!-- see https://github.com/google/guava/wiki/UseGuavaInYourBuild#what-about-guavas-own-dependencies -->
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>listenablefuture</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>com.google.dagger</groupId> <groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId> <artifactId>dagger</artifactId>
<version>${dagger.version}</version> <version>${dagger.version}</version>
</dependency> </dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>2.0.1</version>
</dependency>
<!-- Caffeine -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.2.0</version>
</dependency>
<!-- JUnit / Mockito / Hamcrest --> <!-- JUnit / Mockito / Hamcrest -->
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
@@ -255,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>
@@ -273,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>
@@ -328,6 +313,7 @@
<compilerArgs> <compilerArgs>
<arg>-Adagger.fastInit=enabled</arg> <arg>-Adagger.fastInit=enabled</arg>
<arg>-Adagger.formatGeneratedSource=enabled</arg> <arg>-Adagger.formatGeneratedSource=enabled</arg>
<arg>--enable-preview</arg>
</compilerArgs> </compilerArgs>
</configuration> </configuration>
</plugin> </plugin>
@@ -346,35 +332,14 @@
<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>
<reportFormat>plain</reportFormat> <argLine>--enable-preview</argLine>
<consoleOutputReporter>
<disable>true</disable>
</consoleOutputReporter>
<argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar} --enable-native-access=javafx.graphics</argLine>
<statelessTestsetInfoReporter
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
</statelessTestsetInfoReporter>
</configuration> </configuration>
</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>
<executions> <executions>
<execution>
<id>jar-paths-to-properties</id>
<phase>validate</phase>
<goals>
<goal>properties</goal>
</goals>
</execution>
<!-- sort jars into two buckets (classpath and modulepath). exclude openjfx, which gets jlinked separately --> <!-- sort jars into two buckets (classpath and modulepath). exclude openjfx, which gets jlinked separately -->
<execution> <execution>
<id>copy-mods</id> <id>copy-mods</id>
@@ -447,9 +412,6 @@
<goals> <goals>
<goal>prepare-agent</goal> <goal>prepare-agent</goal>
</goals> </goals>
<configuration>
<propertyName>surefire.jacoco.args</propertyName>
</configuration>
</execution> </execution>
<execution> <execution>
<id>report</id> <id>report</id>
@@ -477,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>
+6 -16
View File
@@ -1,10 +1,8 @@
import ch.qos.logback.classic.spi.Configurator; import ch.qos.logback.classic.spi.Configurator;
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider; import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider;
import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider; import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider;
import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider; import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.GoogleDriveMacLocationPresetsProvider; import org.cryptomator.common.locationpresets.GoogleDriveLocationPresetsProvider;
import org.cryptomator.common.locationpresets.GoogleDriveWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.ICloudMacLocationPresetsProvider; import org.cryptomator.common.locationpresets.ICloudMacLocationPresetsProvider;
import org.cryptomator.common.locationpresets.ICloudWindowsLocationPresetsProvider; import org.cryptomator.common.locationpresets.ICloudWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.LeitzcloudLocationPresetsProvider; import org.cryptomator.common.locationpresets.LeitzcloudLocationPresetsProvider;
@@ -14,9 +12,6 @@ import org.cryptomator.common.locationpresets.OneDriveLinuxLocationPresetsProvid
import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider; import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider;
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider; import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider; import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
import org.cryptomator.networking.SSLContextWithMacKeychain;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
import org.cryptomator.integrations.tray.TrayMenuController; import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.logging.LogbackConfiguratorFactory; import org.cryptomator.logging.LogbackConfiguratorFactory;
import org.cryptomator.ui.traymenu.AwtTrayMenuController; import org.cryptomator.ui.traymenu.AwtTrayMenuController;
@@ -26,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;
@@ -36,13 +32,13 @@ 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;
@@ -51,22 +47,16 @@ open module org.cryptomator.desktop {
requires org.slf4j; requires org.slf4j;
requires org.apache.commons.lang3; requires org.apache.commons.lang3;
/* dagger bs */ /* TODO: filename-based modules: */
requires jakarta.inject; requires static javax.inject; /* ugly dagger/guava crap */
requires static javax.inject;
requires java.compiler;
requires com.github.benmanes.caffeine;
uses org.cryptomator.common.locationpresets.LocationPresetsProvider; uses org.cryptomator.common.locationpresets.LocationPresetsProvider;
uses SSLContextProvider;
uses org.cryptomator.event.NotificationHandler;
provides TrayMenuController with AwtTrayMenuController; provides TrayMenuController with AwtTrayMenuController;
provides Configurator with LogbackConfiguratorFactory; provides Configurator with LogbackConfiguratorFactory;
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;
provides LocationPresetsProvider with // provides LocationPresetsProvider with //
DropboxWindowsLocationPresetsProvider, DropboxMacLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, // DropboxWindowsLocationPresetsProvider, DropboxMacLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, //
GoogleDriveMacLocationPresetsProvider, GoogleDriveWindowsLocationPresetsProvider, // GoogleDriveLocationPresetsProvider, //
ICloudWindowsLocationPresetsProvider, ICloudMacLocationPresetsProvider, // ICloudWindowsLocationPresetsProvider, ICloudMacLocationPresetsProvider, //
LeitzcloudLocationPresetsProvider, // LeitzcloudLocationPresetsProvider, //
MegaLocationPresetsProvider, // MegaLocationPresetsProvider, //
@@ -1,22 +0,0 @@
package org.cryptomator;
import javafx.application.Platform;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class JavaFXUtil {
private JavaFXUtil() {}
public static boolean startPlatform() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
try {
Platform.startup(latch::countDown);
} catch (IllegalStateException e) {
//already initialized
latch.countDown();
}
return latch.await(5, TimeUnit.SECONDS);
}
}
@@ -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;
@@ -23,7 +22,6 @@ public class Environment {
private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath"; private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
private static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath"; private static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath";
private static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths"; private static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths";
private static final String WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.windowsHelloKeychainPaths";
private static final String P12_PATH_PROP_NAME = "cryptomator.p12Path"; private static final String P12_PATH_PROP_NAME = "cryptomator.p12Path";
private static final String LOG_DIR_PROP_NAME = "cryptomator.logDir"; private static final String LOG_DIR_PROP_NAME = "cryptomator.logDir";
private static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias"; private static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias";
@@ -33,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() {}
@@ -46,17 +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(WINDOWS_HELLO_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() {
@@ -79,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);
} }
@@ -87,14 +86,6 @@ public class Environment {
return getPaths(KEYCHAIN_PATHS_PROP_NAME); return getPaths(KEYCHAIN_PATHS_PROP_NAME);
} }
public Stream<Path> getWindowsHelloKeychainPath() {
return getPaths(WINDOWS_HELLO_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);
} }
@@ -103,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);
} }
/** /**
@@ -124,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
@@ -1,160 +0,0 @@
package org.cryptomator.common;
import org.cryptomator.cryptofs.event.BrokenDirFileEvent;
import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.event.VaultEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
/**
* Map containing {@link VaultEvent}s.
* The map is keyed by the ciphertext path of the affected resource _and_ the {@link FilesystemEvent}s class in order to group same events
* <p>
* Use {@link EventMap#put(VaultEvent)} to add an element and {@link EventMap#remove(VaultEvent)} to remove it.
* <p>
* The map is size restricted to {@value MAX_SIZE} elements. If a _new_ element (i.e. not already present) is added, the least recently added is removed.
*/
@Singleton
public class EventMap implements ObservableMap<EventMap.EventKey, VaultEvent> {
private static final int MAX_SIZE = 300;
public record EventKey(Path ciphertextPath, Class<? extends FilesystemEvent> c) {}
private final ObservableMap<EventMap.EventKey, VaultEvent> delegate;
@Inject
public EventMap() {
delegate = FXCollections.observableHashMap();
}
@Override
public void addListener(MapChangeListener<? super EventKey, ? super VaultEvent> mapChangeListener) {
delegate.addListener(mapChangeListener);
}
@Override
public void removeListener(MapChangeListener<? super EventKey, ? super VaultEvent> mapChangeListener) {
delegate.removeListener(mapChangeListener);
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
@Override
public VaultEvent get(Object key) {
return delegate.get(key);
}
@Override
public @Nullable VaultEvent put(EventKey key, VaultEvent value) {
return delegate.put(key, value);
}
@Override
public VaultEvent remove(Object key) {
return delegate.remove(key);
}
@Override
public void putAll(@NotNull Map<? extends EventKey, ? extends VaultEvent> m) {
delegate.putAll(m);
}
@Override
public void clear() {
delegate.clear();
}
@Override
public @NotNull Set<EventKey> keySet() {
return delegate.keySet();
}
@Override
public @NotNull Collection<VaultEvent> values() {
return delegate.values();
}
@Override
public @NotNull Set<Entry<EventKey, VaultEvent>> entrySet() {
return delegate.entrySet();
}
@Override
public void addListener(InvalidationListener invalidationListener) {
delegate.addListener(invalidationListener);
}
@Override
public void removeListener(InvalidationListener invalidationListener) {
delegate.removeListener(invalidationListener);
}
public synchronized void put(VaultEvent e) {
//compute key
var key = computeKey(e.actualEvent());
//if-else
var nullOrEntry = delegate.get(key);
if (nullOrEntry == null) {
if (size() == MAX_SIZE) {
delegate.entrySet().stream() //
.min(Comparator.comparing(entry -> entry.getValue().actualEvent().getTimestamp())) //
.ifPresent(oldestEntry -> delegate.remove(oldestEntry.getKey()));
}
delegate.put(key, e);
} else {
delegate.put(key, nullOrEntry.incrementCount(e.actualEvent()));
}
}
public synchronized VaultEvent remove(VaultEvent similar) {
//compute key
var key = computeKey(similar.actualEvent());
return this.remove(key);
}
private EventKey computeKey(FilesystemEvent e) {
var p = switch (e) {
case DecryptionFailedEvent(_, Path ciphertextPath, _) -> ciphertextPath;
case ConflictResolvedEvent(_, _, _, _, Path resolvedCiphertext) -> resolvedCiphertext;
case ConflictResolutionFailedEvent(_, _, Path conflictingCiphertext, _) -> conflictingCiphertext;
case BrokenDirFileEvent(_, Path ciphertext) -> ciphertext;
case BrokenFileNodeEvent(_, _, Path ciphertext) -> ciphertext;
};
return new EventKey(p, e.getClass());
}
}
@@ -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("\\", "\\\\");
} }
} }
@@ -1,8 +1,8 @@
package org.cryptomator.common.keychain; package org.cryptomator.common.keychain;
import com.github.benmanes.caffeine.cache.Caffeine; import com.google.common.cache.CacheBuilder;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.common.cache.CacheLoader;
import org.cryptomator.common.Passphrase; import com.google.common.cache.LoadingCache;
import org.cryptomator.integrations.keychain.KeychainAccessException; import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.cryptomator.integrations.keychain.KeychainAccessProvider; import org.cryptomator.integrations.keychain.KeychainAccessProvider;
@@ -14,24 +14,20 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@Singleton @Singleton
public class KeychainManager implements KeychainAccessProvider { public class KeychainManager implements KeychainAccessProvider {
private final ObjectExpression<KeychainAccessProvider> keychain; private final ObjectExpression<KeychainAccessProvider> keychain;
private final LoadingCache<String, BooleanProperty> passphraseStoredProperties; private final LoadingCache<String, BooleanProperty> passphraseStoredProperties;
private final ReentrantReadWriteLock lock;
@Inject @Inject
KeychainManager(ObjectExpression<KeychainAccessProvider> selectedKeychain) { KeychainManager(ObjectExpression<KeychainAccessProvider> selectedKeychain) {
this.keychain = selectedKeychain; this.keychain = selectedKeychain;
this.passphraseStoredProperties = Caffeine.newBuilder() // this.passphraseStoredProperties = CacheBuilder.newBuilder() //
.softValues() // .weakValues() //
.build(this::createStoredPassphraseProperty); .build(CacheLoader.from(this::createStoredPassphraseProperty));
keychain.addListener(ignored -> passphraseStoredProperties.invalidateAll()); keychain.addListener(ignored -> passphraseStoredProperties.invalidateAll());
this.lock = new ReentrantReadWriteLock(false);
} }
private KeychainAccessProvider getKeychainOrFail() throws KeychainAccessException { private KeychainAccessProvider getKeychainOrFail() throws KeychainAccessException {
@@ -42,50 +38,34 @@ public class KeychainManager implements KeychainAccessProvider {
return result; return result;
} }
@Override
public String displayName() {
return getClass().getName();
}
@Override @Override
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException { public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
try { getKeychainOrFail().storePassphrase(key, displayName, passphrase);
lock.writeLock().lock();
getKeychainOrFail().storePassphrase(key, displayName, passphrase);
} finally {
lock.writeLock().unlock();
}
setPassphraseStored(key, true); setPassphraseStored(key, true);
} }
@Override @Override
public char[] loadPassphrase(String key) throws KeychainAccessException { public char[] loadPassphrase(String key) throws KeychainAccessException {
char[] passphrase = null; char[] passphrase = getKeychainOrFail().loadPassphrase(key);
try {
lock.readLock().lock();
passphrase = getKeychainOrFail().loadPassphrase(key);
} finally {
lock.readLock().unlock();
}
setPassphraseStored(key, passphrase != null); setPassphraseStored(key, passphrase != null);
return passphrase; return passphrase;
} }
@Override @Override
public void deletePassphrase(String key) throws KeychainAccessException { public void deletePassphrase(String key) throws KeychainAccessException {
try { getKeychainOrFail().deletePassphrase(key);
lock.writeLock().lock();
getKeychainOrFail().deletePassphrase(key);
} finally {
lock.writeLock().unlock();
}
setPassphraseStored(key, false); setPassphraseStored(key, false);
} }
@Override @Override
public void changePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException { public void changePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
if (isPassphraseStored(key)) { if (isPassphraseStored(key)) {
try { getKeychainOrFail().changePassphrase(key, displayName, passphrase);
lock.writeLock().lock();
getKeychainOrFail().changePassphrase(key, displayName, passphrase);
} finally {
lock.writeLock().unlock();
}
setPassphraseStored(key, true); setPassphraseStored(key, true);
} }
} }
@@ -122,11 +102,13 @@ public class KeychainManager implements KeychainAccessProvider {
} }
private void setPassphraseStored(String key, boolean value) { private void setPassphraseStored(String key, boolean value) {
BooleanProperty property = passphraseStoredProperties.get(key, _ -> new SimpleBooleanProperty(value)); BooleanProperty property = passphraseStoredProperties.getIfPresent(key);
if (Platform.isFxApplicationThread()) { if (property != null) {
property.set(value); if (Platform.isFxApplicationThread()) {
} else { property.set(value);
Platform.runLater(() -> property.set(value)); } else {
Platform.runLater(() -> property.set(value));
}
} }
} }
@@ -142,7 +124,7 @@ public class KeychainManager implements KeychainAccessProvider {
* @see #isPassphraseStored(String) * @see #isPassphraseStored(String)
*/ */
public ReadOnlyBooleanProperty getPassphraseStoredProperty(String key) { public ReadOnlyBooleanProperty getPassphraseStoredProperty(String key) {
return passphraseStoredProperties.get(key); return passphraseStoredProperties.getUnchecked(key);
} }
private BooleanProperty createStoredPassphraseProperty(String key) { private BooleanProperty createStoredPassphraseProperty(String key) {
@@ -153,22 +135,4 @@ public class KeychainManager implements KeychainAccessProvider {
} }
} }
public ObjectExpression<KeychainAccessProvider> getKeychainImplementation() {
return this.keychain;
}
public static void migrate(KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider, Map<String, String> idsAndNames) throws KeychainAccessException {
if (oldProvider instanceof KeychainManager || newProvider instanceof KeychainManager) {
throw new IllegalArgumentException("KeychainManger must not be the source or target of migration");
}
for (var entry : idsAndNames.entrySet()) {
var passphrase = oldProvider.loadPassphrase(entry.getKey());
if (passphrase != null) {
var wrapper = new Passphrase(passphrase);
oldProvider.deletePassphrase(entry.getKey()); //we cannot apply "first-write-then-delete" pattern here, since we can potentially write to the same passphrase store (e.g., touchID and regular keychain)
newProvider.storePassphrase(entry.getKey(), entry.getValue(), wrapper);
wrapper.destroy();
}
}
}
} }
@@ -9,11 +9,13 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS; import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
@OperatingSystem(WINDOWS) @OperatingSystem(WINDOWS)
@OperatingSystem(MAC)
@CheckAvailability @CheckAvailability
public final class GoogleDriveWindowsLocationPresetsProvider implements LocationPresetsProvider { public final class GoogleDriveLocationPresetsProvider implements LocationPresetsProvider {
private static final List<Path> LOCATIONS = Arrays.asList( // private static final List<Path> LOCATIONS = Arrays.asList( //
LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive"), // LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive"), //
@@ -35,4 +37,5 @@ public final class GoogleDriveWindowsLocationPresetsProvider implements Location
.findFirst() // .findFirst() //
.stream(); .stream();
} }
} }
@@ -1,144 +0,0 @@
package org.cryptomator.common.locationpresets;
import org.cryptomator.integrations.common.CheckAvailability;
import org.cryptomator.integrations.common.OperatingSystem;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
@OperatingSystem(MAC)
@CheckAvailability
public final class GoogleDriveMacLocationPresetsProvider implements LocationPresetsProvider {
private static final Path ROOT_LOCATION = LocationPresetsProvider.resolveLocation("~/Library/CloudStorage/").toAbsolutePath();
private static final Predicate<String> PATTERN = Pattern.compile("^GoogleDrive-[^/]+$").asMatchPredicate();
private static final List<Path> FALLBACK_LOCATIONS = List.of( //
LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive"), //
LocationPresetsProvider.resolveLocation("~/Google Drive/My Drive"), //
LocationPresetsProvider.resolveLocation("~/GoogleDrive"), //
LocationPresetsProvider.resolveLocation("~/Google Drive") //
);
@Override
public Stream<LocationPreset> getLocations() {
List<LocationPreset> cloudStorageDirLocations = getCloudStorageDirLocations();
return cloudStorageDirLocations.isEmpty() ? getFallbackLocation().stream() : cloudStorageDirLocations.stream();
}
@CheckAvailability
public static boolean isPresent() {
return isRootLocationPresent() || FALLBACK_LOCATIONS.stream().anyMatch(Files::isDirectory);
}
/**
* Checks if a root location directory is present that matches the specified pattern.
* <p>
* This method scans the {@code ROOT_LOCATION} directory for subdirectories and tests each one against a pre-defined pattern ({@code PATTERN}).
*
* @return {@code true} if a matching root location is present, otherwise {@code false}.
*/
public static boolean isRootLocationPresent() {
try (var dirStream = Files.list(ROOT_LOCATION)) {
return dirStream.anyMatch(path -> Files.isDirectory(path) && PATTERN.test(path.getFileName().toString()));
} catch (IOException | UncheckedIOException e) {
return false;
}
}
/**
* Returns Google Drive preset String.
*
* @param accountPath The path to the Google Drive account directory (e.g. {@code ~/Library/CloudStorage/GoogleDrive-username})
* @return {@code String}. For example: "Google Drive - username"
*/
private String getDriveLocationString(Path accountPath) {
String accountName = accountPath.getFileName().toString().replace("GoogleDrive-", "");
return "Google Drive - " + accountName;
}
/**
* Retrieves a list of cloud storage directory locations based on the {@code ROOT_LOCATION}.
* <p>
* This method lists all directories in the {@code ROOT_LOCATION}, filters them based on whether their names match
* a predefined pattern ({@code PATTERN}), and then extracts presets using {@code getPresetsFromAccountPath(Path)}.
* <p>
*
* @return a list of {@code LocationPreset} objects representing valid cloud storage directory locations.
*/
private List<LocationPreset> getCloudStorageDirLocations() {
try (var dirStream = Files.list(ROOT_LOCATION)) {
return dirStream.filter(path -> Files.isDirectory(path) && PATTERN.test(path.getFileName().toString()))
.flatMap(this::getPresetsFromAccountPath)
.toList();
} catch (IOException | UncheckedIOException e) {
return List.of();
}
}
/**
* Retrieves a stream of {@code LocationPreset} objects from a given Google Drive account path.
* <p>
* This method lists all directories within the provided {@code accountPath} and filters them
* to identify folders whose names match any of the translations defined in {@code MY_DRIVE_TRANSLATIONS}.
*
* @param accountPath the root path of the Google Drive account to scan.
* @return a stream of {@code LocationPreset} objects representing matching directories.
*/
private Stream<LocationPreset> getPresetsFromAccountPath(Path accountPath) {
try (var driveStream = Files.list(accountPath)) {
return driveStream
.filter(preset -> MY_DRIVE_TRANSLATIONS
.contains(preset.getFileName().toString()))
.map(drivePath -> new LocationPreset(
getDriveLocationString(accountPath),
drivePath
)).toList().stream();
} catch (IOException e) {
return Stream.empty();
}
}
/**
* Returns a list containing a fallback location preset for Google Drive.
* <p>
* This method iterates through the predefined fallback locations, checks if any of them is a directory,
* and creates a {@code LocationPreset} object for the first matching directory found.
*
* @return a list containing a single fallback location preset if a valid directory is found, otherwise an empty list.
* @deprecated This method is intended for legacy support and may be removed in future releases.
*/
@Deprecated
private List<LocationPreset> getFallbackLocation() {
return FALLBACK_LOCATIONS.stream()
.filter(Files::isDirectory)
.map(location -> new LocationPreset("Google Drive", location))
.findFirst()
.stream()
.toList();
}
/**
* Set of translations for "My Drive" in various languages.
* <p>
* This constant is used to identify different language-specific labels for "My Drive" in Google Drive.
* <p>
* The translations were originally extracted from the Chromium projects Chrome OS translation files.
* <p>
* Source: `ui/chromeos/translations` directory in the Chromium repository.
*/
private static final Set<String> MY_DRIVE_TRANSLATIONS = Set.of("My Drive", "የእኔ Drive", "ملفاتي", "মোৰ ড্ৰাইভ", "Diskim", "Мой Дыск", "Моят диск", "আমার ড্রাইভ", "Moj disk", "La meva unitat", "Můj disk", "Mit drev", "Meine Ablage", "Το Drive μου", "Mi unidad", "Minu ketas", "Nire unitatea", "Aking Drive", "Oma Drive", "Mon disque", "Mon Drive", "A miña unidade", "મારી ડ્રાઇવ", "मेरी ड्राइव", "Saját meghajtó", "Իմ դրայվը", "Drive Saya", "Drifið mitt", "I miei file", "האחסון שלי", "マイドライブ", "ჩემი Drive", "Менің Drive дискім", "ដ្រាយរបស់ខ្ញុំ", "ನನ್ನ ಡ್ರೈವ್", "내 드라이브", "Менин Drive'ым", "Mano Diskas", "Mans disks", "Мојот Drive", "എന്റെ ഡ്രൈവ്", "Миний Драйв", "माझा ड्राइव्ह", "मेरो ड्राइभ", "Mijn Drive", "Min disk", "ମୋ ଡ୍ରାଇଭ୍", "Mój dysk", "Meu Drive", "O meu disco", "Contul meu Drive", "Мой диск", "මගේ Drive", "Môj disk", "Disku im", "Мој диск", "Min enhet", "Hifadhi Yangu", "எனது இயக்ககம்", "నా డ్రైవ్‌", "ไดรฟ์ของฉัน", "Drive'ım", "Мій диск", "میری ڈرائیو", "Drive của tôi", "我的云端硬盘", "我的雲端硬碟", "IDrayivu yami");
}
@@ -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 = 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,33 +25,30 @@ 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 {
private static final Logger LOG = LoggerFactory.getLogger(Settings.class); private static final Logger LOG = LoggerFactory.getLogger(Settings.class);
static final boolean DEFAULT_ASKED_FOR_UPDATE_CHECK = false;
static final boolean DEFAULT_CHECK_FOR_UPDATES = false; static final boolean DEFAULT_CHECK_FOR_UPDATES = false;
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.GnomeKeyringKeychainAccess";
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();
public static final Instant DEFAULT_TIMESTAMP = Instant.parse("2000-01-01T00:00:00Z"); static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
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 checkForUpdates;
public final BooleanProperty startHidden; public final BooleanProperty startHidden;
public final BooleanProperty autoCloseVaults; public final BooleanProperty autoCloseVaults;
public final BooleanProperty useKeychain; public final BooleanProperty useKeychain;
@@ -60,21 +57,18 @@ 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 showTrayIcon; public final BooleanProperty showTrayIcon;
public final BooleanProperty compactMode;
public final IntegerProperty windowXPosition; public final IntegerProperty windowXPosition;
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 BooleanProperty checkForUpdates; public final StringProperty lastUpdateCheck;
public final ObjectProperty<Instant> lastUpdateCheckReminder;
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
private Consumer<Settings> saveCmd; private Consumer<Settings> saveCmd;
@@ -91,10 +85,11 @@ public class Settings {
*/ */
Settings(SettingsJson json) { Settings(SettingsJson json) {
this.directories = FXCollections.observableArrayList(VaultSettings::observables); this.directories = FXCollections.observableArrayList(VaultSettings::observables);
this.askedForUpdateCheck = new SimpleBooleanProperty(this, "askedForUpdateCheck", json.askedForUpdateCheck);
this.checkForUpdates = new SimpleBooleanProperty(this, "checkForUpdates", json.checkForUpdatesEnabled);
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);
@@ -102,28 +97,27 @@ public class Settings {
this.keychainProvider = new SimpleStringProperty(this, "keychainProvider", json.keychainProvider); this.keychainProvider = new SimpleStringProperty(this, "keychainProvider", json.keychainProvider);
this.userInterfaceOrientation = new SimpleObjectProperty<>(this, "userInterfaceOrientation", parseEnum(json.uiOrientation, NodeOrientation.class, NodeOrientation.LEFT_TO_RIGHT)); this.userInterfaceOrientation = new SimpleObjectProperty<>(this, "userInterfaceOrientation", parseEnum(json.uiOrientation, NodeOrientation.class, NodeOrientation.LEFT_TO_RIGHT));
this.licenseKey = new SimpleStringProperty(this, "licenseKey", json.licenseKey); this.licenseKey = new SimpleStringProperty(this, "licenseKey", json.licenseKey);
this.showMinimizeButton = new SimpleBooleanProperty(this, "showMinimizeButton", json.showMinimizeButton);
this.showTrayIcon = new SimpleBooleanProperty(this, "showTrayIcon", json.showTrayIcon); this.showTrayIcon = new SimpleBooleanProperty(this, "showTrayIcon", json.showTrayIcon);
this.compactMode = new SimpleBooleanProperty(this, "compactMode", json.compactMode);
this.windowXPosition = new SimpleIntegerProperty(this, "windowXPosition", json.windowXPosition); this.windowXPosition = new SimpleIntegerProperty(this, "windowXPosition", json.windowXPosition);
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.checkForUpdates = new SimpleBooleanProperty(this, "checkForUpdates", json.checkForUpdatesEnabled);
this.lastUpdateCheckReminder = new SimpleObjectProperty<>(this, "lastUpdateCheckReminder", json.lastReminderForUpdateCheck);
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());
migrateLegacySettings(json); migrateLegacySettings(json);
directories.addListener(this::somethingChanged); directories.addListener(this::somethingChanged);
askedForUpdateCheck.addListener(this::somethingChanged);
checkForUpdates.addListener(this::somethingChanged);
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);
@@ -131,27 +125,20 @@ public class Settings {
keychainProvider.addListener(this::somethingChanged); keychainProvider.addListener(this::somethingChanged);
userInterfaceOrientation.addListener(this::somethingChanged); userInterfaceOrientation.addListener(this::somethingChanged);
licenseKey.addListener(this::somethingChanged); licenseKey.addListener(this::somethingChanged);
showMinimizeButton.addListener(this::somethingChanged);
showTrayIcon.addListener(this::somethingChanged); showTrayIcon.addListener(this::somethingChanged);
compactMode.addListener(this::somethingChanged);
windowXPosition.addListener(this::somethingChanged); windowXPosition.addListener(this::somethingChanged);
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);
checkForUpdates.addListener(this::somethingChanged);
lastUpdateCheckReminder.addListener(this::somethingChanged);
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void migrateLegacySettings(SettingsJson json) { private void migrateLegacySettings(SettingsJson json) {
// migrate renamed keychainAccess
if(this.keychainProvider.getValueSafe().equals("org.cryptomator.linux.SecretServiceKeychainAccess")) {
this.keychainProvider.setValue("org.cryptomator.linux.GnomeKeyringKeychainAccess");
}
// implicit migration of 1.6.x legacy setting "preferredVolumeImpl": // implicit migration of 1.6.x legacy setting "preferredVolumeImpl":
if (this.mountService.get() == null && json.preferredVolumeImpl != null) { if (this.mountService.get() == null && json.preferredVolumeImpl != null) {
this.mountService.set(switch (json.preferredVolumeImpl) { this.mountService.set(switch (json.preferredVolumeImpl) {
@@ -181,10 +168,11 @@ public class Settings {
SettingsJson serialized() { SettingsJson serialized() {
var json = new SettingsJson(); var json = new SettingsJson();
json.directories = directories.stream().map(VaultSettings::serialized).toList(); json.directories = directories.stream().map(VaultSettings::serialized).toList();
json.askedForUpdateCheck = askedForUpdateCheck.get();
json.checkForUpdatesEnabled = checkForUpdates.get();
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();
@@ -192,18 +180,16 @@ public class Settings {
json.keychainProvider = keychainProvider.get(); json.keychainProvider = keychainProvider.get();
json.uiOrientation = userInterfaceOrientation.get().name(); json.uiOrientation = userInterfaceOrientation.get().name();
json.licenseKey = licenseKey.get(); json.licenseKey = licenseKey.get();
json.showMinimizeButton = showMinimizeButton.get();
json.showTrayIcon = showTrayIcon.get(); json.showTrayIcon = showTrayIcon.get();
json.compactMode = compactMode.get();
json.windowXPosition = windowXPosition.get(); json.windowXPosition = windowXPosition.get();
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.checkForUpdatesEnabled = checkForUpdates.get();
json.lastReminderForUpdateCheck = lastUpdateCheckReminder.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)
@@ -18,15 +16,24 @@ class SettingsJson {
@JsonProperty("writtenByVersion") @JsonProperty("writtenByVersion")
String writtenByVersion; String writtenByVersion;
@JsonProperty("askedForUpdateCheck")
boolean askedForUpdateCheck = Settings.DEFAULT_ASKED_FOR_UPDATE_CHECK;
@JsonProperty("autoCloseVaults") @JsonProperty("autoCloseVaults")
boolean autoCloseVaults = Settings.DEFAULT_AUTO_CLOSE_VAULTS; boolean autoCloseVaults = Settings.DEFAULT_AUTO_CLOSE_VAULTS;
@JsonProperty("checkForUpdatesEnabled")
boolean checkForUpdatesEnabled = Settings.DEFAULT_CHECK_FOR_UPDATES;
@JsonProperty("debugMode") @JsonProperty("debugMode")
boolean debugMode = Settings.DEFAULT_DEBUG_MODE; boolean debugMode = Settings.DEFAULT_DEBUG_MODE;
@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;
@@ -45,12 +52,12 @@ class SettingsJson {
@JsonProperty("port") @JsonProperty("port")
int port = Settings.DEFAULT_PORT; int port = Settings.DEFAULT_PORT;
@JsonProperty("showMinimizeButton")
boolean showMinimizeButton = Settings.DEFAULT_SHOW_MINIMIZE_BUTTON;
@JsonProperty("showTrayIcon") @JsonProperty("showTrayIcon")
boolean showTrayIcon; boolean showTrayIcon;
@JsonProperty("compactMode")
boolean compactMode;
@JsonProperty("startHidden") @JsonProperty("startHidden")
boolean startHidden = Settings.DEFAULT_START_HIDDEN; boolean startHidden = Settings.DEFAULT_START_HIDDEN;
@@ -76,20 +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("checkForUpdatesEnabled") @JsonProperty("lastUpdateCheck")
boolean checkForUpdatesEnabled = Settings.DEFAULT_CHECK_FOR_UPDATES; String lastUpdateCheck = Settings.DEFAULT_LAST_UPDATE_CHECK;
@JsonProperty("lastReminderForUpdateCheck")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
Instant lastReminderForUpdateCheck = Settings.DEFAULT_TIMESTAMP;
@JsonProperty("lastSuccessfulUpdateCheck")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
Instant lastSuccessfulUpdateCheck = Settings.DEFAULT_TIMESTAMP;
@JsonProperty("useQuickAccess")
boolean useQuickAccess = Settings.DEFAULT_USE_QUICKACCESS;
@JsonProperty("quickAccessService")
String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE;
} }

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