From fbeeaa4c936a543fbc4bceca1be29e6697469434 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 11 Jun 2025 12:38:38 +0200 Subject: [PATCH 01/18] prepare 1.17.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 29853d0b1..acd936ae1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.cryptomator cryptomator - 1.17.0-SNAPSHOT + 1.17.0 Cryptomator Desktop App From 4d4a93746dc32c187e5edc32e3d0c1f3a4ffa086 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 23 Jun 2025 16:34:31 +0200 Subject: [PATCH 02/18] disable confusing message of kwallet library --- src/main/java/org/cryptomator/logging/LogbackConfigurator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/cryptomator/logging/LogbackConfigurator.java b/src/main/java/org/cryptomator/logging/LogbackConfigurator.java index 3b77993cc..7e8b9e6c4 100644 --- a/src/main/java/org/cryptomator/logging/LogbackConfigurator.java +++ b/src/main/java/org/cryptomator/logging/LogbackConfigurator.java @@ -90,6 +90,9 @@ public class LogbackConfigurator extends ContextAwareBase implements Configurato // configure fuse file locking logger: Logger fuseLocking = context.getLogger("org.cryptomator.frontend.fuse.locks"); fuseLocking.setLevel(Level.OFF); + //deactivate kwallet unsettling message + Logger kdeWallet = context.getLogger("org.purejava.kwallet.freedesktop.dbus.handlers"); + kdeWallet.setLevel(Level.OFF); } return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY; } From 9a14cfc674b3e720facc5dda89ec564a36c6254e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 24 Jun 2025 16:11:44 +0200 Subject: [PATCH 03/18] finalize 1.17.0 --- dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml index 16e2ba876..b088836f7 100644 --- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml +++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml @@ -83,6 +83,9 @@ + + https://github.com/cryptomator/cryptomator/releases/1.17.0 + https://github.com/cryptomator/cryptomator/releases/1.16.2 From e57e5358c4244ec6033a47e6c79ddda8638d6203 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Jun 2025 16:15:46 +0200 Subject: [PATCH 04/18] Add workflow to automatically create AUR PR on release --- .github/workflows/aur.yml | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .github/workflows/aur.yml diff --git a/.github/workflows/aur.yml b/.github/workflows/aur.yml new file mode 100644 index 000000000..c51976fce --- /dev/null +++ b/.github/workflows/aur.yml @@ -0,0 +1,92 @@ +name: Create PR for aur + +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}} + sha256: ${{ steps.sha256.outputs.sha256}} + 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: sha256 + run: | + curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz + TARBALL_SHA256=$(sha256sum cryptomator.tar.gz | cut -d ' ' -f1) + echo "sha256=${TARBALL_SHA256}" >> "$GITHUB_OUTPUT" + aur: + name: Create PR for AUR + runs-on: ubuntu-latest + needs: [tarball, get-version] + env: + AUR_PR_URL: tbd + steps: + - uses: actions/checkout@v4 + with: + repository: 'cryptomator/aur' + token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + - name: Install makepkg + run: sudo apt install makepkg + - name: Checkout release branch + run: | + git checkout -b release/${{ needs.get-version.outputs.semVerStr }} + - name: Update build file + run: | + sed -i -e 's/pkgver=[0-9]\+\.[0-9]\+\.[0-9]\+.*/pkgver=${${{ needs.get-version.outputs.semVerStr }}//-/_}/g' PKGBUILD + sed -i -e 's/sha256sums=(\'[0-9A-Za-z_\+-]\{64\}\'$/sha256sums=(\'${{ needs.tarball.outputs.sha256 }}\'/g' PKGBUILD + makepkg --printsrcinfo > .SRCINFO + # sed -i -e 's/pkgver=[0-9]\+\.[0-9]\+\.[0-9]\+.*/pkgver=${${{ needs.get-version.outputs.semVerStr }}//-/_}/g' PKGBUILD + # sed -i -e 's/sha256sums = [0-9A-Za-z_\+-]\{64\}$/sha256sums = ${{ needs.tarball.outputs.sha256 }}/g'.SRCINFO + - 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 build instructions\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 "AUR_PR_URL=$PR_URL" >> "$GITHUB_ENV" + env: + GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + - name: Slack Notification + uses: rtCamp/action-slack-notify@v2 + #asdif: 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.AUR_PR_URL }}|PR> on how to proceed.>." + SLACK_FOOTER: false + MSG_MINIMAL: true \ No newline at end of file From 414ccad8fb90f4ee55a5c46fd7064317cfe97e45 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Jun 2025 15:35:59 +0200 Subject: [PATCH 05/18] Feature: Automate AUR release (#3910) Extend/add workflows to automatically create PRs for aur and aur-bin repos for a release. --- .github/workflows/appimage.yml | 66 +++++++++++++++++++++++++++++++++- .github/workflows/aur.yml | 21 +++++------ 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 521edeedd..aa49ed4a1 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -52,7 +52,6 @@ jobs: java-version: ${{ env.JAVA_VERSION }} check-latest: true cache: 'maven' - - name: Download OpenJFX jmods id: download-jmods run: | @@ -194,3 +193,68 @@ jobs: cryptomator-*.AppImage cryptomator-*.zsync cryptomator-*.asc + + create-aur-bin-pr: + name: Create PR for aur-bin repo + needs: [build, get-version] + runs-on: ubuntu-latest + if: github.event_name == 'release' + steps: + - name: Download AppImages + uses: actions/download-artifact@v4 + with: + path: downloads/ + merge-multiple: true + - name: Compute sha256 hash of AppImages + id: checksums + run: | + X64_SHA256=$(sha256sum downloads/cryptomator-*-x86_64.AppImage | cut -d ' ' -f1) + echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT" + AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1) + echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT" + - uses: actions/checkout@v4 + with: + repository: 'cryptomator/aur-bin' + token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get -y install makepkg pacman-package-manager + - name: Checkout release branch + run: | + git checkout -b release/${{ needs.get-version.outputs.semVerStr }} + - name: Update build file + run: | + sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD + sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD + sed -i -e "s|^sha256sums_x86_64=.*$|sha256sums_x86_64=('${{ steps.checksums.outputs.x64-sha256sum }}'|" PKGBUILD + sed -i -e "s|^sha256sums_aarch64=.*$|sha256sums_aarch64=('${{ steps.checksums.outputs.aarch64-sha256sum}}'|" PKGBUILD + makepkg --printsrcinfo > .SRCINFO + - 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 + id: create-pr + run: | + printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update build instructions\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md + URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md) + echo "PR_URL=$URL" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + - 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: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created." + SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.PR_URL }}|PR> on how to proceed." + SLACK_FOOTER: false + MSG_MINIMAL: true diff --git a/.github/workflows/aur.yml b/.github/workflows/aur.yml index c51976fce..f3b5e3848 100644 --- a/.github/workflows/aur.yml +++ b/.github/workflows/aur.yml @@ -1,4 +1,4 @@ -name: Create PR for aur +name: Create PR for AUR on: release: @@ -50,18 +50,19 @@ jobs: with: repository: 'cryptomator/aur' token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} - - name: Install makepkg - run: sudo apt install makepkg + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install makepkg pacman-package-manager - name: Checkout release branch run: | git checkout -b release/${{ needs.get-version.outputs.semVerStr }} - name: Update build file run: | - sed -i -e 's/pkgver=[0-9]\+\.[0-9]\+\.[0-9]\+.*/pkgver=${${{ needs.get-version.outputs.semVerStr }}//-/_}/g' PKGBUILD - sed -i -e 's/sha256sums=(\'[0-9A-Za-z_\+-]\{64\}\'$/sha256sums=(\'${{ needs.tarball.outputs.sha256 }}\'/g' PKGBUILD + sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD + sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD + sed -i -e "s|^sha256sums=.*$|sha256sums=('${{ needs.tarball.outputs.sha256 }}'|" PKGBUILD makepkg --printsrcinfo > .SRCINFO - # sed -i -e 's/pkgver=[0-9]\+\.[0-9]\+\.[0-9]\+.*/pkgver=${${{ needs.get-version.outputs.semVerStr }}//-/_}/g' PKGBUILD - # sed -i -e 's/sha256sums = [0-9A-Za-z_\+-]\{64\}$/sha256sums = ${{ needs.tarball.outputs.sha256 }}/g'.SRCINFO - name: Commit and push run: | git config user.name "${{ github.actor }}" @@ -79,14 +80,14 @@ jobs: GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} - name: Slack Notification uses: rtCamp/action-slack-notify@v2 - #asdif: github.event_name == 'release' + 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.AUR_PR_URL }}|PR> on how to proceed.>." + SLACK_TITLE: "AUR release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created." + SLACK_MESSAGE: "See <${{ env.AUR_PR_URL }}|PR> on how to proceed." SLACK_FOOTER: false MSG_MINIMAL: true \ No newline at end of file From 94eb1e365b6aaf489bf5598a5ece2776f944898e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Jun 2025 15:40:06 +0200 Subject: [PATCH 06/18] replace token for PR creation --- .github/workflows/appimage.yml | 4 ++-- .github/workflows/aur.yml | 4 ++-- .github/workflows/flathub.yml | 4 ++-- .github/workflows/winget.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index aa49ed4a1..26111c518 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -215,7 +215,7 @@ jobs: - uses: actions/checkout@v4 with: repository: 'cryptomator/aur-bin' - token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Install dependencies run: | sudo apt-get update @@ -245,7 +245,7 @@ jobs: URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md) echo "PR_URL=$URL" >> "$GITHUB_OUTPUT" env: - GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Slack Notification uses: rtCamp/action-slack-notify@v2 env: diff --git a/.github/workflows/aur.yml b/.github/workflows/aur.yml index f3b5e3848..e290be872 100644 --- a/.github/workflows/aur.yml +++ b/.github/workflows/aur.yml @@ -49,7 +49,7 @@ jobs: - uses: actions/checkout@v4 with: repository: 'cryptomator/aur' - token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Install dependencies run: | sudo apt-get update @@ -77,7 +77,7 @@ jobs: PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md) echo "AUR_PR_URL=$PR_URL" >> "$GITHUB_ENV" env: - GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Slack Notification uses: rtCamp/action-slack-notify@v2 if: github.event_name == 'release' diff --git a/.github/workflows/flathub.yml b/.github/workflows/flathub.yml index da8f6c77f..85e2cb435 100644 --- a/.github/workflows/flathub.yml +++ b/.github/workflows/flathub.yml @@ -49,7 +49,7 @@ jobs: - uses: actions/checkout@v4 with: repository: 'flathub/org.cryptomator.Cryptomator' - token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Checkout release branch run: | git checkout -b release/${{ needs.get-version.outputs.semVerStr }} @@ -72,7 +72,7 @@ jobs: 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 }} + GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Slack Notification uses: rtCamp/action-slack-notify@v2 if: github.event_name == 'release' diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml index 476e409e3..0beb75544 100644 --- a/.github/workflows/winget.yml +++ b/.github/workflows/winget.yml @@ -16,7 +16,7 @@ jobs: run: | gh repo sync cryptomator/winget-pkgs -b master --force env: - GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} + GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Submit package uses: vedantmgoyal2009/winget-releaser@main with: @@ -24,4 +24,4 @@ jobs: version: ${{ inputs.tag }} release-tag: ${{ inputs.tag }} installers-regex: '-x64\.msi$' - token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} \ No newline at end of file + token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} \ No newline at end of file From 5d8457cbddfe0f91a114e4782d54ae7edaa76fed Mon Sep 17 00:00:00 2001 From: Mateo Date: Fri, 4 Jul 2025 04:08:22 -0500 Subject: [PATCH 07/18] Feature: Default to previously used vault directory when creating a vault (#3903) --- .../cryptomator/common/settings/Settings.java | 6 +++++ .../common/settings/SettingsJson.java | 4 ++++ .../CreateNewVaultLocationController.java | 22 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/main/java/org/cryptomator/common/settings/Settings.java b/src/main/java/org/cryptomator/common/settings/Settings.java index b382cd1ac..a711e6536 100644 --- a/src/main/java/org/cryptomator/common/settings/Settings.java +++ b/src/main/java/org/cryptomator/common/settings/Settings.java @@ -25,6 +25,8 @@ import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.NodeOrientation; + +import java.nio.file.Path; import java.time.Instant; import java.util.function.Consumer; @@ -75,6 +77,7 @@ public class Settings { public final BooleanProperty checkForUpdates; public final ObjectProperty lastUpdateCheckReminder; public final ObjectProperty lastSuccessfulUpdateCheck; + public final ObjectProperty previouslyUsedVaultDirectory; private Consumer saveCmd; @@ -114,6 +117,7 @@ public class Settings { 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.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory); this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList()); @@ -143,6 +147,7 @@ public class Settings { checkForUpdates.addListener(this::somethingChanged); lastUpdateCheckReminder.addListener(this::somethingChanged); lastSuccessfulUpdateCheck.addListener(this::somethingChanged); + previouslyUsedVaultDirectory.addListener(this::somethingChanged); } @SuppressWarnings("deprecation") @@ -204,6 +209,7 @@ public class Settings { json.checkForUpdatesEnabled = checkForUpdates.get(); json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get(); json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get(); + json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get(); return json; } diff --git a/src/main/java/org/cryptomator/common/settings/SettingsJson.java b/src/main/java/org/cryptomator/common/settings/SettingsJson.java index 15f5f2790..feb8a0bf2 100644 --- a/src/main/java/org/cryptomator/common/settings/SettingsJson.java +++ b/src/main/java/org/cryptomator/common/settings/SettingsJson.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import java.nio.file.Path; import java.time.Instant; import java.util.List; @@ -92,4 +93,7 @@ class SettingsJson { @JsonProperty("quickAccessService") String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE; + + @JsonProperty("previouslyUsedVaultDirectory") + Path previouslyUsedVaultDirectory; } diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java index c8b7bee22..78a2771df 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java @@ -4,6 +4,7 @@ import dagger.Lazy; import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.locationpresets.LocationPreset; import org.cryptomator.common.locationpresets.LocationPresetsProvider; +import org.cryptomator.common.settings.Settings; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -38,6 +39,7 @@ import javafx.stage.WindowEvent; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; @@ -64,6 +66,7 @@ public class CreateNewVaultLocationController implements FxController { private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false); private final ObservableList radioButtons; private final ObservableList sortedRadioButtons; + private final Settings settings; private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH; @@ -82,6 +85,7 @@ public class CreateNewVaultLocationController implements FxController { @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy chooseExpertSettingsScene, // ObjectProperty vaultPath, // @Named("vaultName") StringProperty vaultName, // + Settings settings, // ExecutorService backgroundExecutor, ResourceBundle resourceBundle) { this.window = window; this.chooseNameScene = chooseNameScene; @@ -96,6 +100,18 @@ public class CreateNewVaultLocationController implements FxController { this.usePresetPath = new SimpleBooleanProperty(); this.radioButtons = FXCollections.observableArrayList(); this.sortedRadioButtons = radioButtons.sorted(this::compareLocationPresets); + this.settings = settings; + + Path previouslyUsedDirectory = settings.previouslyUsedVaultDirectory.get(); + if (previouslyUsedDirectory != null) { + try { + if (Files.exists(previouslyUsedDirectory) && Files.isDirectory(previouslyUsedDirectory) && isActuallyWritable(previouslyUsedDirectory)) { + this.customVaultPath = previouslyUsedDirectory; + } + } catch (InvalidPathException | NullPointerException e) { + LOG.warn("Invalid previously used vault directory path: {}", previouslyUsedDirectory, e); + } + } } private VaultPathStatus validatePath(Path p) throws NullPointerException { @@ -196,6 +212,12 @@ public class CreateNewVaultLocationController implements FxController { @FXML public void next() { if (validVaultPath.getValue()) { + if (this.getVaultPath() != null) { + Path parentPath = this.getVaultPath().getParent(); + if (parentPath != null) { + this.settings.previouslyUsedVaultDirectory.setValue(parentPath); + } + } window.setScene(chooseExpertSettingsScene.get()); } } From 9d15a7664dc5f7a53088d64f22df10033abe5515 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 7 Jul 2025 11:14:19 +0200 Subject: [PATCH 08/18] fix docs links --- .../addvaultwizard/CreateNewVaultExpertSettingsController.java | 2 +- .../org/cryptomator/ui/sharevault/ShareVaultController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java index a35bcdebe..9ca557366 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java @@ -26,7 +26,7 @@ public class CreateNewVaultExpertSettingsController implements FxController { public static final int MAX_SHORTENING_THRESHOLD = 220; public static final int MIN_SHORTENING_THRESHOLD = 36; - private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/architecture/#name-shortening"; + private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/vault/#name-shortening"; private final Stage window; private final Lazy application; diff --git a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java index 859c9e38d..93fb298ed 100644 --- a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java +++ b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java @@ -19,7 +19,7 @@ public class ShareVaultController implements FxController { private static final String SCHEME_PREFIX = "hub+"; private static final String VISIT_HUB_URL = "https://cryptomator.org/hub/"; - private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/en/latest/security/best-practices/#sharing-of-vaults"; + private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/security/best-practices/#sharing-of-vaults"; private final Stage window; private final Lazy application; From 78cffe2f60eb1bdbcf9bf2c336e9a78aa8316264 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 7 Jul 2025 11:32:19 +0200 Subject: [PATCH 09/18] fix password tab on migrated legacy vaults --- .../org/cryptomator/common/vaults/VaultListManager.java | 4 ++-- .../org/cryptomator/ui/keyloading/KeyLoadingStrategy.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index 6dacfcb8a..ce1b2433c 100644 --- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -9,13 +9,13 @@ package org.cryptomator.common.vaults; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.Constants; 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.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -125,7 +125,7 @@ public class VaultListManager { vaultSettings.lastKnownKeyLoader.set(keyIdScheme); } } else if (vaultState == NEEDS_MIGRATION) { - vaultSettings.lastKnownKeyLoader.set(Constants.DEFAULT_KEY_ID.toString()); + vaultSettings.lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME); } return vaultComponentFactory.create(vaultSettings, wrapper, vaultState, null).vault(); } catch (IOException e) { diff --git a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java index b9af0f4a3..eb6ecbfa3 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java +++ b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java @@ -46,15 +46,16 @@ public interface KeyLoadingStrategy extends MasterkeyLoader { /** * Determines whether the provided key loader scheme corresponds to a Masterkey File Vault. *

