From da3c5e901f61353f6f7fa9272056d0ad0fedc4ff Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 15:15:48 +0100 Subject: [PATCH 1/9] fixes #4156 for Windows fallback on JDK shipped cacert file if well-known CA are not present --- .../SSLContextDifferentTrustStoreBase.java | 11 +++++- .../SSLContextWithWindowsCertStore.java | 37 +++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cryptomator/networking/SSLContextDifferentTrustStoreBase.java b/src/main/java/org/cryptomator/networking/SSLContextDifferentTrustStoreBase.java index 87e1b82ef..5da47597a 100644 --- a/src/main/java/org/cryptomator/networking/SSLContextDifferentTrustStoreBase.java +++ b/src/main/java/org/cryptomator/networking/SSLContextDifferentTrustStoreBase.java @@ -18,7 +18,7 @@ abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider { public SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException { try { KeyStore truststore = getTruststore(); - truststore.load(null, null); + ensureLoaded(truststore); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(truststore); @@ -30,4 +30,13 @@ abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider { throw new SSLContextBuildException(e); } } + + static void ensureLoaded(KeyStore truststore) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + try { + truststore.aliases(); + } catch (KeyStoreException e) { + // Not initialized yet (e.g. custom KeyStore SPI); initialize without replacing preloaded stores. + truststore.load(null, null); + } + } } diff --git a/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java b/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java index 0f1ea04b5..1db06e5b1 100644 --- a/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java +++ b/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java @@ -2,20 +2,51 @@ package org.cryptomator.networking; import org.cryptomator.integrations.common.OperatingSystem; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.cert.CertificateException; +import java.util.List; /** - * SSLContextProvider for Windows using the Windows certificate store as trust store + * SSLContextProvider for Windows using the Windows certificate store as trust store and the bundled JDK cacerts as fallback *

