mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-15 09:11:29 +00:00
Compare commits
1 Commits
feature/hy
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bad933c85 |
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -3,7 +3,7 @@
|
||||
## Did you find a bug?
|
||||
|
||||
- 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).
|
||||
- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator/issues/new/choose).
|
||||
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -26,7 +26,6 @@ body:
|
||||
Examples:
|
||||
- Operating System: Windows 10
|
||||
- Cryptomator: 1.5.16
|
||||
- OneDrive: 23.226
|
||||
- LibreOffice: 7.1.4
|
||||
value: |
|
||||
- Operating System:
|
||||
@@ -44,7 +43,6 @@ body:
|
||||
- WinFsp (Local Drive)
|
||||
- FUSE-T
|
||||
- macFUSE
|
||||
- FUSE
|
||||
- WebDAV (Windows Explorer)
|
||||
- WebDAV (AppleScript)
|
||||
- WebDAV (gio)
|
||||
@@ -97,4 +95,4 @@ body:
|
||||
id: further-info
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue?
|
||||
description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue?
|
||||
58
.github/dependabot.yml
vendored
58
.github/dependabot.yml
vendored
@@ -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"
|
||||
100
.github/workflows/appimage.yml
vendored
100
.github/workflows/appimage.yml
vendored
@@ -10,8 +10,7 @@ on:
|
||||
required: false
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '23.0.1+11'
|
||||
JAVA_VERSION: 20
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
@@ -21,71 +20,51 @@ jobs:
|
||||
|
||||
build:
|
||||
name: Build AppImage
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-version]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
appimage-suffix: x86_64
|
||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-x64_bin-jmods.zip'
|
||||
openjfx-sha: '2164bca470bf70a5e2764645e2078ba7f787b274e5be3d7df30d87c5bb62bba6'
|
||||
- os: ubuntu-24.04-arm
|
||||
appimage-suffix: aarch64
|
||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-aarch64_bin-jmods.zip'
|
||||
openjfx-sha: '09c92fa9fa0b82adefd88640a14ebb2a49e5f3f733a57d1542f5590d060ffe1b'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
check-latest: true
|
||||
java-package: 'jdk+fx'
|
||||
cache: 'maven'
|
||||
|
||||
- name: Download OpenJFX jmods
|
||||
id: download-jmods
|
||||
- name: Ensure major jfx version in pom equals in jdk
|
||||
shell: pwsh
|
||||
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 -j 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_AMD64 ]; then
|
||||
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})"
|
||||
$jfxPomVersion = (&mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) -split "\."
|
||||
$jfxJdkVersion = ((Get-Content -path "${env:JAVA_HOME}/lib/javafx.properties" | Where-Object {$_ -like 'javafx.version=*' }) -replace '.*=','') -split "\."
|
||||
if ($jfxPomVersion[0] -ne $jfxJdkVersion[0]) {
|
||||
Write-Error "Major part of JavaFX version in pom($($jfxPomVersion[0])) does not match the version in JDK($($jfxJdkVersion[0])) "
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
- name: Set version
|
||||
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
|
||||
- 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
|
||||
run: |
|
||||
cp LICENSE.txt target
|
||||
cp target/cryptomator-*.jar target/mods
|
||||
- name: Run jlink
|
||||
#Remark: no compression is applied for improved build compression later (here appimage)
|
||||
run: >
|
||||
${JAVA_HOME}/bin/jlink
|
||||
--verbose
|
||||
--output runtime
|
||||
--module-path "${JAVA_HOME}/jmods:openjfx-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
|
||||
--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.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr
|
||||
--strip-native-commands
|
||||
--no-header-files
|
||||
--no-man-pages
|
||||
--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
|
||||
run: >
|
||||
${JAVA_HOME}/bin/jpackage
|
||||
@@ -98,10 +77,10 @@ jobs:
|
||||
--dest appdir
|
||||
--name Cryptomator
|
||||
--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 }}"
|
||||
--java-options "--enable-preview"
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator"
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64"
|
||||
--java-options "-Xss5m"
|
||||
--java-options "-Xmx256m"
|
||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||
@@ -113,10 +92,9 @@ jobs:
|
||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\""
|
||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\""
|
||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\""
|
||||
--java-options "-Dcryptomator.showTrayIcon=true"
|
||||
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
|
||||
--java-options "-Dcryptomator.showTrayIcon=false"
|
||||
--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
|
||||
- name: Patch Cryptomator.AppDir
|
||||
run: |
|
||||
@@ -125,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.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.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.desktop Cryptomator.AppDir/usr/share/applications/org.cryptomator.Cryptomator.desktop
|
||||
cp dist/linux/common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.xml
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/Cryptomator.svg
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
|
||||
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/org.cryptomator.Cryptomator.desktop
|
||||
ln -s org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml
|
||||
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
|
||||
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
||||
- name: Download AppImageKit
|
||||
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
|
||||
./appimagetool.AppImage --appimage-extract
|
||||
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
|
||||
@@ -151,29 +125,29 @@ jobs:
|
||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||
- name: Build AppImage
|
||||
run: >
|
||||
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.appimage-suffix }}.AppImage
|
||||
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.appimage-suffix }}.AppImage.zsync'
|
||||
--sign --sign-key=615D449FE6E6A235
|
||||
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.get-version.outputs.semVerStr }}-x86_64.AppImage
|
||||
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
|
||||
--sign --sign-key=615D449FE6E6A235 --sign-args="--batch --pinentry-mode loopback"
|
||||
- name: Create detached GPG signatures
|
||||
run: |
|
||||
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage
|
||||
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: appimage-${{ matrix.appimage-suffix }}
|
||||
name: appimage
|
||||
path: |
|
||||
cryptomator-*.AppImage
|
||||
cryptomator-*.AppImage.zsync
|
||||
cryptomator-*.asc
|
||||
if-no-files-found: error
|
||||
- name: Publish AppImage on GitHub Releases
|
||||
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
fail_on_unmatched_files: true
|
||||
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
files: |
|
||||
cryptomator-*.AppImage
|
||||
cryptomator-*.zsync
|
||||
cryptomator-*.asc
|
||||
cryptomator-*.asc
|
||||
40
.github/workflows/av-whitelist.yml
vendored
40
.github/workflows/av-whitelist.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: AntiVirus Whitelisting
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
url:
|
||||
description: "Url to the file to upload"
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
url:
|
||||
description: "Url to the file to upload"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
allowlist:
|
||||
name: Anti Virus Allowlisting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download file
|
||||
run: |
|
||||
curl --remote-name ${{ inputs.url }} -L
|
||||
- name: Upload to Kaspersky
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
|
||||
with:
|
||||
protocol: ftps
|
||||
server: allowlist.kaspersky-labs.com
|
||||
port: 990
|
||||
username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
|
||||
password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
|
||||
- name: Upload to Avast
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
|
||||
with:
|
||||
protocol: ftp
|
||||
server: whitelisting.avast.com
|
||||
port: 21
|
||||
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
|
||||
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
|
||||
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -6,8 +6,7 @@ on:
|
||||
types: [labeled]
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 23
|
||||
JAVA_VERSION: 20
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -18,14 +17,14 @@ jobs:
|
||||
name: Compile and Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
cache: 'maven'
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
@@ -33,10 +32,10 @@ jobs:
|
||||
- name: Build and Test
|
||||
run: >
|
||||
xvfb-run
|
||||
mvn -B verify -Djavafx.platform=linux
|
||||
mvn -B verify
|
||||
jacoco:report
|
||||
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
|
||||
-Pcoverage
|
||||
-Pcoverage,dependency-check
|
||||
-Dsonar.projectKey=cryptomator_cryptomator
|
||||
-Dsonar.organization=cryptomator
|
||||
-Dsonar.host.url=https://sonarcloud.io
|
||||
@@ -45,7 +44,7 @@ jobs:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
- name: Draft a release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: releases
|
||||
@@ -53,25 +52,10 @@ jobs:
|
||||
generate_release_notes: true
|
||||
body: |-
|
||||
: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. ⏳
|
||||
|
||||
<!-- 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).
|
||||
|
||||
---
|
||||
<!-- Don't forget to include the 💾 SHA-256 checksums of release artifacts: -->
|
||||
83
.github/workflows/check-jdk-updates.yml
vendored
83
.github/workflows/check-jdk-updates.yml
vendored
@@ -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: '23.0.1+11'
|
||||
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
|
||||
34
.github/workflows/debian.yml
vendored
34
.github/workflows/debian.yml
vendored
@@ -16,21 +16,16 @@ on:
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '23.0.1+11'
|
||||
COFFEELIBS_JDK: 23
|
||||
COFFEELIBS_JDK_VERSION: '23.0.1+11-0ppa1'
|
||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-x64_bin-jmods.zip'
|
||||
OPENJFX_JMODS_AMD64_HASH: '2164bca470bf70a5e2764645e2078ba7f787b274e5be3d7df30d87c5bb62bba6'
|
||||
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-aarch64_bin-jmods.zip'
|
||||
OPENJFX_JMODS_AARCH64_HASH: '09c92fa9fa0b82adefd88640a14ebb2a49e5f3f733a57d1542f5590d060ffe1b'
|
||||
JAVA_VERSION: 20
|
||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-x64_bin-jmods.zip'
|
||||
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-aarch64_bin-jmods.zip'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Debian Package
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- id: versions
|
||||
name: Get version information
|
||||
run: |
|
||||
@@ -44,25 +39,22 @@ jobs:
|
||||
run: |
|
||||
sudo add-apt-repository ppa:coffeelibs/openjdk
|
||||
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
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
check-latest: true
|
||||
cache: '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
|
||||
id: download-jmods
|
||||
run: |
|
||||
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
|
||||
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
|
||||
echo "${{ env.OPENJFX_JMODS_AARCH64_HASH }} openjfx-aarch64.zip" | shasum -a256 --check
|
||||
mkdir -p 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
|
||||
@@ -99,8 +91,7 @@ jobs:
|
||||
run: |
|
||||
cp -r dist/linux/debian/ pkgdir
|
||||
export RFC2822_TIMESTAMP=`date --rfc-2822`
|
||||
export DISABLE_UPDATE_CHECK=${{ inputs.dput }}
|
||||
envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM} ${DISABLE_UPDATE_CHECK}' < dist/linux/debian/rules > pkgdir/debian/rules
|
||||
envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM}' < dist/linux/debian/rules > pkgdir/debian/rules
|
||||
envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog
|
||||
find . -name "*.jar" >> pkgdir/debian/source/include-binaries
|
||||
mv pkgdir cryptomator_${{ inputs.ppaver }}
|
||||
@@ -128,7 +119,7 @@ jobs:
|
||||
run: |
|
||||
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux-deb-package
|
||||
path: |
|
||||
@@ -142,11 +133,12 @@ jobs:
|
||||
- name: Publish on PPA
|
||||
if: inputs.dput
|
||||
run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes
|
||||
|
||||
# If ref is a tag, also upload to GitHub Releases:
|
||||
- name: Publish Debian package on GitHub Releases
|
||||
if: startsWith(github.ref, 'refs/tags/') && inputs.dput
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
run: |
|
||||
artifacts=$(ls | grep cryptomator*.deb)
|
||||
gh release upload ${{ github.ref_name }} $artifacts
|
||||
gh release upload ${{ github.ref_name }} $artifacts
|
||||
18
.github/workflows/dependency-check.yml
vendored
18
.github/workflows/dependency-check.yml
vendored
@@ -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: 23
|
||||
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 }}
|
||||
2
.github/workflows/dl-stats.yml
vendored
2
.github/workflows/dl-stats.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
steps:
|
||||
- name: Get download count of latest releases
|
||||
id: get-stats
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const query = `query($owner:String!, $name:String!) {
|
||||
|
||||
14
.github/workflows/error-db.yml
vendored
14
.github/workflows/error-db.yml
vendored
@@ -2,7 +2,7 @@ name: Update Error Database
|
||||
|
||||
on:
|
||||
discussion:
|
||||
types: [created, edited, deleted, category_changed, answered, unanswered]
|
||||
types: [created, edited, category_changed, answered, unanswered]
|
||||
discussion_comment:
|
||||
types: [created, edited, deleted]
|
||||
|
||||
@@ -12,9 +12,8 @@ jobs:
|
||||
if: github.event.discussion.category.name == 'Errors'
|
||||
steps:
|
||||
- name: Query Discussion Data
|
||||
if: github.event_name == 'discussion_comment' || github.event_name == 'discussion' && github.event.action != 'deleted'
|
||||
id: query-data
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const query = `query ($owner: String!, $name: String!, $discussionNumber: Int!) {
|
||||
@@ -48,13 +47,8 @@ jobs:
|
||||
- name: Merge Error Code Data
|
||||
run: |
|
||||
jq -c '.' ${{ steps.get-gist.outputs.file }} > original.json
|
||||
if [ ! -z "$DISCUSSION" ]
|
||||
then
|
||||
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
|
||||
echo $DISCUSSION | jq -c '.repository.discussion | .comments = .comments.totalCount | {(.id|tostring) : .}' > new.json
|
||||
jq -s '.[0] * .[1]' original.json new.json > merged.json
|
||||
env:
|
||||
DISCUSSION: ${{ steps.query-data.outputs.result }}
|
||||
- name: Patch Gist
|
||||
|
||||
88
.github/workflows/flathub.yml
vendored
88
.github/workflows/flathub.yml
vendored
@@ -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
|
||||
15
.github/workflows/get-version.yml
vendored
15
.github/workflows/get-version.yml
vendored
@@ -22,8 +22,9 @@ on:
|
||||
value: ${{ jobs.determine-version.outputs.type }}
|
||||
|
||||
env:
|
||||
JAVA_VERSION: 20
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 23
|
||||
JAVA_CACHE: 'maven'
|
||||
|
||||
jobs:
|
||||
determine-version:
|
||||
@@ -35,22 +36,22 @@ jobs:
|
||||
revNum: ${{ steps.versions.outputs.revNum }}
|
||||
type: ${{ steps.versions.outputs.type}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
cache: 'maven'
|
||||
cache: ${{ env.JAVA_CACHE }}
|
||||
- id: versions
|
||||
name: Get version information
|
||||
run: |
|
||||
if [[ $GITHUB_REF =~ refs/tags/[0-9]+\.[0-9]+\.[0-9]+.* ]]; then
|
||||
SEM_VER_STR=${GITHUB_REF##*/}
|
||||
elif [[ "${{ inputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+.* ]]; then
|
||||
SEM_VER_STR="${{ inputs.version }}"
|
||||
SEM_VER_STR="${{ github.event.inputs.version }}"
|
||||
else
|
||||
SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
|
||||
fi
|
||||
@@ -71,6 +72,6 @@ jobs:
|
||||
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
|
||||
echo "type=${TYPE}" >> $GITHUB_OUTPUT
|
||||
- name: Validate Version
|
||||
uses: skymatic/semver-validation-action@v3
|
||||
uses: skymatic/semver-validation-action@v2
|
||||
with:
|
||||
version: ${{ steps.versions.outputs.semVerStr }}
|
||||
version: ${{ steps.versions.outputs.semVerStr }}
|
||||
264
.github/workflows/mac-dmg-x64.yml
vendored
264
.github/workflows/mac-dmg-x64.yml
vendored
@@ -1,264 +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.
|
||||
# This workflow can only be triggered by a release.
|
||||
#
|
||||
#######################################
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '23.0.1+11'
|
||||
|
||||
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/23.0.1/openjfx-23.0.1_osx-x64_bin-jmods.zip'
|
||||
openjfx-sha: '8857965975c464a0e5d57709292ce357d0ebb39f6168c41d5ca38301e42c3c8e'
|
||||
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
|
||||
#Remark: no compression is applied for improved build compression later (here dmg)
|
||||
run: >
|
||||
${JAVA_HOME}/bin/jlink
|
||||
--verbose
|
||||
--output runtime
|
||||
--module-path "${JAVA_HOME}/jmods:openjfx-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
|
||||
--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=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
|
||||
89
.github/workflows/mac-dmg.yml
vendored
89
.github/workflows/mac-dmg.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Build macOS .dmg for arm64
|
||||
name: Build macOS .dmg
|
||||
|
||||
on:
|
||||
release:
|
||||
@@ -8,15 +8,9 @@ on:
|
||||
version:
|
||||
description: 'Version'
|
||||
required: false
|
||||
notarize:
|
||||
description: 'Notarize'
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '23.0.1+11'
|
||||
JAVA_VERSION: 20
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
@@ -32,63 +26,56 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
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
|
||||
output-suffix: arm64
|
||||
xcode-path: '/Applications/Xcode_13.2.1.app'
|
||||
fuse-lib: FUSE-T
|
||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_osx-aarch64_bin-jmods.zip'
|
||||
openjfx-sha: 'a800724a1f3e6757ecfa0bd5bf7ed64d2e6a7a3f5b3522650a70b8cfc7782fb6'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
java-package: 'jdk+fx'
|
||||
architecture: ${{ matrix.architecture }}
|
||||
check-latest: true
|
||||
cache: 'maven'
|
||||
- name: Download OpenJFX jmods
|
||||
id: download-jmods
|
||||
- name: Ensure major jfx version in pom equals in jdk
|
||||
if: ${{ !contains(matrix.os, 'self-hosted') }}
|
||||
shell: pwsh
|
||||
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})"
|
||||
$jfxPomVersion = (&mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) -split "\."
|
||||
$jfxJdkVersion = ((Get-Content -path "${env:JAVA_HOME}/lib/javafx.properties" | Where-Object {$_ -like 'javafx.version=*' }) -replace '.*=','') -split "\."
|
||||
if ($jfxPomVersion[0] -ne $jfxJdkVersion[0]) {
|
||||
Write-Error "Major part of JavaFX version in pom($($jfxPomVersion[0])) does not match the version in JDK($($jfxJdkVersion[0])) "
|
||||
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
|
||||
run: mvn -B clean package -Pdependency-check,mac -DskipTests
|
||||
- name: Patch target dir
|
||||
run: |
|
||||
cp LICENSE.txt target
|
||||
cp target/cryptomator-*.jar target/mods
|
||||
- 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 "${JAVA_HOME}/jmods:openjfx-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
|
||||
--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.crypto.ec,jdk.accessibility,jdk.management.jfr
|
||||
--strip-native-commands
|
||||
--no-header-files
|
||||
--no-man-pages
|
||||
--strip-debug
|
||||
--compress zip-0
|
||||
--compress=1
|
||||
- name: Run jpackage
|
||||
run: >
|
||||
${JAVA_HOME}/bin/jpackage
|
||||
@@ -101,7 +88,7 @@ jobs:
|
||||
--dest appdir
|
||||
--name Cryptomator
|
||||
--vendor "Skymatic GmbH"
|
||||
--copyright "(C) 2016 - 2025 Skymatic GmbH"
|
||||
--copyright "(C) 2016 - 2023 Skymatic GmbH"
|
||||
--app-version "${{ needs.get-version.outputs.semVerNum }}"
|
||||
--java-options "--enable-preview"
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.mac"
|
||||
@@ -129,14 +116,12 @@ jobs:
|
||||
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
|
||||
mvn -B license:add-third-party
|
||||
-Dlicense.thirdPartyFilename=license.rtf
|
||||
-Dlicense.outputDirectory=dist/mac/dmg/resources
|
||||
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
|
||||
@@ -169,7 +154,7 @@ jobs:
|
||||
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} {} \;
|
||||
find Cryptomator.app/Contents/runtime/Contents/Home/lib/ -name 'jspawnhelper' -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
|
||||
@@ -188,12 +173,9 @@ jobs:
|
||||
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
|
||||
@@ -220,19 +202,20 @@ jobs:
|
||||
--app-drop-link 512 245
|
||||
--eula "dist/mac/dmg/resources/license.rtf"
|
||||
--icon ".background" 128 758
|
||||
--icon ".fseventsd" 320 758
|
||||
--icon ".VolumeIcon.icns" 512 758
|
||||
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
|
||||
env:
|
||||
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
|
||||
- name: Notarize .dmg
|
||||
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
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'
|
||||
xcode-path: ${{ matrix.xcode-path }}
|
||||
- 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
|
||||
@@ -247,16 +230,14 @@ jobs:
|
||||
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
|
||||
continue-on-error: true
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dmg-${{ matrix.output-suffix }}
|
||||
path: |
|
||||
Cryptomator-*.dmg
|
||||
Cryptomator-*.asc
|
||||
path: Cryptomator-*.dmg
|
||||
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
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
fail_on_unmatched_files: true
|
||||
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
|
||||
2
.github/workflows/no-response.yml
vendored
2
.github/workflows/no-response.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
days-before-stale: 14
|
||||
days-before-close: 0
|
||||
|
||||
2
.github/workflows/post-publish.yml
vendored
2
.github/workflows/post-publish.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||
- name: Publish asc on GitHub Releases
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
fail_on_unmatched_files: true
|
||||
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
|
||||
11
.github/workflows/pullrequest.yml
vendored
11
.github/workflows/pullrequest.yml
vendored
@@ -4,8 +4,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 23
|
||||
JAVA_VERSION: 20
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -17,11 +16,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
cache: 'maven'
|
||||
- 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
|
||||
41
.github/workflows/release-check.yml
vendored
41
.github/workflows/release-check.yml
vendored
@@ -6,26 +6,19 @@ on:
|
||||
- 'release/**'
|
||||
- 'hotfix/**'
|
||||
|
||||
env:
|
||||
JAVA_VERSION: 20
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 23
|
||||
|
||||
jobs:
|
||||
check-preconditions:
|
||||
release-check-precondition:
|
||||
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
cache: 'maven'
|
||||
- uses: actions/checkout@v2
|
||||
- id: validate-pom-version
|
||||
name: Validate POM version
|
||||
run: |
|
||||
@@ -44,27 +37,7 @@ jobs:
|
||||
fi
|
||||
- name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file
|
||||
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"
|
||||
exit 1
|
||||
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: Validate urls used in app
|
||||
uses: urlstechie/urlchecker-action@0.0.34
|
||||
with:
|
||||
file_types: .md,.json
|
||||
include_files: README.md,src/main/resources/hyperlinks.json
|
||||
- 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 }}
|
||||
fi
|
||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
days-before-stale: 365
|
||||
days-before-close: 90
|
||||
|
||||
221
.github/workflows/win-exe.yml
vendored
221
.github/workflows/win-exe.yml
vendored
@@ -10,17 +10,15 @@ on:
|
||||
required: false
|
||||
isDebug:
|
||||
description: 'Build debug version with console output'
|
||||
type: boolean
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'zulu'
|
||||
JAVA_VERSION: '23.0.1+11'
|
||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_windows-x64_bin-jmods.zip'
|
||||
OPENJFX_JMODS_AMD64_HASH: 'ee176dcee3bd78bde7910735bd67f67c792882f5b89626796ae06f7a1c0119d3'
|
||||
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi'
|
||||
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
|
||||
JAVA_VERSION: 20
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_CACHE: 'maven'
|
||||
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:
|
||||
run:
|
||||
@@ -40,23 +38,20 @@ jobs:
|
||||
LOOPBACK_ALIAS: 'cryptomator-vault'
|
||||
WIN_CONSOLE_FLAG: ''
|
||||
steps:
|
||||
- name: Upgrade WIX to latest version
|
||||
run: choco install wixtoolset --version 3.14.1
|
||||
shell: pwsh
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
check-latest: true
|
||||
cache: 'maven'
|
||||
java-package: 'jdk'
|
||||
cache: ${{ env.JAVA_CACHE }}
|
||||
- name: Download and extract JavaFX jmods from Gluon
|
||||
#In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip
|
||||
run: |
|
||||
curl --output jfxjmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}"
|
||||
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) {
|
||||
throw "Wrong checksum of JMOD archive downloaded from ${{ env.OPENJFX_JMODS_AMD64 }}.";
|
||||
curl --output jfxjmods.zip -L "${{ env.JFX_JMODS_URL }}"
|
||||
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.equals("${{ env.JFX_JMODS_HASH }}")) {
|
||||
throw "Wrong checksum of JMOD archive downloaded from ${{ env.JFX_JMODS_URL }}.";
|
||||
}
|
||||
Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
|
||||
Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
|
||||
@@ -77,24 +72,23 @@ jobs:
|
||||
- name: Set version
|
||||
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
|
||||
- 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
|
||||
run: |
|
||||
cp LICENSE.txt target
|
||||
cp target/cryptomator-*.jar target/mods
|
||||
- name: Run jlink
|
||||
#Remark: no compression is applied for improved build compression later (here msi)
|
||||
run: >
|
||||
${JAVA_HOME}/bin/jlink
|
||||
--verbose
|
||||
--output runtime
|
||||
--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
|
||||
--no-header-files
|
||||
--no-man-pages
|
||||
--strip-debug
|
||||
--compress zip-0
|
||||
--compress=1
|
||||
- name: Change win-console flag if debug is active
|
||||
if: ${{ inputs.isDebug }}
|
||||
run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV
|
||||
@@ -110,10 +104,10 @@ jobs:
|
||||
--dest appdir
|
||||
--name Cryptomator
|
||||
--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 }}"
|
||||
--java-options "--enable-preview"
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.win"
|
||||
--java-options "-Xss5m"
|
||||
--java-options "-Xmx256m"
|
||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||
@@ -150,56 +144,26 @@ jobs:
|
||||
- name: Fix permissions
|
||||
run: attrib -r appdir/Cryptomator/Cryptomator.exe
|
||||
shell: pwsh
|
||||
- name: Extract jars with DLLs for Codesigning
|
||||
- name: Extract integrations DLL for code signing
|
||||
shell: pwsh
|
||||
run: |
|
||||
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"
|
||||
run: gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --extract integrations.dll }
|
||||
- name: Codesign
|
||||
uses: skymatic/code-sign-action@v3
|
||||
uses: skymatic/code-sign-action@v2
|
||||
with:
|
||||
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
|
||||
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
|
||||
certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
|
||||
description: Cryptomator
|
||||
timestampUrl: 'http://timestamp.digicert.com'
|
||||
folder: appdir
|
||||
folder: appdir/Cryptomator
|
||||
recursive: true
|
||||
- name: Replace DLLs inside jars with signed ones
|
||||
- name: Repack signed DLL into jar
|
||||
shell: pwsh
|
||||
run: |
|
||||
$jarExtractDir = Resolve-Path ".\appdir\jar-extract"
|
||||
$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 $_)
|
||||
}
|
||||
}
|
||||
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}
|
||||
- name: Generate license for MSI
|
||||
run: >
|
||||
mvn -B license:add-third-party "-Djavafx.platform=win"
|
||||
mvn -B license:add-third-party
|
||||
"-Dlicense.thirdPartyFilename=license.rtf"
|
||||
"-Dlicense.outputDirectory=dist/win/resources"
|
||||
"-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
|
||||
@@ -218,21 +182,20 @@ jobs:
|
||||
--dest installer
|
||||
--name Cryptomator
|
||||
--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}}"
|
||||
--win-menu
|
||||
--win-dir-chooser
|
||||
--win-shortcut-prompt
|
||||
--win-update-url "https:\\cryptomator.org\downloads"
|
||||
--win-update-url "https:\\cryptomator.org"
|
||||
--win-menu-group Cryptomator
|
||||
--resource-dir dist/win/resources
|
||||
--license-file dist/win/resources/license.rtf
|
||||
--file-associations dist/win/resources/FAvaultFile.properties
|
||||
env:
|
||||
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
|
||||
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
|
||||
- name: Codesign MSI
|
||||
uses: skymatic/code-sign-action@v3
|
||||
uses: skymatic/code-sign-action@v2
|
||||
with:
|
||||
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
|
||||
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
|
||||
@@ -250,36 +213,44 @@ jobs:
|
||||
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: msi
|
||||
path: |
|
||||
Cryptomator-*.msi
|
||||
Cryptomator-*.asc
|
||||
if-no-files-found: error
|
||||
- name: Publish .msi on GitHub Releases
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
fail_on_unmatched_files: true
|
||||
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
files: |
|
||||
*.msi
|
||||
*.asc
|
||||
|
||||
build-exe:
|
||||
name: Build .exe installer
|
||||
runs-on: windows-latest
|
||||
needs: [get-version, build-msi]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Download .msi
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: msi
|
||||
path: dist/win/bundle/resources
|
||||
- name: Strip version info from msi file name
|
||||
run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DIST }}
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
check-latest: true
|
||||
cache: 'maven'
|
||||
cache: ${{ env.JAVA_CACHE }}
|
||||
- name: Generate license for exe
|
||||
run: >
|
||||
mvn -B license:add-third-party "-Djavafx.platform=win"
|
||||
mvn -B license:add-third-party
|
||||
"-Dlicense.thirdPartyFilename=license.rtf"
|
||||
"-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
|
||||
"-Dlicense.outputDirectory=dist/win/bundle/resources"
|
||||
@@ -290,11 +261,8 @@ jobs:
|
||||
shell: pwsh
|
||||
- name: Download WinFsp
|
||||
run: |
|
||||
curl --output dist/win/bundle/resources/winfsp.msi -L ${{ env.WINFSP_MSI }}
|
||||
shell: pwsh
|
||||
- name: Download Legacy-WinFsp uninstaller
|
||||
run: |
|
||||
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
|
||||
$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
|
||||
- name: Compile to wixObj file
|
||||
run: >
|
||||
@@ -304,7 +272,7 @@ jobs:
|
||||
-out dist/win/bundle/
|
||||
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
|
||||
-dBundleVendor="Skymatic GmbH"
|
||||
-dBundleCopyright="(C) 2016 - 2025 Skymatic GmbH"
|
||||
-dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
|
||||
-dAboutUrl="https://cryptomator.org"
|
||||
-dHelpUrl="https://cryptomator.org/contact"
|
||||
-dUpdateUrl="https://cryptomator.org/downloads/"
|
||||
@@ -320,7 +288,7 @@ jobs:
|
||||
-ib installer/unsigned/Cryptomator-Installer.exe
|
||||
-o tmp/engine.exe
|
||||
- name: Codesign burn engine
|
||||
uses: skymatic/code-sign-action@v3
|
||||
uses: skymatic/code-sign-action@v2
|
||||
with:
|
||||
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
|
||||
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
|
||||
@@ -334,7 +302,7 @@ jobs:
|
||||
-ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe
|
||||
-o installer/Cryptomator-Installer.exe
|
||||
- name: Codesign EXE
|
||||
uses: skymatic/code-sign-action@v3
|
||||
uses: skymatic/code-sign-action@v2
|
||||
with:
|
||||
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
|
||||
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
|
||||
@@ -352,68 +320,59 @@ jobs:
|
||||
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: exe
|
||||
path: |
|
||||
Cryptomator-*.exe
|
||||
Cryptomator-*.asc
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: Publish installers to the github release
|
||||
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-msi, build-exe]
|
||||
outputs:
|
||||
download-url-msi: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
|
||||
download-url-exe: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }}
|
||||
steps:
|
||||
- name: Download installers
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
merge-multiple: true
|
||||
- name: Publish .msi on GitHub Releases
|
||||
id: publish
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
fail_on_unmatched_files: true
|
||||
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
# do not change ordering of filelist, required for correct job output
|
||||
files: |
|
||||
*.msi
|
||||
*.exe
|
||||
*.asc
|
||||
Cryptomator-*.exe
|
||||
Cryptomator-*.asc
|
||||
|
||||
allowlist-msi:
|
||||
uses: ./.github/workflows/av-whitelist.yml
|
||||
needs: [publish]
|
||||
with:
|
||||
url: ${{ needs.publish.outputs.download-url-msi }}
|
||||
secrets: inherit
|
||||
|
||||
allowlist-exe:
|
||||
uses: ./.github/workflows/av-whitelist.yml
|
||||
needs: [publish]
|
||||
with:
|
||||
url: ${{ needs.publish.outputs.download-url-exe }}
|
||||
secrets: inherit
|
||||
|
||||
notify-winget:
|
||||
name: Notify for winget-release
|
||||
if: needs.get-version.outputs.versionType == 'stable'
|
||||
needs: [publish, get-version]
|
||||
allowlist:
|
||||
name: Anti Virus Allowlisting
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-msi, build-exe]
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_USERNAME: 'Cryptobot'
|
||||
SLACK_ICON: false
|
||||
SLACK_ICON_EMOJI: ':bot:'
|
||||
SLACK_CHANNEL: 'cryptomator-desktop'
|
||||
SLACK_TITLE: "MSI of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published."
|
||||
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml| release to winget>."
|
||||
SLACK_FOOTER: false
|
||||
MSG_MINIMAL: true
|
||||
- name: Download .msi
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: msi
|
||||
path: msi
|
||||
- name: Download .exe
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: exe
|
||||
path: exe
|
||||
- name: Collect files
|
||||
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
.github/workflows/winget.yml
vendored
27
.github/workflows/winget.yml
vendored
@@ -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: '\.msi$'
|
||||
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
|
||||
66
.idea/compiler.xml
generated
66
.idea/compiler.xml
generated
@@ -14,56 +14,32 @@
|
||||
<option name="dagger.fastInit" value="enabled" />
|
||||
<option name="dagger.formatGeneratedSource" value="enabled" />
|
||||
<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/2.55/dagger-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.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.45/dagger-2.45.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-spi/2.55/dagger-spi-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/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/dagger/dagger-producers/2.45/dagger-producers-2.45.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/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/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/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/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/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$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.55/dagger-compiler-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.55/dagger-2.55.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$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.55/dagger-spi-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/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$/org/checkerframework/checker-qual/3.41.0/checker-qual-3.41.0.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$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.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/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$/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>
|
||||
<module name="cryptomator" />
|
||||
</profile>
|
||||
@@ -71,7 +47,7 @@
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<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>
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -8,7 +8,7 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" project-jdk-name="23" 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" />
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/runConfigurations/Cryptomator_Linux.xml
generated
2
.idea/runConfigurations/Cryptomator_Linux.xml
generated
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator-Dev/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator-Dev/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator-Dev/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator-Dev/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
2
.idea/runConfigurations/Cryptomator_Windows.xml
generated
2
.idea/runConfigurations/Cryptomator_Windows.xml
generated
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator" -Dcryptomator.pluginDir="@{appdata}/Cryptomator/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator" -Dcryptomator.pluginDir="@{appdata}/Cryptomator/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator-Dev" -Dcryptomator.pluginDir="@{appdata}/Cryptomator-Dev/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" />
|
||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator-Dev" -Dcryptomator.pluginDir="@{appdata}/Cryptomator-Dev/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</envs>
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator-Dev" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Library/Application Support/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" />
|
||||
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator-Dev" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
25
README.md
25
README.md
@@ -3,7 +3,7 @@
|
||||
[](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild)
|
||||
[](https://snyk.io/test/github/cryptomator/cryptomator)
|
||||
[](https://sonarcloud.io/dashboard?id=cryptomator_cryptomator)
|
||||
[](https://mastodon.online/@cryptomator)
|
||||
[](http://twitter.com/Cryptomator)
|
||||
[](https://translate.cryptomator.org/)
|
||||
[](https://github.com/cryptomator/cryptomator/releases/latest)
|
||||
[](https://community.cryptomator.org)
|
||||
@@ -17,24 +17,31 @@ Cryptomator is provided free of charge as an open-source project despite the hig
|
||||
|
||||
### 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
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<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://www.route4me.com/"><img src="https://cryptomator.org/img/sponsors/route4me.svg" alt="Route4Me" 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.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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### 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
|
||||
- Folder structure gets obfuscated
|
||||
- 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
|
||||
|
||||
@@ -72,13 +79,13 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator
|
||||
|
||||
### 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
|
||||
|
||||
### Dependencies
|
||||
|
||||
* JDK 23 (e.g. temurin, zulu)
|
||||
* JDK 19 (e.g. temurin)
|
||||
* Maven 3
|
||||
|
||||
### Run Maven
|
||||
|
||||
4
dist/linux/appimage/.gitignore
vendored
4
dist/linux/appimage/.gitignore
vendored
@@ -1,6 +1,4 @@
|
||||
# downloaded/created during build
|
||||
openjfx-jmods.zip
|
||||
*.jmod
|
||||
# created during build
|
||||
Cryptomator.AppDir
|
||||
*.AppImage
|
||||
*.AppImage.zsync
|
||||
72
dist/linux/appimage/build.sh
vendored
72
dist/linux/appimage/build.sh
vendored
@@ -1,5 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cd $(dirname $0)
|
||||
REVISION_NO=`git rev-list --count HEAD`
|
||||
@@ -8,62 +7,32 @@ REVISION_NO=`git rev-list --count HEAD`
|
||||
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
|
||||
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 unzip >/dev/null 2>&1 || { echo >&2 "unzip not found."; exit 1; }
|
||||
|
||||
VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
|
||||
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}
|
||||
|
||||
# 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 ../launcher.sh ../../../target
|
||||
cp ../../../target/cryptomator-*.jar ../../../target/mods
|
||||
|
||||
JAVAFX_VERSION=22.0.2
|
||||
JAVAFX_ARCH="x64"
|
||||
JAVAFX_JMODS_SHA256='2164bca470bf70a5e2764645e2078ba7f787b274e5be3d7df30d87c5bb62bba6'
|
||||
if [ "${CPU_ARCH}" = "aarch64" ]; then
|
||||
JAVAFX_ARCH="aarch64"
|
||||
JAVAFX_JMODS_SHA256='09c92fa9fa0b82adefd88640a14ebb2a49e5f3f733a57d1542f5590d060ffe1b'
|
||||
fi
|
||||
|
||||
# download javaFX jmods
|
||||
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_linux-${JAVAFX_ARCH}_bin-jmods.zip"
|
||||
|
||||
|
||||
curl -L ${JAVAFX_JMODS_URL} -o openjfx-jmods.zip
|
||||
echo "${JAVAFX_JMODS_SHA256} openjfx-jmods.zip" | shasum -a256 --check
|
||||
mkdir -p openjfx-jmods
|
||||
unzip -o -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
||||
JMOD_VERSION=$(jmod describe ./openjfx-jmods/javafx.base.jmod | head -1)
|
||||
JMOD_VERSION=${JMOD_VERSION#*@}
|
||||
JMOD_VERSION=${JMOD_VERSION%%.*}
|
||||
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout -B -f ../../../pom.xml)
|
||||
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
|
||||
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
|
||||
if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
|
||||
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# add runtime
|
||||
${JAVA_HOME}/bin/jlink \
|
||||
--verbose \
|
||||
--output runtime \
|
||||
--module-path "${JAVA_HOME}/jmods:openjfx-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 \
|
||||
--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.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
|
||||
--strip-native-commands \
|
||||
--no-header-files \
|
||||
--no-man-pages \
|
||||
--strip-debug \
|
||||
--compress zip-0
|
||||
--compress=1
|
||||
|
||||
# create app dir
|
||||
envsubst '${SEMVER_STR} ${REVISION_NUM}' < ../launcher-gtk2.properties > launcher-gtk2.properties
|
||||
${JAVA_HOME}/bin/jpackage \
|
||||
--verbose \
|
||||
--type app-image \
|
||||
@@ -75,8 +44,8 @@ ${JAVA_HOME}/bin/jpackage \
|
||||
--name Cryptomator \
|
||||
--vendor "Skymatic GmbH" \
|
||||
--java-options "--enable-preview" \
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
|
||||
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \
|
||||
--copyright "(C) 2016 - 2023 Skymatic GmbH" \
|
||||
--java-options "-Xss5m" \
|
||||
--java-options "-Xmx256m" \
|
||||
--app-version "${VERSION}.${REVISION_NO}" \
|
||||
@@ -88,10 +57,9 @@ ${JAVA_HOME}/bin/jpackage \
|
||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \
|
||||
--java-options "-Dcryptomator.showTrayIcon=true" \
|
||||
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\"" \
|
||||
--java-options "-Dcryptomator.showTrayIcon=false" \
|
||||
--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
|
||||
|
||||
# transform AppDir
|
||||
@@ -101,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.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.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.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.metainfo.xml
|
||||
cp ../common/application-vnd.cryptomator.vault.xml Cryptomator.AppDir/usr/share/mime/packages/application-vnd.cryptomator.vault.xml
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/org.cryptomator.Cryptomator.svg
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/Cryptomator.svg
|
||||
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
|
||||
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/org.cryptomator.Cryptomator.desktop
|
||||
ln -s org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/metainfo/org.cryptomator.Cryptomator.appdata.xml
|
||||
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
|
||||
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
||||
|
||||
# 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
|
||||
|
||||
# create AppImage
|
||||
/tmp/appimagetool.AppImage \
|
||||
Cryptomator.AppDir \
|
||||
cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage \
|
||||
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${CPU_ARCH}.AppImage.zsync'
|
||||
cryptomator-${SEMVER_STR}-x86_64.AppImage \
|
||||
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
|
||||
|
||||
echo ""
|
||||
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-${CPU_ARCH}.AppImage"
|
||||
echo ""
|
||||
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir runtime squashfs-root openjfx-jmods; rm /tmp/appimagetool.AppImage openjfx-jmods.zip"
|
||||
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-x86_64.AppImage"
|
||||
echo ""
|
||||
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir jni runtime squashfs-root; rm launcher-gtk2.properties /tmp/appimagetool.AppImage"
|
||||
echo ""
|
||||
@@ -5,27 +5,26 @@
|
||||
<metadata_license>FSFAP</metadata_license>
|
||||
<project_license>GPL-3.0-or-later</project_license>
|
||||
<name>Cryptomator</name>
|
||||
<summary>Encryption made easy and optimized for the cloud</summary>
|
||||
<summary>Multi-platform client-side encryption tool optimized for cloud storages</summary>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
Cryptomator provides easy-to-use, transparent, client-side encryption for your cloud.
|
||||
It protects your documents from unauthorized access and prying eyes, while you will still be able to view and edit your documents locally.
|
||||
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).
|
||||
Cryptomator provides transparent, client-side encryption for your cloud. Protect your documents from unauthorized
|
||||
access. Cryptomator is free and open source software, so you can rest assured there are no backdoors.
|
||||
</p>
|
||||
<p>
|
||||
Cryptomator encrypts file contents and names using the widespread industry standard AES.
|
||||
Your passphrase is protected against brute forcing attempts using scrypt.
|
||||
Additionally, directory structures get obfuscated.
|
||||
For more info about the Cryptomator encryption scheme, check out the online documentation.
|
||||
Cryptomator encrypts file contents and names using AES. Your passphrase is protected against bruteforcing attempts
|
||||
using scrypt. Directory structures get obfuscated. The only thing which cannot be encrypted without breaking your
|
||||
cloud synchronization is the modification date of your files.
|
||||
</p>
|
||||
<p>
|
||||
Cryptomator is a free and open-source software licensed under the GPLv3.
|
||||
This allows anyone to check our code.
|
||||
Thus, it is impossible to introduce backdoors for third parties or to hide vulnerabilities, so you do not need to trust Cryptomator.
|
||||
Also, vendor lock-ins are impossible.
|
||||
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.
|
||||
Cryptomator is a free and open source software licensed under the GPLv3. This allows anyone to check our code. It
|
||||
is impossible to introduce backdoors for third parties. Also we cannot hide vulnerabilities. And the best thing
|
||||
is: There is no need to trust us, as you can control us!
|
||||
</p>
|
||||
<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>
|
||||
</description>
|
||||
|
||||
@@ -43,7 +42,7 @@
|
||||
</provides>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<screenshot>
|
||||
<caption>Light theme</caption>
|
||||
<image>https://user-images.githubusercontent.com/11858409/156986109-6e58f59c-8b8c-4501-b33b-bb1e33007cea.png</image>
|
||||
</screenshot>
|
||||
@@ -53,131 +52,38 @@
|
||||
</screenshot>
|
||||
</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="bugtracker">https://github.com/cryptomator/cryptomator/issues/</url>
|
||||
<url type="donation">https://cryptomator.org/donate</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>
|
||||
|
||||
<developer id="de.skymatic">
|
||||
<name>Skymatic GmbH</name>
|
||||
</developer>
|
||||
<developer_name>Skymatic GmbH</developer_name>
|
||||
|
||||
<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_rating>
|
||||
|
||||
<releases>
|
||||
<release date="2025-02-03" version="1.15.0">
|
||||
<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>
|
||||
<release date="2023-06-07" version="1.9.1"/>
|
||||
<release date="2023-05-30" version="1.9.0"/>
|
||||
<release date="2023-04-25" version="1.8.0"/>
|
||||
<release date="2023-04-07" version="1.7.5"/>
|
||||
<release date="2023-04-05" version="1.7.4"/>
|
||||
<release date="2023-03-15" version="1.7.3"/>
|
||||
<release date="2023-03-07" version="1.7.2"/>
|
||||
<release date="2023-03-03" version="1.7.1"/>
|
||||
<release date="2023-03-01" version="1.7.0"/>
|
||||
<release date="2022-12-14" version="1.6.17"/>
|
||||
<release date="2022-12-06" version="1.6.16"/>
|
||||
<release date="2022-10-06" version="1.6.15"/>
|
||||
<release date="2022-08-31" version="1.6.14"/>
|
||||
<release date="2022-07-27" version="1.6.12"/>
|
||||
<release date="2022-07-26" version="1.6.11"/>
|
||||
<release date="2022-05-03" version="1.6.10"/>
|
||||
<release date="2022-04-27" version="1.6.9"/>
|
||||
<release date="2022-03-30" version="1.6.8"/>
|
||||
<release date="2021-12-16" version="1.6.5"/>
|
||||
</releases>
|
||||
</component>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<svg height="16" viewBox="0 0 42 42" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<style
|
||||
id="current-color-scheme" type="text/css">
|
||||
.ColorScheme-Text {
|
||||
color:#232629;
|
||||
}
|
||||
</style>
|
||||
<g fill-rule="evenodd" style="fill:#f2f2f2;fill-opacity:1" class="ColorScheme-Text" fill="currentColor">
|
||||
<path d="m15.591 35.824c-.019.009-.936.775-1.458 1.208a.418.418 0 0 1 -.627-.111 9.322 9.322 0 0 1 -.3-5.974 15.843 15.843 0 0 0 2.894 2.043c.051 1.03-.161 2.644-.509 2.834zm6.409-6.824h-2l.5-5a2 2 0 1 1 1 0zm-14.544-3.241.744-1.366a1.579 1.579 0 0 0 -.019-1.557l.653-1.2c.2.014-.03-.113.165-.14.051-.217-.051-.336 0-.5a3.269 3.269 0 0 0 0-1.5 7.151 7.151 0 0 1 0-3 2.366 2.366 0 0 0 -2.378 1.448 2.409 2.409 0 0 0 .229 2.661l-.7 1.278a1.779 1.779 0 0 0 -1.317.891l-.741 1.372a1.577 1.577 0 0 0 -.019 1.487 3.028 3.028 0 0 0 -2.746 1.525 2.648 2.648 0 0 0 .044 2.631.748.748 0 0 0 .981.266.656.656 0 0 0 .284-.92 1.37 1.37 0 0 1 -.023-1.361 1.6 1.6 0 0 1 2.079-.63 1.408 1.408 0 0 1 .672 1.95 1.546 1.546 0 0 1 -1.2.78.688.688 0 0 0 -.636.749.707.707 0 0 0 .717.6.789.789 0 0 0 .082 0 2.989 2.989 0 0 0 2.322-1.513 2.669 2.669 0 0 0 -.377-3.084 1.767 1.767 0 0 0 1.184-.867zm13.544-10.759a13.013 13.013 0 0 1 5-1 21.6 21.6 0 0 1 4.5.5 9.312 9.312 0 0 0 -9.5-8.5c-5.794 0-9.176 4-9.5 8.5a21.858 21.858 0 0 1 4.5-.5 12.819 12.819 0 0 1 5 1zm3.5-5c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2zm-7 0c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2zm14.473 6a8.067 8.067 0 0 0 -8.08 8v2.141a3.891 3.891 0 0 0 -2.893 3.734v5.125a23.166 23.166 0 0 1 -4.174-1.623 7.857 7.857 0 0 1 -.027.878 3.263 3.263 0 0 1 -.729 2.074l-1.794 1.483a.379.379 0 0 1 -.276.188h-4c-1.324 0-2.346-1.336-2.653-3.343a7.058 7.058 0 0 1 .234-3.18 3.477 3.477 0 0 1 1.636-2.157 1.868 1.868 0 0 1 .783-.32h1.5a8.035 8.035 0 0 1 -1.5-5 11.1 11.1 0 0 1 .5-3 2.519 2.519 0 0 0 0-1.5 13.272 13.272 0 0 1 -.5-3.5c6.687-1.936 11 0 11 0s4.319-1.955 11 0"/>
|
||||
<path d="m39 28h-10v-4a3.13 3.13 0 0 1 3-3 3.087 3.087 0 0 1 3 3v1a1.034 1.034 0 0 0 1 1h1a1.034 1.034 0 0 0 1-1v-1a6 6 0 0 0 -12 0v4h-1a2.073 2.073 0 0 0 -2 2v6a2.073 2.073 0 0 0 2 2h14a2.073 2.073 0 0 0 2-2v-6a2.073 2.073 0 0 0 -2-2zm-5.391 5.94a1.609 1.609 0 0 1 -3.217 0v-1.876a1.609 1.609 0 0 1 3.217 0z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,8 +0,0 @@
|
||||
<svg height="16" viewBox="0 0 42 42" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<style id="current-color-scheme" type="text/css">
|
||||
.ColorScheme-Text {
|
||||
color:#232629;
|
||||
}
|
||||
</style>
|
||||
<path d="m32.66 29.319a1.432 1.432 0 0 0 -.66-.319h-1.5a8.125 8.125 0 0 0 1.5-5 11.027 11.027 0 0 0 -.5-3 2.519 2.519 0 0 1 0-1.5 12.987 12.987 0 0 0 .5-3.5c-6.681-1.955-11 0-11 0s-4.313-1.936-11 0a13.272 13.272 0 0 0 .5 3.5 2.519 2.519 0 0 1 0 1.5 11.1 11.1 0 0 0 -.5 3 8.035 8.035 0 0 0 1.5 5h-1.5a1.868 1.868 0 0 0 -.783.319 3.477 3.477 0 0 0 -1.636 2.157 7.058 7.058 0 0 0 -.234 3.18c.307 2.008 1.329 3.344 2.653 3.344h4a.379.379 0 0 0 .277-.187l1.793-1.483a3.263 3.263 0 0 0 .729-2.074 7.857 7.857 0 0 0 .027-.878 23.166 23.166 0 0 0 4.174 1.622 24.4 24.4 0 0 0 4.051-1.614 7.848 7.848 0 0 0 .027.869 3.263 3.263 0 0 0 .729 2.074l1.793 1.484a.61.61 0 0 0 .4.187h4c1.324 0 2.223-1.336 2.529-3.343a7.057 7.057 0 0 0 -.234-3.18 3.477 3.477 0 0 0 -1.635-2.158zm-17.069 6.5c-.019.009-.936.775-1.458 1.208a.418.418 0 0 1 -.627-.111 9.322 9.322 0 0 1 -.3-5.974 15.843 15.843 0 0 0 2.894 2.048c.051 1.03-.161 2.644-.509 2.834zm6.409-6.819h-2l.5-5a2 2 0 1 1 1 0zm6.38 7.921a.418.418 0 0 1 -.627.111c-.522-.433-1.439-1.2-1.458-1.208-.348-.189-.56-1.8-.505-2.828a15.84 15.84 0 0 0 2.9-2.037 9.322 9.322 0 0 1 -.31 5.962zm-20.924-11.162.744-1.366a1.579 1.579 0 0 0 -.019-1.557l.653-1.2c.2.014-.03-.113.165-.14.051-.217-.051-.336 0-.5a3.269 3.269 0 0 0 0-1.5 7.151 7.151 0 0 1 0-3 2.366 2.366 0 0 0 -2.378 1.448 2.409 2.409 0 0 0 .229 2.661l-.7 1.278a1.779 1.779 0 0 0 -1.317.891l-.741 1.372a1.577 1.577 0 0 0 -.019 1.487 3.028 3.028 0 0 0 -2.746 1.525 2.648 2.648 0 0 0 .044 2.631.748.748 0 0 0 .981.266.656.656 0 0 0 .284-.92 1.37 1.37 0 0 1 -.023-1.361 1.6 1.6 0 0 1 2.079-.63 1.408 1.408 0 0 1 .672 1.95 1.546 1.546 0 0 1 -1.2.78.688.688 0 0 0 -.636.749.707.707 0 0 0 .717.6.789.789 0 0 0 .082 0 2.989 2.989 0 0 0 2.322-1.513 2.669 2.669 0 0 0 -.377-3.084 1.767 1.767 0 0 0 1.184-.867zm33.217 1.2a3.021 3.021 0 0 0 -2.658-1.525 1.574 1.574 0 0 0 -.107-1.283l-.745-1.367a1.779 1.779 0 0 0 -1.317-.891l-.7-1.278a2.409 2.409 0 0 0 .229-2.661 2.283 2.283 0 0 0 -2.375-1.454 7.039 7.039 0 0 1 0 3 3.272 3.272 0 0 0 0 1.5c.047.152-.047.3 0 .5.227.04-.069.156.165.14l.653 1.2a1.579 1.579 0 0 0 -.019 1.557l.745 1.367a1.753 1.753 0 0 0 1.045.832 2.66 2.66 0 0 0 -.238 2.916 2.989 2.989 0 0 0 2.326 1.509.79.79 0 0 0 .082 0 .707.707 0 0 0 .717-.6.688.688 0 0 0 -.636-.749 1.546 1.546 0 0 1 -1.2-.78 1.408 1.408 0 0 1 .672-1.95 1.628 1.628 0 0 1 1.179-.089 1.512 1.512 0 0 1 .9.719 1.37 1.37 0 0 1 -.023 1.361.656.656 0 0 0 .284.92.748.748 0 0 0 .981-.266 2.648 2.648 0 0 0 .04-2.633zm-19.673-11.959a13.013 13.013 0 0 1 5-1 21.6 21.6 0 0 1 4.5.5 9.312 9.312 0 0 0 -9.5-8.5c-5.794 0-9.176 4-9.5 8.5a21.858 21.858 0 0 1 4.5-.5 12.819 12.819 0 0 1 5 1zm3.5-5c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2zm-7 0c1.209 0 2.5.866 2.5 2h-5c0-1.134 1.291-2 2.5-2z" fill-rule="evenodd" style="fill:#f2f2f2;fill-opacity:1" class="ColorScheme-Text" fill="currentColor"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
2
dist/linux/debian/control
vendored
2
dist/linux/debian/control
vendored
@@ -2,7 +2,7 @@ Source: cryptomator
|
||||
Maintainer: Cryptobot <releases@cryptomator.org>
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>=10), coffeelibs-jdk-23 (>= 23.0.1+11-0ppa1), libgtk-3-0, libxxf86vm1, libgl1
|
||||
Build-Depends: debhelper (>=10), coffeelibs-jdk-20, libgtk2.0-0, libgtk-3-0, libxxf86vm1, libgl1
|
||||
Standards-Version: 4.5.0
|
||||
Homepage: https://cryptomator.org
|
||||
Vcs-Git: https://github.com/cryptomator/cryptomator.git
|
||||
|
||||
4
dist/linux/debian/copyright
vendored
4
dist/linux/debian/copyright
vendored
@@ -4,11 +4,11 @@ Upstream-Contact: Cryptomator <info@cryptomator.org>
|
||||
Source: https://cryptomator.org
|
||||
|
||||
Files: *
|
||||
Copyright: 2016-2025 Skymatic GmbH
|
||||
Copyright: 2016-2023 Skymatic GmbH
|
||||
License: GPL-3+
|
||||
|
||||
Files: debian/org.cryptomator.Cryptomator.appdata.xml
|
||||
Copyright: 2016-2025 Skymatic GmbH
|
||||
Copyright: 2016-2023 Skymatic GmbH
|
||||
License: FSFAP
|
||||
|
||||
License: GPL-3+
|
||||
|
||||
2
dist/linux/debian/cryptomator.install
vendored
2
dist/linux/debian/cryptomator.install
vendored
@@ -1,8 +1,6 @@
|
||||
cryptomator usr/lib
|
||||
common/org.cryptomator.Cryptomator.desktop usr/share/applications
|
||||
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.Cryptomator512.png usr/share/icons/hicolor/512x512/apps
|
||||
common/org.cryptomator.Cryptomator.metainfo.xml usr/share/metainfo
|
||||
|
||||
2
dist/linux/debian/cryptomator.links
vendored
2
dist/linux/debian/cryptomator.links
vendored
@@ -1,3 +1 @@
|
||||
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
|
||||
17
dist/linux/debian/rules
vendored
17
dist/linux/debian/rules
vendored
@@ -4,7 +4,7 @@
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
JAVA_HOME = /usr/lib/jvm/java-23-coffeelibs
|
||||
JAVA_HOME = /usr/lib/jvm/java-20-coffeelibs
|
||||
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
|
||||
ifeq ($(DEB_BUILD_ARCH),amd64)
|
||||
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
|
||||
@@ -24,16 +24,15 @@ override_dh_auto_clean:
|
||||
override_dh_auto_build:
|
||||
mkdir resources
|
||||
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 \
|
||||
--output runtime \
|
||||
--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 \
|
||||
--no-header-files \
|
||||
--no-man-pages \
|
||||
--strip-debug \
|
||||
--compress zip-0
|
||||
--compress=2
|
||||
$(JAVA_HOME)/bin/jpackage \
|
||||
--type app-image \
|
||||
--runtime-image runtime \
|
||||
@@ -44,8 +43,8 @@ override_dh_auto_build:
|
||||
--name cryptomator \
|
||||
--vendor "Skymatic GmbH" \
|
||||
--java-options "--enable-preview" \
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
|
||||
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \
|
||||
--copyright "(C) 2016 - 2023 Skymatic GmbH" \
|
||||
--java-options "-Xss5m" \
|
||||
--java-options "-Xmx256m" \
|
||||
--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.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \
|
||||
--java-options "-Dcryptomator.showTrayIcon=true" \
|
||||
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"/usr/share/icons/hicolor/symbolic/apps\"" \
|
||||
--java-options "-Dcryptomator.showTrayIcon=false" \
|
||||
--java-options "-Dcryptomator.buildNumber=\"deb-${REVISION_NUM}\"" \
|
||||
--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}" \
|
||||
--resource-dir resources \
|
||||
--verbose
|
||||
|
||||
14
dist/linux/launcher-gtk2.properties
vendored
Normal file
14
dist/linux/launcher-gtk2.properties
vendored
Normal 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
dist/mac/.gitignore
vendored
1
dist/mac/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
embedded.provisionprofile
|
||||
8
dist/mac/Cryptomator.entitlements
vendored
8
dist/mac/Cryptomator.entitlements
vendored
@@ -2,10 +2,6 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<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>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
@@ -14,9 +10,5 @@
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>###APP_IDENTIFIER_PREFIX###org.cryptomator</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
7
dist/mac/dmg/.gitignore
vendored
7
dist/mac/dmg/.gitignore
vendored
@@ -1,9 +1,6 @@
|
||||
# downloaded/created during build
|
||||
# created during build
|
||||
Cryptomator.app/
|
||||
runtime/
|
||||
dmg/
|
||||
*.dmg
|
||||
license.rtf
|
||||
openjfx-jmods.zip
|
||||
*.jmod
|
||||
Cryptomator.entitlements
|
||||
license.rtf
|
||||
62
dist/mac/dmg/build.sh
vendored
62
dist/mac/dmg/build.sh
vendored
@@ -1,15 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# parse options
|
||||
usage() { echo "Usage: $0 [-s <codesign-identity>] [-t <team-identifier>]" 1>&2; exit 1; }
|
||||
while getopts ":s:t:" o; do
|
||||
usage() { echo "Usage: $0 [-s <codesign-identity>]" 1>&2; exit 1; }
|
||||
while getopts ":s:" o; do
|
||||
case "${o}" in
|
||||
s)
|
||||
CODESIGN_IDENTITY=${OPTARG}
|
||||
;;
|
||||
t)
|
||||
TEAM_IDENTIFIER=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
@@ -24,7 +21,7 @@ rm -rf runtime dmg *.app *.dmg
|
||||
# set variables
|
||||
APP_NAME="Cryptomator"
|
||||
VENDOR="Skymatic GmbH"
|
||||
COPYRIGHT_YEARS="2016 - 2025"
|
||||
COPYRIGHT_YEARS="2016 - 2023"
|
||||
PACKAGE_IDENTIFIER="org.cryptomator"
|
||||
MAIN_JAR_GLOB="cryptomator-*.jar"
|
||||
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'`
|
||||
FUSE_LIB="FUSE-T"
|
||||
|
||||
JAVAFX_VERSION=23.0.1
|
||||
JAVAFX_ARCH="undefined"
|
||||
JAVAFX_JMODS_SHA256="undefined"
|
||||
if [ "$(machine)" = "arm64e" ]; then
|
||||
JAVAFX_ARCH="aarch64"
|
||||
JAVAFX_JMODS_SHA256="a800724a1f3e6757ecfa0bd5bf7ed64d2e6a7a3f5b3522650a70b8cfc7782fb6"
|
||||
else
|
||||
JAVAFX_ARCH="x64"
|
||||
JAVAFX_JMODS_SHA256="8857965975c464a0e5d57709292ce357d0ebb39f6168c41d5ca38301e42c3c8e"
|
||||
fi
|
||||
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
|
||||
|
||||
# check preconditions
|
||||
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
|
||||
command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found. Fix by 'brew install maven'."; exit 1; }
|
||||
@@ -53,38 +38,20 @@ if [ -n "${CODESIGN_IDENTITY}" ]; then
|
||||
if [[ ! `security find-identity -v -p codesigning | grep -w "${CODESIGN_IDENTITY}"` ]]; then echo "Given codesign identity is invalid."; exit 1; fi
|
||||
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
|
||||
mvn -B -Djavafx.platform=mac -f../../../pom.xml clean package -DskipTests -Pmac
|
||||
cp ../../../LICENSE.txt ../../../target
|
||||
mvn -B -f../../../pom.xml clean package -DskipTests -Pmac
|
||||
cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
|
||||
|
||||
# add runtime
|
||||
${JAVA_HOME}/bin/jlink \
|
||||
--output runtime \
|
||||
--module-path "${JAVA_HOME}/jmods:openjfx-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 \
|
||||
--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,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
|
||||
--strip-native-commands \
|
||||
--no-header-files \
|
||||
--no-man-pages \
|
||||
--strip-debug \
|
||||
--compress zip-0
|
||||
--compress=1
|
||||
|
||||
# create app dir
|
||||
${JAVA_HOME}/bin/jpackage \
|
||||
@@ -124,10 +91,9 @@ ${JAVA_HOME}/bin/jpackage \
|
||||
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_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
|
||||
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
|
||||
|
||||
# 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.outputDirectory=dist/mac/dmg/resources \
|
||||
-Dlicense.fileTemplate=resources/licenseTemplate.ftl \
|
||||
@@ -137,11 +103,7 @@ mvn -B -Djavafx.platform=mac -f../../../pom.xml license:add-third-party \
|
||||
-Dlicense.licenseMergesUrl=file://$(pwd)/../../../license/merges
|
||||
|
||||
# codesign
|
||||
if [ -n "${CODESIGN_IDENTITY}" ] && [ -n "${TEAM_IDENTIFIER}" ]; 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..."
|
||||
if [ -n "${CODESIGN_IDENTITY}" ]; then
|
||||
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
|
||||
if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
|
||||
@@ -159,10 +121,7 @@ if [ -n "${CODESIGN_IDENTITY}" ] && [ -n "${TEAM_IDENTIFIER}" ]; then
|
||||
fi
|
||||
done
|
||||
echo "Codesigning ${APP_NAME}.app..."
|
||||
cp ../${APP_NAME}.entitlements .
|
||||
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
|
||||
codesign --force --deep --entitlements ../${APP_NAME}.entitlements -o runtime -s ${CODESIGN_IDENTITY} ${APP_NAME}.app
|
||||
fi
|
||||
|
||||
# prepare dmg contents
|
||||
@@ -185,5 +144,6 @@ create-dmg \
|
||||
--app-drop-link 512 245 \
|
||||
--eula "resources/license.rtf" \
|
||||
--icon ".background" 128 758 \
|
||||
--icon ".fseventsd" 320 758 \
|
||||
--icon ".VolumeIcon.icns" 512 758 \
|
||||
${APP_NAME}-${VERSION_NO}.dmg dmg
|
||||
|
||||
2
dist/mac/dmg/resources/licenseTemplate.ftl
vendored
2
dist/mac/dmg/resources/licenseTemplate.ftl
vendored
@@ -17,7 +17,7 @@
|
||||
\f1\b0 \
|
||||
\
|
||||
|
||||
\f0\b \'a9 2016 \'96 2025 Skymatic GmbH
|
||||
\f0\b \'a9 2016 \'96 2023 Skymatic GmbH
|
||||
\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.\
|
||||
|
||||
BIN
dist/mac/resources/Cryptomator.icns
vendored
BIN
dist/mac/resources/Cryptomator.icns
vendored
Binary file not shown.
2
dist/mac/resources/Info.plist
vendored
2
dist/mac/resources/Info.plist
vendored
@@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11</string>
|
||||
<string>10.13.0</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleAllowMixedLocalizations</key>
|
||||
|
||||
3
dist/win/.gitignore
vendored
3
dist/win/.gitignore
vendored
@@ -4,7 +4,4 @@ installer
|
||||
*.wixobj
|
||||
*.pdb
|
||||
*.msi
|
||||
*.exe
|
||||
*.jmod
|
||||
resources/jfxJmods.zip
|
||||
license.rtf
|
||||
2
dist/win/build.bat
vendored
2
dist/win/build.bat
vendored
@@ -11,7 +11,7 @@ SET HELP_URL="https://cryptomator.org/contact/"
|
||||
SET MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
|
||||
SET LOOPBACK_ALIAS="cryptomator-vault"
|
||||
|
||||
pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^
|
||||
powershell -NoLogo -ExecutionPolicy Unrestricted -Command .\build.ps1^
|
||||
-AppName %APPNAME%^
|
||||
-MainJarGlob "%MAIN_JAR_GLOB%"^
|
||||
-ModuleAndMainClass "%MODULE_AND_MAIN_CLASS%"^
|
||||
|
||||
50
dist/win/build.ps1
vendored
50
dist/win/build.ps1
vendored
@@ -41,7 +41,7 @@ Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
|
||||
$copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor"
|
||||
|
||||
# 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"
|
||||
|
||||
# add runtime
|
||||
@@ -51,36 +51,32 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
|
||||
}
|
||||
|
||||
## download jfx jmods
|
||||
$javaFxVersion='23.0.1'
|
||||
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
|
||||
$javaFxJmodsSHA256 = 'ee176dcee3bd78bde7910735bd67f67c792882f5b89626796ae06f7a1c0119d3'
|
||||
$javaFxJmods = '.\resources\jfxJmods.zip'
|
||||
if( !(Test-Path -Path $javaFxJmods) ) {
|
||||
Write-Output "Downloading ${javaFxJmodsUrl}..."
|
||||
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
|
||||
$jfxJmodsChecksum = 'd00767334c43b8832b5cf10267d34ca8f563d187c4655b73eb6020dd79c054b5'
|
||||
$jfxJmodsZip = '.\resources\jfxJmods.zip'
|
||||
if( !(Test-Path -Path $jfxJmodsZip) ) {
|
||||
$jmodsUrl = "https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_windows-x64_bin-jmods.zip"
|
||||
Write-Output "Downloading ${jmodsUrl}..."
|
||||
Invoke-WebRequest $jmodsUrl -OutFile $jfxJmodsZip # 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;
|
||||
$jmodsChecksumActual = $(Get-FileHash -Path $jfxJmodsZip -Algorithm SHA256).Hash
|
||||
if( $jmodsChecksumActual -ne $jfxJmodsChecksum ) {
|
||||
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $jfxJmodsChecksum, 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
|
||||
Expand-Archive -Force -Path $jfxJmodsZip -DestinationPath ".\resources\"
|
||||
|
||||
|
||||
## create custom runtime
|
||||
& "$Env:JAVA_HOME\bin\jlink" `
|
||||
--verbose `
|
||||
--output runtime `
|
||||
--module-path "$Env:JAVA_HOME/jmods;$buildDir/resources/javafx-jmods" `
|
||||
--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 `
|
||||
--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.crypto.ec,jdk.accessibility,jdk.management.jfr,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
|
||||
--strip-native-commands `
|
||||
--no-header-files `
|
||||
--no-man-pages `
|
||||
--strip-debug `
|
||||
--compress "zip-0" #do not compress to have improved msi compression
|
||||
--compress=1
|
||||
|
||||
$appPath = ".\$AppName"
|
||||
if ($clean -and (Test-Path -Path $appPath)) {
|
||||
@@ -100,7 +96,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
|
||||
--vendor $Vendor `
|
||||
--copyright $copyright `
|
||||
--java-options "--enable-preview" `
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" `
|
||||
--java-options "--enable-native-access=org.cryptomator.jfuse.win" `
|
||||
--java-options "-Xss5m" `
|
||||
--java-options "-Xmx256m" `
|
||||
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
|
||||
@@ -122,7 +118,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
|
||||
--icon resources/$AppName.ico
|
||||
|
||||
#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.fileTemplate=$buildDir\resources\licenseTemplate.ftl" `
|
||||
"-Dlicense.outputDirectory=$buildDir\resources\" `
|
||||
@@ -145,7 +141,6 @@ try {
|
||||
|
||||
# create .msi
|
||||
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
|
||||
$Env:JP_WIXHELPER_DIR = "."
|
||||
& "$Env:JAVA_HOME\bin\jpackage" `
|
||||
--verbose `
|
||||
--type msi `
|
||||
@@ -167,7 +162,7 @@ $Env:JP_WIXHELPER_DIR = "."
|
||||
--file-associations resources/FAvaultFile.properties
|
||||
|
||||
#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.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl" `
|
||||
"-Dlicense.outputDirectory=$buildDir\bundle\resources\" `
|
||||
@@ -177,15 +172,10 @@ $Env:JP_WIXHELPER_DIR = "."
|
||||
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges"
|
||||
|
||||
# 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}..."
|
||||
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-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi"
|
||||
|
||||
|
||||
45
dist/win/bundle/bundleWithWinfsp.wxs
vendored
45
dist/win/bundle/bundleWithWinfsp.wxs
vendored
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/-->
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html-->
|
||||
<!-- Attributes explicitly not used:
|
||||
@@ -11,10 +10,21 @@
|
||||
AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico">
|
||||
|
||||
<!-- detect outdated WinFsp installations -->
|
||||
<?include "resources\winFspMetaData.wxi" ?>
|
||||
<util:ProductSearch
|
||||
Variable="InstalledLegacyWinFspVersion"
|
||||
Variable="InstalledWinFspVersion"
|
||||
Result="version"
|
||||
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"/>
|
||||
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"
|
||||
/>
|
||||
<!-- Note: The bundle engine takes the Message format literaly -->
|
||||
<bal:Condition Message=
|
||||
"The WinFsp driver used by Cryptomator is outdated and must be removed before the installation.
|
||||
|
||||
1. Open the view of installed apps
|
||||
2. Search for "WinFsp"
|
||||
3. Uninstall the listed application
|
||||
4. Reboot your device
|
||||
5. Restart this installer">(InstalledWinFspVersion = v0.0.0.0) OR ($(var.BundledWinFspVersion) <= InstalledWinFspVersion)</bal:Condition>
|
||||
|
||||
<!-- for definition of the standard themes, see https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/-->
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
|
||||
@@ -26,41 +36,26 @@
|
||||
SuppressOptionsUI="yes"
|
||||
ThemeFile="bundle\customBootstrapperTheme.xml"
|
||||
LocalizationFile="bundle\customBootstrapperTheme.wxl"
|
||||
LogoFile="bundle\resources\logo.png"/>
|
||||
LogoFile="bundle\resources\logo.png"
|
||||
/>
|
||||
<Payload SourceFile="bundle\resources\logoSide.png" />
|
||||
</BootstrapperApplicationRef>
|
||||
|
||||
<Chain>
|
||||
<ExePackage Cache="yes" PerMachine="yes" Permanent="no"
|
||||
SourceFile="resources\winfsp-uninstaller.exe"
|
||||
DisplayName="Removing outdated WinFsp Driver"
|
||||
Description="Executable to remove old winfsp"
|
||||
DetectCondition="false"
|
||||
InstallCondition="(InstalledLegacyWinFspVersion <> v0.0.0.0) AND ((WixBundleAction = 7) OR (WixBundleAction = 5))">
|
||||
<CommandLine Condition="WixBundleUILevel <= 3" InstallArgument="-q -l "[WixBundleLog].winfsp-uninstaller.log"" RepairArgument="-q" UninstallArgument="-s" />
|
||||
<!-- XML allows line breaks in attributes, hence keep the line breaks here -->
|
||||
<CommandLine Condition="WixBundleUILevel > 3" InstallArgument="-l "[WixBundleLog].winfsp-uninstaller.log" -t "Cryptomator Installer" -m "Cryptomator requires a newer version of the WinFsp driver. The installer will now uninstall WinFsp, possibly reboot, and afterwards proceed with the installation.
|
||||
|
||||
Do you want to continue?"" RepairArgument="-q" UninstallArgument="-s" />
|
||||
<ExitCode Behavior="success" Value="0"/>
|
||||
<ExitCode Behavior="success" Value="1"/>
|
||||
<ExitCode Behavior="error" Value="2"/>
|
||||
<ExitCode Behavior="error" Value="3"/>
|
||||
<ExitCode Behavior="forceReboot" Value="4"/>
|
||||
<ExitCode Behavior="success" Value="5"/>
|
||||
</ExePackage>
|
||||
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/msipackage.html-->
|
||||
<MsiPackage
|
||||
SourceFile="resources\Cryptomator.msi"
|
||||
CacheId="cryptomator-bundle-cryptomator"
|
||||
DisplayInternalUI="no"
|
||||
Visible="no"/>
|
||||
Visible="no"
|
||||
/>
|
||||
<MsiPackage
|
||||
SourceFile="resources\winfsp.msi"
|
||||
CacheId="cryptomator-bundle-winfsp"
|
||||
Visible="yes"
|
||||
DisplayInternalUI="no"
|
||||
Permanent="yes"/>
|
||||
Vital="no"
|
||||
Permanent="yes"
|
||||
/>
|
||||
</Chain>
|
||||
</Bundle>
|
||||
</Wix>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
\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
|
||||
\par
|
||||
\b\'a9 2016 \'96 2025 Skymatic GmbH \b0\par
|
||||
\b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
|
||||
\par
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
|
||||
\par
|
||||
|
||||
7
dist/win/bundle/resources/winFspMetaData.wxi
vendored
Normal file
7
dist/win/bundle/resources/winFspMetaData.wxi
vendored
Normal 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>
|
||||
BIN
dist/win/contrib/dokan1.dll
vendored
Executable file
BIN
dist/win/contrib/dokan1.dll
vendored
Executable file
Binary file not shown.
2
dist/win/contrib/patchWebDAV.bat
vendored
2
dist/win/contrib/patchWebDAV.bat
vendored
@@ -3,5 +3,5 @@
|
||||
::REPLACE ME
|
||||
|
||||
cd %~dp0
|
||||
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command .\patchWebDAV.ps1^
|
||||
powershell -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -Command .\patchWebDAV.ps1^
|
||||
-LoopbackAlias %LOOPBACK_ALIAS%
|
||||
5
dist/win/contrib/version170-migrate-settings.bat
vendored
Normal file
5
dist/win/contrib/version170-migrate-settings.bat
vendored
Normal 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
dist/win/contrib/version170-migrate-settings.ps1
vendored
Normal file
35
dist/win/contrib/version170-migrate-settings.ps1
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
2
dist/win/resources/licenseTemplate.ftl
vendored
2
dist/win/resources/licenseTemplate.ftl
vendored
@@ -10,7 +10,7 @@
|
||||
\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
|
||||
\par
|
||||
\b\'a9 2016 \'96 2025 Skymatic GmbH \b0\par
|
||||
\b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
|
||||
\par
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
|
||||
\par
|
||||
|
||||
12
dist/win/resources/main.wxs
vendored
12
dist/win/resources/main.wxs
vendored
@@ -70,7 +70,7 @@
|
||||
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
|
||||
<?endif?>
|
||||
|
||||
<Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll"/>
|
||||
<Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
|
||||
<CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" />
|
||||
|
||||
<?ifndef SkipCryptomatorLegacyCheck ?>
|
||||
@@ -132,12 +132,11 @@
|
||||
<CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
|
||||
<?endif?>
|
||||
|
||||
<Property Id="WixQuietExec64CmdTimeout" Value="20" />
|
||||
<!-- Note for custom actions: Immediate CAs run BEFORE the files are installed, hence if you depend on installed files, the CAs must be deferred.-->
|
||||
<!-- WebDAV patches -->
|
||||
<SetProperty Id="PatchWebDAV" Value=""[INSTALLDIR]patchWebDAV.bat""
|
||||
Sequence="execute" Before="PatchWebDAV" />
|
||||
<CustomAction Id="PatchWebDAV" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
|
||||
<CustomAction Id="PatchWebDAV" Impersonate="no" ExeCommand="[INSTALLDIR]patchWebDAV.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" />
|
||||
|
||||
<!-- 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 -->
|
||||
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
|
||||
@@ -190,6 +189,7 @@
|
||||
<RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications -->
|
||||
|
||||
<Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
|
||||
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<InstallUISequence>
|
||||
|
||||
165
pom.xml
165
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>cryptomator</artifactId>
|
||||
<version>1.16.0-SNAPSHOT</version>
|
||||
<version>1.10.0-SNAPSHOT</version>
|
||||
<name>Cryptomator Desktop App</name>
|
||||
|
||||
<organization>
|
||||
@@ -26,62 +26,49 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.jdk.version>23</project.jdk.version>
|
||||
<project.jdk.version>20</project.jdk.version>
|
||||
|
||||
<!-- 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) -->
|
||||
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds>
|
||||
<!-- Once hypfvieh, swiesend, purejava and integrations-linux have module-info, remove them-->
|
||||
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
|
||||
|
||||
<!-- cryptomator dependencies -->
|
||||
<cryptomator.cryptofs.version>2.8.0</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.5.0</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.3.0</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.2.4</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.5.2</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>5.0.2</cryptomator.fuse.version>
|
||||
<cryptomator.webdav.version>2.0.7</cryptomator.webdav.version>
|
||||
<cryptomator.cryptofs.version>2.6.6</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.2.0</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.2.0</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.2.0</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.2.1</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>3.0.0</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>2.0.0</cryptomator.dokany.version>
|
||||
<cryptomator.webdav.version>2.0.3</cryptomator.webdav.version>
|
||||
|
||||
<!-- 3rd party dependencies -->
|
||||
<commons-lang3.version>3.17.0</commons-lang3.version>
|
||||
<dagger.version>2.55</dagger.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<dagger.version>2.45</dagger.version>
|
||||
<easybind.version>2.2</easybind.version>
|
||||
<jackson.version>2.18.2</jackson.version>
|
||||
<javafx.version>23.0.1</javafx.version>
|
||||
<guava.version>32.0.1-jre</guava.version>
|
||||
<jackson.version>2.15.2</jackson.version>
|
||||
<javafx.version>20.0.1</javafx.version>
|
||||
<jwt.version>4.4.0</jwt.version>
|
||||
<nimbus-jose.version>9.37.3</nimbus-jose.version>
|
||||
<logback.version>1.5.16</logback.version>
|
||||
<slf4j.version>2.0.16</slf4j.version>
|
||||
<tinyoauth2.version>0.8.0</tinyoauth2.version>
|
||||
<zxcvbn.version>1.9.0</zxcvbn.version>
|
||||
<nimbus-jose.version>9.31</nimbus-jose.version>
|
||||
<logback.version>1.4.7</logback.version>
|
||||
<slf4j.version>2.0.7</slf4j.version>
|
||||
<tinyoauth2.version>0.5.1</tinyoauth2.version>
|
||||
<zxcvbn.version>1.7.0</zxcvbn.version>
|
||||
|
||||
<!-- test dependencies -->
|
||||
<junit.jupiter.version>5.11.4</junit.jupiter.version>
|
||||
<mockito.version>5.15.2</mockito.version>
|
||||
<hamcrest.version>3.0</hamcrest.version>
|
||||
<junit.jupiter.version>5.9.3</junit.jupiter.version>
|
||||
<mockito.version>5.3.1</mockito.version>
|
||||
<hamcrest.version>2.2</hamcrest.version>
|
||||
|
||||
<!-- build-time dependencies -->
|
||||
<jetbrains.annotations.version>26.0.1</jetbrains.annotations.version>
|
||||
<dependency-check.version>12.0.1</dependency-check.version>
|
||||
<jacoco.version>0.8.12</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.13.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.2</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>
|
||||
<jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
|
||||
<dependency-check.version>8.1.2</dependency-check.version>
|
||||
<jacoco.version>0.8.9</jacoco.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Cryptomator Libs -->
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>cryptolib</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>cryptofs</artifactId>
|
||||
@@ -92,6 +79,11 @@
|
||||
<artifactId>fuse-nio-adapter</artifactId>
|
||||
<version>${cryptomator.fuse.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>dokany-nio-adapter</artifactId>
|
||||
<version>${cryptomator.dokany.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>webdav-nio-adapter</artifactId>
|
||||
@@ -165,18 +157,11 @@
|
||||
<artifactId>nimbus-jose-jwt</artifactId>
|
||||
<version>${nimbus-jose.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- EasyBind -->
|
||||
<dependency>
|
||||
@@ -193,23 +178,40 @@
|
||||
</dependency>
|
||||
|
||||
<!-- 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>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger</artifactId>
|
||||
<version>${dagger.version}</version>
|
||||
</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 -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
@@ -238,7 +240,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.jimfs</groupId>
|
||||
<artifactId>jimfs</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -256,32 +258,32 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${mvn-compiler.version}</version>
|
||||
<version>3.10.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>${mvn-resources.version}</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>${mvn-dependency.version}</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${mvn-surefire.version}</version>
|
||||
<version>3.0.0-M7</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>${license-generator.version}</version>
|
||||
<version>2.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${mvn-jar.version}</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
@@ -311,6 +313,7 @@
|
||||
<compilerArgs>
|
||||
<arg>-Adagger.fastInit=enabled</arg>
|
||||
<arg>-Adagger.formatGeneratedSource=enabled</arg>
|
||||
<arg>--enable-preview</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -329,35 +332,14 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<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>
|
||||
<reportFormat>plain</reportFormat>
|
||||
<consoleOutputReporter>
|
||||
<disable>true</disable>
|
||||
</consoleOutputReporter>
|
||||
<argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar}</argLine>
|
||||
<statelessTestsetInfoReporter
|
||||
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
|
||||
</statelessTestsetInfoReporter>
|
||||
<argLine>--enable-preview</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<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 -->
|
||||
<execution>
|
||||
<id>copy-mods</id>
|
||||
@@ -430,9 +412,6 @@
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<propertyName>surefire.jacoco.args</propertyName>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
@@ -460,19 +439,17 @@
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<configuration>
|
||||
<nvdValidForHours>24</nvdValidForHours>
|
||||
<cveValidForHours>24</cveValidForHours>
|
||||
<failBuildOnCVSS>0</failBuildOnCVSS>
|
||||
<skipTestScope>true</skipTestScope>
|
||||
<detail>true</detail>
|
||||
<suppressionFile>suppression.xml</suppressionFile>
|
||||
<nvdApiKeyEnvironmentVariable>NVD_API_KEY</nvdApiKeyEnvironmentVariable>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<phase>validate</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import ch.qos.logback.classic.spi.Configurator;
|
||||
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
|
||||
import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.GoogleDriveMacLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.GoogleDriveWindowsLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.GoogleDriveLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.ICloudMacLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.ICloudWindowsLocationPresetsProvider;
|
||||
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.OneDriveWindowsLocationPresetsProvider;
|
||||
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.logging.LogbackConfiguratorFactory;
|
||||
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
||||
@@ -26,6 +21,7 @@ open module org.cryptomator.desktop {
|
||||
|
||||
requires org.cryptomator.cryptolib;
|
||||
requires org.cryptomator.cryptofs;
|
||||
requires org.cryptomator.frontend.dokany;
|
||||
requires org.cryptomator.frontend.fuse;
|
||||
requires org.cryptomator.frontend.webdav;
|
||||
requires org.cryptomator.integrations.api;
|
||||
@@ -36,13 +32,13 @@ open module org.cryptomator.desktop {
|
||||
requires javafx.graphics;
|
||||
requires javafx.controls;
|
||||
requires javafx.fxml;
|
||||
requires jdk.crypto.ec;
|
||||
// 3rd party:
|
||||
requires ch.qos.logback.classic;
|
||||
requires ch.qos.logback.core;
|
||||
requires com.auth0.jwt;
|
||||
requires com.google.common;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires com.fasterxml.jackson.datatype.jsr310;
|
||||
requires com.nimbusds.jose.jwt;
|
||||
requires com.nulabinc.zxcvbn;
|
||||
requires com.tobiasdiez.easybind;
|
||||
@@ -51,21 +47,16 @@ open module org.cryptomator.desktop {
|
||||
requires org.slf4j;
|
||||
requires org.apache.commons.lang3;
|
||||
|
||||
/* dagger bs */
|
||||
requires jakarta.inject;
|
||||
requires static javax.inject;
|
||||
requires java.compiler;
|
||||
requires com.github.benmanes.caffeine;
|
||||
/* TODO: filename-based modules: */
|
||||
requires static javax.inject; /* ugly dagger/guava crap */
|
||||
|
||||
uses org.cryptomator.common.locationpresets.LocationPresetsProvider;
|
||||
uses SSLContextProvider;
|
||||
|
||||
provides TrayMenuController with AwtTrayMenuController;
|
||||
provides Configurator with LogbackConfiguratorFactory;
|
||||
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;
|
||||
provides LocationPresetsProvider with //
|
||||
DropboxWindowsLocationPresetsProvider, DropboxMacLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, //
|
||||
GoogleDriveMacLocationPresetsProvider, GoogleDriveWindowsLocationPresetsProvider, //
|
||||
GoogleDriveLocationPresetsProvider, //
|
||||
ICloudWindowsLocationPresetsProvider, ICloudMacLocationPresetsProvider, //
|
||||
LeitzcloudLocationPresetsProvider, //
|
||||
MegaLocationPresetsProvider, //
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.common;
|
||||
|
||||
import com.tobiasdiez.easybind.EasyBind;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.keychain.KeychainModule;
|
||||
import org.cryptomator.common.mount.MountModule;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
@@ -20,6 +22,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Comparator;
|
||||
@@ -132,4 +136,13 @@ public abstract class CommonsModule {
|
||||
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.Strings;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -32,7 +31,6 @@ public class Environment {
|
||||
private static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
|
||||
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
|
||||
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
|
||||
private static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
|
||||
|
||||
private Environment() {}
|
||||
|
||||
@@ -45,16 +43,15 @@ public class Environment {
|
||||
logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
|
||||
logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
|
||||
logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
|
||||
logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
|
||||
logCryptomatorSystemProperty(LOG_DIR_PROP_NAME);
|
||||
logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME);
|
||||
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
|
||||
logCryptomatorSystemProperty(MOUNTPOINT_DIR_PROP_NAME);
|
||||
logCryptomatorSystemProperty(MIN_PW_LENGTH_PROP_NAME);
|
||||
logCryptomatorSystemProperty(APP_VERSION_PROP_NAME);
|
||||
logCryptomatorSystemProperty(BUILD_NUMBER_PROP_NAME);
|
||||
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
|
||||
logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
|
||||
logCryptomatorSystemProperty(DISABLE_UPDATE_CHECK_PROP_NAME);
|
||||
logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
|
||||
}
|
||||
|
||||
public static Environment getInstance() {
|
||||
@@ -77,6 +74,10 @@ public class Environment {
|
||||
return getPaths(SETTINGS_PATH_PROP_NAME);
|
||||
}
|
||||
|
||||
public Stream<Path> getP12Path() {
|
||||
return getPaths(P12_PATH_PROP_NAME);
|
||||
}
|
||||
|
||||
public Stream<Path> getIpcSocketPath() {
|
||||
return getPaths(IPC_SOCKET_PATH_PROP_NAME);
|
||||
}
|
||||
@@ -85,10 +86,6 @@ public class Environment {
|
||||
return getPaths(KEYCHAIN_PATHS_PROP_NAME);
|
||||
}
|
||||
|
||||
public Stream<Path> getP12Path() {
|
||||
return getPaths(P12_PATH_PROP_NAME);
|
||||
}
|
||||
|
||||
public Optional<Path> getLogDir() {
|
||||
return getPath(LOG_DIR_PROP_NAME);
|
||||
}
|
||||
@@ -97,12 +94,12 @@ public class Environment {
|
||||
return Optional.ofNullable(System.getProperty(LOOPBACK_ALIAS_PROP_NAME));
|
||||
}
|
||||
|
||||
public Optional<Path> getMountPointsDir() {
|
||||
return getPath(MOUNTPOINT_DIR_PROP_NAME);
|
||||
public Optional<Path> getPluginDir() {
|
||||
return getPath(PLUGIN_DIR_PROP_NAME);
|
||||
}
|
||||
|
||||
public int getMinPwLength() {
|
||||
return Integer.getInteger(MIN_PW_LENGTH_PROP_NAME, DEFAULT_MIN_PW_LENGTH);
|
||||
public Optional<Path> getMountPointsDir() {
|
||||
return getPath(MOUNTPOINT_DIR_PROP_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,24 +115,20 @@ public class Environment {
|
||||
return Optional.ofNullable(System.getProperty(BUILD_NUMBER_PROP_NAME));
|
||||
}
|
||||
|
||||
public Optional<Path> getPluginDir() {
|
||||
return getPath(PLUGIN_DIR_PROP_NAME);
|
||||
public int getMinPwLength() {
|
||||
return Integer.getInteger(MIN_PW_LENGTH_PROP_NAME, DEFAULT_MIN_PW_LENGTH);
|
||||
}
|
||||
|
||||
public boolean showTrayIcon() {
|
||||
return Boolean.getBoolean(TRAY_ICON_PROP_NAME);
|
||||
}
|
||||
|
||||
public boolean disableUpdateCheck() {
|
||||
return Boolean.getBoolean(DISABLE_UPDATE_CHECK_PROP_NAME);
|
||||
}
|
||||
|
||||
private Optional<Path> getPath(String propertyName) {
|
||||
String value = System.getProperty(propertyName);
|
||||
return Optional.ofNullable(value).map(Paths::get);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
// visible for testing
|
||||
Stream<Path> getPaths(String propertyName) {
|
||||
Stream<String> rawSettingsPaths = getRawList(propertyName, System.getProperty("path.separator").charAt(0));
|
||||
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.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.Locale;
|
||||
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>
|
||||
* @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) {
|
||||
if (allFrames.length < bottomFrames.length) {
|
||||
// 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) {
|
||||
Preconditions.checkArgument(set.length >= subset.length);
|
||||
// iterate items backwards as long as they are identical
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.cryptomator.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public record Hyperlinks(String docsVolumeType, String docsGettingStarted, String homepageHub) {
|
||||
|
||||
private static final ObjectMapper JSON_DESERIALIZER = new ObjectMapper();
|
||||
/*
|
||||
String docsAccessingVaults;
|
||||
String docsExpertSettings;
|
||||
String docsManualMigration;
|
||||
String homepageDownload;
|
||||
String homepageHub;
|
||||
String homepageDonate;
|
||||
String homepageSponsors;
|
||||
String storeDesktop;
|
||||
*/
|
||||
|
||||
|
||||
public static Hyperlinks load() {
|
||||
try {
|
||||
return JSON_DESERIALIZER.readValue(Hyperlinks.class.getResource("/hyperlinks.json"), Hyperlinks.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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);
|
||||
return "";
|
||||
} else {
|
||||
return Matcher.quoteReplacement(val);
|
||||
return val.replace("\\", "\\\\");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package org.cryptomator.common.keychain;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import org.cryptomator.integrations.keychain.KeychainAccessException;
|
||||
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
|
||||
|
||||
@@ -23,9 +24,9 @@ public class KeychainManager implements KeychainAccessProvider {
|
||||
@Inject
|
||||
KeychainManager(ObjectExpression<KeychainAccessProvider> selectedKeychain) {
|
||||
this.keychain = selectedKeychain;
|
||||
this.passphraseStoredProperties = Caffeine.newBuilder() //
|
||||
this.passphraseStoredProperties = CacheBuilder.newBuilder() //
|
||||
.weakValues() //
|
||||
.build(this::createStoredPassphraseProperty);
|
||||
.build(CacheLoader.from(this::createStoredPassphraseProperty));
|
||||
keychain.addListener(ignored -> passphraseStoredProperties.invalidateAll());
|
||||
}
|
||||
|
||||
@@ -43,7 +44,7 @@ public class KeychainManager implements KeychainAccessProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean ignored) throws KeychainAccessException {
|
||||
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
|
||||
getKeychainOrFail().storePassphrase(key, displayName, passphrase);
|
||||
setPassphraseStored(key, true);
|
||||
}
|
||||
@@ -123,7 +124,7 @@ public class KeychainManager implements KeychainAccessProvider {
|
||||
* @see #isPassphraseStored(String)
|
||||
*/
|
||||
public ReadOnlyBooleanProperty getPassphraseStoredProperty(String key) {
|
||||
return passphraseStoredProperties.get(key);
|
||||
return passphraseStoredProperties.getUnchecked(key);
|
||||
}
|
||||
|
||||
private BooleanProperty createStoredPassphraseProperty(String key) {
|
||||
|
||||
@@ -9,11 +9,13 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
||||
|
||||
@OperatingSystem(WINDOWS)
|
||||
@OperatingSystem(MAC)
|
||||
@CheckAvailability
|
||||
public final class GoogleDriveWindowsLocationPresetsProvider implements LocationPresetsProvider {
|
||||
public final class GoogleDriveLocationPresetsProvider implements LocationPresetsProvider {
|
||||
|
||||
private static final List<Path> LOCATIONS = Arrays.asList( //
|
||||
LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive"), //
|
||||
@@ -35,4 +37,5 @@ public final class GoogleDriveWindowsLocationPresetsProvider implements Location
|
||||
.findFirst() //
|
||||
.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 project’s 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);
|
||||
Process p = command.start();
|
||||
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");
|
||||
}
|
||||
if (process.exitValue() != 0) {
|
||||
@SuppressWarnings("resource") var stdout = process.inputReader(StandardCharsets.ISO_8859_1).lines().collect(Collectors.joining("\n"));
|
||||
@SuppressWarnings("resource") var stderr = process.errorReader(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.UTF_8).lines().collect(Collectors.joining("\n"));
|
||||
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;
|
||||
|
||||
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 {
|
||||
|
||||
private final Path mountpoint;
|
||||
|
||||
public IllegalMountPointException(Path mountpoint) {
|
||||
this(mountpoint, "The provided mountpoint has a problem: " + mountpoint.toString());
|
||||
}
|
||||
|
||||
public IllegalMountPointException(Path mountpoint, String msg) {
|
||||
public IllegalMountPointException(String msg) {
|
||||
super(msg);
|
||||
this.mountpoint = mountpoint;
|
||||
}
|
||||
|
||||
public Path getMountpoint() {
|
||||
return mountpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,21 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.common.ObservableUtil;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.integrations.mount.Mount;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Module
|
||||
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
|
||||
@Singleton
|
||||
static List<MountService> provideSupportedMountServices() {
|
||||
@@ -24,18 +27,46 @@ public class MountModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static ObservableValue<MountService> provideDefaultMountService(List<MountService> mountProviders, Settings settings) {
|
||||
var fallbackProvider = mountProviders.stream().findFirst().get(); //there should always be a mount provider, at least webDAV
|
||||
return ObservableUtil.mapWithDefault(settings.mountService, //
|
||||
serviceName -> mountProviders.stream().filter(s -> s.getClass().getName().equals(serviceName)).findFirst().orElse(fallbackProvider), //
|
||||
fallbackProvider);
|
||||
@Named("FUPFMS")
|
||||
static AtomicReference<MountService> provideFirstUsedProblematicFuseMountService() {
|
||||
return new AtomicReference<>(null);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("usedMountServices")
|
||||
static Set<MountService> provideSetOfUsedMountServices() {
|
||||
return ConcurrentHashMap.newKeySet();
|
||||
static ObservableValue<ActualMountService> provideMountService(Settings settings, List<MountService> serviceImpls, @Named("FUPFMS") AtomicReference<MountService> fupfms) {
|
||||
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
|
||||
|
||||
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;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class MountPointInUseException extends IllegalMountPointException {
|
||||
|
||||
public MountPointInUseException(Path path) {
|
||||
super(path);
|
||||
public MountPointInUseException(String msg) {
|
||||
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;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class MountPointNotSupportedException extends IllegalMountPointException {
|
||||
|
||||
public MountPointNotSupportedException(Path path, String msg) {
|
||||
super(path, msg);
|
||||
public MountPointNotSupportedException(String 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;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryNotEmptyException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.NotDirectoryException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
|
||||
public final class MountWithinParentUtil {
|
||||
|
||||
@@ -21,33 +22,31 @@ public final class MountWithinParentUtil {
|
||||
|
||||
private MountWithinParentUtil() {}
|
||||
|
||||
static void prepareParentNoMountPoint(Path mountPoint) throws IllegalMountPointException, IOException {
|
||||
static void prepareParentNoMountPoint(Path mountPoint) throws MountPointPreparationException {
|
||||
Path hideaway = getHideaway(mountPoint);
|
||||
var mpState = getMountPointState(mountPoint);
|
||||
var mpExists = Files.exists(mountPoint, LinkOption.NOFOLLOW_LINKS);
|
||||
var hideExists = Files.exists(hideaway, LinkOption.NOFOLLOW_LINKS);
|
||||
|
||||
if (mpState == MountPointState.BROKEN_JUNCTION) {
|
||||
LOG.info("Mountpoint \"{}\" is still a junction. Deleting it.", mountPoint);
|
||||
Files.delete(mountPoint); //Throws if mountPoint is also a non-empty folder
|
||||
mpState = MountPointState.NOT_EXISTING;
|
||||
}
|
||||
|
||||
if (mpState == MountPointState.NOT_EXISTING && !hideExists) { //neither mountpoint nor hideaway exist
|
||||
throw new MountPointNotExistingException(mountPoint);
|
||||
} else if (mpState == MountPointState.NOT_EXISTING) { //only hideaway exists
|
||||
checkIsHideawayDirectory(mountPoint, hideaway);
|
||||
//TODO: possible improvement by just deleting an _empty_ hideaway
|
||||
if (mpExists && hideExists) { //both resources exist (whatever type)
|
||||
throw new MountPointPreparationException(new FileAlreadyExistsException(hideaway.toString()));
|
||||
} else if (!mpExists && !hideExists) { //neither mountpoint nor hideaway exist
|
||||
throw new MountPointPreparationException(new NoSuchFileException(mountPoint.toString()));
|
||||
} else if (!mpExists) { //only hideaway exists
|
||||
checkIsDirectory(hideaway);
|
||||
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 {
|
||||
if (hideExists) { //... with hideaway
|
||||
removeResidualHideaway(mountPoint, hideaway);
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
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);
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS);
|
||||
@@ -55,66 +54,30 @@ public final class MountWithinParentUtil {
|
||||
int attempts = 0;
|
||||
while (!Files.notExists(mountPoint)) {
|
||||
if (attempts >= 10) {
|
||||
throw new MountPointCleanupFailedException(mountPoint);
|
||||
throw new MountPointPreparationException("Path " + mountPoint + " could not be cleared");
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new MountPointPreparationException(e);
|
||||
} catch (InterruptedException e) {
|
||||
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) {
|
||||
Path hideaway = getHideaway(mountPoint);
|
||||
try {
|
||||
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);
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
Files.setAttribute(mountPoint, WIN_HIDDEN_ATTR, false);
|
||||
}
|
||||
} 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)) {
|
||||
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) {
|
||||
if (!Files.isDirectory(hideawayToCheck, LinkOption.NOFOLLOW_LINKS)) {
|
||||
throw new HideawayNotDirectoryException(mountPoint, hideawayToCheck);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkIsMountPointEmpty(Path toCheck) throws IllegalMountPointException, IOException {
|
||||
private static void checkIsEmpty(Path toCheck) throws MountPointPreparationException, IOException {
|
||||
try (var dirStream = Files.list(toCheck)) {
|
||||
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) {
|
||||
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.MountFailedException;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
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_TO_EXISTING_DIR;
|
||||
@@ -30,41 +24,24 @@ import static org.cryptomator.integrations.mount.MountCapability.UNMOUNT_FORCED;
|
||||
@Singleton
|
||||
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 Environment env;
|
||||
private final WindowsDriveLetters driveLetters;
|
||||
private final List<MountService> mountProviders;
|
||||
private final Set<MountService> usedMountServices;
|
||||
private final ObservableValue<MountService> defaultMountService;
|
||||
private final ObservableValue<ActualMountService> mountServiceObservable;
|
||||
|
||||
@Inject
|
||||
public Mounter(Environment env, //
|
||||
Settings settings, //
|
||||
WindowsDriveLetters driveLetters, //
|
||||
List<MountService> mountProviders, //
|
||||
@Named("usedMountServices") Set<MountService> usedMountServices, //
|
||||
ObservableValue<MountService> defaultMountService) {
|
||||
this.env = env;
|
||||
public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue<ActualMountService> mountServiceObservable) {
|
||||
this.settings = settings;
|
||||
this.env = env;
|
||||
this.driveLetters = driveLetters;
|
||||
this.mountProviders = mountProviders;
|
||||
this.usedMountServices = usedMountServices;
|
||||
this.defaultMountService = defaultMountService;
|
||||
this.mountServiceObservable = mountServiceObservable;
|
||||
}
|
||||
|
||||
private class SettledMounter {
|
||||
|
||||
private final MountService service;
|
||||
private final MountBuilder builder;
|
||||
private final VaultSettings vaultSettings;
|
||||
private MountService service;
|
||||
private MountBuilder builder;
|
||||
private VaultSettings vaultSettings;
|
||||
|
||||
public SettledMounter(MountService service, MountBuilder builder, VaultSettings vaultSettings) {
|
||||
this.service = service;
|
||||
@@ -76,13 +53,8 @@ public class Mounter {
|
||||
for (var capability : service.capabilities()) {
|
||||
switch (capability) {
|
||||
case FILE_SYSTEM_NAME -> builder.setFileSystemName("cryptoFs");
|
||||
case LOOPBACK_PORT -> {
|
||||
if (vaultSettings.mountService.getValue() == null) {
|
||||
builder.setLoopbackPort(settings.port.get());
|
||||
} else {
|
||||
builder.setLoopbackPort(vaultSettings.port.get());
|
||||
}
|
||||
}
|
||||
case LOOPBACK_PORT ->
|
||||
builder.setLoopbackPort(settings.port.get()); //TODO: move port from settings to vaultsettings (see https://github.com/cryptomator/cryptomator/tree/feature/mount-setting-per-vault)
|
||||
case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName);
|
||||
case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode.get());
|
||||
case MOUNT_FLAGS -> {
|
||||
@@ -127,11 +99,13 @@ public class Mounter {
|
||||
var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\");
|
||||
if (mpIsDriveLetter) {
|
||||
if (driveLetters.getOccupied().contains(userChosenMountPoint)) {
|
||||
throw new MountPointInUseException(userChosenMountPoint);
|
||||
throw new MountPointInUseException(userChosenMountPoint.toString());
|
||||
}
|
||||
} else if (canMountToParent && !canMountToDir) {
|
||||
MountWithinParentUtil.prepareParentNoMountPoint(userChosenMountPoint);
|
||||
cleanup = () -> MountWithinParentUtil.cleanup(userChosenMountPoint);
|
||||
cleanup = () -> {
|
||||
MountWithinParentUtil.cleanup(userChosenMountPoint);
|
||||
};
|
||||
}
|
||||
try {
|
||||
builder.setMountpoint(userChosenMountPoint);
|
||||
@@ -141,13 +115,13 @@ public class Mounter {
|
||||
|| (!canMountToParent && !mpIsDriveLetter) //
|
||||
|| (!canMountToDir && !canMountToParent && !canMountToSystem && !canMountToDriveLetter);
|
||||
if (configNotSupported) {
|
||||
throw new MountPointNotSupportedException(userChosenMountPoint, e.getMessage());
|
||||
throw new MountPointNotSupportedException(e.getMessage());
|
||||
} else if (canMountToDir && !canMountToParent && !Files.exists(userChosenMountPoint)) {
|
||||
//mountpoint must exist
|
||||
throw new MountPointNotExistingException(userChosenMountPoint, e.getMessage());
|
||||
throw new MountPointNotExistsException(e.getMessage());
|
||||
} else {
|
||||
//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 {
|
||||
var mountService = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defaultMountService.getValue());
|
||||
|
||||
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 mountService = this.mountServiceObservable.getValue().service();
|
||||
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();
|
||||
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) {
|
||||
|
||||
}
|
||||
|
||||
@@ -25,33 +25,30 @@ import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.NodeOrientation;
|
||||
import java.time.Instant;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Settings {
|
||||
|
||||
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_START_HIDDEN = false;
|
||||
static final boolean DEFAULT_AUTO_CLOSE_VAULTS = false;
|
||||
static final boolean DEFAULT_USE_KEYCHAIN = true;
|
||||
static final boolean DEFAULT_USE_QUICKACCESS = true;
|
||||
static final int DEFAULT_PORT = 42427;
|
||||
static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
|
||||
static final boolean DEFAULT_DEBUG_MODE = false;
|
||||
static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
|
||||
@Deprecated // to be changed to "whatever is available" eventually
|
||||
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";
|
||||
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_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";
|
||||
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 BooleanProperty askedForUpdateCheck;
|
||||
public final BooleanProperty checkForUpdates;
|
||||
public final BooleanProperty startHidden;
|
||||
public final BooleanProperty autoCloseVaults;
|
||||
public final BooleanProperty useKeychain;
|
||||
@@ -60,21 +57,18 @@ public class Settings {
|
||||
public final BooleanProperty debugMode;
|
||||
public final ObjectProperty<UiTheme> theme;
|
||||
public final StringProperty keychainProvider;
|
||||
public final BooleanProperty useQuickAccess;
|
||||
public final StringProperty quickAccessService;
|
||||
public final ObjectProperty<NodeOrientation> userInterfaceOrientation;
|
||||
public final StringProperty licenseKey;
|
||||
public final BooleanProperty showMinimizeButton;
|
||||
public final BooleanProperty showTrayIcon;
|
||||
public final BooleanProperty compactMode;
|
||||
public final IntegerProperty windowXPosition;
|
||||
public final IntegerProperty windowYPosition;
|
||||
public final IntegerProperty windowWidth;
|
||||
public final IntegerProperty windowHeight;
|
||||
public final StringProperty displayConfiguration;
|
||||
public final StringProperty language;
|
||||
public final StringProperty mountService;
|
||||
public final BooleanProperty checkForUpdates;
|
||||
public final ObjectProperty<Instant> lastUpdateCheckReminder;
|
||||
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
|
||||
public final StringProperty lastUpdateCheck;
|
||||
|
||||
private Consumer<Settings> saveCmd;
|
||||
|
||||
@@ -91,10 +85,11 @@ public class Settings {
|
||||
*/
|
||||
Settings(SettingsJson json) {
|
||||
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.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults);
|
||||
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.numTrayNotifications = new SimpleIntegerProperty(this, "numTrayNotifications", json.numTrayNotifications);
|
||||
this.debugMode = new SimpleBooleanProperty(this, "debugMode", json.debugMode);
|
||||
@@ -102,28 +97,27 @@ public class Settings {
|
||||
this.keychainProvider = new SimpleStringProperty(this, "keychainProvider", json.keychainProvider);
|
||||
this.userInterfaceOrientation = new SimpleObjectProperty<>(this, "userInterfaceOrientation", parseEnum(json.uiOrientation, NodeOrientation.class, NodeOrientation.LEFT_TO_RIGHT));
|
||||
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.compactMode = new SimpleBooleanProperty(this, "compactMode", json.compactMode);
|
||||
this.windowXPosition = new SimpleIntegerProperty(this, "windowXPosition", json.windowXPosition);
|
||||
this.windowYPosition = new SimpleIntegerProperty(this, "windowYPosition", json.windowYPosition);
|
||||
this.windowWidth = new SimpleIntegerProperty(this, "windowWidth", json.windowWidth);
|
||||
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.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
|
||||
this.quickAccessService = new SimpleStringProperty(this, "quickAccessService", json.quickAccessService);
|
||||
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.lastUpdateCheck = new SimpleStringProperty(this, "lastUpdateCheck", json.lastUpdateCheck);
|
||||
|
||||
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
|
||||
|
||||
migrateLegacySettings(json);
|
||||
|
||||
directories.addListener(this::somethingChanged);
|
||||
askedForUpdateCheck.addListener(this::somethingChanged);
|
||||
checkForUpdates.addListener(this::somethingChanged);
|
||||
startHidden.addListener(this::somethingChanged);
|
||||
autoCloseVaults.addListener(this::somethingChanged);
|
||||
useKeychain.addListener(this::somethingChanged);
|
||||
useQuickAccess.addListener(this::somethingChanged);
|
||||
port.addListener(this::somethingChanged);
|
||||
numTrayNotifications.addListener(this::somethingChanged);
|
||||
debugMode.addListener(this::somethingChanged);
|
||||
@@ -131,18 +125,16 @@ public class Settings {
|
||||
keychainProvider.addListener(this::somethingChanged);
|
||||
userInterfaceOrientation.addListener(this::somethingChanged);
|
||||
licenseKey.addListener(this::somethingChanged);
|
||||
showMinimizeButton.addListener(this::somethingChanged);
|
||||
showTrayIcon.addListener(this::somethingChanged);
|
||||
compactMode.addListener(this::somethingChanged);
|
||||
windowXPosition.addListener(this::somethingChanged);
|
||||
windowYPosition.addListener(this::somethingChanged);
|
||||
windowWidth.addListener(this::somethingChanged);
|
||||
windowHeight.addListener(this::somethingChanged);
|
||||
displayConfiguration.addListener(this::somethingChanged);
|
||||
language.addListener(this::somethingChanged);
|
||||
mountService.addListener(this::somethingChanged);
|
||||
quickAccessService.addListener(this::somethingChanged);
|
||||
checkForUpdates.addListener(this::somethingChanged);
|
||||
lastUpdateCheckReminder.addListener(this::somethingChanged);
|
||||
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
|
||||
lastUpdateCheck.addListener(this::somethingChanged);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -176,10 +168,11 @@ public class Settings {
|
||||
SettingsJson serialized() {
|
||||
var json = new SettingsJson();
|
||||
json.directories = directories.stream().map(VaultSettings::serialized).toList();
|
||||
json.askedForUpdateCheck = askedForUpdateCheck.get();
|
||||
json.checkForUpdatesEnabled = checkForUpdates.get();
|
||||
json.startHidden = startHidden.get();
|
||||
json.autoCloseVaults = autoCloseVaults.get();
|
||||
json.useKeychain = useKeychain.get();
|
||||
json.useQuickAccess = useQuickAccess.get();
|
||||
json.port = port.get();
|
||||
json.numTrayNotifications = numTrayNotifications.get();
|
||||
json.debugMode = debugMode.get();
|
||||
@@ -187,18 +180,16 @@ public class Settings {
|
||||
json.keychainProvider = keychainProvider.get();
|
||||
json.uiOrientation = userInterfaceOrientation.get().name();
|
||||
json.licenseKey = licenseKey.get();
|
||||
json.showMinimizeButton = showMinimizeButton.get();
|
||||
json.showTrayIcon = showTrayIcon.get();
|
||||
json.compactMode = compactMode.get();
|
||||
json.windowXPosition = windowXPosition.get();
|
||||
json.windowYPosition = windowYPosition.get();
|
||||
json.windowWidth = windowWidth.get();
|
||||
json.windowHeight = windowHeight.get();
|
||||
json.displayConfiguration = displayConfiguration.get();
|
||||
json.language = language.get();
|
||||
json.mountService = mountService.get();
|
||||
json.quickAccessService = quickAccessService.get();
|
||||
json.checkForUpdatesEnabled = checkForUpdates.get();
|
||||
json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get();
|
||||
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
|
||||
json.lastUpdateCheck = lastUpdateCheck.get();
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.cryptomator.common.settings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@@ -18,15 +16,24 @@ class SettingsJson {
|
||||
@JsonProperty("writtenByVersion")
|
||||
String writtenByVersion;
|
||||
|
||||
@JsonProperty("askedForUpdateCheck")
|
||||
boolean askedForUpdateCheck = Settings.DEFAULT_ASKED_FOR_UPDATE_CHECK;
|
||||
|
||||
@JsonProperty("autoCloseVaults")
|
||||
boolean autoCloseVaults = Settings.DEFAULT_AUTO_CLOSE_VAULTS;
|
||||
|
||||
@JsonProperty("checkForUpdatesEnabled")
|
||||
boolean checkForUpdatesEnabled = Settings.DEFAULT_CHECK_FOR_UPDATES;
|
||||
|
||||
@JsonProperty("debugMode")
|
||||
boolean debugMode = Settings.DEFAULT_DEBUG_MODE;
|
||||
|
||||
@JsonProperty("theme")
|
||||
UiTheme theme = Settings.DEFAULT_THEME;
|
||||
|
||||
@JsonProperty("displayConfiguration")
|
||||
String displayConfiguration;
|
||||
|
||||
@JsonProperty("keychainProvider")
|
||||
String keychainProvider = Settings.DEFAULT_KEYCHAIN_PROVIDER;
|
||||
|
||||
@@ -45,12 +52,12 @@ class SettingsJson {
|
||||
@JsonProperty("port")
|
||||
int port = Settings.DEFAULT_PORT;
|
||||
|
||||
@JsonProperty("showMinimizeButton")
|
||||
boolean showMinimizeButton = Settings.DEFAULT_SHOW_MINIMIZE_BUTTON;
|
||||
|
||||
@JsonProperty("showTrayIcon")
|
||||
boolean showTrayIcon;
|
||||
|
||||
@JsonProperty("compactMode")
|
||||
boolean compactMode;
|
||||
|
||||
@JsonProperty("startHidden")
|
||||
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
|
||||
String preferredVolumeImpl;
|
||||
|
||||
@JsonProperty("checkForUpdatesEnabled")
|
||||
boolean checkForUpdatesEnabled = Settings.DEFAULT_CHECK_FOR_UPDATES;
|
||||
@JsonProperty("lastUpdateCheck")
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ package org.cryptomator.common.settings;
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.slf4j.Logger;
|
||||
@@ -37,7 +36,7 @@ import java.util.stream.Stream;
|
||||
@Singleton
|
||||
public class SettingsProvider implements Supplier<Settings> {
|
||||
|
||||
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true).registerModule(new JavaTimeModule());
|
||||
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SettingsProvider.class);
|
||||
private static final long SAVE_DELAY_MS = 1000;
|
||||
|
||||
@@ -58,10 +57,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
}
|
||||
|
||||
private Settings load() {
|
||||
Settings settings = env.getSettingsPath() //
|
||||
.flatMap(this::tryLoad) //
|
||||
.findFirst() //
|
||||
.orElseGet(() -> Settings.create(env));
|
||||
Settings settings = env.getSettingsPath().flatMap(this::tryLoad).findFirst().orElseGet(() -> Settings.create(env));
|
||||
settings.setSaveCmd(this::scheduleSave);
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ package org.cryptomator.common.settings;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.Bindings;
|
||||
@@ -39,7 +39,6 @@ public class VaultSettings {
|
||||
static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
|
||||
static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false;
|
||||
static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60;
|
||||
static final int DEFAULT_PORT = 42427;
|
||||
|
||||
private static final Random RNG = new Random();
|
||||
|
||||
@@ -56,8 +55,6 @@ public class VaultSettings {
|
||||
public final IntegerProperty autoLockIdleSeconds;
|
||||
public final ObjectProperty<Path> mountPoint;
|
||||
public final StringExpression mountName;
|
||||
public final StringProperty mountService;
|
||||
public final IntegerProperty port;
|
||||
|
||||
VaultSettings(VaultSettingsJson json) {
|
||||
this.id = json.id;
|
||||
@@ -72,8 +69,6 @@ public class VaultSettings {
|
||||
this.autoLockWhenIdle = new SimpleBooleanProperty(this, "autoLockWhenIdle", json.autoLockWhenIdle);
|
||||
this.autoLockIdleSeconds = new SimpleIntegerProperty(this, "autoLockIdleSeconds", json.autoLockIdleSeconds);
|
||||
this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint));
|
||||
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
|
||||
this.port = new SimpleIntegerProperty(this, "port", json.port);
|
||||
// mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318
|
||||
this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> {
|
||||
final String name;
|
||||
@@ -99,7 +94,7 @@ public class VaultSettings {
|
||||
}
|
||||
|
||||
Observable[] observables() {
|
||||
return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService};
|
||||
return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode};
|
||||
}
|
||||
|
||||
public static VaultSettings withRandomId() {
|
||||
@@ -128,12 +123,10 @@ public class VaultSettings {
|
||||
json.autoLockWhenIdle = autoLockWhenIdle.get();
|
||||
json.autoLockIdleSeconds = autoLockIdleSeconds.get();
|
||||
json.mountPoint = mountPoint.map(Path::toString).getValue();
|
||||
json.mountService = mountService.get();
|
||||
json.port = port.get();
|
||||
return json;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
//visible for testing
|
||||
static String normalizeDisplayName(String original) {
|
||||
if (original.isBlank() || ".".equals(original) || "..".equals(original)) {
|
||||
return "_";
|
||||
|
||||
@@ -45,12 +45,6 @@ class VaultSettingsJson {
|
||||
@JsonProperty("autoLockIdleSeconds")
|
||||
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
|
||||
|
||||
@JsonProperty("mountService")
|
||||
String mountService;
|
||||
|
||||
@JsonProperty("port")
|
||||
int port = VaultSettings.DEFAULT_PORT;
|
||||
|
||||
@Deprecated(since = "1.7.0")
|
||||
@JsonProperty(value = "winDriveLetter", access = JsonProperty.Access.WRITE_ONLY) // WRITE_ONLY means value is "written" into the java object during deserialization. Upvote this: https://github.com/FasterXML/jackson-annotations/issues/233
|
||||
String winDriveLetter;
|
||||
|
||||
@@ -11,7 +11,7 @@ package org.cryptomator.common.vaults;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Constants;
|
||||
import org.cryptomator.common.mount.Mounter;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.mount.WindowsDriveLetters;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystem;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
||||
@@ -24,9 +24,6 @@ import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
|
||||
import org.cryptomator.integrations.mount.MountFailedException;
|
||||
import org.cryptomator.integrations.mount.Mountpoint;
|
||||
import org.cryptomator.integrations.mount.UnmountFailedException;
|
||||
import org.cryptomator.integrations.quickaccess.QuickAccessService;
|
||||
import org.cryptomator.integrations.quickaccess.QuickAccessServiceException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -44,7 +41,6 @@ import javafx.beans.property.SimpleBooleanProperty;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.ReadOnlyFileSystemException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@@ -59,7 +55,6 @@ public class Vault {
|
||||
|
||||
private final VaultSettings vaultSettings;
|
||||
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
|
||||
private final AtomicReference<QuickAccessService.QuickAccessEntry> quickAccessEntry;
|
||||
private final VaultState state;
|
||||
private final ObjectProperty<Exception> lastKnownException;
|
||||
private final VaultConfigCache configCache;
|
||||
@@ -73,19 +68,12 @@ public class Vault {
|
||||
private final BooleanBinding unknownError;
|
||||
private final ObjectBinding<Mountpoint> mountPoint;
|
||||
private final Mounter mounter;
|
||||
private final Settings settings;
|
||||
private final BooleanProperty showingStats;
|
||||
|
||||
private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
|
||||
|
||||
@Inject
|
||||
Vault(VaultSettings vaultSettings, //
|
||||
VaultConfigCache configCache, //
|
||||
AtomicReference<CryptoFileSystem> cryptoFileSystem, //
|
||||
VaultState state, //
|
||||
@Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
|
||||
VaultStats stats, //
|
||||
Mounter mounter, Settings settings) {
|
||||
Vault(VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats, WindowsDriveLetters windowsDriveLetters, Mounter mounter) {
|
||||
this.vaultSettings = vaultSettings;
|
||||
this.configCache = configCache;
|
||||
this.cryptoFileSystem = cryptoFileSystem;
|
||||
@@ -101,9 +89,7 @@ public class Vault {
|
||||
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
|
||||
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
|
||||
this.mounter = mounter;
|
||||
this.settings = settings;
|
||||
this.showingStats = new SimpleBooleanProperty(false);
|
||||
this.quickAccessEntry = new AtomicReference<>(null);
|
||||
}
|
||||
|
||||
// ******************************************************************************
|
||||
@@ -112,22 +98,15 @@ public class Vault {
|
||||
|
||||
private CryptoFileSystem createCryptoFileSystem(MasterkeyLoader keyLoader) throws IOException, MasterkeyLoadingFailedException {
|
||||
Set<FileSystemFlags> flags = EnumSet.noneOf(FileSystemFlags.class);
|
||||
var createReadOnly = vaultSettings.usesReadOnlyMode.get();
|
||||
try {
|
||||
FileSystemCapabilityChecker.assertWriteAccess(getPath());
|
||||
} catch (FileSystemCapabilityChecker.MissingCapabilityException e) {
|
||||
if (!createReadOnly) {
|
||||
throw new ReadOnlyFileSystemException();
|
||||
}
|
||||
}
|
||||
if (createReadOnly) {
|
||||
if (vaultSettings.usesReadOnlyMode.get()) {
|
||||
flags.add(FileSystemFlags.READONLY);
|
||||
} else if (vaultSettings.maxCleartextFilenameLength.get() == -1) {
|
||||
LOG.debug("Determining cleartext filename length limitations...");
|
||||
var checker = new FileSystemCapabilityChecker();
|
||||
int shorteningThreshold = configCache.get().allegedShorteningThreshold();
|
||||
int ciphertextLimit = FileSystemCapabilityChecker.determineSupportedCiphertextFileNameLength(getPath());
|
||||
int ciphertextLimit = checker.determineSupportedCiphertextFileNameLength(getPath());
|
||||
if (ciphertextLimit < shorteningThreshold) {
|
||||
int cleartextLimit = FileSystemCapabilityChecker.determineSupportedCleartextFileNameLength(getPath());
|
||||
int cleartextLimit = checker.determineSupportedCleartextFileNameLength(getPath());
|
||||
vaultSettings.maxCleartextFilenameLength.set(cleartextLimit);
|
||||
} else {
|
||||
vaultSettings.maxCleartextFilenameLength.setValue(UNLIMITED_FILENAME_LENGTH);
|
||||
@@ -170,9 +149,6 @@ public class Vault {
|
||||
var rootPath = fs.getRootDirectories().iterator().next();
|
||||
var mountHandle = mounter.mount(vaultSettings, rootPath);
|
||||
success = this.mountHandle.compareAndSet(null, mountHandle);
|
||||
if (settings.useQuickAccess.getValue()) {
|
||||
addToQuickAccess();
|
||||
}
|
||||
} finally {
|
||||
if (!success) {
|
||||
destroyCryptoFileSystem();
|
||||
@@ -197,7 +173,6 @@ public class Vault {
|
||||
mountHandle.mountObj().close();
|
||||
mountHandle.specialCleanup().run();
|
||||
} finally {
|
||||
removeFromQuickAccess();
|
||||
destroyCryptoFileSystem();
|
||||
}
|
||||
|
||||
@@ -205,52 +180,6 @@ public class Vault {
|
||||
LOG.info("Locked vault '{}'", getDisplayName());
|
||||
}
|
||||
|
||||
private synchronized void addToQuickAccess() {
|
||||
if (quickAccessEntry.get() != null) {
|
||||
//we don't throw an exception since we don't wanna block unlocking
|
||||
LOG.warn("Vault already added to quick access area. Will be removed on next lock operation.");
|
||||
return;
|
||||
}
|
||||
|
||||
QuickAccessService.get() //
|
||||
.filter(s -> s.getClass().getName().equals(settings.quickAccessService.getValue())) //
|
||||
.findFirst() //
|
||||
.ifPresentOrElse( //
|
||||
this::addToQuickAccessInternal, //
|
||||
() -> LOG.warn("Unable to add Vault to quick access area: Desired implementation not available.") //
|
||||
);
|
||||
}
|
||||
|
||||
private void addToQuickAccessInternal(@NotNull QuickAccessService s) {
|
||||
if (getMountPoint() instanceof Mountpoint.WithPath mp) {
|
||||
try {
|
||||
var entry = s.add(mp.path(), getDisplayName());
|
||||
quickAccessEntry.set(entry);
|
||||
} catch (QuickAccessServiceException e) {
|
||||
LOG.error("Adding vault to quick access area failed", e);
|
||||
}
|
||||
} else {
|
||||
LOG.warn("Unable to add vault to quick access area: Vault is not mounted to local system path.");
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeFromQuickAccess() {
|
||||
if (quickAccessEntry.get() == null) {
|
||||
LOG.debug("Removing vault from quick access area: Entry not found, nothing to do.");
|
||||
return;
|
||||
}
|
||||
removeFromQuickAccessInternal();
|
||||
}
|
||||
|
||||
private void removeFromQuickAccessInternal() {
|
||||
try {
|
||||
quickAccessEntry.get().remove();
|
||||
quickAccessEntry.set(null);
|
||||
} catch (QuickAccessServiceException e) {
|
||||
LOG.error("Removing vault from quick access area failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************************
|
||||
// Observable Properties
|
||||
// *******************************************************************************
|
||||
@@ -385,6 +314,10 @@ public class Vault {
|
||||
return vaultSettings.path.get();
|
||||
}
|
||||
|
||||
CryptoFileSystem getCryptoFileSystem() {
|
||||
return cryptoFileSystem.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets from the cleartext path its ciphertext counterpart.
|
||||
*
|
||||
@@ -393,23 +326,7 @@ public class Vault {
|
||||
* @throws IllegalStateException if the vault is not unlocked
|
||||
*/
|
||||
public Path getCiphertextPath(Path cleartextPath) throws IOException {
|
||||
if (!state.getValue().equals(VaultState.Value.UNLOCKED)) {
|
||||
throw new IllegalStateException("Vault is not unlocked");
|
||||
}
|
||||
var fs = cryptoFileSystem.get();
|
||||
var osPathSeparator = cleartextPath.getFileSystem().getSeparator();
|
||||
var cryptoFsPathSeparator = fs.getSeparator();
|
||||
|
||||
if (getMountPoint() instanceof Mountpoint.WithPath mp) {
|
||||
var absoluteCryptoFsPath = cryptoFsPathSeparator + mp.path().relativize(cleartextPath).toString();
|
||||
if (!cryptoFsPathSeparator.equals(osPathSeparator)) {
|
||||
absoluteCryptoFsPath = absoluteCryptoFsPath.replace(osPathSeparator, cryptoFsPathSeparator);
|
||||
}
|
||||
var cryptoPath = fs.getPath(absoluteCryptoFsPath);
|
||||
return fs.getCiphertextPath(cryptoPath);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("URI mount points not supported.");
|
||||
}
|
||||
return state.get().getCiphertextPath(this, cleartextPath);
|
||||
}
|
||||
|
||||
public VaultConfigCache getVaultConfigCache() {
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.common.vaults;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
||||
import org.cryptomator.cryptofs.DirStructure;
|
||||
import org.cryptomator.cryptofs.migration.Migrators;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -26,7 +24,6 @@ import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@@ -41,21 +38,14 @@ public class VaultListManager {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
|
||||
|
||||
private final AutoLocker autoLocker;
|
||||
private final List<MountService> mountServices;
|
||||
private final VaultComponent.Factory vaultComponentFactory;
|
||||
private final ObservableList<Vault> vaultList;
|
||||
private final String defaultVaultName;
|
||||
|
||||
@Inject
|
||||
public VaultListManager(ObservableList<Vault> vaultList, //
|
||||
AutoLocker autoLocker, //
|
||||
List<MountService> mountServices,
|
||||
VaultComponent.Factory vaultComponentFactory,
|
||||
ResourceBundle resourceBundle,
|
||||
Settings settings) {
|
||||
public VaultListManager(ObservableList<Vault> vaultList, AutoLocker autoLocker, VaultComponent.Factory vaultComponentFactory, ResourceBundle resourceBundle, Settings settings) {
|
||||
this.vaultList = vaultList;
|
||||
this.autoLocker = autoLocker;
|
||||
this.mountServices = mountServices;
|
||||
this.vaultComponentFactory = vaultComponentFactory;
|
||||
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
|
||||
|
||||
@@ -86,15 +76,6 @@ public class VaultListManager {
|
||||
} else {
|
||||
vaultSettings.displayName.set(defaultVaultName);
|
||||
}
|
||||
|
||||
//due to https://github.com/cryptomator/cryptomator/issues/2880#issuecomment-1680313498
|
||||
var nameOfWinfspLocalMounter = "org.cryptomator.frontend.fuse.mount.WinFspMountProvider";
|
||||
if (SystemUtils.IS_OS_WINDOWS //
|
||||
&& vaultSettings.path.get().toString().contains("Dropbox") //
|
||||
&& mountServices.stream().anyMatch(s -> s.getClass().getName().equals(nameOfWinfspLocalMounter))) {
|
||||
vaultSettings.mountService.setValue(nameOfWinfspLocalMounter);
|
||||
}
|
||||
|
||||
return vaultSettings;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.cryptomator.common.vaults;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.cryptomator.integrations.mount.Mountpoint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -8,6 +9,8 @@ import javax.inject.Inject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ObservableObjectValue;
|
||||
import javafx.beans.value.ObservableValueBase;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
@@ -43,12 +46,40 @@ public class VaultState extends ObservableValueBase<VaultState.Value> implements
|
||||
/**
|
||||
* Vault is unlocked
|
||||
*/
|
||||
UNLOCKED,
|
||||
UNLOCKED {
|
||||
/**
|
||||
* Gets from the cleartext path its ciphertext counterpart.
|
||||
*
|
||||
* @return Local os path to the ciphertext resource
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws IllegalStateException if the vault is not unlocked
|
||||
*/
|
||||
Path getCiphertextPath(Vault vault, Path cleartextPath) throws IOException {
|
||||
var fs = vault.getCryptoFileSystem();
|
||||
var osPathSeparator = cleartextPath.getFileSystem().getSeparator();
|
||||
var cryptoFsPathSeparator = fs.getSeparator();
|
||||
|
||||
if (vault.getMountPoint() instanceof Mountpoint.WithPath mp) {
|
||||
var absoluteCryptoFsPath = cryptoFsPathSeparator + mp.path().relativize(cleartextPath).toString();
|
||||
if (!cryptoFsPathSeparator.equals(osPathSeparator)) {
|
||||
absoluteCryptoFsPath = absoluteCryptoFsPath.replace(osPathSeparator, cryptoFsPathSeparator);
|
||||
}
|
||||
var cryptoPath = fs.getPath(absoluteCryptoFsPath);
|
||||
return fs.getCiphertextPath(cryptoPath);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("URI mount points not supported.");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unknown state due to preceding unrecoverable exceptions.
|
||||
*/
|
||||
ERROR;
|
||||
|
||||
Path getCiphertextPath(Vault vault, Path cleartextPath) throws IOException {
|
||||
throw new IllegalStateException("Vault is not unlocked");
|
||||
}
|
||||
}
|
||||
|
||||
private final AtomicReference<Value> value;
|
||||
|
||||
@@ -9,9 +9,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import dagger.Lazy;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.ShutdownHook;
|
||||
import org.cryptomator.common.SubstitutingProperties;
|
||||
import org.cryptomator.networking.SSLContextProvider;
|
||||
import org.cryptomator.common.ShutdownHook;
|
||||
import org.cryptomator.ipc.IpcCommunicator;
|
||||
import org.cryptomator.logging.DebugMode;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||
@@ -20,10 +19,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -51,16 +48,14 @@ public class Cryptomator {
|
||||
private final Environment env;
|
||||
private final Lazy<IpcMessageHandler> ipcMessageHandler;
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final SecureRandom csprng;
|
||||
|
||||
@Inject
|
||||
Cryptomator(DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy<IpcMessageHandler> ipcMessageHandler, ShutdownHook shutdownHook, SecureRandom csprng) {
|
||||
Cryptomator(DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy<IpcMessageHandler> ipcMessageHandler, ShutdownHook shutdownHook) {
|
||||
this.debugMode = debugMode;
|
||||
this.supportedLanguages = supportedLanguages;
|
||||
this.env = env;
|
||||
this.ipcMessageHandler = ipcMessageHandler;
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.csprng = csprng;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -94,7 +89,7 @@ public class Cryptomator {
|
||||
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
|
||||
debugMode.initialize();
|
||||
supportedLanguages.applyPreferred();
|
||||
changeDefaultSSLContext();
|
||||
|
||||
/*
|
||||
* Attempts to create an IPC connection to a running Cryptomator instance and sends it the given args.
|
||||
* If no external process could be reached, the args will be handled by the loopback IPC endpoint.
|
||||
@@ -120,17 +115,6 @@ public class Cryptomator {
|
||||
}
|
||||
}
|
||||
|
||||
private void changeDefaultSSLContext() {
|
||||
SSLContextProvider.loadAll().findFirst().ifPresent(p -> {
|
||||
try {
|
||||
var context = p.getContext(csprng);
|
||||
SSLContext.setDefault(context);
|
||||
} catch (SSLContextProvider.SSLContextBuildException e) {
|
||||
LOG.warn("Failed to change default SSL context with provider {}", p.getClass().getName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the JavaFX application, blocking the main thread until shuts down.
|
||||
*
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.cryptomator.launcher;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.common.Hyperlinks;
|
||||
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
||||
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
|
||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
||||
@@ -24,12 +23,6 @@ class CryptomatorModule {
|
||||
return ResourceBundle.getBundle("i18n.strings");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Hyperlinks provideHyperlinks() {
|
||||
return Hyperlinks.load();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("launchEventQueue")
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.launcher;
|
||||
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -49,7 +48,7 @@ class FileOpenRequestHandler {
|
||||
handleLaunchArgs(FileSystems.getDefault(), args);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
// visible for testing
|
||||
void handleLaunchArgs(FileSystem fs, List<String> args) {
|
||||
Collection<Path> pathsToOpen = args.stream().map(str -> {
|
||||
try {
|
||||
|
||||
@@ -20,7 +20,7 @@ public class SupportedLanguages {
|
||||
// "en" is not part of this list - it is always inserted at the top.
|
||||
public static final List<String> LANGUAGE_TAGS = List.of("ar", "be", "bn", "bs", "ca", "cs", "da", "de", "el", "es", "fr", "gl", "he", //
|
||||
"hi", "hr", "hu", "id", "it", "ja", "ko", "lv", "nb", "nl", "nn", "pa", "pl", "pt", "pt-BR", "ro", "ru", "sk", "sr", "sr-Latn", "sv", "sw", //
|
||||
"ta", "th", "tr", "ug", "uk", "vi", "zh", "zh-HK", "zh-TW");
|
||||
"ta", "th", "tr", "uk", "vi", "zh", "zh-HK", "zh-TW");
|
||||
public static final String ENGLISH = "en";
|
||||
|
||||
private final List<String> sortedLanguageTags;
|
||||
|
||||
@@ -5,7 +5,6 @@ import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
import ch.qos.logback.classic.spi.Configurator;
|
||||
import ch.qos.logback.classic.spi.ConfiguratorRank;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Appender;
|
||||
import ch.qos.logback.core.ConsoleAppender;
|
||||
@@ -20,7 +19,6 @@ import org.cryptomator.common.Environment;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
@ConfiguratorRank(ConfiguratorRank.CUSTOM_NORMAL_PRIORITY)
|
||||
public class LogbackConfigurator extends ContextAwareBase implements Configurator {
|
||||
|
||||
private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.cryptomator.networking;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
||||
|
||||
abstract KeyStore getTruststore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException;
|
||||
|
||||
@Override
|
||||
public SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException {
|
||||
try {
|
||||
KeyStore truststore = getTruststore();
|
||||
truststore.load(null, null);
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(truststore);
|
||||
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, tmf.getTrustManagers(), csprng);
|
||||
return context;
|
||||
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | KeyManagementException | IOException e) {
|
||||
throw new SSLContextBuildException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user