- * This method checks if the {@code keyLoader} parameter matches the known Masterkey File Vault scheme + * This method checks if the {@code keyLoader} parameter starts with the known Masterkey File Vault scheme * {@link MasterkeyFileLoadingStrategy#SCHEME}. + * This allows identifying not only exact matches but also variants or extended schemes based on the Masterkey scheme. *

* * @param keyLoader A string representing the key loader scheme to be checked. - * @return {@code true} if the given key loader scheme represents a Masterkey File Vault; {@code false} otherwise. + * @return {@code true} if the given key loader scheme starts with the Masterkey File Vault scheme; {@code false} otherwise. */ static boolean isMasterkeyFileVault(String keyLoader) { - return MasterkeyFileLoadingStrategy.SCHEME.equals(keyLoader); + return keyLoader.startsWith(MasterkeyFileLoadingStrategy.SCHEME); } /** From 54b7f3c842996c5e3c830b05bc4075cacda1a712 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 7 Jul 2025 16:13:17 +0200 Subject: [PATCH 10/18] exclude early access javafx versions in dependency updates --- .github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b2ace54c2..ea6be2047 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,6 +14,8 @@ updates: versions: ["2.0.1.MR"] - dependency-name: "org.openjfx:*" update-types: ["version-update:semver-major"] + - dependency-name: "org.openjfx:*" + versions: ["*-ea*"] groups: java-test-dependencies: patterns: From 5a086f52b5f6092b01d9fe31444e5faca21e5651 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 8 Jul 2025 13:35:43 +0200 Subject: [PATCH 11/18] Revert "exclude early access javafx versions in dependency updates" This reverts commit 54b7f3c842996c5e3c830b05bc4075cacda1a712. --- .github/dependabot.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ea6be2047..b2ace54c2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,8 +14,6 @@ updates: versions: ["2.0.1.MR"] - dependency-name: "org.openjfx:*" update-types: ["version-update:semver-major"] - - dependency-name: "org.openjfx:*" - versions: ["*-ea*"] groups: java-test-dependencies: patterns: From 698ac639e96dcf4340447b79d8988915cd6abbce Mon Sep 17 00:00:00 2001 From: Cryptobot Date: Tue, 8 Jul 2025 13:40:09 +0200 Subject: [PATCH 12/18] New Crowdin updates (#3913) New translations strings.properties Arabic; Portuguese; [ci skip] --- src/main/resources/i18n/strings_ar.properties | 46 ++++++++++++++++-- src/main/resources/i18n/strings_pt.properties | 48 +++++++++---------- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/main/resources/i18n/strings_ar.properties b/src/main/resources/i18n/strings_ar.properties index 4e4b34095..f69f4b67c 100644 --- a/src/main/resources/i18n/strings_ar.properties +++ b/src/main/resources/i18n/strings_ar.properties @@ -62,9 +62,9 @@ addvaultwizard.new.locationIsOk=الموقع المناسب للمخزن الخ addvaultwizard.new.invalidName=اسم المخزن غير صالح addvaultwizard.new.validName=اسم المخزن صالح addvaultwizard.new.validCharacters.message=قد يحتوي اسم المخزن على الأحرف التالية: -addvaultwizard.new.validCharacters.chars=أحرف الكلمات (أمثلة: a, ж, 수) -addvaultwizard.new.validCharacters.numbers=الأعداد -addvaultwizard.new.validCharacters.dashes=الشرطة (%s) أو الشرطة السفلية (%s) +addvaultwizard.new.validCharacters.chars=أحرف لكن دون علامات (#, $, !, @...) +addvaultwizard.new.validCharacters.numbers=الأرقام +addvaultwizard.new.validCharacters.dashes=ناقص (%s) أو شِرْطَةٌ سفلية (%s) ### Expert Settings addvaultwizard.new.expertSettings.enableExpertSettingsCheckbox=تمكين إعدادات الخبراء addvaultwizard.new.expertSettings.shorteningThreshold.invalid=أدخل قيمة بين 36 و 220 (الافتراضي 220) @@ -319,7 +319,7 @@ preferences.volume.feature.readOnly=تحميل للقراءة فقط ## Updates preferences.updates=تحديثات preferences.updates.currentVersion=الإصدار الحالي: %s -preferences.updates.autoUpdateCheck=تحقق من التحديثات اوتوماتيكيا +preferences.updates.autoUpdateCheck=التحقق من وجود تحديثات تلقائياً preferences.updates.checkNowBtn=تحقق الان preferences.updates.updateAvailable=التحديث إلى الإصدار %s متاح. preferences.updates.lastUpdateCheck=آخر فحص: %s @@ -395,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=إظهار خيارات المخزن main.vaultlist.contextMenu.reveal=اظهار القرص main.vaultlist.addVaultBtn.menuItemNew=إنشاء مخزن جديد... main.vaultlist.addVaultBtn.menuItemExisting=افتح مخزن موجود... +main.vaultlist.showEventsButton.tooltip=عرض الإشعارات ##Notificaition main.notification.updateAvailable=هناك تحديث متاح. main.notification.support=دعم Cryptomator. @@ -423,7 +424,9 @@ main.vaultDetail.stats=إحصائيات الخزنة main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة! +main.vaultDetail.locateEncrypted.filePickerTitle=اختر الملَف من الخزنة main.vaultDetail.decryptName.buttonLabel=فك تشفير اسم الملف +main.vaultDetail.decryptName.tooltip=اختر ملَف مشفر لفك تشفير اسمه ### Missing main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار. main.vaultDetail.missing.recheck=إعادة الفحص @@ -473,7 +476,7 @@ vaultOptions.mount.mountPoint.custom=استخدام المجلد المختار vaultOptions.mount.mountPoint.directoryPickerButton=اختر… vaultOptions.mount.mountPoint.directoryPickerTitle=إختر مجلد vaultOptions.mount.volumeType.default=الافتراضي (%s) -vaultOptions.mount.volumeType.restartRequired=لاستخدام هذا النوع ‮من وحدة التخزين يحتاج Cryptomator إلى إعادة تشغيله. +vaultOptions.mount.volumeType.restartRequired=لاستخدام هذا النوع من وحدة التخزين يحتاج Cryptomator إلى إعادة تشغيل. vaultOptions.mount.volume.tcp.port=منفذ TCP vaultOptions.mount.volume.type=‮نوع وحدة التخزين ## Master Key @@ -580,7 +583,40 @@ shareVault.hub.instruction.2=2. امنح الوصول لعضو الفريق في shareVault.hub.openHub=زيارة Cryptomator Hub # Decrypt File Names +decryptNames.title=فك تشفير اسم الملَف +decryptNames.filePicker.title=اختر ملَف مشفر +decryptNames.filePicker.extensionDescription=ملف مشفر +decryptNames.copyTable.tooltip=نسخ الجدول +decryptNames.clearTable.tooltip=مسح الجدول +decryptNames.copyHint=نسخ محتوى الخلية مع %s +decryptNames.dropZone.message=إسقاط الملفات أو انقر لتحديد +decryptNames.dropZone.error.vaultInternalFiles=مخزن الملفات الداخلية مع عدم تحديد اسم قابل للتشفير +decryptNames.dropZone.error.foreignFiles=الملفات لا تنتمي إلى مخزن "%s" +decryptNames.dropZone.error.noDirIdBackup=مسار الملفات المحددة لا يحتوي على ملَف dirId.c9r +decryptNames.dropZone.error.generic=فشل فك تشفير أسماء الملفات # Event View +eventView.title=أحداث +eventView.filter.allVaults=الكل +eventView.clearListButton.tooltip=تفريغ القائمة ## event list entries +eventView.entry.vaultLocked.description=فتح "%s" للحصول على التفاصيل +eventView.entry.conflictResolved.message=تم حل التضارب +eventView.entry.conflictResolved.showDecrypted=إظهار الملف غير المشفر +eventView.entry.conflictResolved.copyDecrypted=نسخ المسار غير المشفر +eventView.entry.conflict.message=فشل حل التضارب +eventView.entry.conflict.showDecrypted=إظهار الملَف غير المشفر الأصلي +eventView.entry.conflict.copyDecrypted=نسخ المسار غير المشفر والأصلي +eventView.entry.conflict.showEncrypted=إظهار ملف متضارب ومشفر +eventView.entry.conflict.copyEncrypted=نسخ مسار التشفير المتعارض +eventView.entry.decryptionFailed.message=فشل فك التشفير +eventView.entry.decryptionFailed.showEncrypted=عرض ملَف المشفر +eventView.entry.decryptionFailed.copyEncrypted=نسخ مسار المشفر +eventView.entry.brokenDirFile.message=رابط الدليل المكسور +eventView.entry.brokenDirFile.showEncrypted=إظهار الرابط المكسور، المشفر +eventView.entry.brokenDirFile.copyEncrypted=نسخ مسار الرابط المكسور +eventView.entry.brokenFileNode.message=عقدة ملفات النظام التافلة +eventView.entry.brokenFileNode.showEncrypted=عرض العقدة المشفّرة التافلة +eventView.entry.brokenFileNode.copyEncrypted=نسخ مسار العقدة المشفّرة التافلة +eventView.entry.brokenFileNode.copyDecrypted=نسخ المسار غير المشفر diff --git a/src/main/resources/i18n/strings_pt.properties b/src/main/resources/i18n/strings_pt.properties index e123071b0..bb048b2cf 100644 --- a/src/main/resources/i18n/strings_pt.properties +++ b/src/main/resources/i18n/strings_pt.properties @@ -424,9 +424,9 @@ main.vaultDetail.stats=Estatísticas do Cofre main.vaultDetail.locateEncryptedFileBtn=Localizar Ficheiro Encriptado main.vaultDetail.locateEncryptedFileBtn.tooltip=Escolha um ficheiro do seu cofre para localizar a sua contraparte encriptada main.vaultDetail.encryptedPathsCopied=Caminhos copiados para a área de transferência! -main.vaultDetail.locateEncrypted.filePickerTitle=Selecionar ficheiro dentro do cofre -main.vaultDetail.decryptName.buttonLabel=Desencriptar nome do ficheiro -main.vaultDetail.decryptName.tooltip=Escolha um ficheiro de cofre encriptado para desencriptar o seu nome +main.vaultDetail.locateEncrypted.filePickerTitle=Selecione o ficheiro no cofre +main.vaultDetail.decryptName.buttonLabel=Descriptografar o nome do ficheiro +main.vaultDetail.decryptName.tooltip=Escolha um ficheiro encriptado do cofre para desencriptar o seu nome ### Missing main.vaultDetail.missing.info=O Cryptomator não conseguiu encontrar um cofre neste diretório. main.vaultDetail.missing.recheck=Verificar novamente @@ -583,17 +583,17 @@ shareVault.hub.instruction.2=2. Conceder acesso ao membro da equipe no Hub Crypt shareVault.hub.openHub=Abrir Hub do Cryptomator # Decrypt File Names -decryptNames.title=Desencriptar nomes de ficheiros +decryptNames.title=Desencriptar os nomes dos ficheiros decryptNames.filePicker.title=Selecione o ficheiro encriptado -decryptNames.filePicker.extensionDescription=Ficheiro encriptado do Cryptomator -decryptNames.copyTable.tooltip=Copiar tabela -decryptNames.clearTable.tooltip=Limpar tabela -decryptNames.copyHint=Copiar conteúdo da célula com %s -decryptNames.dropZone.message=Solte os ficheiros ou clique para selecionar -decryptNames.dropZone.error.vaultInternalFiles=Ficheiros internos do cofre sem nome decifrável selecionado -decryptNames.dropZone.error.foreignFiles=Ficheiros não pertencem ao cofre "%s" +decryptNames.filePicker.extensionDescription=Ficheiro encriptado pelo Criptomator +decryptNames.copyTable.tooltip=Copiar a tabela +decryptNames.clearTable.tooltip=Limpar a tabela +decryptNames.copyHint=Copiar o conteúdo da célula com %s +decryptNames.dropZone.message=Largue os ficheiros ou clique para selecionar +decryptNames.dropZone.error.vaultInternalFiles=Ficheiros internos do coftre sem nome desencriptável selecionado +decryptNames.dropZone.error.foreignFiles=Os ficheiros não pertencem ao cofre "%s" decryptNames.dropZone.error.noDirIdBackup=O diretório dos ficheiros selecionados não contém o ficheiro dirId.c9r -decryptNames.dropZone.error.generic=Falha ao desencriptar nomes de ficheiros +decryptNames.dropZone.error.generic=Falha ao desencriptar os nomes dos ficheiros # Event View @@ -603,20 +603,20 @@ eventView.clearListButton.tooltip=Limpar lista ## event list entries eventView.entry.vaultLocked.description=Desbloquear "%s" para detalhes eventView.entry.conflictResolved.message=Conflito resolvido -eventView.entry.conflictResolved.showDecrypted=Mostrar ficheiro desencriptado -eventView.entry.conflictResolved.copyDecrypted=Copiar caminho desencriptado -eventView.entry.conflict.message=Resolução de conflito falhou -eventView.entry.conflict.showDecrypted=Mostrar ficheiro original desencriptado -eventView.entry.conflict.copyDecrypted=Copie caminho original desencriptado -eventView.entry.conflict.showEncrypted=Mostrar ficheiro encriptado conflitante -eventView.entry.conflict.copyEncrypted=Copiar caminho encriptado conflituante -eventView.entry.decryptionFailed.message=Falha na desencriptação +eventView.entry.conflictResolved.showDecrypted=Mostrar o ficheiro desencriptado +eventView.entry.conflictResolved.copyDecrypted=Copiar o caminho desencriptado +eventView.entry.conflict.message=A resolução do conflito falhou +eventView.entry.conflict.showDecrypted=Mostrar o ficheiro original desencriptado +eventView.entry.conflict.copyDecrypted=Copie o caminho original desencriptado +eventView.entry.conflict.showEncrypted=Mostrar o ficheiro encriptado em conflito +eventView.entry.conflict.copyEncrypted=Copiar o caminho encriptado em conflito +eventView.entry.decryptionFailed.message=A desencriptação falhou eventView.entry.decryptionFailed.showEncrypted=Mostrar ficheiro encriptado -eventView.entry.decryptionFailed.copyEncrypted=Copiar caminho de encriptação +eventView.entry.decryptionFailed.copyEncrypted=Copiar o caminho encriptado eventView.entry.brokenDirFile.message=Link de diretório quebrado -eventView.entry.brokenDirFile.showEncrypted=Mostrar link quebrado e encriptado +eventView.entry.brokenDirFile.showEncrypted=Mostrar o link quebrado e encriptado eventView.entry.brokenDirFile.copyEncrypted=Copiar caminho do link quebrado eventView.entry.brokenFileNode.message=Nó do sistema de ficheiros avariado -eventView.entry.brokenFileNode.showEncrypted=Mostrar nó encriptado quebrado +eventView.entry.brokenFileNode.showEncrypted=Mostrar nó encriptado e danificado eventView.entry.brokenFileNode.copyEncrypted=Copiar o caminho do nó encriptado e danificado -eventView.entry.brokenFileNode.copyDecrypted=Copiar caminho desencriptado +eventView.entry.brokenFileNode.copyDecrypted=Copiar o caminho desencriptado From d74248ff639cdacf2e7a2d6146e842441606d82a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 8 Jul 2025 13:41:04 +0200 Subject: [PATCH 13/18] prepare 1.17.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index caba8e342..cb8d62ba0 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.cryptomator cryptomator - 1.18.0-SNAPSHOT + 1.17.1 Cryptomator Desktop App From 581b16e35448feec35e1cfcb7531ebc67b4237b6 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 8 Jul 2025 13:42:43 +0200 Subject: [PATCH 14/18] finalize 1.17.1 --- dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml index b088836f7..e986431a8 100644 --- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml +++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml @@ -83,6 +83,9 @@ + + https://github.com/cryptomator/cryptomator/releases/1.17.1 + https://github.com/cryptomator/cryptomator/releases/1.17.0 From 7ad9b10138e54c5ac4278fca3c09f0fb440e69f2 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 8 Jul 2025 17:43:08 +0200 Subject: [PATCH 15/18] Feature: Windows debug launcher (#2666) Add additonal launcher to windows release to debug javafx problems. --- .github/workflows/win-exe.yml | 9 ++- dist/win/.gitignore | 3 +- dist/win/build.bat | 6 +- dist/win/build.ps1 | 96 ++++++++++++++++++++---------- dist/win/debug-launcher.properties | 4 ++ dist/win/launcher.bat | 15 ----- 6 files changed, 79 insertions(+), 54 deletions(-) create mode 100644 dist/win/debug-launcher.properties delete mode 100644 dist/win/launcher.bat diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index cfbbc05a7..70e05f892 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -126,9 +126,6 @@ jobs: --no-man-pages --strip-debug --compress zip-0 - - name: Change win-console flag if debug is active - if: ${{ inputs.isDebug }} - run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV - name: Run jpackage run: > ${JAVA_HOME}/bin/jpackage @@ -166,7 +163,7 @@ jobs: --java-options "-Djavafx.verbose=${{ inputs.isDebug }}" --resource-dir dist/win/resources --icon dist/win/resources/Cryptomator.ico - ${WIN_CONSOLE_FLAG} + --add-launcher "Cryptomator (Debug)=dist/win/debug-launcher.properties" - name: Patch Application Directory run: | cp dist/win/contrib/* appdir/Cryptomator @@ -181,7 +178,9 @@ jobs: exit 1 } - name: Fix permissions - run: attrib -r appdir/Cryptomator/Cryptomator.exe + run: | + attrib -r appdir/Cryptomator/Cryptomator.exe + attrib -r "appdir/Cryptomator/Cryptomator (Debug).exe" shell: pwsh - name: Extract jars with DLLs for Codesigning shell: pwsh diff --git a/dist/win/.gitignore b/dist/win/.gitignore index 7b2faa4b5..a9cb10372 100644 --- a/dist/win/.gitignore +++ b/dist/win/.gitignore @@ -4,7 +4,8 @@ installer *.wixobj *.pdb *.msi +*Debug.properties *.exe *.jmod resources/jfxJmods.zip -license.rtf \ No newline at end of file +license.rtf diff --git a/dist/win/build.bat b/dist/win/build.bat index 3532a69fd..c8f23a82b 100644 --- a/dist/win/build.bat +++ b/dist/win/build.bat @@ -11,6 +11,10 @@ SET HELP_URL="https://cryptomator.org/contact/" SET MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator" SET LOOPBACK_ALIAS="cryptomator-vault" +:: read clean parameter from command line +SET CLEAN=0 +IF "%~1"=="clean" SET CLEAN=1 + pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^ -AppName %APPNAME%^ -MainJarGlob "%MAIN_JAR_GLOB%"^ @@ -22,4 +26,4 @@ pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^ -HelpUrl "%HELP_URL%"^ -UpdateUrl "%UPDATE_URL%"^ -LoopbackAlias "%LOOPBACK_ALIAS%"^ - -Clean 1 \ No newline at end of file + -Clean %CLEAN% \ No newline at end of file diff --git a/dist/win/build.ps1 b/dist/win/build.ps1 index a861cf40d..b1706a28e 100644 --- a/dist/win/build.ps1 +++ b/dist/win/build.ps1 @@ -9,9 +9,15 @@ Param( [Parameter(Mandatory, HelpMessage="Please provide an update url")][string] $UpdateUrl, [Parameter(Mandatory, HelpMessage="Please provide an about url")][string] $AboutUrl, [Parameter(Mandatory, HelpMessage="Please provide an alias for localhost")][string] $LoopbackAlias, - [bool] $clean + [bool] $clean = $false # if true, cleans up previous build artifacts ) +# ============================ +# Function Definitions Section +# ============================ + +function Main { + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $ProgressPreference = 'SilentlyContinue' # disables Invoke-WebRequest's progress bar, which slows down downloads to a few bytes/s @@ -50,11 +56,11 @@ $version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project. $semVerNo = $version -replace '(\d+\.\d+\.\d+).*','$1' $revisionNo = $(git rev-list --count HEAD) -Write-Output "`$version=$version" -Write-Output "`$semVerNo=$semVerNo" -Write-Output "`$revisionNo=$revisionNo" -Write-Output "`$buildDir=$buildDir" -Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME" +Write-Host "`$version=$version" +Write-Host "`$semVerNo=$semVerNo" +Write-Host "`$revisionNo=$revisionNo" +Write-Host "`$buildDir=$buildDir" +Write-Host "`$Env:JAVA_HOME=$Env:JAVA_HOME" $copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor" @@ -71,7 +77,7 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) { ## download jfx jmods for X64, while they are part of the Arm64 JDK $archCode = (Get-CimInstance Win32_Processor).Architecture $archName = switch ($archCode) { - 9 { "x64 (AMD64)" } + 9 { "x64" } 12 { "ARM64" } default { "WMI Win32_Processor.Architecture code ($archCode)" } } @@ -86,14 +92,14 @@ switch ($archName) { $jmodPaths = "$Env:JAVA_HOME/jmods" } - 'x64 (AMD64)' { + 'x64' { $javaFxVersion='24.0.1' $javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip" $javaFxJmodsSHA256 = 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f' $javaFxJmods = '.\resources\jfxJmods.zip' if( !(Test-Path -Path $javaFxJmods) ) { - Write-Output "Downloading ${javaFxJmodsUrl}..." + Write-Host "Downloading ${javaFxJmodsUrl}..." Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default } @@ -139,6 +145,29 @@ if ($clean -and (Test-Path -Path $appPath)) { Remove-Item -Path $appPath -Force -Recurse } + +$javaOptions = @( +"--java-options", "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win" +"--java-options", "-Xss5m" +"--java-options", "-Xmx256m" +"--java-options", "-Dcryptomator.appVersion=`"$semVerNo`"" +"--java-options", "-Dfile.encoding=`"utf-8`"" +"--java-options", "-Djava.net.useSystemProxies=true" +"--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" +"--java-options", "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" +"--java-options", "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`"" +"--java-options", "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`"" +"--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`"" +"--java-options", "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`"" +"--java-options", "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" +"--java-options", "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" +"--java-options", "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" +"--java-options", "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`"" +"--java-options", "-Dcryptomator.showTrayIcon=true" +"--java-options", "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" +) + + # create app dir & "$Env:JAVA_HOME\bin\jpackage" ` --verbose ` @@ -151,28 +180,16 @@ if ($clean -and (Test-Path -Path $appPath)) { --name $AppName ` --vendor $Vendor ` --copyright $copyright ` - --java-options "--enable-preview" ` - --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win" ` - --java-options "-Xss5m" ` - --java-options "-Xmx256m" ` - --java-options "-Dcryptomator.appVersion=`"$semVerNo`"" ` --app-version "$semVerNo.$revisionNo" ` - --java-options "-Dfile.encoding=`"utf-8`"" ` - --java-options "-Djava.net.useSystemProxies=true" ` - --java-options "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" ` - --java-options "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" ` - --java-options "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`"" ` - --java-options "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`"" ` - --java-options "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`"" ` - --java-options "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`"" ` - --java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" ` - --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" ` - --java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" ` - --java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`"" ` - --java-options "-Dcryptomator.showTrayIcon=true" ` - --java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" ` --resource-dir resources ` - --icon resources/$AppName.ico + --icon resources/$AppName.ico ` + --add-launcher "${AppName} (Debug)=$buildDir\debug-launcher.properties" ` + @javaOptions + +if ($LASTEXITCODE -ne 0) { + Write-Error "jpackage Appimage failed with exit code $LASTEXITCODE" + return 1; +} #Create RTF license for msi &mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" ` @@ -187,6 +204,7 @@ if ($clean -and (Test-Path -Path $appPath)) { # patch app dir Copy-Item "contrib\*" -Destination "$AppName" attrib -r "$AppName\$AppName.exe" +attrib -r "$AppName\${AppName} (Debug).exe" # patch batch script to set hostfile $webDAVPatcher = "$AppName\patchWebDAV.bat" try { @@ -237,7 +255,7 @@ if ($LASTEXITCODE -ne 0) { # download Winfsp $winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi' $winfspMsiHash = '073A70E00F77423E34BED98B86E600DEF93393BA5822204FAC57A29324DB9F7A' -Write-Output "Downloading ${winfspMsiUrl}..." +Write-Host "Downloading ${winfspMsiUrl}..." Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default $computedHash = $(Get-FileHash -Path '.\bundle\resources\winfsp.msi' -Algorithm SHA256).Hash if (! $computedHash.Equals($winfspMsiHash)) { @@ -251,7 +269,7 @@ if (! $computedHash.Equals($winfspMsiHash)) { # download legacy-winfsp uninstaller $winfspUninstaller= 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe' -Write-Output "Downloading ${winfspUninstaller}..." +Write-Host "Downloading ${winfspUninstaller}..." Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninstaller.exe" # redirects are followed by default # copy MSI to bundle resources @@ -271,4 +289,18 @@ Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName .\bundle\bundleWithWinfsp.wxs ` -out "installer\$AppName-Installer.exe" -Write-Output "Created EXE installer .\installer\$AppName-Installer.exe" +Write-Host "Created EXE installer .\installer\$AppName-Installer.exe" +return 0; +} + +# ============================ +# Script Execution Starts Here +# ============================ +if ($clean) { + Write-Host "Cleaning up previous build artifacts..." + Remove-Item -Path ".\runtime" -Force -Recurse -ErrorAction Ignore + Remove-Item -Path ".\$AppName" -Force -Recurse -ErrorAction Ignore + Remove-Item -Path ".\installer" -Force -Recurse -ErrorAction Ignore +} +return Main + diff --git a/dist/win/debug-launcher.properties b/dist/win/debug-launcher.properties new file mode 100644 index 000000000..d8789ab7a --- /dev/null +++ b/dist/win/debug-launcher.properties @@ -0,0 +1,4 @@ +win-console=true +win-shortcut=false +win-menu=false +description=Debug Launcher with Console for Cryptomator \ No newline at end of file diff --git a/dist/win/launcher.bat b/dist/win/launcher.bat deleted file mode 100644 index 0e6ec7042..000000000 --- a/dist/win/launcher.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -java ^ - -p "mods" ^ - -cp "libs/*" ^ - -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" ^ - -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^ - -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^ - -Dcryptomator.mountPointsDir="~/Cryptomator" ^ - -Dcryptomator.integrationsWin.keychainPaths="~/AppData/Roaming/Cryptomator/keychain.json" ^ - -Dcryptomator.integrationsWin.windowsHelloKeychainPaths="~/AppData/Roaming/Cryptomator/windowsHelloKeychain.json" ^ - -Xss20m ^ - -Xmx512m ^ - --enable-preview ` - --enable-native-access=org.cryptomator.jfuse.win ` - -m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator From 27c10080d66f335b3408c59b1875aab792af3902 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 14 Jul 2025 12:20:49 +0200 Subject: [PATCH 16/18] fixes #3925 Stop listening for ipc messages when to many failed requests in a row --- src/main/java/org/cryptomator/ipc/Server.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/cryptomator/ipc/Server.java b/src/main/java/org/cryptomator/ipc/Server.java index 770373681..193a2ff6b 100644 --- a/src/main/java/org/cryptomator/ipc/Server.java +++ b/src/main/java/org/cryptomator/ipc/Server.java @@ -53,18 +53,26 @@ class Server implements IpcCommunicator { @Override public void listen(IpcMessageListener listener, Executor executor) { executor.execute(() -> { + int errorCount = 0; while (serverSocketChannel.isOpen()) { try (var ch = serverSocketChannel.accept()) { while (ch.isConnected()) { var msg = IpcMessage.receive(ch); listener.handleMessage(msg); } + errorCount = 0; } catch (AsynchronousCloseException e) { + LOG.info("Closing server socket due to closed channel."); return; // serverSocketChannel closed or listener interrupted } catch (EOFException | ClosedChannelException e) { // continue with next connected client } catch (IOException e) { + errorCount++; LOG.error("Failed to read IPC message", e); + if(errorCount > 100) { //apparently something is broken, prevent log spam + LOG.info("Closing server socket due to too many failed requests."); + return; + } } } }); From 8b1d2101db05715fa77957da0d062ebe1a37fc3b Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 28 Jul 2025 15:13:15 +0200 Subject: [PATCH 17/18] Feature: Switch to different windows signer (#3943) Replace usage of signtool with Actalis code signer. --- .github/actions/win-sign-action/action.yml | 145 +++++++++++++++++++++ .github/workflows/win-exe.yml | 67 +++++----- 2 files changed, 180 insertions(+), 32 deletions(-) create mode 100644 .github/actions/win-sign-action/action.yml diff --git a/.github/actions/win-sign-action/action.yml b/.github/actions/win-sign-action/action.yml new file mode 100644 index 000000000..a57e8f7b1 --- /dev/null +++ b/.github/actions/win-sign-action/action.yml @@ -0,0 +1,145 @@ +name: 'Windows Signing' +description: 'Sign files on Windows' +inputs: + base-dir: + description: 'The base directory to search for files' + required: true + file-extensions: + description: 'List of file extensions to sign, separated by comma' + required: true + username: + description: 'Username for signing' + required: true + password: + description: 'Password for signing' + required: true + recursive: + description: 'Whether to search recursively in subdirectories' + required: false + default: 'false' + sign-description: + description: 'Signature description' + required: false + default: 'Cryptomator' + sign-url: + description: 'Signature URL' + required: false + default: 'https://cryptomator.org' + +runs: + using: "composite" + steps: + - name: Download Actalis CodeSigner if not present + id: download-signer + run: | + if (! (Test-Path -Path '${{ env.SIGNER_PATH }}')) { + echo "Downloading Actalis CodeSigner..." + curl --output "${{ env.SIGNER_NAME }}.zip" -L "${{ env.SIGNER_URL }}" + if (!(Get-FileHash -Path "${{ env.SIGNER_NAME }}.zip" -Algorithm SHA256).Hash.ToLower().equals("${{ env.SIGNER_HASH }}")) { + echo "Signer hash mismatch, exiting." + exit 1 + } + Expand-Archive -Path "${{ env.SIGNER_NAME }}.zip" -DestinationPath "${{ env.SIGNER_NAME }}" -Force + } + env: + SIGNER_PATH: ${{ github.workspace }}/actalis-signer/ActalisCodeSigner.exe + SIGNER_NAME: actalis-signer + SIGNER_URL: 'https://static.cryptomator.org/other/CodeSigner-win-x64-latest.zip' + SIGNER_HASH: '44a1e09ab72707d049d3e59656e3e35de92e8cda357eec1cfc367016e45835ab' + shell: pwsh + - name: Generate, mask, and output the input secrets + id: set-secrets + run: | + echo "::add-mask::${{ inputs.username }}" + echo "::add-mask::${{ inputs.password }}" + echo "username=${{ inputs.username }}" >> "$GITHUB_OUTPUT" + echo "password=${{ inputs.password }}" >> "$GITHUB_OUTPUT" + shell: bash + - name: Sign DLLs with Actalis CodeSigner + run: | + $signerPath = '${{ env.SIGNER_PATH }}' + $username = '${{ steps.set-secrets.outputs.username }}' + $password = '${{ steps.set-secrets.outputs.password }}' + $signDescription = '${{ inputs.sign-description }}' + $signUrl = '${{ inputs.sign-url }}' + $extensions = '${{ inputs.file-extensions }}'.split(",") | ForEach-Object { "*.$($_.Trim())" } + $recursive = '${{ inputs.recursive }}' -eq 'true' + $files = Get-ChildItem -Path '${{ inputs.base-dir }}\*' -Include $extensions -Recurse:$recursive + + if($files.Count -eq 0) { + Write-Host "`n❌ No files found to sign." + exit 1 + } + Write-Host "`n📝 Found $($files.Count) files to sign:" + $files | ForEach-Object { Write-Host " - $($_.FullName)" } + + # Create log directory + $logDir = "~/.Acsi/log" + if (!(Test-Path $logDir)) { + New-Item -Path $logDir -ItemType Directory -Force | Out-Null + } + + $jobs = @() + foreach ($file in $files) { + # Run signing in a job + $job = Start-Job -ScriptBlock { + param($signerPath, $username, $password, $signDescription, $signUrl, $filePath) + + Write-Host "`n🔐 Signing: $($filePath)" + $logFile = "~/.Acsi/log/$(Split-Path -Leaf $filePath).log" + $arguments = @( + '-ts', + 'http://timestamp.digicert.com', + '-fu', $username, + '-fp', $password, + '-pm', "`"$signDescription`"", + '--program-url', $signUrl, + '-in', "`"$filePath`"" + ) + $process = Start-Process -FilePath "$signerPath" -ArgumentList $arguments -Wait -PassThru -RedirectStandardOutput "$logFile" -NoNewWindow + + return @{ + FilePath = $filePath + ExitCode = $process.ExitCode + LogFile = $logFile + } + } -ArgumentList $signerPath, $username, $password, $signDescription, $signUrl, $file.FullName + $jobs += $job + + # Throttle to max 5 concurrent jobs + if ($jobs.Count -ge 5) { + $completed = $jobs | Wait-Job -Any + $result = $completed | Receive-Job + + # Check result and exit on failure + if ($result.ExitCode -ne 0) { + $jobs | Stop-Job | Remove-Job + Write-Host "❌ Signing failed for $($result.FilePath) with exit code: $($result.ExitCode)" + exit 1 + } + Write-Host " ✅ Successfully signed $($result.FilePath)" + + $jobs = $jobs | Where-Object { $_.Id -ne $completed.Id } + $completed | Remove-Job + + } + } + # Wait for remaining jobs + $jobs | Wait-Job | Receive-Job | ForEach-Object { + if ($_.ExitCode -ne 0) { + Write-Host "❌ Signing failed for $($_.FilePath) with exit code: $($_.ExitCode)" + exit 1 + } + Write-Host " ✅ Successfully signed $($_.FilePath)" + } + Write-Host "`n✅ Successfully signed $($files.Count) files." + env: + SIGNER_PATH: ${{ github.workspace }}/actalis-signer/ActalisCodeSigner.exe + shell: pwsh + - name: Upload log on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: signing-log-${{ runner.arch }} + path: | + ~/.Acsi/log/*.log diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 70e05f892..629cb56be 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -12,6 +12,11 @@ on: description: 'Build debug version with console output' type: boolean default: false + sign: + description: 'Sign binaries' + required: false + type: boolean + default: false push: branches-ignore: - 'dependabot/**' @@ -205,16 +210,15 @@ jobs: New-Item -Path appdir/jpackage-jmod -ItemType Directory & $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod" Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir" - - name: Codesign - uses: skymatic/code-sign-action@v3 + - name: Sign DLLs with Actalis CodeSigner + if: inputs.sign || github.event_name == 'release' + uses: ./.github/actions/win-sign-action with: - certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} - password: ${{ secrets.WIN_CODESIGN_P12_PW }} - certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A - description: Cryptomator - timestampUrl: 'http://timestamp.digicert.com' - folder: appdir + base-dir: 'appdir' + file-extensions: 'dll,exe,ps1' recursive: true + username: ${{ secrets.WIN_CODESIGN_USERNAME }} + password: ${{ secrets.WIN_CODESIGN_PW }} - name: Replace DLLs inside jars with signed ones shell: pwsh run: | @@ -263,15 +267,15 @@ jobs: 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 + - name: Sign msi with Actalis CodeSigner + if: inputs.sign || github.event_name == 'release' + uses: ./.github/actions/win-sign-action with: - certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} - password: ${{ secrets.WIN_CODESIGN_P12_PW }} - certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A - description: Cryptomator Installer - timestampUrl: 'http://timestamp.digicert.com' - folder: installer + base-dir: 'installer' + file-extensions: 'msi' + sign-description: 'Cryptomator Installer' + username: ${{ secrets.WIN_CODESIGN_USERNAME }} + password: ${{ secrets.WIN_CODESIGN_PW }} - name: Add possible alpha/beta tags and architecture to installer name run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi - name: Create detached GPG signature with key 615D449FE6E6A235 @@ -374,27 +378,26 @@ jobs: - name: Detach burn engine in preparation to sign run: > wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe - - name: Codesign burn engine - uses: skymatic/code-sign-action@v3 + - name: Sign burn engine with Actalis CodeSigner + if: inputs.sign || github.event_name == 'release' + uses: ./.github/actions/win-sign-action with: - certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} - password: ${{ secrets.WIN_CODESIGN_P12_PW }} - certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A - description: Cryptomator Installer - timestampUrl: 'http://timestamp.digicert.com' - folder: tmp + base-dir: 'tmp' + file-extensions: 'exe' + username: ${{ secrets.WIN_CODESIGN_USERNAME }} + password: ${{ secrets.WIN_CODESIGN_PW }} - name: Reattach signed burn engine to installer run: > wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe - - name: Codesign EXE - uses: skymatic/code-sign-action@v3 + - name: Sign installer with Actalis CodeSigner + if: inputs.sign || github.event_name == 'release' + uses: ./.github/actions/win-sign-action with: - certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }} - password: ${{ secrets.WIN_CODESIGN_P12_PW }} - certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A - description: Cryptomator Installer - timestampUrl: 'http://timestamp.digicert.com' - folder: installer + base-dir: 'installer' + file-extensions: 'exe' + sign-description: 'Cryptomator Bundle Installer' + username: ${{ secrets.WIN_CODESIGN_USERNAME }} + password: ${{ secrets.WIN_CODESIGN_PW }} - name: Add possible alpha/beta tags to installer name run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe - name: Create detached GPG signature with key 615D449FE6E6A235 From f64455d8fbfced499f1b4f898f84238377988f16 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 29 Jul 2025 13:02:01 +0200 Subject: [PATCH 18/18] dedup code references #3943 --- .github/actions/win-sign-action/action.yml | 145 --------------------- .github/workflows/win-exe.yml | 14 +- 2 files changed, 10 insertions(+), 149 deletions(-) delete mode 100644 .github/actions/win-sign-action/action.yml diff --git a/.github/actions/win-sign-action/action.yml b/.github/actions/win-sign-action/action.yml deleted file mode 100644 index a57e8f7b1..000000000 --- a/.github/actions/win-sign-action/action.yml +++ /dev/null @@ -1,145 +0,0 @@ -name: 'Windows Signing' -description: 'Sign files on Windows' -inputs: - base-dir: - description: 'The base directory to search for files' - required: true - file-extensions: - description: 'List of file extensions to sign, separated by comma' - required: true - username: - description: 'Username for signing' - required: true - password: - description: 'Password for signing' - required: true - recursive: - description: 'Whether to search recursively in subdirectories' - required: false - default: 'false' - sign-description: - description: 'Signature description' - required: false - default: 'Cryptomator' - sign-url: - description: 'Signature URL' - required: false - default: 'https://cryptomator.org' - -runs: - using: "composite" - steps: - - name: Download Actalis CodeSigner if not present - id: download-signer - run: | - if (! (Test-Path -Path '${{ env.SIGNER_PATH }}')) { - echo "Downloading Actalis CodeSigner..." - curl --output "${{ env.SIGNER_NAME }}.zip" -L "${{ env.SIGNER_URL }}" - if (!(Get-FileHash -Path "${{ env.SIGNER_NAME }}.zip" -Algorithm SHA256).Hash.ToLower().equals("${{ env.SIGNER_HASH }}")) { - echo "Signer hash mismatch, exiting." - exit 1 - } - Expand-Archive -Path "${{ env.SIGNER_NAME }}.zip" -DestinationPath "${{ env.SIGNER_NAME }}" -Force - } - env: - SIGNER_PATH: ${{ github.workspace }}/actalis-signer/ActalisCodeSigner.exe - SIGNER_NAME: actalis-signer - SIGNER_URL: 'https://static.cryptomator.org/other/CodeSigner-win-x64-latest.zip' - SIGNER_HASH: '44a1e09ab72707d049d3e59656e3e35de92e8cda357eec1cfc367016e45835ab' - shell: pwsh - - name: Generate, mask, and output the input secrets - id: set-secrets - run: | - echo "::add-mask::${{ inputs.username }}" - echo "::add-mask::${{ inputs.password }}" - echo "username=${{ inputs.username }}" >> "$GITHUB_OUTPUT" - echo "password=${{ inputs.password }}" >> "$GITHUB_OUTPUT" - shell: bash - - name: Sign DLLs with Actalis CodeSigner - run: | - $signerPath = '${{ env.SIGNER_PATH }}' - $username = '${{ steps.set-secrets.outputs.username }}' - $password = '${{ steps.set-secrets.outputs.password }}' - $signDescription = '${{ inputs.sign-description }}' - $signUrl = '${{ inputs.sign-url }}' - $extensions = '${{ inputs.file-extensions }}'.split(",") | ForEach-Object { "*.$($_.Trim())" } - $recursive = '${{ inputs.recursive }}' -eq 'true' - $files = Get-ChildItem -Path '${{ inputs.base-dir }}\*' -Include $extensions -Recurse:$recursive - - if($files.Count -eq 0) { - Write-Host "`n❌ No files found to sign." - exit 1 - } - Write-Host "`n📝 Found $($files.Count) files to sign:" - $files | ForEach-Object { Write-Host " - $($_.FullName)" } - - # Create log directory - $logDir = "~/.Acsi/log" - if (!(Test-Path $logDir)) { - New-Item -Path $logDir -ItemType Directory -Force | Out-Null - } - - $jobs = @() - foreach ($file in $files) { - # Run signing in a job - $job = Start-Job -ScriptBlock { - param($signerPath, $username, $password, $signDescription, $signUrl, $filePath) - - Write-Host "`n🔐 Signing: $($filePath)" - $logFile = "~/.Acsi/log/$(Split-Path -Leaf $filePath).log" - $arguments = @( - '-ts', - 'http://timestamp.digicert.com', - '-fu', $username, - '-fp', $password, - '-pm', "`"$signDescription`"", - '--program-url', $signUrl, - '-in', "`"$filePath`"" - ) - $process = Start-Process -FilePath "$signerPath" -ArgumentList $arguments -Wait -PassThru -RedirectStandardOutput "$logFile" -NoNewWindow - - return @{ - FilePath = $filePath - ExitCode = $process.ExitCode - LogFile = $logFile - } - } -ArgumentList $signerPath, $username, $password, $signDescription, $signUrl, $file.FullName - $jobs += $job - - # Throttle to max 5 concurrent jobs - if ($jobs.Count -ge 5) { - $completed = $jobs | Wait-Job -Any - $result = $completed | Receive-Job - - # Check result and exit on failure - if ($result.ExitCode -ne 0) { - $jobs | Stop-Job | Remove-Job - Write-Host "❌ Signing failed for $($result.FilePath) with exit code: $($result.ExitCode)" - exit 1 - } - Write-Host " ✅ Successfully signed $($result.FilePath)" - - $jobs = $jobs | Where-Object { $_.Id -ne $completed.Id } - $completed | Remove-Job - - } - } - # Wait for remaining jobs - $jobs | Wait-Job | Receive-Job | ForEach-Object { - if ($_.ExitCode -ne 0) { - Write-Host "❌ Signing failed for $($_.FilePath) with exit code: $($_.ExitCode)" - exit 1 - } - Write-Host " ✅ Successfully signed $($_.FilePath)" - } - Write-Host "`n✅ Successfully signed $($files.Count) files." - env: - SIGNER_PATH: ${{ github.workspace }}/actalis-signer/ActalisCodeSigner.exe - shell: pwsh - - name: Upload log on failure - if: failure() - uses: actions/upload-artifact@v4 - with: - name: signing-log-${{ runner.arch }} - path: | - ~/.Acsi/log/*.log diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 629cb56be..2045fc6da 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -212,11 +212,13 @@ jobs: Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir" - name: Sign DLLs with Actalis CodeSigner if: inputs.sign || github.event_name == 'release' - uses: ./.github/actions/win-sign-action + uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f with: base-dir: 'appdir' file-extensions: 'dll,exe,ps1' recursive: true + sign-description: 'Cryptomator' + sign-url: 'https://cryptomator.org' username: ${{ secrets.WIN_CODESIGN_USERNAME }} password: ${{ secrets.WIN_CODESIGN_PW }} - name: Replace DLLs inside jars with signed ones @@ -269,11 +271,12 @@ jobs: JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir - name: Sign msi with Actalis CodeSigner if: inputs.sign || github.event_name == 'release' - uses: ./.github/actions/win-sign-action + uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f with: base-dir: 'installer' file-extensions: 'msi' sign-description: 'Cryptomator Installer' + sign-url: 'https://cryptomator.org' username: ${{ secrets.WIN_CODESIGN_USERNAME }} password: ${{ secrets.WIN_CODESIGN_PW }} - name: Add possible alpha/beta tags and architecture to installer name @@ -380,10 +383,12 @@ jobs: wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe - name: Sign burn engine with Actalis CodeSigner if: inputs.sign || github.event_name == 'release' - uses: ./.github/actions/win-sign-action + uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f with: base-dir: 'tmp' file-extensions: 'exe' + sign-description: 'Cryptomator Bundle Installer' + sign-url: 'https://cryptomator.org' username: ${{ secrets.WIN_CODESIGN_USERNAME }} password: ${{ secrets.WIN_CODESIGN_PW }} - name: Reattach signed burn engine to installer @@ -391,11 +396,12 @@ jobs: wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe - name: Sign installer with Actalis CodeSigner if: inputs.sign || github.event_name == 'release' - uses: ./.github/actions/win-sign-action + uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f with: base-dir: 'installer' file-extensions: 'exe' sign-description: 'Cryptomator Bundle Installer' + sign-url: 'https://cryptomator.org' username: ${{ secrets.WIN_CODESIGN_USERNAME }} password: ${{ secrets.WIN_CODESIGN_PW }} - name: Add possible alpha/beta tags to installer name