* In order to work, the jdk.crypto.mscapi jmod is needed */ @OperatingSystem(OperatingSystem.Value.WINDOWS) public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider { + private static final String DEFAULT_TRUSTSTORE_PASSWORD = ""; + @Override - KeyStore getTruststore() throws KeyStoreException { - return KeyStore.getInstance("WINDOWS-ROOT"); + KeyStore getTruststore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + var windowsKeyStore = KeyStore.getInstance("WINDOWS-ROOT"); + var jdkKeyStore = getShippedCaCertsStore(); + ensureLoaded(windowsKeyStore); + ensureLoaded(jdkKeyStore); + try { + CombinedKeyStoreSpi spi = CombinedKeyStoreSpi.create(windowsKeyStore, jdkKeyStore); + Provider dummyProvider = new Provider("CombinedKeyStoreProvider", "1.0", "Provides a combined, read-only KeyStore") {}; + return new KeyStore(spi, dummyProvider, "CombinedKeyStoreProvider") {}; + } catch (IllegalArgumentException e) { + throw new KeyStoreException(e); + } + } + + KeyStore getShippedCaCertsStore() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException { + var javaHome = Path.of(System.getProperty("java.home")); + var trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", DEFAULT_TRUSTSTORE_PASSWORD).toCharArray(); + for (var candidate : List.of(javaHome.resolve("lib/security/cacerts"), javaHome.resolve("conf/security/cacerts"))) { + if (Files.isRegularFile(candidate)) { + return KeyStore.getInstance(candidate.toFile(), trustStorePassword); + } + } + throw new NoSuchFileException("Could not locate cacerts below java.home: " + javaHome); } } From f884861373af0ba1d331b6dc3ffae8f46006bf23 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 15:48:35 +0100 Subject: [PATCH 2/9] skip fallback if failing to load --- .../SSLContextWithWindowsCertStore.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java b/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java index 1db06e5b1..5a179e56e 100644 --- a/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java +++ b/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java @@ -1,10 +1,12 @@ package org.cryptomator.networking; +import org.cryptomator.common.Nullable; import org.cryptomator.integrations.common.OperatingSystem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.security.KeyStore; import java.security.KeyStoreException; @@ -21,12 +23,17 @@ import java.util.List; @OperatingSystem(OperatingSystem.Value.WINDOWS) public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider { - private static final String DEFAULT_TRUSTSTORE_PASSWORD = ""; + private static final Logger LOG = LoggerFactory.getLogger(SSLContextWithWindowsCertStore.class); + private static final String DEFAULT_TRUSTSTORE_PASSWORD = "changeit"; //default JDK cacerts password @Override KeyStore getTruststore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { var windowsKeyStore = KeyStore.getInstance("WINDOWS-ROOT"); var jdkKeyStore = getShippedCaCertsStore(); + if (jdkKeyStore == null) { + return windowsKeyStore; + } + ensureLoaded(windowsKeyStore); ensureLoaded(jdkKeyStore); try { @@ -38,15 +45,20 @@ public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStor } } - KeyStore getShippedCaCertsStore() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException { + @Nullable + KeyStore getShippedCaCertsStore() { var javaHome = Path.of(System.getProperty("java.home")); var trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", DEFAULT_TRUSTSTORE_PASSWORD).toCharArray(); for (var candidate : List.of(javaHome.resolve("lib/security/cacerts"), javaHome.resolve("conf/security/cacerts"))) { - if (Files.isRegularFile(candidate)) { - return KeyStore.getInstance(candidate.toFile(), trustStorePassword); + try { + if (Files.isRegularFile(candidate)) { + return KeyStore.getInstance(candidate.toFile(), trustStorePassword); + } + } catch (CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException e) { + LOG.info("Unable to load fallback cacerts {} file. Skipping fallback.", candidate, e); } } - throw new NoSuchFileException("Could not locate cacerts below java.home: " + javaHome); + return null; } } From 792734b48659f0de79b8e81b44670c40d7cca062 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 16:20:34 +0100 Subject: [PATCH 3/9] add unit tests --- .../SSLContextWithWindowsCertStore.java | 13 ++- .../SSLContextWithWindowsCertStoreTest.java | 97 +++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 src/test/java/org/cryptomator/networking/SSLContextWithWindowsCertStoreTest.java diff --git a/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java b/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java index 5a179e56e..83815b611 100644 --- a/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java +++ b/src/main/java/org/cryptomator/networking/SSLContextWithWindowsCertStore.java @@ -2,6 +2,7 @@ package org.cryptomator.networking; import org.cryptomator.common.Nullable; import org.cryptomator.integrations.common.OperatingSystem; +import org.jetbrains.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +15,7 @@ import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.cert.CertificateException; import java.util.List; +import java.util.Properties; /** * SSLContextProvider for Windows using the Windows certificate store as trust store and the bundled JDK cacerts as fallback @@ -47,8 +49,15 @@ public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStor @Nullable KeyStore getShippedCaCertsStore() { - var javaHome = Path.of(System.getProperty("java.home")); - var trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", DEFAULT_TRUSTSTORE_PASSWORD).toCharArray(); + return getCaCertsStoreByProperties(System.getProperties()); + } + + //for testability + @VisibleForTesting + @Nullable + KeyStore getCaCertsStoreByProperties(Properties props) { + var javaHome = Path.of(props.getProperty("java.home")); + var trustStorePassword = props.getProperty("javax.net.ssl.trustStorePassword", DEFAULT_TRUSTSTORE_PASSWORD).toCharArray(); for (var candidate : List.of(javaHome.resolve("lib/security/cacerts"), javaHome.resolve("conf/security/cacerts"))) { try { if (Files.isRegularFile(candidate)) { diff --git a/src/test/java/org/cryptomator/networking/SSLContextWithWindowsCertStoreTest.java b/src/test/java/org/cryptomator/networking/SSLContextWithWindowsCertStoreTest.java new file mode 100644 index 000000000..dca3c3ced --- /dev/null +++ b/src/test/java/org/cryptomator/networking/SSLContextWithWindowsCertStoreTest.java @@ -0,0 +1,97 @@ +package org.cryptomator.networking; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.Properties; + +public class SSLContextWithWindowsCertStoreTest { + + private static final String JAVA_HOME_PROP = "java.home"; + private static final String TRUSTSTORE_PASSWORD_PROP = "javax.net.ssl.trustStorePassword"; + + @TempDir + Path tmpDir; + + @Test + public void testGetCaCertsStoreByPropertiesReturnsNullIfNoCandidateExists() { + var props = propsFor(tmpDir, null); + + var inTest = new SSLContextWithWindowsCertStore(); + + Assertions.assertNull(inTest.getCaCertsStoreByProperties(props)); + } + + @Test + public void testGetCaCertsStoreByPropertiesLoadsLibSecurityCacertsByDefault() throws Exception { + var cacerts = tmpDir.resolve("lib/security/cacerts"); + writePkcs12Keystore(cacerts, "changeit".toCharArray()); + var props = propsFor(tmpDir, null); + + var inTest = new SSLContextWithWindowsCertStore(); + + Assertions.assertNotNull(inTest.getCaCertsStoreByProperties(props)); + } + + @Test + public void testGetCaCertsStoreByPropertiesTriesSecondCandidateAfterFirstFails() throws Exception { + var invalidLibCacerts = tmpDir.resolve("lib/security/cacerts"); + Files.createDirectories(invalidLibCacerts.getParent()); + Files.writeString(invalidLibCacerts, "not a keystore"); + var confCacerts = tmpDir.resolve("conf/security/cacerts"); + writePkcs12Keystore(confCacerts, "changeit".toCharArray()); + var props = propsFor(tmpDir, null); + + var inTest = new SSLContextWithWindowsCertStore(); + + Assertions.assertNotNull(inTest.getCaCertsStoreByProperties(props)); + } + + @Test + public void testGetCaCertsStoreByPropertiesReturnsNullOnWrongPassword() throws Exception { + var cacerts = tmpDir.resolve("lib/security/cacerts"); + writePkcs12Keystore(cacerts, "changeit".toCharArray()); + var props = propsFor(tmpDir, "wrong-password"); + + var inTest = new SSLContextWithWindowsCertStore(); + + Assertions.assertNull(inTest.getCaCertsStoreByProperties(props)); + } + + @Test + public void testGetCaCertsStoreByPropertiesUsesCustomPasswordProperty() throws Exception { + var cacerts = tmpDir.resolve("lib/security/cacerts"); + writePkcs12Keystore(cacerts, "custom-password".toCharArray()); + var props = propsFor(tmpDir, "custom-password"); + + var inTest = new SSLContextWithWindowsCertStore(); + + Assertions.assertNotNull(inTest.getCaCertsStoreByProperties(props)); + } + + private static void writePkcs12Keystore(Path target, char[] password) throws CertificateException, IOException, NoSuchAlgorithmException, java.security.KeyStoreException { + Files.createDirectories(target.getParent()); + var keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); + try (var out = Files.newOutputStream(target)) { + keystore.store(out, password); + } + } + + private static Properties propsFor(Path javaHome, String truststorePassword) { + var props = new Properties(); + props.setProperty(JAVA_HOME_PROP, javaHome.toString()); + if (truststorePassword != null) { + props.setProperty(TRUSTSTORE_PASSWORD_PROP, truststorePassword); + } + return props; + } + +} From 4d62f2303dc15959f68229c08b1779d90feb7df9 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 16:27:57 +0100 Subject: [PATCH 4/9] prepare version 1.18.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d93a96cc2..fddfd38c8 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.cryptomator cryptomator - 1.18.0 + 1.18.1 Cryptomator Desktop App From d6010889482423fef74feb0b071d089a5ef46869 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 16:44:50 +0100 Subject: [PATCH 5/9] [skip metadata check] update workflow for hotfix --- .github/workflows/release-check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml index e1739326e..4d36fa70d 100644 --- a/.github/workflows/release-check.yml +++ b/.github/workflows/release-check.yml @@ -43,6 +43,7 @@ jobs: exit 1 fi - name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file + if: ${{ ! contains(github.event.commits.message, '[skip metadata check]') }} run: | if ! grep -q "" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml" From 50f6a8778893beb465d730a1fe9578e9e879ce13 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 16:49:29 +0100 Subject: [PATCH 6/9] [skip metadata check] fix release check workflow --- .github/workflows/release-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml index 4d36fa70d..e2bfdb8ea 100644 --- a/.github/workflows/release-check.yml +++ b/.github/workflows/release-check.yml @@ -43,7 +43,7 @@ jobs: exit 1 fi - name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file - if: ${{ ! contains(github.event.commits.message, '[skip metadata check]') }} + if: ${{ ! (contains(github.event.head_commit.message, '[skip metadata check]') || contains(github.event.head_commit.message, '[metadata check skip]')) }} run: | if ! grep -q "" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml" From 688090095efe8916d8a7c75f2e10cdd2cefa174c Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Feb 2026 17:49:38 +0100 Subject: [PATCH 7/9] harden curl downloads on CI (#4158) --- .github/workflows/appimage.yml | 4 ++-- .github/workflows/av-whitelist.yml | 2 +- .github/workflows/debian.yml | 4 ++-- .github/workflows/flathub.yml | 2 +- .github/workflows/mac-dmg-x64.yml | 2 +- .github/workflows/mac-dmg.yml | 2 +- .github/workflows/post-publish.yml | 2 +- .github/workflows/win-exe.yml | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 824f996f4..6bb406441 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -63,7 +63,7 @@ jobs: - name: Download OpenJFX jmods id: download-jmods run: | - curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip + curl --silent --fail-with-body --proto "=https" -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 @@ -165,7 +165,7 @@ jobs: ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun - name: Download AppImageKit run: | - curl -L "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.arch }}.AppImage" -o appimagetool.AppImage + curl --silent --fail-with-body --proto "=https" -L "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.arch }}.AppImage" -o appimagetool.AppImage chmod +x appimagetool.AppImage ./appimagetool.AppImage --appimage-extract - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235 diff --git a/.github/workflows/av-whitelist.yml b/.github/workflows/av-whitelist.yml index 4a8aba9af..1a7488fd2 100644 --- a/.github/workflows/av-whitelist.yml +++ b/.github/workflows/av-whitelist.yml @@ -49,7 +49,7 @@ jobs: url="${INPUT_URL}" echo "fileName=${url##*/}" >> $GITHUB_OUTPUT - name: Download file - run: curl "${INPUT_URL}" -L -o "${{steps.extractName.outputs.fileName}}" --fail-with-body + run: curl --silent --fail-with-body --proto "=https" -L "${INPUT_URL}" -o "${{steps.extractName.outputs.fileName}}" - name: Upload artifact uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml index 178f46441..f4e9a09a4 100644 --- a/.github/workflows/debian.yml +++ b/.github/workflows/debian.yml @@ -71,11 +71,11 @@ jobs: - name: Download OpenJFX jmods id: download-jmods run: | - curl -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip + curl --silent --fail-with-body --proto "=https" -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 + curl --silent --fail-with-body --proto "=https" -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 diff --git a/.github/workflows/flathub.yml b/.github/workflows/flathub.yml index e31f4cfdc..bf22cec30 100644 --- a/.github/workflows/flathub.yml +++ b/.github/workflows/flathub.yml @@ -33,7 +33,7 @@ jobs: - 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 + curl --silent --fail-with-body --proto "=https" -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: diff --git a/.github/workflows/mac-dmg-x64.yml b/.github/workflows/mac-dmg-x64.yml index 9afc867a6..102e104c6 100644 --- a/.github/workflows/mac-dmg-x64.yml +++ b/.github/workflows/mac-dmg-x64.yml @@ -59,7 +59,7 @@ jobs: - name: Download OpenJFX jmods id: download-jmods run: | - curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip + curl --silent --fail-with-body --proto "=https" -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 diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index 06116d2a7..b2b962b6f 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -57,7 +57,7 @@ jobs: - name: Download OpenJFX jmods id: download-jmods run: | - curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip + curl --silent --fail-with-body --proto "=https" -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 diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index d685381c7..619f0f607 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Download source tarball run: | - curl -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz + curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz - name: Sign source tarball with key 615D449FE6E6A235 run: | echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index e41d3c618..30e2f9f67 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -72,7 +72,7 @@ jobs: if: matrix.arch == 'x64' #In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip run: | - curl --output openjfx-jmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}" + curl --silent --fail-with-body --proto "=https" -L "${{ env.OPENJFX_JMODS_AMD64 }}" --output openjfx-jmods.zip if(!(Get-FileHash -Path openjfx-jmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) { throw "Wrong checksum of JMOD archive downloaded from ${{ env.OPENJFX_JMODS_AMD64 }}."; } @@ -338,7 +338,7 @@ jobs: shell: pwsh - name: Download WinFsp run: | - curl --output $env:WINFSP_PATH -L ${{ env.WINFSP_MSI }} + curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_MSI }} --output $env:WINFSP_PATH $computedHash = (Get-FileHash -Path $env:WINFSP_PATH -Algorithm SHA256).Hash.ToLower() if ($computedHash -ne "${{ env.WINFSP_MSI_HASH }}") { throw "Checksum mismatch for $env:WINFSP_PATH (expected ${{ env.WINFSP_MSI_HASH }}, got $computedHash)." @@ -348,7 +348,7 @@ jobs: shell: pwsh - name: Download Legacy-WinFsp uninstaller run: | - curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }} + curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_UNINSTALLER }} --output dist/win/bundle/resources/winfsp-uninstaller.exe shell: pwsh - name: Create Wix Burn bundle working-directory: dist/win From 29bfbdc52432c498de2359c0ed6ad0e2135b52b5 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 27 Feb 2026 15:08:32 +0100 Subject: [PATCH 8/9] Adjust wording for in use feature --- src/main/resources/i18n/strings.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/i18n/strings.properties b/src/main/resources/i18n/strings.properties index e3595be48..8c5e062f8 100644 --- a/src/main/resources/i18n/strings.properties +++ b/src/main/resources/i18n/strings.properties @@ -712,17 +712,17 @@ eventView.entry.brokenFileNode.message=Broken filesystem node eventView.entry.brokenFileNode.showEncrypted=Show broken, encrypted node eventView.entry.brokenFileNode.copyEncrypted=Copy path of broken, encrypted node eventView.entry.brokenFileNode.copyDecrypted=Copy decrypted path -eventView.entry.inUse.message=Locked File +eventView.entry.inUse.message=File in use eventView.entry.inUse.showDecrypted=Show decrypted file eventView.entry.inUse.copyDecrypted=Copy decrypted path eventView.entry.inUse.showEncrypted=Show encrypted file eventView.entry.inUse.copyEncrypted=Copy encrypted path eventView.entry.inUse.copyUserAndDevice=Copy locking user and device name -eventView.entry.inUse.ignoreLock=Ignore Lock +eventView.entry.inUse.ignoreLock=Ignore use status # Notifications ## FileIsInUse Notification -notification.inUse.message=File is locked by another device -notification.inUse.description=The file is opened by %s on device %s. Ask the user to close the file and sync again. Otherwise, you can ignore the lock and open it anyway. -notification.inUse.action=Ignore Lock \ No newline at end of file +notification.inUse.message=File is in use on another device +notification.inUse.description=The file is open by %s on %s. Ask them to close the file and let synchronization finish. You can ignore the status to open it now, but this may cause conflicts or overwrite newer changes. +notification.inUse.action=Ignore Use Status \ No newline at end of file From 4090413290ca1b1790bb9067160a654dfb1cb60f Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 27 Feb 2026 15:52:30 +0100 Subject: [PATCH 9/9] increase slightly notify window heigth --- src/main/resources/fxml/notification.fxml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/fxml/notification.fxml b/src/main/resources/fxml/notification.fxml index 74ed9b18a..84dd2fa26 100644 --- a/src/main/resources/fxml/notification.fxml +++ b/src/main/resources/fxml/notification.fxml @@ -15,7 +15,7 @@ @@ -65,7 +65,7 @@