Merge branch 'release/1.19.3'

This commit is contained in:
Armin Schrenk
2026-06-29 13:52:10 +02:00
123 changed files with 3827 additions and 1101 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ runs:
echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT"
shell: bash
- name: Sign DLLs with Azure Trusted Signing
uses: azure/artifact-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0
uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2.0.0
with:
files-folder: ${{ inputs.base-dir }}
files-folder-filter: ${{ inputs.file-extensions }}
+4 -36
View File
@@ -3,51 +3,19 @@ updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "Etc/UTC"
interval: "monthly"
ignore:
- dependency-name: "org.cryptomator:integrations-api"
versions: ["2.0.0-alpha1"]
- dependency-name: "jakarta.inject:jakarta.inject-api"
versions: ["2.0.1.MR"]
- dependency-name: "org.openjfx:*"
update-types: ["version-update:semver-major"]
# due to https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter/issues/68
- dependency-name: "org.apache.maven.plugins:maven-surefire-plugin"
versions: [ "3.5.4", "3.5.5" ]
- dependency-name: "com.fasterxml.jackson.*"
versions: [ "[2.22,)" ] # 2.21.x is LTS, see https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.21
groups:
java-test-dependencies:
patterns:
- "org.junit.jupiter:*"
- "org.mockito:*"
- "org.hamcrest:*"
- "com.google.jimfs:jimfs"
maven-build-plugins:
patterns:
- "org.apache.maven.plugins:*"
- "org.jacoco:jacoco-maven-plugin"
- "org.owasp:dependency-check-maven"
- "me.fabriciorby:maven-surefire-junit5-tree-reporter"
- "org.codehaus.mojo:license-maven-plugin"
javafx:
patterns:
- "org.openjfx:*"
java-production-dependencies:
maven-dependencies:
patterns:
- "*"
exclude-patterns:
- "org.openjfx:*"
- "org.apache.maven.plugins:*"
- "org.jacoco:jacoco-maven-plugin"
- "org.owasp:dependency-check-maven"
- "me.fabriciorby:maven-surefire-junit5-tree-reporter"
- "org.codehaus.mojo:license-maven-plugin"
- "org.junit.jupiter:*"
- "org.mockito:*"
- "org.hamcrest:*"
- "com.google.jimfs:jimfs"
- package-ecosystem: "github-actions"
directory: "/" # even for `.github/workflows`
+34
View File
@@ -0,0 +1,34 @@
<!-- HEADER -->
> [!WARN]
> 🚧 DO NOT EDIT 🚧
>
> The [builds are still running](https://github.com/cryptomator/cryptomator/actions/workflows/create-release.yml).
> This banner will be replaced after the builds are finished.
<!-- /HEADER -->
<!--REPLACE with auto-generated release notes (see below)
### What's New 🎉
### Bugfixes 🐛
### Other Changes 📎
END REPLACE-->
For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/$VERSION/CHANGELOG.md).
---
💾 SHA-256 checksums of release artifacts:
```
$TARBALL
$EXE
$MSI
$DMG_x64
$DMG_arm64
$APPIMAGE_x86_64
$APPIMAGE_aarch64
```
> [!TIP]
> You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
<!-- Auto-Generated Release Notes: -->
+189
View File
@@ -0,0 +1,189 @@
# Cryptomator Release Workflow
This document describes the automated release pipeline defined in [`draft-release.yml`](draft-release.yml) and [`post-publish.yml`](post-publish.yml).
## Overview
The release process has two phases:
1. **Draft phase** (`draft-release.yml`) -- triggered by pushing a signed git tag. Compiles, tests, builds platform installers, and creates a **draft** GitHub Release.
2. **Post-publish phase** (`post-publish.yml`) -- triggered when the draft release is manually **published**. Submits Windows installers for AV whitelisting, notifies the team for DEB build and latest-version update, and triggers downstream updates (website, docs, winget).
```mermaid
---
config:
htmlLabels: false
---
flowchart TD
%% ── Trigger ──────────────────────────────────────────────
push_tag([🏷 Signed tag pushed])
%% ── Draft phase ──────────────────────────────────────────
push_tag --> get-version
subgraph draft["draft-release.yml"]
get-version["get-version
*parse semver from tag*"]
get-version --> create-release-draft
create-release-draft["create-release-draft
*compile & test (Linux)
create draft release
sign source tarball*"]
create-release-draft --> build-exe-and-msi
create-release-draft --> build-dmg-arm64
create-release-draft --> build-dmg-x64
create-release-draft --> build-appimages
build-exe-and-msi["build-exe-and-msi
*calls win-exe.yml
MSI + EXE (x64)
code-signed & GPG-signed*"]
build-dmg-arm64["build-dmg-arm64
*calls mac-dmg.yml
DMG (arm64)
notarized & GPG-signed*"]
build-dmg-x64["build-dmg-x64
*calls mac-dmg-x64.yml
DMG (x64)
notarized & GPG-signed*"]
build-appimages["build-appimages
*calls appimage.yml
AppImage (x86_64 + aarch64)
GPG-signed*"]
build-exe-and-msi --> update-sha256sums
build-dmg-arm64 --> update-sha256sums
build-dmg-x64 --> update-sha256sums
build-appimages --> update-sha256sums
update-sha256sums["update-sha256sums
*compute checksums
update release body*"]
end
update-sha256sums --> manual_review
%% ── Manual gate ──────────────────────────────────────────
manual_review{{Manual review
& publish}}
%% ── Post-publish phase ───────────────────────────────────
manual_review --> published([📢 Release published])
published --> post-publish
subgraph post-publish["post-publish.yml"]
direction TB
check-release["check-release
*classify release tag
stable, alpha, beta, rc, unknown*"]
notify["notify
*Slack notifications
deb build & version check*"]
get-asset-urls["get-asset-urls
*extract MSI & EXE
download URLs*"]
check-release --> notify-winget
check-release --> trigger-website
check-release --> trigger-docs
get-asset-urls --> allowlist-msi
allowlist-msi --> allowlist-exe
allowlist-msi["allowlist-msi-x64
*av-whitelist.yml
Kaspersky & Avast*"]
allowlist-exe["allowlist-exe-x64
*av-whitelist.yml
Kaspersky & Avast*"]
notify-winget["notify-winget
*Slack: ready for winget
stable only*"]
trigger-website["trigger-website-update
*dispatch to
cryptomator.github.io
stable only*"]
trigger-docs["trigger-docs-update
*dispatch to
cryptomator/docs
stable only, Windows*"]
end
```
## Phase 1: Draft Release (`draft-release.yml`)
**Trigger:** push of any tag (`*`)
### Jobs
| Job | Runs on | Description |
|-----|---------|-------------|
| **get-version** | ubuntu | Parses the tag into semver components (`semVerNum`, `semVerSuffix`, `revNum`, `versionType`). The release is aborted if not an alpha, beta, rc or 'stable' release. |
| **create-release-draft** | ubuntu | Checks out the repo, verifies the tag is **signed** and lives on a `main` or `release/*` branch. Runs `./mvnw verify` (with `xvfb-run`). Creates a GitHub Release **draft** using the [release body template](../release-body.md.template). Downloads and GPG-signs the source tarball. |
| **build-exe-and-msi** | windows | Calls [`win-exe.yml`](win-exe.yml). Builds the MSI and EXE bundle installer for x64 Windows. Code-signed via Azure Trusted Signing, GPG-signed, and uploaded to the draft release. Outputs SHA-256 checksums. |
| **build-dmg-arm64** | macos-15 | Calls [`mac-dmg.yml`](mac-dmg.yml). Builds the DMG for Apple Silicon. Code-signed, notarized with Apple, GPG-signed, and uploaded. Outputs SHA-256 checksum. |
| **build-dmg-x64** | macos-15-large | Calls [`mac-dmg-x64.yml`](mac-dmg-x64.yml). Same as above but for Intel Macs. Uses macFUSE instead of FUSE-T. |
| **build-appimages** | ubuntu | Calls [`appimage.yml`](appimage.yml). Builds AppImages for x86_64 and aarch64 (matrix). GPG-signed and uploaded with `.zsync` delta-update files. Outputs SHA-256 checksums. |
| **update-sha256sums** | ubuntu | Runs after all builds complete. Computes the source tarball checksum, collects all artifact checksums, and updates the draft release body via `envsubst`. Replaces the "builds still running" banner with a success notice. |
### Release Artifacts
After the draft phase, the GitHub Release contains:
| Artifact | Platform |
|----------|----------|
| `cryptomator-<ver>.tar.gz.asc` | Source (GPG signature) |
| `Cryptomator-<ver>-x64.msi` + `.asc` | Windows |
| `Cryptomator-<ver>-x64.exe` + `.asc` | Windows |
| `Cryptomator-<ver>-arm64.dmg` + `.asc` | macOS (Apple Silicon) |
| `Cryptomator-<ver>-x64.dmg` + `.asc` | macOS (Intel) |
| `cryptomator-<ver>-x86_64.AppImage` + `.zsync` + `.asc` | Linux (x86_64) |
| `cryptomator-<ver>-aarch64.AppImage` + `.zsync` + `.asc` | Linux (aarch64) |
All artifacts are signed with GPG key [`615D449FE6E6A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
## Manual Review Gate
After the draft phase completes, a maintainer reviews the draft release on GitHub. This is the point to:
- Verify all artifacts are present and checksums look correct.
- Edit the auto-generated release notes (What's New, Bugfixes, Other Changes).
- **Publish** the release when ready, which triggers phase 2.
## Phase 2: Post-Publish (`post-publish.yml`)
**Trigger:** `release: [published]`
### Jobs
| Job | Condition | Description |
|-----|-----------|-------------|
| **notify** | always | Sends Slack notifications to `#cryptomator-desktop`: ready to build `.deb` package, and reminder to update `latest-version.json` on S3. |
| **get-asset-urls** | always | Extracts MSI and EXE download URLs from the release assets. |
| **check-release** | always | Classifies the published release tag as `stable`, `alpha`, `beta`, `rc`, or `unknown`. Stable-only follow-up jobs depend on this output. Unlike `get-version.yml` workflow, this job does not perform semver validation. |
| **allowlist-msi-x64** | Windows release | Calls [`av-whitelist.yml`](av-whitelist.yml). Uploads the MSI to Kaspersky and Avast for whitelisting. |
| **allowlist-exe-x64** | Windows release | Same as above for the EXE. Runs sequentially after MSI. |
| **notify-winget** | stable + Windows | Sends a Slack notification that the release is ready for [winget submission](winget.yml). |
| **trigger-website-update** | stable | Dispatches `desktop-release` event to `cryptomator/cryptomator.github.io`. |
| **trigger-docs-update** | stable + Windows | Dispatches `desktop-release` event to `cryptomator/docs`. |
### Manual Follow-ups
These steps are triggered by team members after Slack notifications:
- **Debian package** -- Run the [`debian.yml`](debian.yml) workflow to build `.deb` and optionally upload to the PPA.
- **winget** -- Run the [`winget.yml`](winget.yml) workflow to submit to the Windows Package Manager.
- **latest-version.json** -- Update the version-check file on S3 (`static.cryptomator.org/desktop/latest-version.json`).
## Signing & Security
- **Git tag** must be SSH-signed and reside on `main` or `release/*`.
- **Windows** installers are code-signed using Azure Trusted Signing.
- **macOS** DMGs are code-signed with an Apple Developer certificate and notarized via `notarytool`.
- **All artifacts** receive a detached GPG signature (`.asc`) using key `615D449FE6E6A235`.
- **AV whitelisting** is submitted to Kaspersky and Avast after publish (Windows installers only).
- The draft release is created using `CRYPTOBOT_RELEASE_TOKEN`, not `GITHUB_TOKEN`, to ensure proper permissions and trigger downstream workflows.
+75 -108
View File
@@ -1,17 +1,44 @@
name: Build AppImage
on:
release:
types: [published]
schedule:
- cron: '0 23 20 * *'
workflow_call:
inputs:
semVerNum:
type: string
description: 'The Major.Minor.Patch part of the version'
required: true
revisionNum:
type: string
description: 'The revision number'
required: true
semVerSuffix:
type: string
description: 'The suffix of the version, including dash'
required: true
upload-to-draft:
type: boolean
default: true
outputs:
sha256-appimage-x64:
description: "SHA256 sum of the x64 appimage"
value: ${{ jobs.collect-sha256sums.outputs.x64-sha256sum}}
sha256-appimage-aarch64:
description: "SHA256 sum of the aarch64 appimage"
value: ${{ jobs.collect-sha256sums.outputs.aarch64-sha256sum}}
workflow_dispatch:
inputs:
version:
description: 'Version'
semVerNum:
description: 'The Major.Minor.Patch part of the version'
required: false
create-pr:
description: 'Create a PR for aur-bin repo'
type: boolean
default: false
revisionNum:
description: 'The revision number'
required: false
semVerSuffix:
description: 'The suffix of the version, including dash'
required: false
default: '-SNAPSHOT'
push:
branches-ignore:
- 'dependabot/**'
@@ -23,40 +50,34 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.2+10.0.LTS'
JAVA_VERSION: '26.0.1+8'
VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}}
REVISION_NUM: ${{ inputs.revisionNum || '0' }}
VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}}
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }} #okay if not defined
build:
name: Build AppImage
runs-on: ${{ matrix.os }}
needs: [get-version]
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
SEMVER_NUM: ${{ needs.get-version.outputs.semVerNum }}
REV_NUM: ${{ needs.get-version.outputs.revNum }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
arch: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_linux-x64_bin-jmods.zip'
openjfx-sha: '47035c653863a8e4be3dc6f142b8dbd84b4bb1efc9a8cbc68413e6a5ff5e9f50'
appimagetool-sha: 'ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0'
- os: ubuntu-24.04-arm
arch: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_linux-aarch64_bin-jmods.zip'
openjfx-sha: 'e3fd682354346845d2944a2da2b1ff2b6cb9259d92027f2f9c121b9b93c5e42f'
appimagetool-sha: 'f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -74,7 +95,7 @@ jobs:
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(./mvnw help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
@@ -83,9 +104,9 @@ jobs:
exit 1
fi
- name: Set version
run : mvn versions:set -DnewVersion="$SEMVER_STR"
run : ./mvnw versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}"
- name: Run maven
run: mvn -B clean package -Plinux -DskipTests
run: ./mvnw -B clean package -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
@@ -125,13 +146,13 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${SEMVER_NUM}.${REV_NUM}"
--copyright "(C) 2016 - 2026 Skymatic GmbH"
--app-version "${VERSION_NUM}.${REVISION_NUM}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator"
--java-options "-Xss5m"
--java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\""
--java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\""
--java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\""
@@ -142,7 +163,7 @@ jobs:
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
--java-options "-Dcryptomator.buildNumber=\"appimage-${REV_NUM}\""
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NUM}\""
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
@@ -181,7 +202,7 @@ jobs:
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Build AppImage
run: >
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${SEMVER_STR}-${{ matrix.arch }}.AppImage
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.arch }}.AppImage
-u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.arch }}.AppImage.zsync"
--sign --sign-key=615D449FE6E6A235
- name: Create detached GPG signatures
@@ -189,7 +210,7 @@ jobs:
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: appimage-${{ matrix.arch }}
path: |
@@ -198,9 +219,10 @@ jobs:
cryptomator-*.asc
if-no-files-found: error
- name: Publish AppImage on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
if: inputs.upload-to-draft
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
draft: true
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
@@ -208,79 +230,24 @@ jobs:
cryptomator-*.zsync
cryptomator-*.asc
create-aur-bin-pr:
name: Create PR for aur-bin repo
if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
collect-sha256sums:
name: Collect AppImage checksums
runs-on: ubuntu-latest
needs: [build, get-version]
container:
image: archlinux:base-devel
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
PKGDEST: ${{ github.workspace }}/pkgdest
SRCDEST: ${{ github.workspace }}/srcdest
needs: [build]
if: inputs.upload-to-draft
outputs:
x64-sha256sum: ${{ steps.sha256sum.outputs.x64-sha256sum }}
aarch64-sha256sum: ${{ steps.sha256sum.outputs.aarch64-sha256sum }}
steps:
- name: Prepare pacman
run: |
pacman-key --init
pacman-key --populate archlinux
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl pacman-contrib
- name: Checkout cryptomator/aur-bin
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Download AppImage artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
repository: 'cryptomator/aur-bin'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Create build user
pattern: appimage-*
path: appimage-artifacts
- name: Compute SHA256 sums
id: sha256sum
run: |
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
chown -R builder:builder "$GITHUB_WORKSPACE"
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
- name: Import Cryptomator release signing key
# try first ubuntu. on failure try openpgp keyservers
run: >
sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|| sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
- name: Checkout release branch
run: |
git config --global safe.directory '*'
git checkout -b "release/${SEMVER_STR}"
- name: Update build file
run: |
sed -i -e "s|^pkgver=.*$|pkgver=${SEMVER_STR}|" PKGBUILD
sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
sudo -u builder updpkgsums
sudo -u builder makepkg --printsrcinfo > .SRCINFO
- name: Build package with makepkg
run: >
sudo -u builder
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
makepkg --syncdeps --cleanbuild --noconfirm --log
- name: Commit and push
run: |
git config user.name "cryptobot"
git config user.email "cryptobot@users.noreply.github.com"
git config push.autoSetupRemote true
git stage PKGBUILD .SRCINFO
git commit -m "Prepare release ${SEMVER_STR}"
git push
- name: Create pull request
id: create-pr
run: |
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
PR_URL=$(gh pr create --title "Release ${SEMVER_STR}" --body-file pr_body.md)
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
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 }} ${{ needs.get-version.outputs.semVerStr }} created."
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
SLACK_FOOTER: false
MSG_MINIMAL: true
read -ra X64_SUM < <(sha256sum appimage-artifacts/appimage-x86_64/cryptomator-*-x86_64.AppImage)
read -ra AARCH64_SUM < <(sha256sum appimage-artifacts/appimage-aarch64/cryptomator-*-aarch64.AppImage)
echo "x64-sha256sum=${X64_SUM[0]}" >> "$GITHUB_OUTPUT"
echo "aarch64-sha256sum=${AARCH64_SUM[0]}" >> "$GITHUB_OUTPUT"
+115
View File
@@ -0,0 +1,115 @@
name: PR for aur-bin repo
on:
release:
types: [published]
workflow_dispatch:
inputs:
src-tag:
description: 'Source or Release tag'
required: false
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.src-tag }}
create-aur-bin-pr:
name: Create PR for aur-bin repo
if: (github.event_name == 'workflow_dispatch') || (github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable')
runs-on: ubuntu-latest
needs: [get-version]
container:
image: archlinux:base-devel
env:
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
PKGDEST: ${{ github.workspace }}/pkgdest
SRCDEST: ${{ github.workspace }}/srcdest
steps:
- name: Prepare pacman
run: |
pacman-key --init
pacman-key --populate archlinux
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl pacman-contrib
- name: Checkout cryptomator/aur-bin
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: 'cryptomator/aur-bin'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Create build user
run: |
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
chown -R builder:builder "$GITHUB_WORKSPACE"
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
- name: Import Cryptomator release signing key
# try first ubuntu. on failure try openpgp keyservers
run: >
sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|| sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
- name: Checkout release branch
run: |
git config --global safe.directory '*'
git checkout -b "release/${SEMVER_STR}"
- name: Determine pkgrel
id: pkgrel
run: |
CURRENT_VERSION="$(sed -nE 's/^pkgver=(.*)$/\1/p' PKGBUILD | head -n1)"
CURRENT_REL="$(sed -nE 's/^pkgrel=([0-9]+).*$/\1/p' PKGBUILD | head -n1)"
if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" && "$CURRENT_REL" =~ ^[0-9]+$ ]]; then
NEXT_REL=$((CURRENT_REL + 1))
else
NEXT_REL=1
fi
echo "value=${NEXT_REL}" >> "$GITHUB_OUTPUT"
echo "dist-version=${TARGET_VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT"
env:
TARGET_VERSION: ${{ needs.get-version.outputs.semVerStr }}
- name: Update build file
run: |
sed -i -e "s|^pkgver=.*$|pkgver=${PKG_VERSION}|" PKGBUILD
sed -i -e "s|^pkgrel=.*$|pkgrel=${PKG_RELEASE}|" PKGBUILD
sudo -u builder updpkgsums
sudo -u builder makepkg --printsrcinfo > .SRCINFO
env:
PKG_VERSION: ${{ needs.get-version.outputs.semVerNum }}
PKG_RELEASE: ${{ steps.pkgrel.outputs.value }}
- name: Build package with makepkg
run: >
sudo -u builder
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
makepkg --syncdeps --cleanbuild --noconfirm --log
- name: Commit and push
run: |
git config user.name "cryptobot"
git config user.email "cryptobot@users.noreply.github.com"
git config push.autoSetupRemote true
git stage PKGBUILD .SRCINFO
git commit -m "Prepare release ${DIST_VERSION}"
git push
env:
DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }}
- name: Create pull request
id: create-pr
run: |
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
PR_URL=$(gh pr create --title "Release ${DIST_VERSION}" --body-file pr_body.md)
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
env:
DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }}
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: ''
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ needs.get-version.outputs.semVerStr }} created."
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
SLACK_FOOTER: ''
MSG_MINIMAL: true
+7 -7
View File
@@ -37,7 +37,7 @@ on:
jobs:
download-file:
name: Downloads the file into the VM
runs-on: ubuntu-latest
runs-on: ubuntu-slim
outputs:
fileName: ${{ steps.extractName.outputs.fileName}}
env:
@@ -51,24 +51,24 @@ jobs:
- name: Download file
run: curl --silent --fail-with-body --proto "=https" -L "${INPUT_URL}" -o "${{steps.extractName.outputs.fileName}}"
- name: Upload artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ steps.extractName.outputs.fileName }}
path: ${{ steps.extractName.outputs.fileName }}
if-no-files-found: error
allowlist-kaspersky:
name: Anti Virus Allowlisting Kaspersky
runs-on: ubuntu-latest
runs-on: ubuntu-slim
needs: download-file
if: inputs.kaspersky
steps:
- name: Download artifact
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@a51268f67f6605236975928ae28b0f7e9971d50a # v4.6.3
uses: SamKirkland/FTP-Deploy-Action@110f9186c050f71550953127052e77650219c287 # v4.6.3
with:
protocol: ftps
server: allowlist.kaspersky-labs.com
@@ -78,12 +78,12 @@ jobs:
local-dir: ./upload/
allowlist-avast:
name: Anti Virus Allowlisting Avast
runs-on: ubuntu-latest
runs-on: ubuntu
needs: download-file
if: inputs.avast
steps:
- name: Download artifact
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
+5 -42
View File
@@ -11,7 +11,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 25
JAVA_VERSION: 26
defaults:
run:
@@ -22,14 +22,14 @@ jobs:
name: Compile and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Cache SonarCloud packages
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
@@ -37,7 +37,7 @@ jobs:
- name: Build and Test
run: >
xvfb-run
mvn -B verify
./mvnw -B verify
jacoco:report
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
-Pcoverage
@@ -47,40 +47,3 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Draft a release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
draft: true
discussion_category_name: releases
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
generate_release_notes: true
body: |-
> [!NOTE]
> 🚧 Work in Progress 🚧
>
> Please be patient, the [builds are still running](https://github.com/cryptomator/cryptomator/actions). Binary packages can be found here in a few moments.
<!--REPLACE with auto-generated release notes (see below)
### What's New 🎉
### Bugfixes 🐛
### Other Changes 📎
END REPLACE-->
For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md).
---
<!-- Don't forget to include the
💾 SHA-256 checksums of release artifacts:
```
```
-->
> [!TIP]
> You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
<!-- Auto-Generated Release Notes: -->
+4 -4
View File
@@ -26,7 +26,7 @@ jobs:
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV"
shell: pwsh
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
java-version: ${{ env.JDK_MAJOR_VERSION}}
distribution: ${{ env.JDK_VENDOR }}
@@ -70,14 +70,14 @@ jobs:
}
- name: Notify
if: steps.determine.outputs.UPDATE_AVAILABLE == 'true'
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON: ''
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "JDK update available"
SLACK_MESSAGE: "Cryptomator-CI JDK can be upgraded to ${{ steps.determine.outputs.LATEST_JDK_VERSION }}. Check the Nextcloud collective for instructions."
SLACK_FOOTER: false
SLACK_FOOTER: ''
MSG_MINIMAL: true
+14 -11
View File
@@ -1,6 +1,8 @@
name: Build Debian Package
on:
schedule:
- cron: '0 22 20 * *'
workflow_dispatch:
inputs:
semver:
@@ -23,12 +25,12 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.2+10.0.LTS'
DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
JAVA_VERSION: '26.0.1+8'
DEB_BUILD_DEPENDS: 'debhelper (>=10), coffeelibs-jdk-26 (>= 26.0.1+8-0ppa1), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '47035c653863a8e4be3dc6f142b8dbd84b4bb1efc9a8cbc68413e6a5ff5e9f50'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: 'e3fd682354346845d2944a2da2b1ff2b6cb9259d92027f2f9c121b9b93c5e42f'
jobs:
get-version:
@@ -43,7 +45,7 @@ jobs:
env:
INPUT_PPAVER: ${{ inputs.ppaver }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- id: deb-version
name: Determine deb-version
run: |
@@ -54,20 +56,21 @@ jobs:
fi
- name: Install build tools
run: |
sudo add-apt-repository -y ppa:coffeelibs/openjdk
sudo apt-get update
sudo apt-get install devscripts dput
sudo apt-get satisfy "${DEB_BUILD_DEPENDS}"
env:
DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }}
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
check-latest: true
cache: 'maven'
- name: Run maven
run: mvn -B clean package -Plinux -DskipTests
run: ./mvnw -B clean package -DskipTests
- name: Download OpenJFX jmods
id: download-jmods
run: |
@@ -87,7 +90,7 @@ jobs:
JMOD_VERSION_AARCH64=$(jmod describe jmods/aarch64/javafx.base.jmod | head -1)
JMOD_VERSION_AARCH64=${JMOD_VERSION_AARCH64#*@}
JMOD_VERSION_AARCH64=${JMOD_VERSION_AARCH64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(./mvnw help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
@@ -143,7 +146,7 @@ jobs:
run: |
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: linux-deb-package
path: |
+2 -2
View File
@@ -7,11 +7,11 @@ on:
jobs:
check-dependencies:
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # v3.0.3
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@8356563bf7b8d1c8d693f75ca487e8f57573cec9 # v3.1.0
with:
runner-os: 'ubuntu-latest'
java-distribution: 'temurin'
java-version: 25
java-version: 26
secrets:
nvd-api-key: ${{ secrets.NVD_API_KEY }}
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
steps:
- name: Get download count of latest releases
id: get-stats
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const query = `query($owner:String!, $name:String!) {
+157
View File
@@ -0,0 +1,157 @@
name: Draft a Cryptomator Release
on:
push:
tags:
- '*'
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '26.0.1+8'
defaults:
run:
shell: bash
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ''
create-release-draft:
name: Compile and Test
runs-on: ubuntu-latest
needs: get-version
if: needs.get-version.outputs.versionType != 'unknown'
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Check the git tag is signed
run: git cat-file -p "${GITHUB_REF_NAME}" | grep "BEGIN SSH SIGNATURE"
- name: Check the git tag is on release or main branch
run: git branch -r --contains "${GITHUB_REF_NAME}" | grep -E '^\s*origin/(main|release/.*)\s*$'
- uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Build and Test
run: xvfb-run ./mvnw -B verify
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
- name: Draft a release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
draft: true
discussion_category_name: releases
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
generate_release_notes: true
body_path: .github/release-body.md.template
- name: Download source tarball
run: |
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/${{ github.ref }}.tar.gz --output cryptomator-${{ github.ref_name }}.tar.gz
- name: Sign source tarball with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.tar.gz
env:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Publish asc on GitHub Releases
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
draft: true
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
cryptomator-*.tar.gz.asc
build-exe-and-msi:
needs: [get-version, create-release-draft]
uses: ./.github/workflows/win-exe.yml
with:
semVerNum: ${{needs.get-version.outputs.semVerNum}}
revisionNum: ${{needs.get-version.outputs.revNum}}
semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}}
secrets: inherit
build-dmg-arm64:
needs: [get-version, create-release-draft]
uses: ./.github/workflows/mac-dmg.yml
with:
semVerNum: ${{needs.get-version.outputs.semVerNum}}
revisionNum: ${{needs.get-version.outputs.revNum}}
semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}}
secrets: inherit
build-dmg-x64:
needs: [get-version, create-release-draft]
uses: ./.github/workflows/mac-dmg-x64.yml
with:
semVerNum: ${{needs.get-version.outputs.semVerNum}}
revisionNum: ${{needs.get-version.outputs.revNum}}
semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}}
secrets: inherit
build-appimages:
needs: [get-version, create-release-draft]
uses: ./.github/workflows/appimage.yml
with:
semVerNum: ${{needs.get-version.outputs.semVerNum}}
revisionNum: ${{needs.get-version.outputs.revNum}}
semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}}
secrets: inherit
update-sha256sums:
runs-on: ubuntu-latest
needs: [get-version, build-exe-and-msi, build-dmg-arm64, build-dmg-x64, build-appimages]
env:
TAG: ${{ github.ref_name }}
SEMVER: ${{ needs.get-version.outputs.semVerStr }}
GH_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Compute source tarball SHA256
id: src-sha256
run: |
curl --silent --fail-with-body --proto "=https" -L \
-H "Accept: application/vnd.github+json" \
"https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz" \
--output "cryptomator-${SEMVER}.tar.gz"
read -ra CMD_OUTPUT < <(sha256sum "cryptomator-${SEMVER}.tar.gz")
echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT
- name: Update release body with checksums
run: |
CURRENT_BODY=$(gh release view "${TAG}" --json body --jq .body)
RELEASE_BODY=$(printf '%s\n' "${CURRENT_BODY}" | sed '/<!-- HEADER -->/,/<!-- \/HEADER -->/c\
<!-- HEADER -->\
> [!NOTE]\
> Release artifacts finished building successfully.\
>\
> SHA-256 checksums have been updated below.\
<!-- /HEADER -->')
export TARBALL="${SRC_SHA} cryptomator-${SEMVER}.tar.gz"
export MSI="${MSI_SHA} Cryptomator-${SEMVER}-x64.msi"
export EXE="${EXE_SHA} Cryptomator-${SEMVER}-x64.exe"
export DMG_arm64="${DMG_ARM64_SHA} Cryptomator-${SEMVER}-arm64.dmg"
export DMG_x64="${DMG_X64_SHA} Cryptomator-${SEMVER}-x64.dmg"
export APPIMAGE_x86_64="${APPIMAGE_X64_SHA} cryptomator-${SEMVER}-x86_64.AppImage"
export APPIMAGE_aarch64="${APPIMAGE_AARCH64_SHA} cryptomator-${SEMVER}-aarch64.AppImage"
envsubst '$VERSION $TARBALL $EXE $MSI $DMG_x64 $DMG_arm64 $APPIMAGE_x86_64 $APPIMAGE_aarch64' \
<<< "${RELEASE_BODY}" \
> release-body.md
gh release edit "${TAG}" --draft --notes-file release-body.md
env:
VERSION: ${{ needs.get-version.outputs.semVerStr }}
SRC_SHA: ${{ steps.src-sha256.outputs.value }}
MSI_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-msi }}
EXE_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-exe }}
DMG_ARM64_SHA: ${{ needs.build-dmg-arm64.outputs.sha256-dmg }}
DMG_X64_SHA: ${{ needs.build-dmg-x64.outputs.sha256-dmg }}
APPIMAGE_X64_SHA: ${{ needs.build-appimages.outputs.sha256-appimage-x64 }}
APPIMAGE_AARCH64_SHA: ${{ needs.build-appimages.outputs.sha256-appimage-aarch64 }}
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
- name: Query Discussion Data
if: github.event_name == 'discussion_comment' || github.event_name == 'discussion' && github.event.action != 'deleted'
id: query-data
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const query = `query ($owner: String!, $name: String!, $discussionNumber: Int!) {
-85
View File
@@ -1,85 +0,0 @@
name: Create PR for flathub
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag'
required: true
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.tag }}
tarball:
name: Determines tarball url and compute checksum
runs-on: ubuntu-latest
needs: [get-version]
if: github.event_name == 'workflow_dispatch' || needs.get-version.outputs.versionType == 'stable'
outputs:
url: ${{ steps.url.outputs.url}}
sha512: ${{ steps.sha512.outputs.sha512}}
steps:
- name: Determine tarball url
id: url
run: |
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz"
echo "url=${URL}" >> "$GITHUB_OUTPUT"
env:
TAG: ${{ inputs.tag || github.event.release.tag_name}}
- name: Download source tarball and compute checksum
id: sha512
run: |
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:
name: Create PR for flathub
runs-on: ubuntu-latest
needs: [tarball, get-version]
env:
FLATHUB_PR_URL: tbd
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
- name: Update build file
run: |
sed -i -e 's/VERSION: [0-9]\+\.[0-9]\+\.[0-9]\+.*/VERSION: ${{ needs.get-version.outputs.semVerStr }}/g' org.cryptomator.Cryptomator.yaml
sed -i -e 's/sha512: [0-9A-Za-z_\+-]\{128\} #CRYPTOMATOR/sha512: ${{ needs.tarball.outputs.sha512 }} #CRYPTOMATOR/g' org.cryptomator.Cryptomator.yaml
sed -i -e 's;url: https://github.com/cryptomator/cryptomator/archive/refs/tags/[^[:blank:]]\+;url: ${{ needs.tarball.outputs.url }};g' org.cryptomator.Cryptomator.yaml
- name: Commit and push
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
git config push.autoSetupRemote true
git stage .
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
git push
- name: Create pull request
run: |
printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update maven dependencies\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
if: github.event_name == 'release'
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "Flathub release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
SLACK_MESSAGE: "See <${{ env.FLATHUB_PR_URL }}|PR> on how to proceed.>."
SLACK_FOOTER: false
MSG_MINIMAL: true
+19 -10
View File
@@ -14,6 +14,9 @@ on:
semVerNum:
description: "The numerical part of the version string"
value: ${{ jobs.determine-version.outputs.semVerNum}}
semVerSuffix:
description: "The suffix of the version string"
value: ${{ jobs.determine-version.outputs.semVerSuffix}}
revNum:
description: "The revision number"
value: ${{ jobs.determine-version.outputs.revNum}}
@@ -23,7 +26,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 25
JAVA_VERSION: 26
jobs:
determine-version:
@@ -32,14 +35,15 @@ jobs:
outputs:
semVerNum: ${{ steps.versions.outputs.semVerNum }}
semVerStr: ${{ steps.versions.outputs.semVerStr }}
semVerSuffix: ${{ steps.versions.outputs.semVerSuffix }}
revNum: ${{ steps.versions.outputs.revNum }}
type: ${{ steps.versions.outputs.type}}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -52,27 +56,32 @@ jobs:
elif [[ "${VERSION_STRING}" =~ [0-9]+\.[0-9]+\.[0-9]+.* ]]; then
SEM_VER_STR="${VERSION_STRING}"
else
SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
SEM_VER_STR=`./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout`
fi
SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'`
SEM_VER_NUM=$(echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
SEM_VER_SUFFIX="${SEM_VER_STR#"$SEM_VER_NUM"}"
REVCOUNT=`git rev-list --count HEAD`
TYPE="unknown"
if [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+$ ]]; then
if [[ -z $SEM_VER_SUFFIX ]]; then
TYPE="stable"
elif [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+-alpha[1-9]+$ ]]; then
elif [[ $SEM_VER_SUFFIX =~ -alpha[1-9]+$ ]]; then
TYPE="alpha"
elif [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+-beta[1-9]+$ ]]; then
elif [[ $SEM_VER_SUFFIX =~ -beta[1-9]+$ ]]; then
TYPE="beta"
elif [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+-rc[1-9]$ ]]; then
elif [[ $SEM_VER_SUFFIX =~ -rc[1-9]+$ ]]; then
TYPE="rc"
fi
echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT
echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT
echo "semVerSuffix=${SEM_VER_SUFFIX}" >> $GITHUB_OUTPUT
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
echo "type=${TYPE}" >> $GITHUB_OUTPUT
env:
VERSION_STRING: ${{ inputs.version }}
- name: Validate Version
uses: skymatic/semver-validation-action@7a6ae1c9e121540d11c9c7e4e667c83d583aa153 # v3.0.0
uses: skymatic/semver-validation-action@7c80b6b03a18b42884761daa9862ff5683ec8c8a # v4.0.0
with:
version: ${{ steps.versions.outputs.semVerStr }}
+264
View File
@@ -0,0 +1,264 @@
name: Build flatpak
on:
release:
types: [published]
workflow_dispatch:
inputs:
src-tag:
description: 'Source or Release tag'
required: false
create-pr:
description: 'Create Flathub PR'
required: false
type: boolean
default: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/get-version.yml'
- '.github/workflows/linux-flatpak.yml'
- 'dist/linux/flatpak/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.src-tag }}
build-flatpak:
name: "Build flatpak"
needs: [get-version]
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08
options: --privileged
strategy:
fail-fast: false
matrix:
variant:
- arch: x86_64
runner: ubuntu-24.04
- arch: aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.variant.runner }}
permissions:
contents: read
env:
SRC_GIT_SHA: ${{ inputs.src-tag || github.sha}}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: flathub/org.cryptomator.Cryptomator
submodules: true
- name: Checkout build script
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: build-scripts
- name: Checkout app source
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: cryptomator
ref: ${{ env.SRC_GIT_SHA }}
fetch-depth: 0
- name: Prepare build files
# using envsubst instead of yq to keep linebreaks
run: |
cp -r -f build-scripts/dist/linux/flatpak/* .
envsubst '$FLATPAK_VERSION $FLATPAK_REVISION $CRYPTOMATOR_SOURCE' < org.cryptomator.Cryptomator.TEMPLATE.yaml > org.cryptomator.Cryptomator.yaml
env:
FLATPAK_VERSION: ${{ needs.get-version.outputs.semVerNum }}
FLATPAK_REVISION: 1
CRYPTOMATOR_SOURCE: |-
type: git
path: cryptomator
commit: ${{ env.SRC_GIT_SHA }}
- name: Copy build script for upload
run: cp org.cryptomator.Cryptomator.yaml org.cryptomator.Cryptomator.${{matrix.variant.arch}}.yaml
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
archive: false
if-no-files-found: error
path: |
org.cryptomator.Cryptomator.${{matrix.variant.arch}}.yaml
- uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb # SNAPSHOT due to using keep-build-dirs
with:
bundle: cryptomator.flatpak
manifest-path: org.cryptomator.Cryptomator.yaml
cache-key: flatpak-builder-${{ env.SRC_GIT_SHA }}
arch: ${{ matrix.variant.arch }}
keep-build-dirs: true
- name: Collect maven dependencies
working-directory: .flatpak-builder/build/cryptomator-1/.m2/repository/
run: |
find * -type f \( -iname '*.jar' -o -iname '*.pom' \) | sort -V > /tmp/maven-dependency-files.txt
grep -v '^org/openjfx/javafx-' /tmp/maven-dependency-files.txt > maven-dependency-files-common.txt
grep '^org/openjfx/javafx-' /tmp/maven-dependency-files.txt > maven-dependency-files-javafx.txt
- name: Update arch independent maven dependencies
run: |
(
cd .flatpak-builder/build/cryptomator-1/.m2/repository/
while IFS= read -r dependencyPath; do
dependencyName=$(dirname "$dependencyPath")
dependencySha=$(sha256sum "$dependencyPath" | cut -c 1-64)
cat <<EOF
- type: file
dest: .m2/repository/${dependencyName}
url: https://repo.maven.apache.org/maven2/${dependencyPath}
sha256: ${dependencySha}
EOF
done < maven-dependency-files-common.txt
) > maven-dependencies.yaml
- name: Update arch specific maven dependencies
run: |
(
cd .flatpak-builder/build/cryptomator-1/.m2/repository/
while IFS= read -r dependencyPath; do
dependencyName=$(dirname "$dependencyPath")
dependencySha=$(sha256sum "$dependencyPath" | cut -c 1-64)
cat <<EOF
- type: file
dest: .m2/repository/${dependencyName}
url: https://repo.maven.apache.org/maven2/${dependencyPath}
sha256: ${dependencySha}
only-arches: [${{ matrix.variant.arch }}]
EOF
done < maven-dependency-files-javafx.txt
) > javafx-maven-dependencies-${{ matrix.variant.arch }}.yaml
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: maven-sources-${{ matrix.variant.arch }}
if-no-files-found: error
path: |
maven-dependencies.yaml
javafx-maven-dependencies-${{ matrix.variant.arch }}.yaml
verify-maven-sources:
name: Verify maven sources
runs-on: ubuntu-latest
needs: [build-flatpak]
permissions:
contents: none
steps:
- name: Download updated maven aarch64 dependencies
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: maven-sources-aarch64
path: mvn-src-aarch64
- name: Download updated maven x86_64 dependencies
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: maven-sources-x86_64
path: mvn-src-x64
- name: Verify arch independent maven dependencies
run: cmp --silent mvn-src-aarch64/maven-dependencies.yaml mvn-src-x64/maven-dependencies.yaml
create-pr:
name: Create PR for flathub
runs-on: ubuntu-latest
needs: [get-version, verify-maven-sources]
if: (github.event_name == 'workflow_dispatch' && inputs.create-pr ) || (github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable')
permissions:
contents: write
env:
TARBALL_URL: 'https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name || inputs.src-tag }}.tar.gz'
steps:
- name: Check that input "src-tag" is actually a tag
if: github.event_name == 'workflow_dispatch'
run: |
if [ -z "$SRC_TAG" ]; then
echo '::error::Input "src-tag" must be set to create a Flathub PR'
exit 1
fi
env:
SRC_TAG: ${{ inputs.src-tag }}
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: flathub/org.cryptomator.Cryptomator
submodules: true #TODO: Update submodule!
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Checkout release branch
run: |
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: cryptomator
- name: Download source tarball and compute checksum
id: sha512
run: |
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${TARBALL_URL} --output cryptomator.tar.gz
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
echo "value=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
- name: Download updated maven aarch64 dependencies
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: maven-sources-aarch64
path: mvn-src-aarch64
- name: Download updated maven x86_64 dependencies
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: maven-sources-x86_64
path: mvn-src-x64
- name: Determine revision
id: revision
run: |
CURRENT_VERSION="$(yq '(.modules[] | select(.name == "cryptomator") | .build-options.env.VERSION)' org.cryptomator.Cryptomator.yaml)"
CURRENT_REVISION="$(yq '(.modules[] | select(.name == "cryptomator") | .build-options.env.REVISION_NO)' org.cryptomator.Cryptomator.yaml)"
if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" && "$CURRENT_REVISION" =~ ^[0-9]+$ ]]; then
NEXT_REVISION=$((CURRENT_REVISION + 1))
else
NEXT_REVISION=1
fi
echo "value=${NEXT_REVISION}" >> "$GITHUB_OUTPUT"
env:
TARGET_VERSION: ${{ needs.get-version.outputs.semVerStr }}
- name: Update build files
run: |
cp -r -f cryptomator/dist/linux/flatpak/* .
cp -r -f mvn-src-x64/* .
cp -r -f mvn-src-aarch64/* .
envsubst '$FLATPAK_VERSION $FLATPAK_REVISION $CRYPTOMATOR_SOURCE' < org.cryptomator.Cryptomator.TEMPLATE.yaml > org.cryptomator.Cryptomator.yaml
yq -i 'del(.modules[] | select(.name == "cryptomator") | .build-options.build-args)' org.cryptomator.Cryptomator.yaml
yq -i '(.modules[] | select(.name == "cryptomator") | .sources) += ["maven-dependencies.yaml", "javafx-maven-dependencies-x86_64.yaml", "javafx-maven-dependencies-aarch64.yaml"]' org.cryptomator.Cryptomator.yaml
env:
FLATPAK_VERSION: ${{ needs.get-version.outputs.semVerNum }}
FLATPAK_REVISION: ${{ steps.revision.outputs.value}}
CRYPTOMATOR_SOURCE: |-
type: archive
sha512: ${{steps.sha512.outputs.value}}
url: ${{ env.TARBALL_URL }}
- name: Commit and push
run: |
git config user.name "cryptobot"
git config user.email "cryptobot@users.noreply.github.com"
git config push.autoSetupRemote true
git stage org.cryptomator.Cryptomator.yaml maven-dependencies.yaml javafx-maven-dependencies-aarch64.yaml javafx-maven-dependencies-x86_64.yaml
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
git push
- name: Create pull request
id: create-pr
run: |
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
if: github.event_name == 'release'
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: ''
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 <${{ steps.create-pr.outputs.FLATHUB_PR_URL }}|PR> on how to proceed."
SLACK_FOOTER: ''
MSG_MINIMAL: true
+12 -11
View File
@@ -3,6 +3,8 @@ name: Build Arch package
on:
release:
types: [published]
schedule:
- cron: '0 21 20 * *'
workflow_dispatch:
inputs:
version:
@@ -42,7 +44,7 @@ jobs:
pacman-key --init
pacman-key --populate archlinux
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: cryptomator
- name: Create build user
@@ -67,13 +69,13 @@ jobs:
sudo -u builder
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
makepkg --syncdeps --cleanbuild --noconfirm --log
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: arch-package
if-no-files-found: error
path: |
${{ env.PKGDEST }}/*.pkg.tar.zst
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pkgbuild-file
if-no-files-found: error
@@ -106,7 +108,7 @@ jobs:
env:
TAG: ${{ needs.get-version.outputs.semVerStr || github.event.release.tag_name }}
- name: Checkout cryptomator/aur repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: 'cryptomator/aur'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
@@ -130,7 +132,6 @@ jobs:
- name: Determine pkgrel
id: pkgrel
run: |
TARGET_VERSION='${{ needs.get-version.outputs.semVerStr }}'
CURRENT_VERSION="$(sed -nE 's/^pkgver=(.*)$/\1/p' PKGBUILD | head -n1)"
CURRENT_REL="$(sed -nE 's/^pkgrel=([0-9]+).*$/\1/p' PKGBUILD | head -n1)"
@@ -141,11 +142,11 @@ jobs:
fi
echo "value=${NEXT_REL}" >> "$GITHUB_OUTPUT"
echo "dist-version=${VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT"
echo "dist-version=${TARGET_VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT"
env:
VERSION: ${{ needs.get-version.outputs.semVerStr }}
TARGET_VERSION: ${{ needs.get-version.outputs.semVerStr }}
- name: Download PKGBUILD template
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: pkgbuild-file
- name: Prepare PKGBUILD
@@ -187,14 +188,14 @@ jobs:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Slack Notification
if: github.event_name == 'release'
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON: ''
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "AUR release PR created for ${{ github.event.repository.name }} ${{ steps.pkgrel.outputs.dist-version }} ."
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
SLACK_FOOTER: false
SLACK_FOOTER: ''
MSG_MINIMAL: true
+69 -36
View File
@@ -9,13 +9,45 @@ name: Build macOS .dmg for x64
#######################################
on:
release:
types: [published]
schedule:
- cron: '0 20 20 * *'
workflow_call:
inputs:
semVerNum:
type: string
description: 'The Major.Minor.Patch part of the version'
required: true
revisionNum:
type: string
description: 'The revision number'
required: true
semVerSuffix:
type: string
description: 'The suffix of the version, including dash'
required: true
notarize:
description: 'Notarize'
default: true
type: boolean
upload-to-draft:
type: boolean
default: true
outputs:
sha256-dmg:
description: "SHA256 sum of the x64 dmg"
value: ${{ jobs.build.outputs.sha256sum}}
workflow_dispatch:
inputs:
version:
description: 'Version'
semVerNum:
description: 'The Major.Minor.Patch part of the version'
required: false
revisionNum:
description: 'The revision number'
required: false
semVerSuffix:
description: 'The suffix of the version, including dash'
required: false
default: '-SNAPSHOT'
notarize:
description: 'Notarize'
required: true
@@ -24,18 +56,18 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.2+10.0.LTS'
JAVA_VERSION: '26.0.1+8'
VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}}
REVISION_NUM: ${{ inputs.revisionNum || '0' }}
VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}}
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }}
build-arm:
build:
name: Build Cryptomator.app for ${{ matrix.output-suffix }}
runs-on: ${{ matrix.os }}
needs: [get-version]
outputs:
sha256sum: ${{ steps.sha256sum.outputs.value }}
strategy:
fail-fast: false
matrix:
@@ -44,12 +76,12 @@ jobs:
architecture: x64
output-suffix: x64
fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_osx-x64_bin-jmods.zip'
openjfx-sha: '3512fabe43aee467538d329cfbbaab3c53dff2a810f0d54e381f461d5e0fac43'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -68,7 +100,7 @@ jobs:
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(./mvnw help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
@@ -77,9 +109,9 @@ jobs:
exit 1
fi
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
run : ./mvnw versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}"
- name: Run maven
run: mvn -B clean package -Pmac -DskipTests
run: ./mvnw -B clean package -Pmac -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
@@ -117,8 +149,8 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--copyright "(C) 2016 - 2026 Skymatic GmbH"
--app-version "${VERSION_NUM}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m"
@@ -127,7 +159,7 @@ jobs:
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\""
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
@@ -137,7 +169,7 @@ jobs:
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NUM}\""
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--mac-package-identifier org.cryptomator
--resource-dir dist/mac/resources
@@ -146,16 +178,14 @@ jobs:
mv appdir/Cryptomator.app Cryptomator.app
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NUM}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NUM}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Generate license for dmg
run: >
mvn -B license:add-third-party
./mvnw -B license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
@@ -240,16 +270,14 @@ jobs:
--eula "dist/mac/dmg/resources/license.rtf"
--icon ".background" 128 758
--icon ".VolumeIcon.icns" 512 758
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
Cryptomator-${VERSION_NUM}-${{ matrix.output-suffix }}.dmg dmg
- name: Codesign .dmg
run: |
codesign -s ${CODESIGN_IDENTITY} --timestamp Cryptomator-*.dmg
env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
- name: Notarize .dmg
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
if: inputs.notarize || github.event_name == 'schedule'
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
with:
app-path: 'Cryptomator-*.dmg'
@@ -257,8 +285,12 @@ jobs:
password: ${{ secrets.MACOS_NOTARIZATION_PW }}
team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
xcode-path: '/Applications/Xcode_16.app'
- id: sha256sum
run: |
read -ra CMD_OUTPUT < <(shasum -a256 Cryptomator-*.dmg)
echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT
- name: Add possible alpha/beta tags to installer name
run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg
run: mv Cryptomator-*.dmg "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.output-suffix }}.dmg"
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -271,7 +303,7 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dmg-${{ matrix.output-suffix }}
path: |
@@ -279,9 +311,10 @@ jobs:
Cryptomator-*.asc
if-no-files-found: error
- name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
if: inputs.upload-to-draft
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
draft: true
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
+68 -35
View File
@@ -1,13 +1,45 @@
name: Build macOS .dmg for arm64
on:
release:
types: [published]
schedule:
- cron: '0 20 20 * *'
workflow_call:
inputs:
semVerNum:
type: string
description: 'The Major.Minor.Patch part of the version'
required: true
revisionNum:
type: string
description: 'The revision number'
required: true
semVerSuffix:
type: string
description: 'The suffix of the version, including dash'
required: true
notarize:
description: 'Notarize'
default: true
type: boolean
upload-to-draft:
type: boolean
default: true
outputs:
sha256-dmg:
description: "SHA256 sum of the arm64 dmg"
value: ${{ jobs.build.outputs.sha256sum}}
workflow_dispatch:
inputs:
version:
description: 'Version'
semVerNum:
description: 'The Major.Minor.Patch part of the version'
required: false
revisionNum:
description: 'The revision number'
required: false
semVerSuffix:
description: 'The suffix of the version, including dash'
required: false
default: '-SNAPSHOT'
notarize:
description: 'Notarize'
required: true
@@ -22,18 +54,18 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.2+10.0.LTS'
JAVA_VERSION: '26.0.1+8'
VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}}
REVISION_NUM: ${{ inputs.revisionNum || '0' }}
VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}}
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }}
build:
name: Build Cryptomator.app for ${{ matrix.output-suffix }}
runs-on: ${{ matrix.os }}
needs: [get-version]
outputs:
sha256sum: ${{ steps.sha256sum.outputs.value }}
strategy:
fail-fast: false
matrix:
@@ -42,12 +74,12 @@ jobs:
architecture: aarch64
output-suffix: arm64
fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: '4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a'
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_osx-aarch64_bin-jmods.zip'
openjfx-sha: 'a52014d625b8b04e57fd71650f881c1397542b4018e1b04f1b4e66c8800a1f34'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -66,7 +98,7 @@ jobs:
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(./mvnw help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
@@ -75,9 +107,9 @@ jobs:
exit 1
fi
- name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
run : ./mvnw versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}"
- name: Run maven
run: mvn -B clean package -Pmac -DskipTests
run: ./mvnw -B clean package -Pmac -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
@@ -115,8 +147,8 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--copyright "(C) 2016 - 2026 Skymatic GmbH"
--app-version "${VERSION_NUM}"
--java-options "--enable-preview"
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m"
@@ -125,7 +157,7 @@ jobs:
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\""
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
@@ -135,7 +167,7 @@ jobs:
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NUM}\""
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
--mac-package-identifier org.cryptomator
@@ -145,16 +177,14 @@ jobs:
mv appdir/Cryptomator.app Cryptomator.app
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NUM}|g" Cryptomator.app/Contents/Info.plist
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NUM}|g" Cryptomator.app/Contents/Info.plist
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
- name: Generate license for dmg
run: >
mvn -B license:add-third-party
./mvnw -B license:add-third-party
-Dlicense.thirdPartyFilename=license.rtf
-Dlicense.outputDirectory=dist/mac/dmg/resources
-Dlicense.fileTemplate=dist/mac/dmg/resources/licenseTemplate.ftl
@@ -239,16 +269,14 @@ jobs:
--eula "dist/mac/dmg/resources/license.rtf"
--icon ".background" 128 758
--icon ".VolumeIcon.icns" 512 758
Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg
env:
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
Cryptomator-${VERSION_NUM}-${{ matrix.output-suffix }}.dmg dmg
- name: Codesign .dmg
run: |
codesign -s ${CODESIGN_IDENTITY} --timestamp Cryptomator-*.dmg
env:
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
- name: Notarize .dmg
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
if: inputs.notarize || github.event_name == 'schedule'
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
with:
app-path: 'Cryptomator-*.dmg'
@@ -256,8 +284,12 @@ jobs:
password: ${{ secrets.MACOS_NOTARIZATION_PW }}
team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
xcode-path: '/Applications/Xcode_16.app'
- id: sha256sum
run: |
read -ra CMD_OUTPUT < <(shasum -a256 Cryptomator-*.dmg)
echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT
- name: Add possible alpha/beta tags to installer name
run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg
run: mv Cryptomator-*.dmg "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.output-suffix }}.dmg"
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -270,7 +302,7 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dmg-${{ matrix.output-suffix }}
path: |
@@ -278,9 +310,10 @@ jobs:
Cryptomator-*.asc
if-no-files-found: error
- name: Publish dmg on GitHub Releases
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
if: inputs.upload-to-draft
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
draft: true
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
+2 -2
View File
@@ -7,12 +7,12 @@ on:
jobs:
no-response:
runs-on: ubuntu-latest
runs-on: ubuntu-slim
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
with:
days-before-stale: 14
days-before-close: 0
+130 -24
View File
@@ -5,35 +5,141 @@ on:
types: [published]
jobs:
get-version:
runs-on: ubuntu-latest
notify:
runs-on: ubuntu
steps:
- name: Download source tarball
run: |
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
echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.tar.gz
env:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Publish asc on GitHub Releases
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
cryptomator-*.tar.gz.asc
- name: Slack Notification
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
- name: Notify about DEB build
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON: ''
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "Release ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published."
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/debian.yml|build deb Package>."
SLACK_FOOTER: false
MSG_MINIMAL: true
SLACK_FOOTER: ''
MSG_MINIMAL: true
- name: Notify about latest-version update
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: ''
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "Requiring version check source update for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }}."
SLACK_MESSAGE: 'Check S3 bucket for <https://static.cryptomator.org/desktop/latest-version.json|latest-version.json>.'
SLACK_FOOTER: ''
MSG_MINIMAL: true
get-asset-urls:
name: Get release asset URLs
runs-on: ubuntu-slim
outputs:
is-windows-release: ${{ steps.urls.outputs.urls-present }}
msi-url: ${{ steps.urls.outputs.msi }}
exe-url: ${{ steps.urls.outputs.exe }}
steps:
- name: Extract MSI and EXE download URLs
id: urls
run: |
MSI_URL=$(jq -r '[.[] | select(.name | endswith("-x64.msi"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS")
EXE_URL=$(jq -r '[.[] | select(.name | endswith("-x64.exe"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS")
if [[ "$MSI_URL" == "null" || -z "$MSI_URL" || "$EXE_URL" == "null" || -z "$EXE_URL" ]]; then
echo "urls-present=false" >> $GITHUB_OUTPUT
else
echo "urls-present=true" >> $GITHUB_OUTPUT
echo "msi=${MSI_URL}" >> $GITHUB_OUTPUT
echo "exe=${EXE_URL}" >> $GITHUB_OUTPUT
fi
env:
RELEASE_ASSETS: ${{ toJson(github.event.release.assets) }}
allowlist-msi-x64:
needs: [get-asset-urls]
if: needs.get-asset-urls.outputs.is-windows-release == 'true'
uses: ./.github/workflows/av-whitelist.yml
with:
url: ${{ needs.get-asset-urls.outputs.msi-url }}
secrets: inherit
allowlist-exe-x64:
needs: [get-asset-urls, allowlist-msi-x64]
if: needs.get-asset-urls.outputs.is-windows-release == 'true'
uses: ./.github/workflows/av-whitelist.yml
with:
url: ${{ needs.get-asset-urls.outputs.exe-url }}
secrets: inherit
check-release:
name: Analyzes the release for certain properties
runs-on: ubuntu-slim
outputs:
release-kind: ${{steps.determine-kind.outputs.value}} # Possible values are [alpha, beta, rc, stable, unknown]
steps:
- id: determine-kind
run: |
SEM_VER_NUM=$(echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
SEM_VER_SUFFIX="${SEM_VER_STR#"$SEM_VER_NUM"}"
TYPE="unknown"
if [[ -z $SEM_VER_SUFFIX ]]; then
TYPE="stable"
elif [[ $SEM_VER_SUFFIX =~ -alpha[1-9]+$ ]]; then
TYPE="alpha"
elif [[ $SEM_VER_SUFFIX =~ -beta[1-9]+$ ]]; then
TYPE="beta"
elif [[ $SEM_VER_SUFFIX =~ -rc[1-9]+$ ]]; then
TYPE="rc"
fi
echo "value=${TYPE}" >> $GITHUB_OUTPUT
env:
SEM_VER_STR: ${{ github.event.release.tag_name }}
notify-winget:
name: Notify for winget-release
if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.check-release.outputs.release-kind == 'stable'
needs: [check-release, get-asset-urls]
runs-on: ubuntu
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: ''
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "Release ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published."
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml|release to winget>."
SLACK_FOOTER: ''
MSG_MINIMAL: true
trigger-website-update:
needs: [check-release]
runs-on: ubuntu-slim
if: needs.check-release.outputs.release-kind == 'stable'
steps:
- name: Start website update workflow
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
event-type: desktop-release
token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }}
repository: cryptomator/cryptomator.github.io
client-payload: '{ "version": "${{ github.event.release.tag_name }}", "release": ${{ toJson(github.event.release.assets) }} }'
trigger-docs-update:
needs: [check-release, get-asset-urls]
runs-on: ubuntu-slim
if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.check-release.outputs.release-kind == 'stable'
steps:
- name: Start docs update workflow
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
event-type: desktop-release
token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }}
repository: cryptomator/docs
client-payload: '{ "version": "${{ github.event.release.tag_name }}", "release": ${{ toJson(github.event.release.assets) }} }'
+4 -4
View File
@@ -5,7 +5,7 @@ on:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 25
JAVA_VERSION: 26
defaults:
run:
@@ -16,11 +16,11 @@ jobs:
name: Compile and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Build and Test
run: xvfb-run mvn -B clean install jacoco:report -Pcoverage
run: xvfb-run ./mvnw -B clean install jacoco:report -Pcoverage
+5 -20
View File
@@ -12,16 +12,16 @@ defaults:
env:
JAVA_DIST: 'temurin'
JAVA_VERSION: 25
JAVA_VERSION: 26
jobs:
check-preconditions:
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }}
@@ -36,7 +36,7 @@ jobs:
exit 1
fi
if [[ ${SEM_VER_STR} == `mvn help:evaluate -Dexpression=project.version -q -DforceStdout` ]]; then
if [[ ${SEM_VER_STR} == `./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout` ]]; then
echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT
else
echo "Version not set in POM"
@@ -48,19 +48,4 @@ jobs:
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\">" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml"
exit 1
fi
- name: Cache NVD DB
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.m2/repository/org/owasp/dependency-check-data/
key: dependency-check-${{ github.run_id }}
restore-keys: |
dependency-check
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5
- name: Run org.owasp:dependency-check plugin
id: dependency-check
continue-on-error: true
run: mvn -B verify -Pdependency-check -DskipTests
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
fi
+2 -2
View File
@@ -7,12 +7,12 @@ on:
jobs:
stale:
runs-on: ubuntu-latest
runs-on: ubuntu-slim
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
with:
days-before-stale: 365
days-before-close: 90
+130 -129
View File
@@ -1,13 +1,48 @@
name: Build Windows Installer
on:
release:
types: [published]
schedule:
- cron: '0 19 20 * *'
workflow_call:
inputs:
semVerNum:
type: string
description: 'The Major.Minor.Patch part of the version'
required: true
revisionNum:
type: string
description: 'The revision number'
required: true
semVerSuffix:
type: string
description: 'The suffix of the version, including dash'
required: true
sign:
description: 'Sign binaries'
default: true
type: boolean
upload-to-draft:
type: boolean
default: true
outputs:
sha256-msi:
description: "SHA256 sum of the x64 msi"
value: ${{ jobs.build-msi.outputs.sha256sum}}
sha256-exe:
description: "SHA256 sum of the x64 exe"
value: ${{ jobs.build-exe.outputs.sha256sum}}
workflow_dispatch:
inputs:
version:
description: 'Version'
semVerNum:
description: 'The Major.Minor.Patch part of the version'
required: false
revisionNum:
description: 'The revision number'
required: false
semVerSuffix:
description: 'The suffix of the version, including dash'
required: false
default: '-SNAPSHOT'
sign:
description: 'Sign binaries'
required: false
@@ -22,8 +57,11 @@ on:
env:
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}}
REVISION_NUM: ${{ inputs.revisionNum || '0' }}
VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}}
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '0bf9b83260b85607a9ba200124debabd9cdb013cbc0d659e62a20192a7137907'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
WINFSP_MSI_HASH: '073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
@@ -34,27 +72,23 @@ defaults:
shell: bash
jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.version }}
build-msi:
name: Build .msi Installer
runs-on: ${{ matrix.os }}
needs: [ get-version ]
outputs:
sha256sum: ${{ steps.sha256sum.outputs.value }}
strategy:
matrix:
include:
- arch: x64
os: windows-latest
java-dist: 'zulu' #cannot use temurin, see https://github.com/cryptomator/cryptomator/issues/3824#issuecomment-2829827427
java-version: '25.0.1+8'
java-dist: 'temurin'
java-version: '26.0.1+8'
java-package: 'jdk'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }}
@@ -85,7 +119,7 @@ jobs:
JMOD_VERSION_AMD64=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@}
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(./mvnw help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
@@ -94,9 +128,9 @@ jobs:
exit 1
fi
- name: Set version
run: mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
run: ./mvnw versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}"
- name: Run maven
run: mvn -B clean package -Pwin -DskipTests
run: ./mvnw -B clean package -Pwin -DskipTests
- name: Patch target dir
run: |
cp LICENSE.txt target
@@ -134,13 +168,13 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--copyright "(C) 2016 - 2026 Skymatic GmbH"
--app-version "${VERSION_NUM}.${REVISION_NUM}"
--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=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\""
--java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dcryptomator.adminConfigPath=\"C:/ProgramData/Cryptomator/config.properties\""
@@ -151,7 +185,7 @@ jobs:
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Cryptomator\""
--java-options "-Dcryptomator.loopbackAlias=\"cryptomator-vault\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.buildNumber=\"msi-${REVISION_NUM}\""
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\""
--java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\""
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
@@ -186,33 +220,32 @@ jobs:
}
$jar.Dispose()
}
- name: Extract wixhelper.dll for Codesigning #see https://github.com/cryptomator/cryptomator/issues/3130
shell: pwsh
- name: Get msi helper dll for code signing
run: |
New-Item -Path appdir/jpackage-jmod -ItemType Directory
& $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
${JAVA_HOME}/bin/jpackage --type msi --win-upgrade-uuid bda45523-42b1-4cae-9354-a45475ed4775 --app-image appdir/Cryptomator --dest /tmp/ --name Test --vendor Test --copyright "None" --app-version "1.0" --temp msi-helper
find ./msi-helper/ -type f -name msica.dll -exec mv {} ./appdir \;
- name: Sign DLLs with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
if: inputs.sign || github.event_name == 'schedule'
uses: ./.github/actions/win-sign-action
with:
base-dir: ${{ github.workspace }}\appdir
file-extensions: 'exe,dll'
recursive: true
append-signature: true
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign DLLs with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
- name: Sign Scripts with Azure Trusted Signing
if: inputs.sign || github.event_name == 'schedule'
uses: ./.github/actions/win-sign-action
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 }}
base-dir: ${{ github.workspace }}\appdir\Cryptomator
file-extensions: 'ps1'
recursive: false
append-signature: false # Powershell scripts cannot be signed in append mode, see #4260
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Replace DLLs inside jars with signed ones
shell: pwsh
run: |
@@ -229,7 +262,7 @@ jobs:
}
- name: Generate license for MSI
run: >
mvn -B license:add-third-party
./mvnw -B license:add-third-party
"-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.outputDirectory=dist/win/resources"
"-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
@@ -238,6 +271,16 @@ jobs:
"-Dlicense.failOnMissing=true"
"-Dlicense.licenseMergesUrl=file:///${{ github.workspace }}/license/merges"
shell: pwsh
- name: Create file association file from template
working-directory: dist/win
run: |
$Env:JP_WIXWIZARD_RESOURCES_PROPERTIES_FORMAT = "${Env:JP_WIXWIZARD_RESOURCES}".Replace('\', '\\');
Get-Content .\resources\FAvaultFile.template.properties `
| ForEach-Object { $ExecutionContext.InvokeCommand.ExpandString($_) } `
| Out-File -FilePath .\resources\FAvaultFile.properties
env:
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources/ # requires abs path, used in resources/main.wxs
shell: pwsh
- name: Create MSI
run: >
${JAVA_HOME}/bin/jpackage
@@ -248,21 +291,21 @@ jobs:
--dest installer
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
--copyright "(C) 2016 - 2026 Skymatic GmbH"
--app-version "${VERSION_NUM}.${REVISION_NUM}"
--win-menu
--win-dir-chooser
--win-shortcut-prompt
--win-update-url "https:\\cryptomator.org\downloads"
--win-update-url "https://cryptomator.org/downloads"
--win-menu-group Cryptomator
--resource-dir dist/win/resources
--license-file dist/win/resources/license.rtf
--file-associations dist/win/resources/FAvaultFile.properties
env:
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources/ # requires abs path, used in resources/main.wxs
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir\
- name: Sign MSI with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
if: inputs.sign || github.event_name == 'schedule'
uses: ./.github/actions/win-sign-action
with:
base-dir: ${{ github.workspace }}\installer
@@ -271,8 +314,12 @@ jobs:
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- id: sha256sum
run: |
read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.msi)
echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT
- 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
run: mv installer/Cryptomator-*.msi "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.arch }}.msi"
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -281,7 +328,7 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: msi-${{ matrix.arch }}
path: |
@@ -292,18 +339,20 @@ jobs:
build-exe:
name: Build .exe installer
runs-on: ${{ matrix.os }}
needs: [ get-version, build-msi ]
needs: [ build-msi ]
outputs:
sha256sum: ${{ steps.sha256sum.outputs.value }}
strategy:
matrix:
include:
- arch: x64
os: windows-latest
executable-suffix: x64
java-dist: 'zulu'
java-version: '24.0.1+9'
java-dist: 'temurin'
java-version: '26.0.1+8'
java-package: 'jdk'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version ${WIX_VERSION}
@@ -312,14 +361,14 @@ jobs:
env:
WIX_VERSION: ${{ env.WIX_VERSION }}
- name: Download .msi
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: msi-${{ matrix.arch }}
path: dist/win/bundle/resources
- name: Strip version info from msi file name
run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }}
@@ -328,7 +377,7 @@ jobs:
cache: 'maven'
- name: Generate license for exe
run: >
mvn -B license:add-third-party
./mvnw -B license:add-third-party
"-Dlicense.thirdPartyFilename=license.rtf"
"-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
"-Dlicense.outputDirectory=dist/win/bundle/resources"
@@ -339,10 +388,10 @@ jobs:
shell: pwsh
- name: Download WinFsp
run: |
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)."
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)."
}
env:
WINFSP_PATH: 'dist/win/bundle/resources/winfsp.msi'
@@ -356,21 +405,22 @@ jobs:
run: >
wix build
-define BundleName="Cryptomator"
-define BundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
-define BundleVersion="${VERSION_NUM}.${REVISION_NUM}"
-define BundleVendor="Skymatic GmbH"
-define BundleCopyright="(C) 2016 - 2025 Skymatic GmbH"
-define BundleCopyright="(C) 2016 - 2026 Skymatic GmbH"
-define AboutUrl="https://cryptomator.org"
-define HelpUrl="https://cryptomator.org/contact"
-define UpdateUrl="https://cryptomator.org/downloads/"
-ext "WixToolset.Util.wixext"
-ext "WixToolset.BootstrapperApplications.wixext"
./bundle/bundleWithWinfsp.wxs
-out "../../installer/unsigned/Cryptomator-Installer.exe"
-out "../../installer/Cryptomator-Installer.exe"
- name: Detach burn engine in preparation to sign
if: inputs.sign || github.event_name == 'schedule'
run: >
wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
wix burn detach installer/Cryptomator-Installer.exe -engine tmp/engine.exe
- name: Sign WiX burn engine with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
if: inputs.sign || github.event_name == 'schedule'
uses: ./.github/actions/win-sign-action
with:
base-dir: ${{ github.workspace }}\tmp
@@ -380,21 +430,14 @@ jobs:
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign burn engine with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
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
run: >
wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
if: inputs.sign || github.event_name == 'schedule'
shell: pwsh
run: |
Move-Item -Path installer/Cryptomator-Installer.exe -Destination tmp/Cryptomator-Installer.exe
wix burn reattach tmp/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
- name: Sign EXE installer with Azure Trusted Signing
if: inputs.sign || github.event_name == 'release'
if: inputs.sign || github.event_name == 'schedule'
uses: ./.github/actions/win-sign-action
with:
base-dir: ${{ github.workspace }}\installer
@@ -404,18 +447,12 @@ jobs:
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
client-id: ${{ secrets.AZURE_CLIENT_ID }}
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign installer with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
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 }}
- id: sha256sum
run: |
read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.exe)
echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT
- name: Add possible alpha/beta tags to installer name
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe
run: mv installer/Cryptomator-Installer.exe "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.executable-suffix }}.exe"
- name: Create detached GPG signature with key 615D449FE6E6A235
run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -424,7 +461,7 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: exe-${{ matrix.executable-suffix }}
path: |
@@ -434,58 +471,22 @@ jobs:
publish:
name: Publish installers to the github release
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
if: inputs.upload-to-draft
runs-on: ubuntu-latest
needs: [ build-msi, build-exe ]
outputs:
download-url-msi-x64: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
steps:
- name: Download installers
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
merge-multiple: true
- name: Publish installers on GitHub Releases
id: publish
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
draft: true
fail_on_unmatched_files: true
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
# do not change ordering of filelist, required for correct job output
files: |
*x64.msi
*x64.exe
*.asc
allowlist-msi-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish ]
with:
url: ${{ needs.publish.outputs.download-url-msi-x64 }}
secrets: inherit
allowlist-exe-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-x64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe-x64 }}
secrets: inherit
notify-winget:
name: Notify for winget-release
if: needs.get-version.outputs.versionType == 'stable'
needs: [publish, get-version]
runs-on: ubuntu-latest
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: 'Cryptobot'
SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "MSI packages of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published."
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml| release them to winget>."
SLACK_FOOTER: false
MSG_MINIMAL: true
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
env:
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
- name: Submit package
uses: vedantmgoyal2009/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f # no_specific_version
uses: vedantmgoyal2009/winget-releaser@7bd472be23763def6e16bd06cc8b1cdfab0e2fd5 # no_specific_version
with:
identifier: Cryptomator.Cryptomator
version: ${{ inputs.tag }}
+4
View File
@@ -0,0 +1,4 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
distributionSha256Sum=5af3b743dd8b876b5c45da33b676251e5f1687712644abb4ee519ca56e1d89ce
+31
View File
@@ -7,6 +7,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
The changelog starts with version 1.19.0.
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
## [1.19.3](https://github.com/cryptomator/cryptomator/releases/1.19.3) - 2026-06-29
### Added
* New error dialog if importing a vault fails ([#4243](https://github.com/cryptomator/cryptomator/pull/4243))
### Fixed
* Fixed Cryptomator file extensions were not registered on Windows ([#4219](https://github.com/cryptomator/cryptomator/issues/4219))
* Fixed warning was displayed when accessing update tab in settings even though an update check did not ran ([#4199](https://github.com/cryptomator/cryptomator/pull/4199))
* Fixed several Decrypt Name dialogs could be opened on the same vault ([#4164](https://github.com/cryptomator/cryptomator/pull/4164))
* Fixed not all mount options in vault specific settings could be displayed ([#4227](https://github.com/cryptomator/cryptomator/pull/4227))
* Fixed localhost alias on Windows was not removed on uninstall ([#3993](https://github.com/cryptomator/cryptomator/issues/3993))
### Changed
* Refactored release pipeline to allow immutable releases ([#4205](https://github.com/cryptomator/cryptomator/pull/4205))
* Updated to JDK 26.0.1 ([#4244](https://github.com/cryptomator/cryptomator/pull/4244))
* Updated to JavaFX 25.0.3 ([#4255](https://github.com/cryptomator/cryptomator/pull/4255))
* Drop signing with Actalis issued certificate ([#4169](https://github.com/cryptomator/cryptomator/pull/4169), [#4262](https://github.com/cryptomator/cryptomator/pull/4262))
* Fix dagger binding graph issues ([#4147](https://github.com/cryptomator/cryptomator/pull/4147))
* Added flatpak build to CI ([#4199](https://github.com/cryptomator/cryptomator/pull/4199))
* Updated dependencies:
- `org.cryptomator:webdav-nio-adapter` from 3.0.1 to 3.0.2
- `org.cryptomator:integrations-api` from 1.8.0 to 1.9.0
- `org.slf4j:slf4j-api` from 2.0.17 to 2.0.18
- `ch.qos.logback:logback-core` from 1.5.32 to 1.5.35
- `ch.qos.logback:logback-classic` from 1.5.32 to 1.5.35
- `com.auth0:java-jwt` from 4.5.1 4.5.2
- `com.fasterxml.jackson.core:jackson-databind` from 2.21.1 to 2.21.4
- `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.21.1 to 2.21.4
- `com.github.ben-manes.caffeine:caffeine` from 3.2.3 to 3.2.4
## [1.19.2](https://github.com/cryptomator/cryptomator/releases/1.19.2) - 2026-03-20
### Security
+1 -5
View File
@@ -79,15 +79,11 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies
* JDK 25 (e.g. temurin, zulu)
* Maven 3
### Run Maven
```
mvn clean install
# or mvn clean install -Pwin
# or mvn clean install -Pmac
# or mvn clean install -Plinux
./mvnw clean install
```
This will build all the jars and bundle them together with their OS-specific dependencies under `target`. This can now be used to build native packages.
+9 -9
View File
@@ -6,29 +6,29 @@ REVISION_NO=`git rev-list --count HEAD`
# check preconditions
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found."; exit 1; }
[ -x ../../../mvnw ] || { echo >&2 "mvnw not found at ../../../mvnw."; exit 1; }
command -v curl >/dev/null 2>&1 || { echo >&2 "curl not found."; exit 1; }
command -v unzip >/dev/null 2>&1 || { echo >&2 "unzip not found."; exit 1; }
VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
VERSION=$(../../../mvnw -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
SEMVER_STR=${VERSION}
CPU_ARCH=$(uname -m)
if [[ ! "${CPU_ARCH}" =~ x86_64|aarch64 ]]; then echo "Platform ${CPU_ARCH} not supported"; exit 1; fi
mvn -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR}
../../../mvnw -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR}
# compile
mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
../../../mvnw -B -f ../../../pom.xml clean package -DskipTests
cp ../../../LICENSE.txt ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods
JAVAFX_VERSION=25.0.2
JAVAFX_VERSION=25.0.3
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
JAVAFX_JMODS_SHA256='47035c653863a8e4be3dc6f142b8dbd84b4bb1efc9a8cbc68413e6a5ff5e9f50'
if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
JAVAFX_JMODS_SHA256='e3fd682354346845d2944a2da2b1ff2b6cb9259d92027f2f9c121b9b93c5e42f'
fi
# download javaFX jmods
@@ -42,7 +42,7 @@ unzip -o -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/jav
JMOD_VERSION=$(jmod describe ./openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout -B -f ../../../pom.xml)
POM_JFX_VERSION=$(../../../mvnw help:evaluate "-Dexpression=javafx.version" -q -DforceStdout -B -f ../../../pom.xml)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
@@ -82,7 +82,7 @@ ${JAVA_HOME}/bin/jpackage \
--vendor "Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
--copyright "(C) 2016 - 2026 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--app-version "${VERSION}.${REVISION_NO}" \
@@ -84,6 +84,9 @@
</content_rating>
<releases>
<release date="2026-06-29" version="1.19.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.3</url>
</release>
<release date="2026-03-20" version="1.19.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.2</url>
</release>
+1 -1
View File
@@ -2,7 +2,7 @@ Source: cryptomator
Maintainer: Cryptobot <releases@cryptomator.org>
Section: utils
Priority: optional
Build-Depends: debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1
Build-Depends: debhelper (>=10), coffeelibs-jdk-26 (>= 26.0.1+8-0ppa1), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1
Standards-Version: 4.5.0
Homepage: https://cryptomator.org
Vcs-Git: https://github.com/cryptomator/cryptomator.git
+2 -3
View File
@@ -4,12 +4,11 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
JAVA_HOME = /usr/lib/jvm/java-26-coffeelibs
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
ifeq ($(DEB_BUILD_ARCH),amd64)
JAVA_HOME = /usr/lib/jvm/java-25-openjdk-amd64
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
else ifeq ($(DEB_BUILD_ARCH),arm64)
JAVA_HOME = /usr/lib/jvm/java-25-openjdk-arm64
JMODS_PATH = jmods/aarch64:${JAVA_HOME}/jmods
endif
@@ -46,7 +45,7 @@ override_dh_auto_build:
--vendor "Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \
--copyright "(C) 2016 - 2026 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
# From: https://gitlab.gnome.org/GNOME/gnome-builder/-/blob/main/build-aux/flatpak/fusermount-wrapper.sh
if [ -z "$_FUSE_COMMFD" ]; then
FD_ARGS=
else
FD_ARGS="--env=_FUSE_COMMFD=${_FUSE_COMMFD} --forward-fd=${_FUSE_COMMFD}"
fi
if [ -e /proc/self/fd/3 ] && [ 3 != "$_FUSE_COMMFD" ]; then
FD_ARGS="$FD_ARGS --forward-fd=3"
fi
exec flatpak-spawn --host --forward-fd=1 --forward-fd=2 $FD_ARGS fusermount3 "$@"
@@ -0,0 +1,182 @@
app-id: org.cryptomator.Cryptomator
command: cryptomator
runtime: org.freedesktop.Platform
runtime-version: '25.08'
sdk: org.freedesktop.Sdk
separate-locales: false
finish-args:
# Required for FUSE, see https://github.com/flathub/org.cryptomator.Cryptomator/pull/68#issuecomment-1935136502
- --device=all
# Set the PATH environment variable in the application, as flatpak is resetting the shell's PATH
- --env=PATH=/app/bin/:/usr/bin/
# Allow filesystem access to the user's home dir
# Needed to manage vaults there
- --filesystem=home
# Reading system certificates
- --filesystem=host-etc:ro
# Allow access to the XDG data directory
# Needed to connect to KeePassXC's UNIX domain socket
- --filesystem=xdg-run/org.keepassxc.KeePassXC.BrowserServer
- --filesystem=xdg-run/app/org.keepassxc.KeePassXC/
# Share IPC namespace with the host, without it the X11 shared memory extension will not work
- --share=ipc
# Allow access to the network
- --share=network
# Show windows using X11
- --socket=x11
# Needed to reveal encrypted files
- --talk-name=org.freedesktop.FileManager1
# Run any command on the host
# Needed to spawn fusermount on the host
- --talk-name=org.freedesktop.Flatpak
# Allow desktop notifications
- --talk-name=org.freedesktop.Notifications
# Allow access to the GNOME secret service API and to talk to the GNOME keyring daemon
- --talk-name=org.freedesktop.secrets
- --talk-name=org.gnome.keyring
# Allow to talk to the KDE kwallet daemon
- --talk-name=org.kde.kwalletd5
- --talk-name=org.kde.kwalletd6
# Needed to talk to the gvfs daemons over D-Bus and list mounts using the GIO APIs
- --talk-name=org.gtk.vfs.*
# Allow access to appindicator icons
- --talk-name=org.ayatana
# Allow access to appindicator icons on KDE
- --talk-name=org.kde.StatusNotifierWatcher
cleanup:
- /include
- /lib/pkgconfig
modules:
- shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json
- name: libfuse
buildsystem: meson
config-opts:
- -Dexamples=false
- -Dinitscriptdir=
- -Duseroot=false
- -Dtests=false
# don't install rules on the host
- -Dudevrulesdir=/tmp/
sources:
- type: archive
url: https://github.com/libfuse/libfuse/releases/download/fuse-3.16.2/fuse-3.16.2.tar.gz
sha256: f797055d9296b275e981f5f62d4e32e089614fc253d1ef2985851025b8a0ce87
x-checker-data:
type: anitya
project-id: 861
url-template: https://github.com/libfuse/libfuse/releases/download/fuse-$version/fuse-$version.tar.gz
versions: {<: '3.17.0'}
- name: host-command-wrapper
buildsystem: simple
build-commands:
- install fusermount-wrapper.sh /app/bin/fusermount3
sources:
- type: file
path: build-aux/fusermount-wrapper.sh
- name: cryptomator
buildsystem: simple
build-options:
build-args:
- --share=network
env:
PATH: /app/bin:/usr/bin
MAVEN_OPTS: -Dmaven.repo.local=.m2/repository
JAVA_HOME: jdk
JMODS_PATH: jmods
VERSION: $FLATPAK_VERSION
REVISION_NO: '$FLATPAK_REVISION'
build-commands:
# Setup Java
- tar xvfz jdk.tar.gz --transform 's!^[^/]*!jdk!'
- mkdir jmods
- unzip -j openjfx.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods
# Setup Maven
- mkdir maven
- tar xf maven.tar.gz --strip-components=1 --exclude=jansi-native --directory=maven
# Build project
- maven/bin/mvn clean package -DskipTests
- cp target/cryptomator-*.jar target/mods
- cd target
- $JAVA_HOME/bin/jlink
--output runtime
--module-path $JMODS_PATH
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler
--no-header-files
--no-man-pages
--strip-debug
--compress=zip-0
- $JAVA_HOME/bin/jpackage
--type app-image
--runtime-image runtime
--input target/libs
--module-path target/mods
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
--dest .
--name Cryptomator
--vendor 'Skymatic GmbH'
--copyright '(C) 2016 - 2026 Skymatic GmbH'
--java-options '--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator'
--java-options "--sun-misc-unsafe-memory-access=allow"
--java-options '-Xss5m'
--java-options '-Xmx256m'
--java-options '-Dfile.encoding='utf-8''
--java-options '-Djava.net.useSystemProxies=true'
--java-options "-Dcryptomator.appVersion='${VERSION}'"
--java-options "-Dcryptomator.buildNumber='flatpak-${REVISION_NO}'"
--java-options '-Dcryptomator.ipcSocketPath='@{userhome}/.config/Cryptomator/ipc.socket''
--java-options '-Dcryptomator.adminConfigPath='/run/host/etc/cryptomator/config.properties''
--java-options '-Dcryptomator.logDir='@{userhome}/.local/share/Cryptomator/logs''
--java-options '-Dcryptomator.mountPointsDir='@{userhome}/.local/share/Cryptomator/mnt''
--java-options '-Dcryptomator.pluginDir='@{userhome}/.local/share/Cryptomator/plugins''
--java-options '-Dcryptomator.p12Path='@{userhome}/.config/Cryptomator/key.p12''
--java-options '-Dcryptomator.settingsPath='@{userhome}/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json''
--java-options '-Dcryptomator.showTrayIcon=true'
--java-options '-Dcryptomator.updateMechanism=org.cryptomator.linux.update.FlatpakUpdater'
--java-options '-Dcryptomator.networking.truststore.p12Path='/run/host/etc/cryptomator/certs.p12''
--java-options '-Dcryptomator.hub.enableTrustOnFirstUse=true'
--app-version "${VERSION}.${REVISION_NO}"
--verbose
- cp -R Cryptomator /app/
- ln -s /app/Cryptomator/bin/Cryptomator /app/bin/cryptomator
- cp -R /app/lib/* /app/Cryptomator/lib/app/
- install -D -m0644 -t /app/share/applications/ dist/linux/common/org.cryptomator.Cryptomator.desktop
- install -D -m0644 -t /app/share/icons/hicolor/scalable/apps/ dist/linux/common/org.cryptomator.Cryptomator.svg
- install -D -m0644 -T dist/linux/common/org.cryptomator.Cryptomator.tray.svg /app/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg
- install -D -m0644 -T dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg /app/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.svg
- install -D -m0644 -t /app/share/metainfo/ dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
sources:
- $CRYPTOMATOR_SOURCE
- type: file
dest-filename: jdk.tar.gz
only-arches:
- x86_64
url: https://github.com/adoptium/temurin26-binaries/releases/download/jdk-26.0.1%2B8/OpenJDK26U-jdk_x64_linux_hotspot_26.0.1_8.tar.gz
sha512: eb46cda97ffd46e2e0c1f6f977dc204d9cc969b958946287b7e7d0bfe859fd92faccb2f6ef79995421a963c6de140c436af559403e0a2cd27c90b06c20260d5c
- type: file
dest-filename: jdk.tar.gz
only-arches:
- aarch64
url: https://github.com/adoptium/temurin26-binaries/releases/download/jdk-26.0.1%2B8/OpenJDK26U-jdk_aarch64_linux_hotspot_26.0.1_8.tar.gz
sha512: 3c31671552712a8f0df96df2eeae7e9ad5156c0e98ebd5bf4fa04c14bba58bd5e19ff567ddcdc7aa478f6f4b0a852762a09bd88d3132acb121e667cfe0397034
- type: file
dest-filename: openjfx.zip
only-arches:
- x86_64
url: https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_linux-x64_bin-jmods.zip
sha512: 75605440f13d0337e70ada1220f77d0d9780fb4602e676f1f07674d8b2e296b25080549d07edcca8f66733e15388860e3472d4ff6d51fd72b0452ed8bbe78022
- type: file
dest-filename: openjfx.zip
only-arches:
- aarch64
url: https://download2.gluonhq.com/openjfx/25.0.3/openjfx-25.0.3_linux-aarch64_bin-jmods.zip
sha512: 30c509b880ced1b29e0fafa41073d2350a16296d9439124b9a0e3bb391bf7f27e34d5abcfb338df11e5e898175699bceac40574bc9ad123ff071a5964f8fb14d
- type: file
dest-filename: maven.tar.gz
url: https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.13/apache-maven-3.9.13-bin.tar.gz
sha512: d9ccd44ba2991586e359c29eb86780ae8ff4ec1b88b0b8af3af074803472690cf2017782a9c4401343c62cbcd056231db9612e1e551cbd9747c21746d732c015
x-checker-data:
type: anitya
project-id: 1894
stable-only: true
url-template: https://repo1.maven.org/maven2/org/apache/maven/apache-maven/$version/apache-maven-$version-bin.tar.gz
versions: {<: '4.0'}
+7 -7
View File
@@ -14,8 +14,8 @@ license=('GPL3')
depends=('fuse3' 'alsa-lib' 'hicolor-icon-theme' 'libxtst' 'libnet' 'libxrender')
makedepends=('maven' 'unzip')
optdepends=('keepassxc-cryptomator: Use KeePassXC to store vault passwords' 'ttf-hanazono: Install this font when using Japanese system language')
_jdkver=25.0.2+10
_jfxver=25.0.2
_jdkver=26.0.1+8
_jfxver=25.0.3
_src_app_dir=cryptomator-${pkgver//_/-}
source=($SOURCES);
source_x86_64=("jdk-${_jdkver}.tar.gz::https://github.com/adoptium/temurin${_jdkver:0:2}-binaries/releases/download/jdk-${_jdkver//\+/%2B}/OpenJDK${_jdkver:0:2}U-jdk_x64_linux_hotspot_${_jdkver//\+/_}.tar.gz"
@@ -24,10 +24,10 @@ source_aarch64=("jdk-${_jdkver}.tar.gz::https://github.com/adoptium/temurin${_jd
"openjfx-${_jfxver}.zip::https://download2.gluonhq.com/openjfx/${_jfxver}/openjfx-${_jfxver}_linux-aarch64_bin-jmods.zip")
noextract=("jdk-${_jdkver}.tar.gz" "openjfx-${_jfxver}.zip")
sha256sums=($SOURCES_SHA)
sha256sums_x86_64=('987387933b64b9833846dee373b640440d3e1fd48a04804ec01a6dbf718e8ab8'
'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b')
sha256sums_aarch64=('a9d73e711d967dc44896d4f430f73a68fd33590dabc29a7f2fb9f593425b854c'
'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646')
sha256sums_x86_64=('8e512f13e575a43655fc92319436c94890c137b9035cc6bd6f9cf24239704d3a'
'47035c653863a8e4be3dc6f142b8dbd84b4bb1efc9a8cbc68413e6a5ff5e9f50')
sha256sums_aarch64=('613f9b2861dea937b24d5eca745ef8567733b377d0bb612195acaad0e3f61360'
'e3fd682354346845d2944a2da2b1ff2b6cb9259d92027f2f9c121b9b93c5e42f')
options=('!strip')
validpgpkeys=('58117AFA1F85B3EEC154677D615D449FE6E6A235')
@@ -47,7 +47,7 @@ build() {
cd "${srcdir}/${_src_app_dir}"
mvn -B clean package -DskipTests -Plinux
mvn -B clean package -DskipTests
cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods
+9 -9
View File
@@ -24,29 +24,29 @@ rm -rf runtime dmg *.app *.dmg
# set variables
APP_NAME="Cryptomator"
VENDOR="Skymatic GmbH"
COPYRIGHT_YEARS="2016 - 2025"
COPYRIGHT_YEARS="2016 - 2026"
PACKAGE_IDENTIFIER="org.cryptomator"
MAIN_JAR_GLOB="cryptomator-*.jar"
MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
REVISION_NO=`git rev-list --count HEAD`
VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
VERSION_NO=`../../../mvnw -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
FUSE_LIB="FUSE-T"
JAVAFX_VERSION=25.0.2
JAVAFX_VERSION=25.0.3
JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a"
JAVAFX_JMODS_SHA256="a52014d625b8b04e57fd71650f881c1397542b4018e1b04f1b4e66c8800a1f34"
else
JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c"
JAVAFX_JMODS_SHA256="3512fabe43aee467538d329cfbbaab3c53dff2a810f0d54e381f461d5e0fac43"
fi
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
# check preconditions
if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found. Fix by 'brew install maven'."; exit 1; }
[ -x ../../../mvnw ] || { echo >&2 "mvnw not found at ../../../mvnw."; exit 1; }
command -v create-dmg >/dev/null 2>&1 || { echo >&2 "create-dmg not found. Fix by 'brew install create-dmg'."; exit 1; }
if [ -n "${CODESIGN_IDENTITY}" ]; then
command -v codesign >/dev/null 2>&1 || { echo >&2 "codesign not found. Fix by 'xcode-select --install'."; exit 1; }
@@ -61,7 +61,7 @@ unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javaf
JMOD_VERSION=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION=${JMOD_VERSION#*@}
JMOD_VERSION=${JMOD_VERSION%%.*}
POM_JFX_VERSION=$(mvn -f../../../pom.xml help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=$(../../../mvnw -f../../../pom.xml help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
@@ -71,7 +71,7 @@ if [ "${POM_JFX_VERSION}" -ne "${JMOD_VERSION}" ]; then
fi
# compile
mvn -B -f../../../pom.xml clean package -DskipTests -Pmac
../../../mvnw -B -f../../../pom.xml clean package -DskipTests -Pmac
cp ../../../LICENSE.txt ../../../target
cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
@@ -137,7 +137,7 @@ sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Inf
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
# generate license
mvn -B -f../../../pom.xml license:add-third-party \
../../../mvnw -B -f../../../pom.xml license:add-third-party \
-Dlicense.thirdPartyFilename=license.rtf \
-Dlicense.outputDirectory=dist/mac/dmg/resources \
-Dlicense.fileTemplate=resources/licenseTemplate.ftl \
+90 -66
View File
@@ -16,6 +16,19 @@ Param(
# Function Definitions Section
# ============================
function Invoke-CommandWithExitCheck {
param (
[string]$Command,
[string[]]$Arguments
)
& $Command @Arguments
if ($LASTEXITCODE -ne 0) {
Write-Error "Command '$Command' failed with exit code $LASTEXITCODE"
exit $LASTEXITCODE
}
}
function Main {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
@@ -65,7 +78,8 @@ Write-Host "`$Env:JAVA_HOME=$Env:JAVA_HOME"
$copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor"
# compile
&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin
Invoke-CommandWithExitCheck -Command `
"mvn" -Arguments @("-B", "-f", "$buildDir/../../pom.xml", "clean", "package", "-DskipTests", "-Pwin")
Copy-Item "$buildDir\..\..\target\$MainJarGlob.jar" -Destination "$buildDir\..\..\target\mods"
# add runtime
@@ -93,9 +107,9 @@ switch ($archName) {
$jmodPaths = "$Env:JAVA_HOME/jmods"
}
'x64' {
$javaFxVersion='25.0.2'
$javaFxVersion='25.0.3'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
$javaFxJmodsSHA256 = '0bf9b83260b85607a9ba200124debabd9cdb013cbc0d659e62a20192a7137907'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
@@ -129,16 +143,18 @@ if ((& "$Env:JAVA_HOME\bin\jlink" --help | Select-String -Pattern "Linking from
}
### create runtime
& "$Env:JAVA_HOME\bin\jlink" `
--verbose `
--output runtime `
--module-path $jmodPaths `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,jdk.crypto.cryptoki,jdk.crypto.ec,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--strip-native-commands `
--no-header-files `
--no-man-pages `
--strip-debug `
--compress "zip-0" #do not compress and use msi compression
Invoke-CommandWithExitCheck -Command `
"$Env:JAVA_HOME\bin\jlink" -Arguments @(
"--verbose",
"--output", "runtime",
"--module-path", $jmodPaths,
"--add-modules", "java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,jdk.crypto.cryptoki,jdk.crypto.ec,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml",
"--strip-native-commands",
"--no-header-files",
"--no-man-pages",
"--strip-debug",
"--compress", "zip-0" #do not compress and use msi compression
)
$appPath = ".\$AppName"
if ($clean -and (Test-Path -Path $appPath)) {
@@ -195,14 +211,15 @@ if ($LASTEXITCODE -ne 0) {
}
#Create RTF license for msi
&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
"-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\resources\" `
"-Dlicense.includedScopes=compile" `
"-Dlicense.excludedGroups=^org\.cryptomator" `
"-Dlicense.failOnMissing=true" `
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges"
Invoke-CommandWithExitCheck -Command `
"mvn" -Arguments @("-B", "-f", "$buildDir/../../pom.xml", "license:add-third-party", `
"-Dlicense.thirdPartyFilename=license.rtf", `
"-Dlicense.fileTemplate=$buildDir\resources\licenseTemplate.ftl", `
"-Dlicense.outputDirectory=$buildDir\resources\", `
"-Dlicense.includedScopes=compile", `
"-Dlicense.excludedGroups=^org\.cryptomator", `
"-Dlicense.failOnMissing=true", `
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges")
# patch app dir
Copy-Item "contrib\*" -Destination "$AppName"
@@ -210,42 +227,46 @@ attrib -r "$AppName\$AppName.exe"
attrib -r "$AppName\${AppName} (Debug).exe"
# create .msi
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
$Env:JP_WIXHELPER_DIR = "."
& "$Env:JAVA_HOME\bin\jpackage" `
--verbose `
--type msi `
--win-upgrade-uuid $UpgradeUUID `
--app-image $AppName `
--dest installer `
--name $AppName `
--vendor $Vendor `
--copyright $copyright `
--app-version "$semVerNo.$revisionNo" `
--win-menu `
--win-dir-chooser `
--win-shortcut-prompt `
--win-menu-group $AppName `
--resource-dir resources `
--license-file resources/license.rtf `
--win-update-url $UpdateUrl `
--about-url $AboutUrl `
--file-associations resources/FAvaultFile.properties
$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources\"
$Env:JP_WIXWIZARD_RESOURCES_PROPERTIES_FORMAT = "${Env:JP_WIXWIZARD_RESOURCES}".Replace('\', '\\');
$Env:JP_WIXHELPER_DIR = ""
if ($LASTEXITCODE -ne 0) {
Write-Error "jpackage MSI failed with exit code $LASTEXITCODE"
return 1;
}
Get-Content .\resources\FAvaultFile.template.properties ` # Similar to envsubst
| ForEach-Object { $ExecutionContext.InvokeCommand.ExpandString($_) } `
| Out-File -FilePath .\resources\FAvaultFile.properties
Invoke-CommandWithExitCheck -Command `
"$Env:JAVA_HOME\bin\jpackage" -Arguments @(
"--verbose",
"--type", "msi",
"--win-upgrade-uuid", $UpgradeUUID,
"--app-image", $AppName,
"--dest", "installer",
"--name", $AppName,
"--vendor", $Vendor,
"--copyright", $copyright,
"--app-version", "$semVerNo.$revisionNo",
"--win-menu",
"--win-dir-chooser",
"--win-shortcut-prompt",
"--win-menu-group", $AppName,
"--resource-dir", "resources",
"--license-file", "resources/license.rtf",
"--win-update-url", $UpdateUrl,
"--about-url", $AboutUrl,
"--file-associations", "resources/FAvaultFile.properties"
)
#Create RTF license for bundle
&mvn -B -f $buildDir/../../pom.xml license:add-third-party `
"-Dlicense.thirdPartyFilename=license.rtf" `
"-Dlicense.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl" `
"-Dlicense.outputDirectory=$buildDir\bundle\resources\" `
"-Dlicense.includedScopes=compile" `
"-Dlicense.excludedGroups=^org\.cryptomator" `
"-Dlicense.failOnMissing=true" `
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges"
Invoke-CommandWithExitCheck -Command `
"mvn" -Arguments @("-B", "-f", "$buildDir/../../pom.xml", "license:add-third-party", `
"-Dlicense.thirdPartyFilename=license.rtf", `
"-Dlicense.fileTemplate=$buildDir\bundle\resources\licenseTemplate.ftl", `
"-Dlicense.outputDirectory=$buildDir\bundle\resources\", `
"-Dlicense.includedScopes=compile", `
"-Dlicense.excludedGroups=^org\.cryptomator", `
"-Dlicense.failOnMissing=true", `
"-Dlicense.licenseMergesUrl=file:///$buildDir/../../license/merges")
# download Winfsp
$winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
@@ -271,18 +292,21 @@ Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninsta
Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi" -Force
# create bundle including winfsp
& wix build `
-define BundleName="$AppName" `
-define BundleVersion="$semVerNo.$revisionNo" `
-define BundleVendor="$Vendor" `
-define BundleCopyright="$copyright" `
-define AboutUrl="$AboutUrl" `
-define HelpUrl="$HelpUrl" `
-define UpdateUrl="$UpdateUrl" `
-ext "WixToolset.Util.wixext" `
-ext "WixToolset.BootstrapperApplications.wixext" `
.\bundle\bundleWithWinfsp.wxs `
-out "installer\$AppName-Installer.exe"
Invoke-CommandWithExitCheck -Command `
"wix" -Arguments @(
"build",
"-define", "BundleName=$AppName",
"-define", "BundleVersion=$semVerNo.$revisionNo",
"-define", "BundleVendor=$Vendor",
"-define", "BundleCopyright=$copyright",
"-define", "AboutUrl=$AboutUrl",
"-define", "HelpUrl=$HelpUrl",
"-define", "UpdateUrl=$UpdateUrl",
"-ext", "WixToolset.Util.wixext",
"-ext", "WixToolset.BootstrapperApplications.wixext",
".\bundle\bundleWithWinfsp.wxs",
"-out", ".\installer\$AppName-Installer.exe"
)
Write-Host "Created EXE installer .\installer\$AppName-Installer.exe"
return 0;
+4 -1
View File
@@ -4,15 +4,18 @@
:: This file must be located in the INSTALLDIR
set "LOOPBACK_ALIAS=%1"
set "ACTION=%2"
if "%ACTION%"=="" set "ACTION=install"
:: Log for debugging
echo LOOPBACK_ALIAS=%LOOPBACK_ALIAS%
echo ACTION=%ACTION%
:: Change to INSTALLDIR
cd %~dp0
:: Execute the PowerShell script
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File .\patchWebDAV.ps1^
-LoopbackAlias %LOOPBACK_ALIAS%
-LoopbackAlias %LOOPBACK_ALIAS% -Action %ACTION%
:: Return the exit code from PowerShell
exit /b %ERRORLEVEL%
+36 -11
View File
@@ -1,15 +1,17 @@
#Requires -RunAsAdministrator
Param(
[Parameter(Mandatory, HelpMessage="Please provide an alias for 127.0.0.1")][string] $LoopbackAlias
[Parameter(Mandatory, HelpMessage="Please provide an alias for 127.0.0.1")][string] $LoopbackAlias,
[string] $Action = "install"
)
New-Variable -Name "sysdir" -Value ([Environment]::SystemDirectory) -Option Constant -Scope Global
New-Variable -Name "hostsFile" -Value "$sysdir\drivers\etc\hosts" -Option Constant -Scope Global
# Adds an alias for 127.0.0.1 to the hosts file
function Add-AliasToHost {
param (
[string]$LoopbackAlias
)
$sysdir = [Environment]::SystemDirectory
$hostsFile = "$sysdir\drivers\etc\hosts"
$aliasLine = "127.0.0.1 $LoopbackAlias"
foreach ($line in Get-Content $hostsFile) {
@@ -18,9 +20,26 @@ function Add-AliasToHost {
}
}
Add-Content -Path $hostsFile -Encoding ascii -Value "`r`n$aliasLine"
$content = Get-Content $hostsFile
$content += "`r`n$aliasLine"
$content | Set-Content "$hostsFile.tmp" -Encoding ascii
Move-Item "$hostsFile.tmp" $hostsFile -Force
}
# Removes an alias for 127.0.0.1 from the hosts file
function Remove-AliasFromHost {
param (
[string]$LoopbackAlias
)
$aliasLine = "127.0.0.1 $LoopbackAlias"
$content = Get-Content $hostsFile
$newContent = $content | Where-Object { $_ -ne $aliasLine }
$newContent | Set-Content "$hostsFile.tmp" -Encoding ascii
Move-Item "$hostsFile.tmp" $hostsFile -Force
}
# Sets in the registry the webclient file size limit to the maximum value
function Set-WebDAVFileSizeLimit {
@@ -54,14 +73,20 @@ function Edit-ProviderOrder {
New-ItemProperty -Path $RegistryPath -Name $Name -Value $UpdatedOrder -PropertyType String -Force | Out-Null
}
if ($Action -eq "install") {
Add-AliasToHost $LoopbackAlias
Write-Output 'Ensured alias exists in hosts file'
Add-AliasToHost $LoopbackAlias
Write-Output 'Ensured alias exists in hosts file'
Set-WebDAVFileSizeLimit
Write-Output 'Set WebDAV file size limit'
Set-WebDAVFileSizeLimit
Write-Output 'Set WebDAV file size limit'
Edit-ProviderOrder
Write-Output 'Ensured correct provider order'
Edit-ProviderOrder
Write-Output 'Ensured correct provider order'
} elseif ($Action -eq "uninstall") {
Remove-AliasFromHost $LoopbackAlias
Write-Output 'Ensured alias removed from hosts file'
} else {
Write-Error "Invalid action: $Action. Only 'install' or 'uninstall' are valid."
}
exit 0
+1 -1
View File
@@ -1,4 +1,4 @@
mime-type=application/vnd.cryptomator.vault
extension=cryptomator
description=Cryptomator Vault File
icon=resources/Cryptomator-Vault.ico
icon=C:\\Users\\Arbeit\\Skymatic\\cryptomator-jdk26-jpackage\\dist\\win\\resources\\Cryptomator-Vault.ico
+4
View File
@@ -0,0 +1,4 @@
mime-type=application/vnd.cryptomator.vault
extension=cryptomator
description=Cryptomator Vault File
icon=${env:JP_WIXWIZARD_RESOURCES_PROPERTIES_FORMAT}Cryptomator-Vault.ico
+10 -7
View File
@@ -68,7 +68,7 @@
<?endif?>
<!-- TODO: how does this work again? -->
<ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll" />
<ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)msica.dll"></ns0:Binary>
<ns0:CustomAction Id="JpFindRelatedProducts" BinaryRef="JpCaDll" DllEntry="FindRelatedProductsEx" />
<?ifndef SkipCryptomatorLegacyCheck ?>
@@ -158,9 +158,13 @@
<ns0:CustomAction Id="DisableUserConfig" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- WebDAV patches -->
<ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot;" Sequence="execute" Before="PatchWebDAV" />
<ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot; install" Sequence="execute" Before="PatchWebDAV" />
<ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- WebDAV patches (Uninstall) -->
<ns0:SetProperty Id="PatchWebDAVUninstall" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot; uninstall" Sequence="execute" Before="PatchWebDAVUninstall" />
<ns0:CustomAction Id="PatchWebDAVUninstall" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- Update check configuration -->
<ns0:SetProperty Id="PatchUpdateCheck" Value="&quot;[INSTALLDIR]patchUpdateCheck.bat&quot; &quot;[DISABLEUPDATECHECK]&quot;" Sequence="execute" Before="PatchUpdateCheck" />
<ns0:CustomAction Id="PatchUpdateCheck" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
@@ -214,9 +218,8 @@
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
<ns0:Custom Action="DisableUserConfig" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
<!-- Skip action on uninstall -->
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
<ns0:Custom Action="PatchWebDAV" After="DisableUserConfig" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
<ns0:Custom Action="PatchWebDAVUninstall" Before="RemoveFiles" Condition="Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE" />
<!-- Configure update check setting if property is provided -->
<ns0:Custom Action="PatchUpdateCheck" After="PatchWebDAV" Condition="DISABLEUPDATECHECK AND NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
</ns0:InstallExecuteSequence>
@@ -225,7 +228,7 @@
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
</ns0:InstallUISequence>
<ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
<ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
<ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)banner.bmp" />
<ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)background.bmp" />
</ns0:Package>
</ns0:Wix>
</ns0:Wix>
Vendored Executable
+295
View File
@@ -0,0 +1,295 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.4
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
scriptDir="$(dirname "$0")"
scriptName="$(basename "$0")"
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
# Find the actual extracted directory name (handles snapshots where filename != directory name)
actualDistributionDir=""
# First try the expected directory name (for regular distributions)
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
actualDistributionDir="$distributionUrlNameMain"
fi
fi
# If not found, search for any directory with the Maven executable (for snapshots)
if [ -z "$actualDistributionDir" ]; then
# enable globbing to iterate over items
set +f
for dir in "$TMP_DOWNLOAD_DIR"/*; do
if [ -d "$dir" ]; then
if [ -f "$dir/bin/$MVN_CMD" ]; then
actualDistributionDir="$(basename "$dir")"
break
fi
fi
done
set -f
fi
if [ -z "$actualDistributionDir" ]; then
verbose "Contents of $TMP_DOWNLOAD_DIR:"
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
die "Could not find Maven distribution directory in extracted archive"
fi
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"
Vendored
+189
View File
@@ -0,0 +1,189 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.4
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_M2_PATH = "$HOME/.m2"
if ($env:MAVEN_USER_HOME) {
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
}
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
}
$MAVEN_WRAPPER_DISTS = $null
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
} else {
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
# Find the actual extracted directory name (handles snapshots where filename != directory name)
$actualDistributionDir = ""
# First try the expected directory name (for regular distributions)
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
$actualDistributionDir = $distributionUrlNameMain
}
# If not found, search for any directory with the Maven executable (for snapshots)
if (!$actualDistributionDir) {
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
if (Test-Path -Path $testPath -PathType Leaf) {
$actualDistributionDir = $_.Name
}
}
}
if (!$actualDistributionDir) {
Write-Error "Could not find Maven distribution directory in extracted archive"
}
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+62 -39
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId>
<version>1.19.2</version>
<version>1.19.3</version>
<name>Cryptomator Desktop App</name>
<organization>
@@ -26,7 +26,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>25</project.jdk.version>
<project.jdk.version>26</project.jdk.version>
<!-- Group IDs of jars that need to stay on the class path for now -->
<!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) -->
@@ -35,43 +35,42 @@
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.10.0</cryptomator.cryptofs.version>
<cryptomator.cryptolib.version>2.2.2</cryptomator.cryptolib.version>
<cryptomator.integrations.version>1.8.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
<cryptomator.integrations.version>1.9.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.6.1</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.5.0</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.7.0</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>6.0.1</cryptomator.fuse.version>
<cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
<cryptomator.webdav.version>3.0.2</cryptomator.webdav.version>
<cryptomator.webdav-servlet.version>1.2.12</cryptomator.webdav-servlet.version>
<!-- 3rd party dependencies -->
<caffeine.version>3.2.3</caffeine.version>
<caffeine.version>3.2.4</caffeine.version>
<commons-lang3.version>3.20.0</commons-lang3.version>
<dagger.version>2.59.2</dagger.version>
<easybind.version>2.2</easybind.version>
<jackson.version>2.21.1</jackson.version>
<javafx.version>25.0.2</javafx.version>
<jwt.version>4.5.1</jwt.version>
<jackson.version>2.21.4</jackson.version>
<javafx.version>25.0.3</javafx.version>
<jwt.version>4.5.2</jwt.version>
<nimbus-jose.version>10.5</nimbus-jose.version>
<logback.version>1.5.32</logback.version>
<slf4j.version>2.0.17</slf4j.version>
<logback.version>1.5.35</logback.version>
<slf4j.version>2.0.18</slf4j.version>
<tinyoauth2.version>0.8.1</tinyoauth2.version>
<zxcvbn.version>1.9.0</zxcvbn.version>
<!-- test dependencies -->
<junit.jupiter.version>6.0.3</junit.jupiter.version>
<mockito.version>5.22.0</mockito.version>
<junit.jupiter.version>6.1.0</junit.jupiter.version>
<mockito.version>5.23.0</mockito.version>
<hamcrest.version>3.0</hamcrest.version>
<!-- build-time dependencies -->
<jetbrains.annotations.version>26.1.0</jetbrains.annotations.version>
<dependency-check.version>12.2.0</dependency-check.version>
<jacoco.version>0.8.14</jacoco.version>
<dependency-check.version>12.2.2</dependency-check.version>
<jacoco.version>0.8.15</jacoco.version>
<license-generator.version>2.7.1</license-generator.version>
<junit-tree-reporter.version>1.5.1</junit-tree-reporter.version>
<mvn-compiler.version>3.15.0</mvn-compiler.version>
<mvn-resources.version>3.5.0</mvn-resources.version>
<mvn-dependency.version>3.10.0</mvn-dependency.version>
<mvn-surefire.version>3.5.3</mvn-surefire.version>
<mvn-dependency.version>3.11.0</mvn-dependency.version>
<mvn-surefire.version>3.5.6</mvn-surefire.version>
<mvn-jar.version>3.5.0</mvn-jar.version>
<!-- Property used by surefire to determine jacoco engine -->
@@ -356,22 +355,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>me.fabriciorby</groupId>
<artifactId>maven-surefire-junit5-tree-reporter</artifactId>
<version>${junit-tree-reporter.version}</version>
</dependency>
</dependencies>
<configuration>
<reportFormat>plain</reportFormat>
<consoleOutputReporter>
<disable>true</disable>
</consoleOutputReporter>
<argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar} --enable-native-access=javafx.graphics</argLine>
<statelessTestsetInfoReporter
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
</statelessTestsetInfoReporter>
</configuration>
</plugin>
<plugin>
@@ -513,9 +502,6 @@
<os>
<family>mac</family>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
@@ -527,15 +513,55 @@
</profile>
<profile>
<id>linux</id>
<id>linux-aarch64</id>
<activation>
<os>
<family>unix</family>
<name>Linux</name>
<name>linux</name>
<arch>aarch64</arch>
</os>
</activation>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-linux</artifactId>
<version>${cryptomator.integrations.linux.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${javafx.version}</version>
<classifier>linux-aarch64</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
<classifier>linux-aarch64</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
<classifier>linux-aarch64</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
<classifier>linux-aarch64</classifier>
</dependency>
</dependencies>
</profile>
<profile>
<id>linux-x86_64</id>
<activation>
<os>
<family>unix</family>
<name>linux</name>
<arch>amd64</arch>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
@@ -552,9 +578,6 @@
<os>
<family>windows</family>
</os>
<property>
<name>idea.version</name>
</property>
</activation>
<dependencies>
<dependency>
@@ -0,0 +1,32 @@
package org.cryptomator.common.vaults;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
public class NotAVaultDirectoryException extends NoSuchFileException {
public enum Reason {
MISSING_DATA_DIR,
DATA_NOT_A_DIRECTORY,
MISSING_VAULT_CONFIG,
VAULT_CONFIG_ACCESS_DENIED,
UNSUPPORTED_STRUCTURE
}
private final transient Path path;
private final Reason reason;
public NotAVaultDirectoryException(Path path, Reason reason) {
super(path.toString(), null, "Not a vault directory: " + reason);
this.path = path;
this.reason = reason;
}
public Path path() {
return path;
}
public Reason notAVaultReason() {
return reason;
}
}
@@ -22,20 +22,31 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.ResourceBundle;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
import static org.cryptomator.common.vaults.VaultState.Value.*;
import static org.cryptomator.common.vaults.VaultState.Value.ALL_MISSING;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.MISSING;
import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
import static org.cryptomator.common.vaults.VaultState.Value.PROCESSING;
import static org.cryptomator.common.vaults.VaultState.Value.UNLOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.VAULT_CONFIG_MISSING;
import static org.cryptomator.cryptofs.common.Constants.DATA_DIR_NAME;
@Singleton
public class VaultListManager {
@@ -72,18 +83,57 @@ public class VaultListManager {
return vaultList.stream().anyMatch(v -> vaultPath.equals(v.getPath()));
}
/**
* Safe to call from any thread: the IO work runs on the calling thread, but the
* {@code ObservableList} mutation is marshaled to the JavaFX application thread.
*/
public Vault add(Path pathToVault) throws IOException {
Path normalizedPathToVault = pathToVault.normalize().toAbsolutePath();
if (CryptoFileSystemProvider.checkDirStructureForVault(normalizedPathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) == DirStructure.UNRELATED) {
throw new NoSuchFileException(normalizedPathToVault.toString(), null, "Not a vault directory");
}
assertIsVaultDirectory(normalizedPathToVault);
return get(normalizedPathToVault) //
.orElseGet(() -> {
Vault newVault = create(newVaultSettings(normalizedPathToVault));
vaultList.add(newVault);
return newVault;
});
return get(normalizedPathToVault).orElseGet(() -> {
Vault newVault = create(newVaultSettings(normalizedPathToVault));
if (Platform.isFxApplicationThread()) {
addVault(newVault);
} else {
Platform.runLater(() -> addVault(newVault));
}
return newVault;
});
}
public static void assertIsVaultDirectory(Path pathToVault) throws IOException {
if (CryptoFileSystemProvider.checkDirStructureForVault(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) == DirStructure.UNRELATED) {
checkDataDir(pathToVault);
checkConfigFile(pathToVault);
//if vault is legacy _and_ not readable, just say unsupported
throw new NotAVaultDirectoryException(pathToVault, NotAVaultDirectoryException.Reason.UNSUPPORTED_STRUCTURE);
}
}
static void checkDataDir(Path pathToVault) throws NotAVaultDirectoryException {
Path dataDir = pathToVault.resolve(DATA_DIR_NAME);
if (!Files.exists(dataDir)) {
throw new NotAVaultDirectoryException(pathToVault, NotAVaultDirectoryException.Reason.MISSING_DATA_DIR);
}
if (!Files.isDirectory(dataDir)) {
throw new NotAVaultDirectoryException(pathToVault, NotAVaultDirectoryException.Reason.DATA_NOT_A_DIRECTORY);
}
}
static void checkConfigFile(Path pathToVault) throws NotAVaultDirectoryException {
Path vaultConfig = pathToVault.resolve(VAULTCONFIG_FILENAME);
try (var ch = Files.newByteChannel(vaultConfig, StandardOpenOption.READ)) {
ch.read(ByteBuffer.allocate(1));
} catch (AccessDeniedException e) {
throw new NotAVaultDirectoryException(pathToVault, NotAVaultDirectoryException.Reason.VAULT_CONFIG_ACCESS_DENIED);
} catch (NoSuchFileException e) {
throw new NotAVaultDirectoryException(pathToVault, NotAVaultDirectoryException.Reason.MISSING_VAULT_CONFIG);
} catch (IOException e) {
LOG.warn("Failed to read vault config: {}", e.getMessage());
throw new NotAVaultDirectoryException(pathToVault, NotAVaultDirectoryException.Reason.UNSUPPORTED_STRUCTURE);
}
}
private VaultSettings newVaultSettings(Path path) {
@@ -153,7 +203,7 @@ public class VaultListManager {
//for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
vaultSettings.lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME);
}
case VAULT_CONFIG_MISSING -> {
case VAULT_CONFIG_MISSING -> {
//Nothing to do here, since there is no config to read
}
case MISSING, ALL_MISSING, ERROR, PROCESSING -> {
@@ -2,12 +2,14 @@ package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.NotAVaultDirectoryException;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.integrations.uiappearance.Theme;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.dialogs.Dialogs;
import org.cryptomator.ui.fxapp.FxApplicationStyle;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.slf4j.Logger;
@@ -41,6 +43,7 @@ public class ChooseExistingVaultController implements FxController {
private final ObjectProperty<Vault> vault;
private final VaultListManager vaultListManager;
private final ResourceBundle resourceBundle;
private final Dialogs dialogs;
private final ObservableValue<Image> screenshot;
@Inject
@@ -51,6 +54,7 @@ public class ChooseExistingVaultController implements FxController {
@AddVaultWizardWindow ObjectProperty<Vault> vault, //
VaultListManager vaultListManager, //
ResourceBundle resourceBundle, //
Dialogs dialogs, //
FxApplicationStyle applicationStyle) {
this.window = window;
this.successScene = successScene;
@@ -59,6 +63,7 @@ public class ChooseExistingVaultController implements FxController {
this.vault = vault;
this.vaultListManager = vaultListManager;
this.resourceBundle = resourceBundle;
this.dialogs = dialogs;
this.screenshot = applicationStyle.appliedAppThemeProperty().map(this::selectScreenshot);
}
@@ -87,6 +92,9 @@ public class ChooseExistingVaultController implements FxController {
Vault newVault = vaultListManager.add(vaultPath.get());
vault.set(newVault);
window.setScene(successScene.get());
} catch (NotAVaultDirectoryException e) {
LOG.warn("Selected folder is not a vault directory: {}", e.getMessage());
dialogs.prepareNotAVaultDirectoryDialog(window, e).build().showAndWait();
} catch (IOException e) {
LOG.error("Failed to open existing vault.", e);
appWindows.showErrorWindow(e, window, window.getScene());
@@ -58,8 +58,6 @@ public class DecryptFileNamesViewController implements FxController {
private final Stage window;
private final Vault vault;
private final ResourceBundle resourceBundle;
private final List<Path> initialList;
@FXML
public TableColumn<CipherAndCleartext, String> ciphertextColumn;
@FXML
@@ -68,12 +66,11 @@ public class DecryptFileNamesViewController implements FxController {
public TableView<CipherAndCleartext> cipherToCleartextTable;
@Inject
public DecryptFileNamesViewController(@DecryptNameWindow Stage window, @DecryptNameWindow Vault vault, @DecryptNameWindow List<Path> pathsToDecrypt, ResourceBundle resourceBundle) {
public DecryptFileNamesViewController(@DecryptNameWindow Stage window, @DecryptNameWindow Vault vault, ResourceBundle resourceBundle) {
this.window = window;
this.vault = vault;
this.resourceBundle = resourceBundle;
this.mapping = new SimpleListProperty<>(FXCollections.observableArrayList());
this.initialList = pathsToDecrypt;
}
@FXML
@@ -97,8 +94,7 @@ public class DecryptFileNamesViewController implements FxController {
});
cipherToCleartextTable.setOnDragDropped(event -> {
if (event.getGestureSource() == null && event.getDragboard().hasFiles()) {
checkAndDecrypt(event.getDragboard().getFiles().stream().map(File::toPath).toList());
cipherToCleartextTable.setItems(mapping);
decrypt(event.getDragboard().getFiles().stream().map(File::toPath).toList());
}
});
cipherToCleartextTable.setOnDragExited(_ -> cipherToCleartextTable.setItems(mapping));
@@ -124,9 +120,7 @@ public class DecryptFileNamesViewController implements FxController {
});
}
});
if (!initialList.isEmpty()) {
checkAndDecrypt(initialList);
}
window.setOnHidden(_ -> mapping.clear());
}
private void copySingleCelltoClipboard() {
@@ -149,10 +143,18 @@ public class DecryptFileNamesViewController implements FxController {
fileChooser.setInitialDirectory(vault.getPath().toFile());
var ciphertextNodes = fileChooser.showOpenMultipleDialog(window);
if (ciphertextNodes != null) {
checkAndDecrypt(ciphertextNodes.stream().map(File::toPath).toList());
decrypt(ciphertextNodes.stream().map(File::toPath).toList());
}
}
public void decrypt(List<Path> pathsToDecrypt) {
if (pathsToDecrypt.isEmpty()) {
return;
}
checkAndDecrypt(pathsToDecrypt);
cipherToCleartextTable.setItems(mapping);
}
private void checkAndDecrypt(List<Path> pathsToDecrypt) {
mapping.clear();
//Assumption: All files are in the same directory
@@ -28,23 +28,28 @@ public interface DecryptNameComponent {
@FxmlScene(FxmlFile.DECRYPTNAMES)
Lazy<Scene> decryptNamesView();
DecryptFileNamesViewController controller();
@DecryptNameWindow
Vault vault();
default void showDecryptFileNameWindow() {
default void showDecryptFileNameWindow(List<Path> pathsToDecrypt) {
Stage s = window();
s.setScene(decryptNamesView().get());
s.sizeToScene();
if (vault().isUnlocked()) {
controller().decrypt(pathsToDecrypt);
s.show();
s.requestFocus();
} else {
LOG.error("Aborted showing DecryptFileName window: vault state is not {}, but {}.", VaultState.Value.UNLOCKED, vault().getState());
s.close();
}
}
@Subcomponent.Factory
interface Factory {
DecryptNameComponent create(@BindsInstance @DecryptNameWindow Vault vault, @BindsInstance @Named("windowOwner") Stage owner, @BindsInstance @DecryptNameWindow List<Path> pathsToDecrypt);
DecryptNameComponent create(@BindsInstance @DecryptNameWindow Vault vault, @BindsInstance @Named("windowOwner") Stage owner);
}
}
@@ -1,6 +1,7 @@
package org.cryptomator.ui.dialogs;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.vaults.NotAVaultDirectoryException;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.StageFactory;
@@ -139,6 +140,24 @@ public class Dialogs {
.setCancelAction(Stage::close);
}
public SimpleDialog.Builder prepareNotAVaultDirectoryDialog(Stage window, NotAVaultDirectoryException e) {
String descriptionKey = switch (e.notAVaultReason()) {
case MISSING_DATA_DIR -> "addvaultwizard.existing.notAVault.description.missingDataDir";
case DATA_NOT_A_DIRECTORY -> "addvaultwizard.existing.notAVault.description.dataNotADirectory";
case MISSING_VAULT_CONFIG -> "addvaultwizard.existing.notAVault.description.missingVaultConfig";
case VAULT_CONFIG_ACCESS_DENIED -> "addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied";
case UNSUPPORTED_STRUCTURE -> "addvaultwizard.existing.notAVault.description.unsupportedStructure";
};
return createDialogBuilder() //
.setOwner(window) //
.setTitleKey("addvaultwizard.existing.notAVault.title") //
.setMessageKey("addvaultwizard.existing.notAVault.message") //
.setDescriptionKey(descriptionKey, e.path().getFileName() != null ? e.path().getFileName().toString() : e.path().toString()) //
.setIcon(FontAwesome5Icon.EXCLAMATION) //
.setOkButtonKey(BUTTON_KEY_CLOSE) //
.setOkAction(Stage::close);
}
public SimpleDialog.Builder prepareNoDDirectorySelectedDialog(Stage window) {
return createDialogBuilder() //
.setOwner(window) //
@@ -1,15 +1,18 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.common.vaults.NotAVaultDirectoryException;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.launcher.AppLaunchEvent;
import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.dialogs.Dialogs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.stage.Stage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
@@ -29,14 +32,18 @@ class AppLaunchEventHandler {
private final FxApplicationWindows appWindows;
private final VaultListManager vaultListManager;
private final VaultService vaultService;
private final Stage primaryStage;
private final Dialogs dialogs;
@Inject
public AppLaunchEventHandler(@Named("launchEventQueue") BlockingQueue<AppLaunchEvent> launchEventQueue, ExecutorService executorService, FxApplicationWindows appWindows, VaultListManager vaultListManager, VaultService vaultService) {
public AppLaunchEventHandler(@Named("launchEventQueue") BlockingQueue<AppLaunchEvent> launchEventQueue, ExecutorService executorService, FxApplicationWindows appWindows, VaultListManager vaultListManager, VaultService vaultService, @PrimaryStage Stage primaryStage, Dialogs dialogs) {
this.launchEventQueue = launchEventQueue;
this.executorService = executorService;
this.appWindows = appWindows;
this.vaultListManager = vaultListManager;
this.vaultService = vaultService;
this.primaryStage = primaryStage;
this.dialogs = dialogs;
}
public void startHandlingLaunchEvents() {
@@ -58,31 +65,33 @@ class AppLaunchEventHandler {
private void handleLaunchEvent(AppLaunchEvent event) {
switch (event.type()) {
case REVEAL_APP -> appWindows.showMainWindow();
case OPEN_FILE -> Platform.runLater(() -> {
event.pathsToOpen().forEach(this::openPotentialVault);
});
case OPEN_FILE -> event.pathsToOpen().forEach(this::openPotentialVault);
default -> LOG.warn("Unsupported event type: {}", event.type());
}
}
// TODO deduplicate MainWindowController...
private void openPotentialVault(Path path) {
assert Platform.isFxApplicationThread();
try {
Path potentialVaultPath = path.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT) ? path.getParent() : path;
final Optional<Vault> v = vaultListManager.get(potentialVaultPath);
if (v.isPresent()) {
if (v.get().isUnlocked()) {
vaultService.reveal(v.get());
} else if (v.get().isLocked()) {
appWindows.startUnlockWorkflow(v.get(), null);
Path potentialVaultPath = path.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT) ? path.getParent() : path;
Optional<Vault> existing = vaultListManager.get(potentialVaultPath.normalize().toAbsolutePath());
if (existing.isPresent()) {
Platform.runLater(() -> {
if (existing.get().isUnlocked()) {
vaultService.reveal(existing.get());
} else if (existing.get().isLocked()) {
appWindows.startUnlockWorkflow(existing.get(), null);
}
} else {
vaultListManager.add(potentialVaultPath);
LOG.debug("Added vault {}", potentialVaultPath);
}
});
return;
}
try {
vaultListManager.add(potentialVaultPath);
LOG.debug("Added vault {}", potentialVaultPath);
} catch (NotAVaultDirectoryException e) {
LOG.warn("Cannot add {}: {}", potentialVaultPath, e.getMessage());
Platform.runLater(() -> dialogs.prepareNotAVaultDirectoryDialog(primaryStage, e).build().showAndWait());
} catch (IOException e) {
LOG.error("Failed to add vault " + path, e);
LOG.error("Failed to add vault {}", potentialVaultPath, e);
}
}
@@ -64,17 +64,6 @@ abstract class FxApplicationModule {
return builder.build();
}
@Provides
@FxApplicationScoped
static MainWindowComponent provideMainWindowComponent(MainWindowComponent.Builder builder) {
return builder.build();
}
@Provides
@FxApplicationScoped
static PreferencesComponent providePreferencesComponent(PreferencesComponent.Builder builder) {
return builder.build();
}
@Provides
@FxApplicationScoped
@@ -88,10 +77,4 @@ abstract class FxApplicationModule {
return factory.create();
}
@Provides
@FxApplicationScoped
static NotificationComponent provideNotificationComponent(NotificationComponent.Factory factory) {
return factory.create();
}
}
@@ -39,6 +39,7 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
@FxApplicationScoped
public class FxApplicationWindows {
@@ -47,15 +48,15 @@ public class FxApplicationWindows {
private final Stage primaryStage;
private final Optional<TrayIntegrationProvider> trayIntegration;
private final Lazy<MainWindowComponent> mainWindow;
private final Lazy<PreferencesComponent> preferencesWindow;
private final CachedLazy<MainWindowComponent> mainWindow;
private final CachedLazy<PreferencesComponent> preferencesWindow;
private final QuitComponent.Builder quitWindowBuilder;
private final UnlockComponent.Factory unlockWorkflowFactory;
private final UpdateReminderComponent.Factory updateReminderWindowFactory;
private final LockComponent.Factory lockWorkflowFactory;
private final ErrorComponent.Factory errorWindowFactory;
private final Lazy<EventViewComponent> eventViewWindow;
private final Lazy<NotificationComponent> notificationWindow;
private final CachedLazy<EventViewComponent> eventViewWindow;
private final CachedLazy<NotificationComponent> notificationWindow;
private final ExecutorService executor;
private final VaultOptionsComponent.Factory vaultOptionsWindow;
private final ShareVaultComponent.Factory shareVaultWindow;
@@ -65,8 +66,8 @@ public class FxApplicationWindows {
@Inject
public FxApplicationWindows(@PrimaryStage Stage primaryStage, //
Optional<TrayIntegrationProvider> trayIntegration, //
Lazy<MainWindowComponent> mainWindow, //
Lazy<PreferencesComponent> preferencesWindow, //
MainWindowComponent.Builder mainWindowBuilder, //
PreferencesComponent.Builder preferencesWindowBuilder, //
QuitComponent.Builder quitWindowBuilder, //
UnlockComponent.Factory unlockWorkflowFactory, //
UpdateReminderComponent.Factory updateReminderWindowFactory, //
@@ -74,21 +75,21 @@ public class FxApplicationWindows {
ErrorComponent.Factory errorWindowFactory, //
VaultOptionsComponent.Factory vaultOptionsWindow, //
ShareVaultComponent.Factory shareVaultWindow, //
Lazy<EventViewComponent> eventViewWindow, //
Lazy<NotificationComponent> notificationWindow,
EventViewComponent.Factory eventViewWindowFactory, //
NotificationComponent.Factory notificationWindowFactory, //
ExecutorService executor, //
Dialogs dialogs) {
this.primaryStage = primaryStage;
this.trayIntegration = trayIntegration;
this.mainWindow = mainWindow;
this.preferencesWindow = preferencesWindow;
this.mainWindow = new CachedLazy<>(mainWindowBuilder::build);
this.preferencesWindow = new CachedLazy<>(preferencesWindowBuilder::build);
this.quitWindowBuilder = quitWindowBuilder;
this.unlockWorkflowFactory = unlockWorkflowFactory;
this.updateReminderWindowFactory = updateReminderWindowFactory;
this.lockWorkflowFactory = lockWorkflowFactory;
this.errorWindowFactory = errorWindowFactory;
this.eventViewWindow = eventViewWindow;
this.notificationWindow = notificationWindow;
this.eventViewWindow = new CachedLazy<>(eventViewWindowFactory::create);
this.notificationWindow = new CachedLazy<>(notificationWindowFactory::create);
this.executor = executor;
this.vaultOptionsWindow = vaultOptionsWindow;
this.shareVaultWindow = shareVaultWindow;
@@ -218,4 +219,29 @@ public class FxApplicationWindows {
LOG.error("Failed to display stage", error);
}
}
private static class CachedLazy<T> implements Lazy<T> {
private final Supplier<T> supplier;
private volatile T instance = null;
public CachedLazy(Supplier<T> supplier) {
this.supplier = supplier;
}
@Override
public T get() {
T value = instance;
if (value == null) {
synchronized (this) {
value = instance;
if (value == null) {
value = supplier.get();
instance = value;
}
}
}
return instance;
}
}
}
@@ -1,9 +1,8 @@
package org.cryptomator.ui.mainwindow;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tobiasdiez.easybind.EasyBind;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Nullable;
@@ -58,6 +57,7 @@ public class VaultDetailUnlockedController implements FxController {
private final DecryptNameComponent.Factory decryptNameWindowFactory;
private final ResourceBundle resourceBundle;
private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats;
private final LoadingCache<Vault, DecryptNameComponent> decryptNameWindows;
private final VaultStatisticsComponent.Builder vaultStatsBuilder;
private final ObservableValue<Boolean> accessibleViaPath;
private final ObservableValue<Boolean> accessibleViaUri;
@@ -89,7 +89,8 @@ public class VaultDetailUnlockedController implements FxController {
this.revealPathService = revealPathService;
this.decryptNameWindowFactory = decryptNameWindowFactory;
this.resourceBundle = resourceBundle;
this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats));
this.vaultStats = Caffeine.newBuilder().weakValues().build(this::buildVaultStats);
this.decryptNameWindows = Caffeine.newBuilder().weakValues().build(this::buildDecryptNameWindow);
this.vaultStatsBuilder = vaultStatsBuilder;
var mp = vault.flatMap(Vault::mountPointProperty);
this.accessibleViaPath = mp.map(m -> m instanceof Mountpoint.WithPath).orElse(false);
@@ -161,7 +162,7 @@ public class VaultDetailUnlockedController implements FxController {
}
private void showDecryptNameWindow(List<Path> pathsToDecrypt) {
decryptNameWindowFactory.create(vault.get(), mainWindow, pathsToDecrypt).showDecryptFileNameWindow();
decryptNameWindows.get(vault.get()).showDecryptFileNameWindow(pathsToDecrypt);
}
private boolean startsWithVaultAccessPoint(Path path) {
@@ -198,6 +199,10 @@ public class VaultDetailUnlockedController implements FxController {
return vaultStatsBuilder.vault(vault).build();
}
private DecryptNameComponent buildDecryptNameWindow(Vault vault) {
return decryptNameWindowFactory.create(vault, mainWindow);
}
@FXML
public void revealAccessLocation() {
vaultService.reveal(vault.get());
@@ -217,7 +222,7 @@ public class VaultDetailUnlockedController implements FxController {
@FXML
public void showVaultStatistics() {
vaultStats.getUnchecked(vault.get()).showVaultStatisticsWindow();
vaultStats.get(vault.get()).showVaultStatisticsWindow();
}
/* Getter/Setter */
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.recovery.RecoveryActionType;
import org.cryptomator.common.recovery.VaultPreparator;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.vaults.NotAVaultDirectoryException;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultComponent;
import org.cryptomator.common.vaults.VaultListManager;
@@ -23,6 +24,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
@@ -55,6 +57,7 @@ import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_EXT;
@@ -90,6 +93,7 @@ public class VaultListController implements FxController {
private final VaultComponent.Factory vaultComponentFactory;
private final RecoveryKeyComponent.Factory recoveryKeyWindow;
private final List<MountService> mountServices;
private final ExecutorService executor;
public ListView<Vault> vaultList;
public StackPane root;
@@ -113,7 +117,8 @@ public class VaultListController implements FxController {
RecoveryKeyComponent.Factory recoveryKeyWindow, //
VaultComponent.Factory vaultComponentFactory, //
List<MountService> mountServices, //
FxFSEventList fxFSEventList) {
FxFSEventList fxFSEventList, //
ExecutorService executor) {
this.mainWindow = mainWindow;
this.vaults = vaults;
this.selectedVault = selectedVault;
@@ -127,6 +132,7 @@ public class VaultListController implements FxController {
this.recoveryKeyWindow = recoveryKeyWindow;
this.vaultComponentFactory = vaultComponentFactory;
this.mountServices = mountServices;
this.executor = executor;
this.emptyVaultList = Bindings.isEmpty(vaults);
this.unreadEvents = fxFSEventList.unreadEventsProperty();
@@ -324,15 +330,18 @@ public class VaultListController implements FxController {
}
private void addVault(Path pathToVault) {
try {
if (pathToVault.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
vaultListManager.add(pathToVault.getParent());
} else {
vaultListManager.add(pathToVault);
Path target = pathToVault.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT) ? pathToVault.getParent() : pathToVault;
executor.execute(() -> {
try {
vaultListManager.add(target);
} catch (NotAVaultDirectoryException e) {
LOG.warn("Cannot add {}: {}", target, e.getMessage());
Platform.runLater(() -> dialogs.prepareNotAVaultDirectoryDialog(mainWindow, e).build().showAndWait());
} catch (IOException e) {
LOG.warn("Failed to add vault {}", target, e);
Platform.runLater(() -> appWindows.showErrorWindow(e, mainWindow, null));
}
} catch (IOException e) {
LOG.debug("Not a vault: {}", pathToVault);
}
});
}
@FXML
@@ -260,7 +260,7 @@ public class UpdatesPreferencesController implements FxController {
public boolean isProhibitUpdateWhileUnlocked() {
// If the result of the last update check was from the fallback mechanism, we don't need to show the warning
return !unlockedVaults.isEmpty() && !FallbackUpdateInfo.class.isInstance(updateChecker.getUpdate());
return !unlockedVaults.isEmpty() && updateChecker.isUpdateAvailable() && !FallbackUpdateInfo.class.isInstance(updateChecker.getUpdate());
}
public BooleanBinding prohibitUpdateWhileUnlockedProperty() {
@@ -18,7 +18,10 @@ import java.net.URISyntaxException;
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 VISIT_HUB_URL = "https://cryptomator.org/hub/" //
+ "?utm_source=cryptomator-desktop" //
+ "&utm_medium=app" //
+ "&utm_campaign=share-vault";
private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/security/best-practices/#sharing-of-vaults";
private final Stage window;
@@ -22,7 +22,7 @@
</ImageView>
<VBox spacing="3" HBox.hgrow="ALWAYS" alignment="CENTER_LEFT">
<FormattedLabel styleClass="label-extra-large" format="Cryptomator %s" arg1="${controller.fullApplicationVersion}"/>
<Label text="© 2016 2025 Skymatic GmbH"/>
<Label text="© 2016 2026 Skymatic GmbH"/>
</VBox>
</HBox>
@@ -9,90 +9,94 @@
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.vaultoptions.MountOptionsController"
spacing="6">
<fx:define>
<ToggleGroup fx:id="mountPointToggleGroup"/>
</fx:define>
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%vaultOptions.mount.volume.type" labelFor="$vaultVolumeTypeChoiceBox"/>
<ChoiceBox fx:id="vaultVolumeTypeChoiceBox"/>
<Hyperlink contentDisplay="GRAPHIC_ONLY" onAction="#openVolumePreferences" visible="${controller.defaultMountServiceSelected}" managed="${controller.defaultMountServiceSelected}" accessibleText="%vaultOptions.mount.info">
<graphic>
<FontAwesome5IconView glyph="COGS" styleClass="glyph-icon-muted"/>
</graphic>
<tooltip>
<Tooltip text="%vaultOptions.mount.info" showDelay="100ms"/>
</tooltip>
</Hyperlink>
<Hyperlink contentDisplay="GRAPHIC_ONLY" onAction="#openDocs" visible="${!controller.defaultMountServiceSelected}" managed="${!controller.defaultMountServiceSelected}" accessibleText="%preferences.volume.docsTooltip">
<graphic>
<FontAwesome5IconView glyph="QUESTION_CIRCLE" styleClass="glyph-icon-muted"/>
</graphic>
<tooltip>
<Tooltip text="%preferences.volume.docsTooltip" showDelay="100ms"/>
</tooltip>
</Hyperlink>
</HBox>
<Label styleClass="label-red" text="%vaultOptions.mount.volumeType.restartRequired" visible="${controller.selectedMountServiceRequiresRestart}" managed="${controller.selectedMountServiceRequiresRestart}"/>
<HBox spacing="12" alignment="CENTER_LEFT" visible="${controller.loopbackPortChangeable}" managed="${controller.loopbackPortChangeable}">
<Label text="%vaultOptions.mount.volume.tcp.port" labelFor="$vaultLoopbackPortField"/>
<NumericTextField fx:id="vaultLoopbackPortField"/>
<Button text="%generic.button.apply" fx:id="vaultLoopbackPortApplyButton" onAction="#doChangeLoopbackPort"/>
</HBox>
<CheckBox fx:id="readOnlyCheckbox" text="%vaultOptions.mount.readonly" visible="${controller.readOnlyOptionAllowed}" managed="${controller.readOnlyOptionAllowed}"/>
<VBox visible="${controller.mountFlagsSupported}" managed="${controller.mountFlagsSupported}">
<CheckBox fx:id="customMountFlagsCheckbox" text="%vaultOptions.mount.customMountFlags" onAction="#toggleUseCustomMountFlags"/>
<TextField fx:id="mountFlagsField" HBox.hgrow="ALWAYS" maxWidth="Infinity" accessibleText="%vaultOptions.mount.customMountFlags">
<VBox.margin>
<Insets left="24"/>
</VBox.margin>
</TextField>
</VBox>
<Label text="%vaultOptions.mount.mountPoint">
<VBox.margin>
<Insets top="9"/>
</VBox.margin>
</Label>
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointAutoBtn" text="%vaultOptions.mount.mountPoint.auto"/>
<HBox spacing="6" visible="${controller.mountpointDriveLetterSupported}" managed="${controller.mountpointDriveLetterSupported}">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDriveLetterBtn" text="%vaultOptions.mount.mountPoint.driveLetter"/>
<ChoiceBox fx:id="driveLetterSelection" disable="${!mountPointDriveLetterBtn.selected}" accessibleText="%vaultOptions.mount.mountPoint.driveLetter"/>
</HBox>
<VBox spacing="6" visible="${controller.mountpointDirSupported}" managed="${controller.mountpointDirSupported}">
<HBox spacing="6" alignment="CENTER_LEFT">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDirBtn" text="%vaultOptions.mount.mountPoint.custom"/>
<Button text="%vaultOptions.mount.mountPoint.directoryPickerButton" onAction="#chooseCustomMountPoint" contentDisplay="LEFT" disable="${!mountPointDirBtn.selected}">
<ScrollPane xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.vaultoptions.MountOptionsController"
fitToWidth="true"
hbarPolicy="NEVER">
<VBox spacing="6">
<fx:define>
<ToggleGroup fx:id="mountPointToggleGroup"/>
</fx:define>
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%vaultOptions.mount.volume.type" labelFor="$vaultVolumeTypeChoiceBox"/>
<ChoiceBox fx:id="vaultVolumeTypeChoiceBox"/>
<Hyperlink contentDisplay="GRAPHIC_ONLY" onAction="#openVolumePreferences" visible="${controller.defaultMountServiceSelected}" managed="${controller.defaultMountServiceSelected}" accessibleText="%vaultOptions.mount.info">
<graphic>
<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
<FontAwesome5IconView glyph="COGS" styleClass="glyph-icon-muted"/>
</graphic>
</Button>
<tooltip>
<Tooltip text="%vaultOptions.mount.info" showDelay="100ms"/>
</tooltip>
</Hyperlink>
<Hyperlink contentDisplay="GRAPHIC_ONLY" onAction="#openDocs" visible="${!controller.defaultMountServiceSelected}" managed="${!controller.defaultMountServiceSelected}" accessibleText="%preferences.volume.docsTooltip">
<graphic>
<FontAwesome5IconView glyph="QUESTION_CIRCLE" styleClass="glyph-icon-muted"/>
</graphic>
<tooltip>
<Tooltip text="%preferences.volume.docsTooltip" showDelay="100ms"/>
</tooltip>
</Hyperlink>
</HBox>
<TextField fx:id="directoryPathField" text="${controller.directoryPath}" visible="${mountPointDirBtn.selected}" managed="${mountPointDirBtn.managed}" maxWidth="Infinity" editable="false" accessibleText="%vaultOptions.mount.mountPoint.custom">
<VBox.margin>
<Insets left="24"/>
</VBox.margin>
</TextField>
</VBox>
</children>
</VBox>
<Label styleClass="label-red" text="%vaultOptions.mount.volumeType.restartRequired" visible="${controller.selectedMountServiceRequiresRestart}" managed="${controller.selectedMountServiceRequiresRestart}"/>
<HBox spacing="12" alignment="CENTER_LEFT" visible="${controller.loopbackPortChangeable}" managed="${controller.loopbackPortChangeable}">
<Label text="%vaultOptions.mount.volume.tcp.port" labelFor="$vaultLoopbackPortField"/>
<NumericTextField fx:id="vaultLoopbackPortField"/>
<Button text="%generic.button.apply" fx:id="vaultLoopbackPortApplyButton" onAction="#doChangeLoopbackPort"/>
</HBox>
<CheckBox fx:id="readOnlyCheckbox" text="%vaultOptions.mount.readonly" visible="${controller.readOnlyOptionAllowed}" managed="${controller.readOnlyOptionAllowed}"/>
<VBox visible="${controller.mountFlagsSupported}" managed="${controller.mountFlagsSupported}">
<CheckBox fx:id="customMountFlagsCheckbox" text="%vaultOptions.mount.customMountFlags" onAction="#toggleUseCustomMountFlags"/>
<TextField fx:id="mountFlagsField" HBox.hgrow="ALWAYS" maxWidth="Infinity" accessibleText="%vaultOptions.mount.customMountFlags">
<VBox.margin>
<Insets left="24"/>
</VBox.margin>
</TextField>
</VBox>
<Label text="%vaultOptions.mount.mountPoint">
<VBox.margin>
<Insets top="9"/>
</VBox.margin>
</Label>
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointAutoBtn" text="%vaultOptions.mount.mountPoint.auto"/>
<HBox spacing="6" visible="${controller.mountpointDriveLetterSupported}" managed="${controller.mountpointDriveLetterSupported}">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDriveLetterBtn" text="%vaultOptions.mount.mountPoint.driveLetter"/>
<ChoiceBox fx:id="driveLetterSelection" disable="${!mountPointDriveLetterBtn.selected}" accessibleText="%vaultOptions.mount.mountPoint.driveLetter"/>
</HBox>
<VBox spacing="6" visible="${controller.mountpointDirSupported}" managed="${controller.mountpointDirSupported}">
<HBox spacing="6" alignment="CENTER_LEFT">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDirBtn" text="%vaultOptions.mount.mountPoint.custom"/>
<Button text="%vaultOptions.mount.mountPoint.directoryPickerButton" onAction="#chooseCustomMountPoint" contentDisplay="LEFT" disable="${!mountPointDirBtn.selected}">
<graphic>
<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
</graphic>
</Button>
</HBox>
<TextField fx:id="directoryPathField" text="${controller.directoryPath}" visible="${mountPointDirBtn.selected}" managed="${mountPointDirBtn.managed}" maxWidth="Infinity" editable="false" accessibleText="%vaultOptions.mount.mountPoint.custom">
<VBox.margin>
<Insets left="24"/>
</VBox.margin>
</TextField>
</VBox>
</children>
</VBox>
</ScrollPane>
@@ -110,6 +110,13 @@ addvaultwizard.existing.restore=Restore…
addvaultwizard.existing.chooseBtn=Choose…
addvaultwizard.existing.filePickerTitle=Select Vault File
addvaultwizard.existing.filePickerMimeDesc=Cryptomator Vault
addvaultwizard.existing.notAVault.title=Not a Vault
addvaultwizard.existing.notAVault.message=The selected folder is not a Cryptomator vault
addvaultwizard.existing.notAVault.description.missingDataDir=The required "d" subdirectory is missing inside "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=The "d" entry inside "%s" is not a directory.
addvaultwizard.existing.notAVault.description.missingVaultConfig=The required "vault.cryptomator" file is missing inside "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=File "vault.cryptomator" inside "%s" cannot be read due to insufficient access rights.
addvaultwizard.existing.notAVault.description.unsupportedStructure=The directory structure of "%s" is not supported.
## Success
addvaultwizard.success.nextStepsInstructions=Added vault "%s".\nYou need to unlock this vault to access or add contents. Alternatively you can unlock it at any later point in time.
addvaultwizard.success.unlockNow=Unlock Now
@@ -32,6 +32,7 @@
## Success
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -40,6 +41,7 @@
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -154,4 +156,4 @@
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -154,6 +154,8 @@ unlock.error.title=فشل فتح "%s"
hub.noKeychain.message=غير قادر على الوصول إلى مفتاح الجهاز
hub.noKeychain.description=من أجل فتح مركز مخازن، مطلوب مفتاح جهاز، يتم تأمينه باستخدام سلسلة مفاتيح. للمضي قدما، قم بتمكين "%s" واختر سلسلة مفاتيح في التفضيلات.
hub.noKeychain.openBtn=فتح التفضيلات
### Check Host Authenticity
hub.checkHostTrust.trustBtn=ثق
### Waiting
hub.auth.message=جاري الانتظار للمصادقة…
hub.auth.description=يجب أن يتم إعادة توجيهك تلقائياً إلى صفحة تسجيل الدخول.
@@ -183,6 +185,7 @@ hub.registerFailed.description.deviceAlreadyExists=هذا الجهاز مسجل
### Unauthorized
hub.unauthorized.message=تم رفض الوصول
hub.unauthorized.description=غير مسموح لك بفتح هذا المستودع. اتصل بمالك المستودع لطلب الوصول.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=مطلوب اتخاذ إجراء
hub.requireAccountInit.description.0=للمتابعة، يرجى إكمال الخطوات المطلوبة في
@@ -645,4 +648,4 @@ eventView.entry.inUse.showEncrypted=عرض ملَف المشفر
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -151,6 +151,8 @@ unlock.error.title="%s" биге асылманы
hub.noKeychain.message=Йыһаз асҡысына инеү рөхсәте юҡ
hub.noKeychain.description=Хаб һаҡлағыстарын асыу өсөн йыһаз асҡысы кәрәк, ул иһә асҡыс сылбырында һаҡлана. Артабан “%s” мөмкинлеге бирегеҙ һәм көйләүҙәрҙә асҡыс сылбырын һайлағыҙ.
hub.noKeychain.openBtn=Көйләүҙәрҙе ас
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Ышан
### Waiting
hub.auth.message=Аутентиклау көтөлә…
hub.auth.description=Автоматик рәүештә инеү битенә йүнәлтелергә тейешһегеҙ.
@@ -170,6 +172,7 @@ hub.registerSuccess.unlockBtn=Биген ас
### Archived
### Unauthorized
hub.unauthorized.message=Инеү кире ҡағылды
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Эш-хәрәкәт кәрәкле
hub.requireAccountInit.description.0=Дауам итер өсөн, кәрәкле аҙымдар тамамланырға тейеш урын:
@@ -555,4 +558,4 @@ dokanySupportEnd.preferencesBtn=Көйләүҙәрҙе ас
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -145,6 +145,7 @@ unlock.error.customPath.description.inUse=Дыскавая літара або
hub.noKeychain.message=Няма доступу да ключа прылады
hub.noKeychain.description=Каб разамкнуць скарбніцы Hub, патрэбны ключ прылады, які захаваны ў звязку ключоў. Каб працягнуць, уключы "%s" ды абяры звязак ключоў у наладах.
hub.noKeychain.openBtn=Адчыніць налады
### Check Host Authenticity
### Waiting
hub.auth.message=Чаканне спраўджання…
hub.auth.description=Ты мусіш аўтаматычна перанакіравацца на старонку ўваходу.
@@ -162,6 +163,7 @@ hub.registerSuccess.unlockBtn=Адамкнуць
### Archived
### Unauthorized
hub.unauthorized.message=Адмова ў доступе
### Untrusted Host
### Requires Account Initialization
### License Exceeded
hub.invalidLicense.message=Несапраўдная ліцэнзія Hub
@@ -532,4 +534,4 @@ dokanySupportEnd.preferencesBtn=Адчыніць налады
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -158,6 +158,7 @@ unlock.error.title=Неуспешно отключване на „%s“
hub.noKeychain.message=Няма достъп до ключа на устройството
hub.noKeychain.description=За да отключите хранилищата в Hub е необходим ключ за устройството, който се защитава с помощта на ключодържател. За да продължите, разрешете „%s“ и изберете ключодържателя в настройките.
hub.noKeychain.openBtn=Към настройките
### Check Host Authenticity
### Waiting
hub.auth.message=Изчакване на удостоверяване…
hub.auth.description=Автоматично ще бъдете пренасочени към страницата за вход.
@@ -177,6 +178,7 @@ hub.registerSuccess.unlockBtn=Отключване
### Archived
### Unauthorized
hub.unauthorized.message=Отказан достъп
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Необходимо е действие
hub.requireAccountInit.description.0=За да продължите завършете необходимите стъпки в
@@ -563,4 +565,4 @@ dokanySupportEnd.preferencesBtn=Към настройките
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -92,6 +92,7 @@ unlock.unlockBtn=আনলক করুন
## Success
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -101,6 +102,7 @@ hub.registerSuccess.unlockBtn=আনলক করুন
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -221,4 +223,4 @@ vaultOptions.mount.mountPoint.directoryPickerButton=নির্বাচন ক
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -104,6 +104,8 @@ unlock.success.rememberChoice=Zapamtite izbor, ne pokazujte ovo ponovo
unlock.success.revealBtn=Otkrij pogon
## Failure
## Hub
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Povjerenje
### Waiting
### Receive Key
### Register Device
@@ -113,6 +115,7 @@ hub.registerSuccess.unlockBtn=Otključaj
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -356,4 +359,4 @@ quit.lockAndQuitBtn=Zaključaj i zatvori
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -155,6 +155,8 @@ unlock.error.title=El desblocatge de "%s" ha fallat
hub.noKeychain.message=No es pot accedir a la clau del dispositiu
hub.noKeychain.description=Per poder desblocar caixes fortes del Hub es requereix la clau d'un dispositiu, que s'emmagatzema de forma segura en un clauer. Per continuar, habiliti "%s" i seleccioni un clauer en les Preferències.
hub.noKeychain.openBtn=Obrir les Preferències
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Confia-hi
### Waiting
hub.auth.message=Sestà esperant lautenticació…
hub.auth.description=Hauríeu de ser redirigits a la pàgina d'accés.
@@ -184,6 +186,7 @@ hub.registerFailed.description.deviceAlreadyExists=El dispositiu ja ha estat reg
### Unauthorized
hub.unauthorized.message=Accés denegat
hub.unauthorized.description=No estàs autoritzat a obrir aquesta caixa forta. Contacta amb el seu propietari per obtenir accés.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Acció necessària
hub.requireAccountInit.description.0=Per a continuar, si us plau, seguiu els passos necessaris en el vostre
@@ -611,4 +614,4 @@ shareVault.hub.openHub=Obre Cryptomator Hub
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -150,6 +150,8 @@ unlock.error.title=Odemknutí "%s" selhalo
hub.noKeychain.message=Nelze získat přístup ke klíči zařízení
hub.noKeychain.description=Chcete-li odemknout Hub trezory, je potřeba použít klíč zařízení, který je zabezpečen pomocí klíčenky. Chcete-li pokračovat, povolte „%s“ a vyberte klíčenku v nastavení.
hub.noKeychain.openBtn=Otevřít předvolby
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Důvěřovat
### Waiting
hub.auth.message=Čekání na ověření…
hub.auth.description=Měli byste být automaticky přesměrováni na přihlašovací stránku.
@@ -178,6 +180,7 @@ hub.registerFailed.description.deviceAlreadyExists=Toto zařízení je již regi
### Archived
### Unauthorized
hub.unauthorized.message=Přístup odepřen
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Požadována akce
hub.requireAccountInit.description.0=Chcete-li pokračovat, vyplňte prosím požadované kroky ve vašem
@@ -572,4 +575,4 @@ shareVault.hub.openHub=Otevřít Cryptomator Hub
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+18 -1
View File
@@ -109,6 +109,13 @@ addvaultwizard.existing.restore=Gendan…
addvaultwizard.existing.chooseBtn=Vælg…
addvaultwizard.existing.filePickerTitle=Vælg boks-fil
addvaultwizard.existing.filePickerMimeDesc=Cryptomator boks
addvaultwizard.existing.notAVault.title=Ikke en boks
addvaultwizard.existing.notAVault.message=Den valgte mappe skal være en gyldig Cryptomator boks
addvaultwizard.existing.notAVault.description.missingDataDir=Den krævede "d" undermappe mangler inde i "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=Indgangen "d" inde i "%s" er ikke en mappe.
addvaultwizard.existing.notAVault.description.missingVaultConfig=Den påkrævede "vault.cryptomator"-fil mangler inde i "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=Filen "vault.cryptomator" inde i "%s" kan ikke læses på grund af utilstrækkelige adgangsrettigheder.
addvaultwizard.existing.notAVault.description.unsupportedStructure=Mappestrukturen for "%s" understøttes ikke.
## Success
addvaultwizard.success.nextStepsInstructions=Tilføjede boks "%s".\nDu skal låse op for denne boks for at tilgå indholdet. Alternativt kan du låse den op på et senere tidspunkt.
addvaultwizard.success.unlockNow=Lås op nu
@@ -161,6 +168,12 @@ unlock.error.title=Oplåsning af "%s" mislykkedes
hub.noKeychain.message=Kan ikke tilgå enhedsnøgle
hub.noKeychain.description=En enhedsnøgle er påkrævet for at låse Hub bokse op. Enhedsnøglen er sikret i en nøglering. For at fortsætte, aktivér “%s” og vælg en nøglering i indstillingerne.
hub.noKeychain.openBtn=Åbn Indstillinger
### Check Host Authenticity
hub.checkHostTrust.message.check=Kontrollerer konfiguration…
hub.checkHostTrust.message.ask=Stol på denne vært?
hub.checkHostTrust.message.ask.plural=Stol på disse værter?
hub.checkHostTrust.trustBtn=Hav tillid
hub.checkHostTrust.denyBtn=Afvis
### Waiting
hub.auth.message=Afventer godkendelse…
hub.auth.description=Du burde automatisk blive omdirigeret til login-siden.
@@ -192,6 +205,9 @@ hub.archived.description=Denne boks er blevet arkiveret og er ikke længere tilg
### Unauthorized
hub.unauthorized.message=Adgang nægtet
hub.unauthorized.description=Du har ikke tilladelse til at åbne denne boks. Kontant ejeren af boksen for at anmode om adgang.
### Untrusted Host
hub.untrustedHost.message=Vært Ikke pålidelig
hub.untrustedHost.description=Forbindelsen til Hub blev blokeret for din sikkerhed. Hvis du mener, at Hub-værten er sikker, så kontakt din Hub-administrator eller prøv igen.
### Requires Account Initialization
hub.requireAccountInit.message=Handling påkrævet
hub.requireAccountInit.description.0=For at fortsætte, skal du fuldføre de nødvendige trin i din
@@ -305,6 +321,7 @@ preferences.general.debugDirectory=Vis logfiler
preferences.general.autoStart=Start Cryptomator automatisk ved opstart
preferences.general.keychainBackend=Gem adgangskoder med
preferences.general.quickAccessService=Tilføj oplåste bokse til området hurtig adgang
preferences.general.resetTrustedHosts=Nulstil betroede værter
## Interface
preferences.interface=Brugerflade
preferences.interface.theme=Udseende
@@ -716,4 +733,4 @@ eventView.entry.inUse.ignoreLock=Ignorér anvendelsesstatus
## FileIsInUse Notification
notification.inUse.message=Filen er i brug på en anden enhed
notification.inUse.description=Filen er åbnet af %s på %s. Bed dem om at lukke filen og lade synkroniseringen afslutte. Du kan ignorere status for at åbne den nu, men det kan forårsage konflikter eller overskrive nyere ændringer.
notification.inUse.action=Ignorér anvendelsesstatus
notification.inUse.action=Ignorér anvendelsesstatus
@@ -104,6 +104,7 @@ addvaultwizard.existing.restore=Wiederherstellen…
addvaultwizard.existing.chooseBtn=Durchsuchen …
addvaultwizard.existing.filePickerTitle=Tresordatei auswählen
addvaultwizard.existing.filePickerMimeDesc=Cryptomator-Tresor
addvaultwizard.existing.notAVault.description.unsupportedStructure=Die Verzeichnisstruktur von "%s" wird nicht unterstützt.
## Success
addvaultwizard.success.nextStepsInstructions=Tresor „%s“ wurde hinzugefügt.\nUm auf Inhalte zuzugreifen oder welche hinzuzufügen, musst du den Tresor entsperren. Du kannst ihn aber auch zu jedem späteren Zeitpunkt entsperren.
addvaultwizard.success.unlockNow=Jetzt entsperren
@@ -156,6 +157,8 @@ unlock.error.title=„%s“ konnte nicht entsperrt werden
hub.noKeychain.message=Zugriff auf Geräteschlüssel nicht möglich
hub.noKeychain.description=Zum Entsperren von Hub-Tresoren wird ein Geräteschlüssel benötigt, der in einem Schlüsselbund gesichert ist. Um fortzufahren, aktiviere „%s“ und wähle in den Einstellungen einen Schlüsselbund.
hub.noKeychain.openBtn=Einstellungen öffnen
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Vertrauen
### Waiting
hub.auth.message=Warten auf Authentifizierung …
hub.auth.description=Du solltest automatisch zur Anmeldeseite weitergeleitet werden.
@@ -187,6 +190,7 @@ hub.archived.description=Dieser Tresor wurde archiviert, daher ist ein Zugriff d
### Unauthorized
hub.unauthorized.message=Zugriff verweigert
hub.unauthorized.description=Du bist nicht berechtigt, diesen Tresor zu öffnen. Wende dich an den Tresoreigentümer, um Zugriff zu erhalten.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Aktion erforderlich
hub.requireAccountInit.description.0=Um fortzufahren, führe bitte die erforderlichen Schritte in deinem
@@ -298,6 +302,7 @@ preferences.general.debugDirectory=Protokolldateien anzeigen
preferences.general.autoStart=Cryptomator beim Systemstart starten
preferences.general.keychainBackend=Passwörter speichern mit
preferences.general.quickAccessService=Entsperrte Tresore zum Schnellzugriff hinzufügen
preferences.general.resetTrustedHosts=Vertrauenswürdige Hosts zurücksetzen
## Interface
preferences.interface=Benutzeroberfläche
preferences.interface.theme=Erscheinungsbild
@@ -701,4 +706,4 @@ eventView.entry.inUse.copyUserAndDevice=Benutzer- und Gerätenamen der Sperre ko
# Notifications
## FileIsInUse Notification
notification.inUse.action=Verwendungsstatus ignorieren
notification.inUse.action=Verwendungsstatus ignorieren
@@ -154,6 +154,8 @@ unlock.error.title=Ξεκλείδωμα "%s" απέτυχε
hub.noKeychain.message=Δεν είναι δυνατή η πρόσβαση στο κλειδί της συσκευής
hub.noKeychain.description=Για να ξεκλειδώσετε τις κρύπτες Hub, απαιτείται ένα κλειδί συσκευής, το οποίο ασφαλίζεται με χρήση μπρελόκ. Για να συνεχίσετε, ενεργοποιήστε το "%s" και επιλέξτε ένα keychain στις προτιμήσεις.
hub.noKeychain.openBtn=Άνοιγμα Προτιμήσεων
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Εμπιστευτείτε
### Waiting
hub.auth.message=Αναμονή για επαλήθευση…
hub.auth.description=Θα πρέπει να ανακατευθυνθείτε αυτόματα στη σελίδα σύνδεσης.
@@ -183,6 +185,7 @@ hub.registerFailed.description.deviceAlreadyExists=Αυτή η συσκευή ε
### Unauthorized
hub.unauthorized.message=Δεν επιτρέπεται η πρόσβαση
hub.unauthorized.description=Δεν είστε εξουσιοδοτημένοι να ανοίξετε αυτή την κρύπτη. Επικοινωνήστε με τον ιδιοκτήτη τς κρύπτης για να ζητήσετε πρόσβαση.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Απαιτείται ενέργεια
hub.requireAccountInit.description.0=Για να συνεχίσετε, παρακαλούμε ολοκληρώστε τα βήματα που απαιτούνται στο δικό σας
@@ -645,4 +648,4 @@ eventView.entry.inUse.showEncrypted=Εμφάνιση κρυπτογραφημέ
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+30 -1
View File
@@ -18,6 +18,11 @@ generic.button.print=Imprimir
generic.button.remove=Eliminar
## Vault state
vault.state.locked=Bloqueada
vault.state.unlocked=Desbloqueada
vault.state.missing=Faltante
vault.state.migrationNeeded=Migración obligatoria
vault.state.processing=Procesando
vault.state.error=Error
# Error
@@ -104,6 +109,13 @@ addvaultwizard.existing.restore=…
addvaultwizard.existing.chooseBtn=Elegir…
addvaultwizard.existing.filePickerTitle=Seleccionar archivo de bóveda
addvaultwizard.existing.filePickerMimeDesc=Bóveda de Cryptomator
addvaultwizard.existing.notAVault.title=No es una bóveda
addvaultwizard.existing.notAVault.message=La carpeta seleccionada no es una bóveda de Cryptomator
addvaultwizard.existing.notAVault.description.missingDataDir=Falta el subdirectorio "d" necesario dentro de "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=La entrada "d" dentro de "%s" no es un directorio.
addvaultwizard.existing.notAVault.description.missingVaultConfig=Falta el archivo "vault.cryptomator" necesario dentro de "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=El archivo "vault.cryptomator" dentro de "%s" no se puede leer debido a la falta de permisos de acceso.
addvaultwizard.existing.notAVault.description.unsupportedStructure=La estructura de directorios de "%s" no está soportada.
## Success
addvaultwizard.success.nextStepsInstructions=Bóveda "%s" añadida.\nSe necesita desbloquear esta bóveda para acceder o añadir contenido. Alternativamente se \n puede desbloquear en otro momento.
addvaultwizard.success.unlockNow=Desbloquear ahora
@@ -156,6 +168,12 @@ unlock.error.title=Error al desbloquear "%s"
hub.noKeychain.message=No se puede acceder a la clave del dispositivo
hub.noKeychain.description=Para desbloquear las bóvedas de Hub, se requiere una clave de dispositivo que se asegura con un llavero. Para continuar, habilite "%s" y seleccione un llavero en las preferencias.
hub.noKeychain.openBtn=Abrir preferencias
### Check Host Authenticity
hub.checkHostTrust.message.check=Comprobando configuración…
hub.checkHostTrust.message.ask=¿Confiar en este host?
hub.checkHostTrust.message.ask.plural=¿Confiar en estos hosts?
hub.checkHostTrust.trustBtn=Confiar
hub.checkHostTrust.denyBtn=Denegar
### Waiting
hub.auth.message=Esperando la autenticación…
hub.auth.description=Debería ser redirigido automáticamente a la página de inicio de sesión.
@@ -182,9 +200,14 @@ hub.registerFailed.message=El registro del dispositivo ha fallado
hub.registerFailed.description.generic=Ha ocurrido un error al intentar registrarse. Para más detalles, consulte el registro de la aplicación.
hub.registerFailed.description.deviceAlreadyExists=Este dispositivo ya se ha registrado para otro usuario. Intente cambiar la cuenta de usuario o utilice un dispositivo diferente.
### Archived
hub.archived.message=Bóveda archivada
hub.archived.description=Esta bóveda ha sido archivada y ya no es accesible. Póngase en contacto con el propietario de la bóveda.
### Unauthorized
hub.unauthorized.message=Acceso denegado
hub.unauthorized.description=No tiene autorización para abrir esta bóveda. Contacta al propietario de la bóveda para solicitar acceso.
### Untrusted Host
hub.untrustedHost.message=Host no confiable
hub.untrustedHost.description=La conexión al Hub fue bloqueada por su seguridad. Si cree que el Hub es seguro, póngase en contacto con la administración de Hub o vuelva a intentarlo.
### Requires Account Initialization
hub.requireAccountInit.message=Acción requerida
hub.requireAccountInit.description.0=Para continuar, por favor complete los pasos necesarios en su
@@ -298,6 +321,7 @@ preferences.general.debugDirectory=Revelar archivos de registro
preferences.general.autoStart=Cargar Cryptomator al iniciar el sistema
preferences.general.keychainBackend=Guardar contraseñas con
preferences.general.quickAccessService=Añadir bóvedas desbloqueadas al área de acceso rápido
preferences.general.resetTrustedHosts=Restablecer hosts de confianza
## Interface
preferences.interface=Interfaz
preferences.interface.theme=Apariencia
@@ -403,6 +427,7 @@ stats.access.total=Accesos totales: %d
# Main Window
## Vault List
main.vaultlist=Bóvedas
main.vaultlist.listEntry=Bóveda %s (%s)
main.vaultlist.emptyList.onboardingInstruction=Haga clic aquí para añadir una bóveda
main.vaultlist.contextMenu.remove=Eliminar…
main.vaultlist.contextMenu.lock=Bloquear
@@ -420,9 +445,11 @@ main.vaultlist.showPreferencesButton.tooltip=Mostrar preferencias
##Notification
main.notification.updateAvailable=Existen actualizaciones disponibles.
main.notification.support=Soporte de Cryptomator.
main.notification.closeButton.tooltip=Cerrar barra de información
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Gracias por elegir Cryptomator para proteger sus archivos. En caso de necesitar ayuda, revise nuestras guías:
main.vaultDetail.storageLocation=Ubicación de almacenamiento en bóveda
### Locked
main.vaultDetail.lockedStatus=BLOQUEADA
main.vaultDetail.unlockBtn=Desbloquear…
@@ -511,6 +538,7 @@ vaultOptions.masterkey.forgetSavedPasswordBtn=Olvidar contraseña guardada
vaultOptions.masterkey.recoveryKeyExplanation=Una clave de recuperación es el único medio para restaurar el acceso a una bóveda si pierde su contraseña.
vaultOptions.masterkey.showRecoveryKeyBtn=Mostrar clave de recuperación
vaultOptions.masterkey.recoverPasswordBtn=Restablecer contraseña
vaultOptions.masterkey.missingMasterkeyFile=Estas opciones sólo están disponibles si el archivo masterkey está presente en el directorio de la bóveda.
## Hub
vaultOptions.hub=Recuperación
vaultOptions.hub.convertInfo=Puede utilizar la clave de recuperación para convertir esta bóveda de Hub en una bóveda con contraseña en una emergencia.
@@ -697,6 +725,7 @@ eventView.entry.brokenFileNode.copyDecrypted=Copiar ruta descifrada
eventView.entry.inUse.message=Fichero en uso
eventView.entry.inUse.showDecrypted=Mostrar archivo descifrado
eventView.entry.inUse.showEncrypted=Mostrar archivo cifrado
eventView.entry.inUse.copyUserAndDevice=Copiar nombre de usuario y dispositivo de bloqueo
eventView.entry.inUse.ignoreLock=Ignorar el estado de uso
@@ -704,4 +733,4 @@ eventView.entry.inUse.ignoreLock=Ignorar el estado de uso
## FileIsInUse Notification
notification.inUse.message=El archivo está en uso en otro dispositivo
notification.inUse.description=El archivo está abierto por %s en %s. Solicítale que cierre el archivo y deje que finalice la sincronización. Puede ignorar el estado para abrirlo ahora, pero esto puede causar conflictos o sobrescribir cambios más recientes.
notification.inUse.action=Ignorar el Estado de Uso
notification.inUse.action=Ignorar el Estado de Uso
@@ -114,6 +114,7 @@ unlock.success.revealBtn=نمایش درایو
## Failure
## Hub
hub.noKeychain.openBtn=باز کردن تنظیمات
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -124,6 +125,7 @@ hub.registerSuccess.unlockBtn=بازکردن قفل
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -256,4 +258,4 @@ dokanySupportEnd.preferencesBtn=باز کردن تنظیمات
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -156,6 +156,7 @@ unlock.error.title="%s" avaaminen epäonnistui
hub.noKeychain.message=Laitteen avainta ei löytynyt
hub.noKeychain.description=Hub-holvien purkamiseksi tarvitaan laiteavain joka on suojattu avainrenkaalla. Jatkaaksesi, kytke “%s” päälle ja valitse avainrengas asetuksista.
hub.noKeychain.openBtn=Avaa asetukset
### Check Host Authenticity
### Waiting
hub.auth.message=Odotetaan todennusta…
hub.auth.description=Pitäisi ohjata sinut automaattisesti uudelleen kirjautumissivulle.
@@ -185,6 +186,7 @@ hub.registerFailed.description.deviceAlreadyExists=Tämä laite on jo rekisterö
### Unauthorized
hub.unauthorized.message=Pääsy estetty
hub.unauthorized.description=Sinulla ei ole oikeutta avata tätä holvia. Ota yhteyttä holvin omistajaan pyytääksesi pääsyä.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Toimia vaaditaan
hub.requireAccountInit.description.0=Jatkaaksesi, ole hyvä ja suorita tarvittavat toimenpiteet
@@ -698,4 +700,4 @@ eventView.entry.inUse.showEncrypted=Näytä salattu tiedosto
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -154,6 +154,8 @@ unlock.error.title=Hindi mabuksan ang "%s"
hub.noKeychain.message=Hindi ma-access ang key ng device
hub.noKeychain.description=Para ma-unlock ang mga Hub vault, kailangan ng device key, na sini-secure gamit ang keychain. Upang magpatuloy, paganahin ang “%s” at pumili ng keychain sa mga kagustuhan.
hub.noKeychain.openBtn=Buksan ang Mga Kagustuhan
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Magtiwala
### Waiting
hub.auth.message=Naghihintay para sa pagpapatunay…
hub.auth.description=Dapat kang awtomatikong mai-redirect sa pahina ng pag-login.
@@ -182,6 +184,7 @@ hub.registerFailed.description.deviceAlreadyExists=Ang device na ito ay registra
### Archived
### Unauthorized
hub.unauthorized.message=Walang pahintulot
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Kinakailangan ang pagkilos
hub.requireAccountInit.description.0=Upang magpatuloy, mangyaring kumpletuhin ang mga hakbang na kinakailangan sa iyong
@@ -598,4 +601,4 @@ shareVault.hub.openHub=Buksan ang Cryptomator Hub
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+22 -5
View File
@@ -109,6 +109,13 @@ addvaultwizard.existing.restore=Restaurer…
addvaultwizard.existing.chooseBtn=Choisir…
addvaultwizard.existing.filePickerTitle=Sélectionnez le fichier correspondant au volume chiffré
addvaultwizard.existing.filePickerMimeDesc=Coffre-fort Cryptomator
addvaultwizard.existing.notAVault.title=Pas un coffre
addvaultwizard.existing.notAVault.message=Le dossier sélectionné nest pas un coffre Cryptomator
addvaultwizard.existing.notAVault.description.missingDataDir=Le sous-répertoire « d » requis est manquant dans «%s».
addvaultwizard.existing.notAVault.description.dataNotADirectory=L'entrée « d » dans « %s » n'est pas un répertoire.
addvaultwizard.existing.notAVault.description.missingVaultConfig=Le fichier « vault.cryptomator » requis est manquant dans « %s ».
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=Le fichier « vault.cryptomator » dans « %s » ne peut pas être lu en raison de droits daccès insuffisants.
addvaultwizard.existing.notAVault.description.unsupportedStructure=La structure de répertoire de « %s » n'est pas prise en charge.
## Success
addvaultwizard.success.nextStepsInstructions=Coffre “%s” ajouté.\nIl faudra déverrouiller ce coffre afin dy accéder ou dy ajouter du contenu. Cette action peut être réalisée ultérieurement.
addvaultwizard.success.unlockNow=Déverrouiller
@@ -161,6 +168,12 @@ unlock.error.title=Échec du déverrouillage de "%s"
hub.noKeychain.message=Impossible d'accéder à la clé du périphérique
hub.noKeychain.description=Le déverrouillage des coffres Hub nécessite une clé de périphérique sécurisée à l'aide d'un trousseau. Pour continuer, activez « %s » et sélectionnez un trousseau dans les préférences.
hub.noKeychain.openBtn=Ouvrir les préférences
### Check Host Authenticity
hub.checkHostTrust.message.check=Vérification de configuration…
hub.checkHostTrust.message.ask=Faire confiance à cet hôte ?
hub.checkHostTrust.message.ask.plural=Faire confiance à ces hôtes ?
hub.checkHostTrust.trustBtn=Approuver
hub.checkHostTrust.denyBtn=Refuser
### Waiting
hub.auth.message=Authentification en cours…
hub.auth.description=Vous devriez automatiquement être redirigé vers la page de connexion.
@@ -192,6 +205,9 @@ hub.archived.description=Ce coffre a été archivé et n'est plus accessible. Ve
### Unauthorized
hub.unauthorized.message=Accès refusé
hub.unauthorized.description=Vous n'êtes pas autorisé à ouvrir ce coffre. Contactez le propriétaire du coffre pour en demander l'accès.
### Untrusted Host
hub.untrustedHost.message=Hôte non fiable
hub.untrustedHost.description=La connexion à Hub a été bloquée pour votre sécurité. Si vous pensez que l'hôte Hub est en sécurité, contactez son administrateur ou réessayez.
### Requires Account Initialization
hub.requireAccountInit.message=Action requise
hub.requireAccountInit.description.0=Pour continuer, veuillez compléter les étapes requises
@@ -300,11 +316,12 @@ preferences.title=Préférences
preferences.general=Général
preferences.general.startHidden=Démarrer Cryptomator en mode caché
preferences.general.autoCloseVaults=Verrouiller les coffres sans confirmation lors de la fermeture de l'application
preferences.general.debugLogging=Activer les logs debug
preferences.general.debugDirectory=Afficher le journal
preferences.general.debugLogging=Activer les logs de débogage
preferences.general.debugDirectory=Afficher les logs
preferences.general.autoStart=Lancer Cryptomator au démarrage du système
preferences.general.keychainBackend=Stocker les mots de passe avec
preferences.general.quickAccessService=Ajouter les coffres déverrouillés à la zone d'accès rapide
preferences.general.resetTrustedHosts=Réinitialiser les hôtes de confiance
## Interface
preferences.interface=Interface
preferences.interface.theme=Apparence
@@ -369,7 +386,7 @@ removeCert.description=Les fonctionnalités principales de Cryptomator ne sont p
#<-- Add entries for donations and code/translation/documentation contribution -->
## About
preferences.about=A propos
preferences.about=À propos
preferences.about.thirdPartyLicenses=Licences tierces
# Vault Statistics
@@ -428,7 +445,7 @@ main.vaultlist.showPreferencesButton.tooltip=Afficher les préférences
##Notification
main.notification.updateAvailable=Mise à jour disponible.
main.notification.support=Soutenir Cryptomator.
main.notification.closeButton.tooltip="Fermer la barre d'information"
main.notification.closeButton.tooltip=Fermer la barre d'information
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Merci d'avoir choisi Cryptomator pour protéger vos fichiers. Si vous avez besoin d'aide, consultez nos guides de démarrage :
@@ -716,4 +733,4 @@ eventView.entry.inUse.ignoreLock=Ignorer le statut dutilisation
## FileIsInUse Notification
notification.inUse.message=Le fichier est utilisé sur un autre appareil
notification.inUse.description=Le fichier est ouvert par %s sur %s. Demandez-lui à fermer le fichier et laissez la synchronisation se terminer. Vous pouvez ignorer le statut pour louvrir maintenant, mais cela pourrait entraîner des conflits ou écraser des modifications récentes.
notification.inUse.action=Ignorer le statut dutilisation
notification.inUse.action=Ignorer le statut dutilisation
@@ -46,6 +46,7 @@ error.message=Produciuse un erro
## Success
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -54,6 +55,7 @@ error.message=Produciuse un erro
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -169,4 +171,4 @@ lock.forced.retryBtn=Tentar de novo
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -150,6 +150,8 @@ unlock.error.customPath.description.notEmptyDir=הנתיב המותאם "%s" א
hub.noKeychain.message=לא ניתן לגשת למפתח המכשיר
hub.noKeychain.description=כדאי לשחרר כספות האב נדרש מפתח מכשיר שיאובטח בצרור מפתחות. כדאי להמשיך, אפשר ״%s״ ובחר את צרור המפתחות בהעדפות.
hub.noKeychain.openBtn=פתח העדפות
### Check Host Authenticity
hub.checkHostTrust.trustBtn=סמוך
### Waiting
hub.auth.message=ממתין לאימות…
hub.auth.description=אתה אמור להיות מופנה אוטומטית למסך ההזדהות.
@@ -166,6 +168,7 @@ hub.registerSuccess.unlockBtn=בטל נעילה
### Archived
### Unauthorized
hub.unauthorized.message=הגישה נדחתה
### Untrusted Host
### Requires Account Initialization
### License Exceeded
hub.invalidLicense.message=רישיון האב לא תקף
@@ -531,4 +534,4 @@ dokanySupportEnd.preferencesBtn=פתח העדפות
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -142,6 +142,8 @@ unlock.error.title="%s" तिजोरी खोलना विफल रह
## Hub
hub.noKeychain.message=उपकरण के कुंजी तक पहुंचने में असमर्थ
hub.noKeychain.openBtn=प्राथमिकताएँ खोलें
### Check Host Authenticity
hub.checkHostTrust.trustBtn=भरोसा करे
### Waiting
hub.auth.message=प्रमाणन के लिए इंतज़ार कर रहे...
hub.auth.description=आपको स्वचालित रूप से लॉगिन पृष्ठ पर पुनः निर्देशित किया जाना चाहिए।
@@ -158,6 +160,7 @@ hub.registerSuccess.unlockBtn=अनलॉक करें
### Archived
### Unauthorized
hub.unauthorized.message=प्रवेश अस्वीकृत
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=कार्रवाई आवश्यक है
hub.requireAccountInit.description.0=आगे बढ़ने के लिए, कृपया अपने आवश्यक चरणों को पूरा करें
@@ -354,4 +357,4 @@ dokanySupportEnd.preferencesBtn=प्राथमिकताएँ खोल
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -116,6 +116,8 @@ unlock.success.rememberChoice=Zapamti izbor, ne prikazuj ovo više
unlock.success.revealBtn=Otkrij pogon
## Failure
## Hub
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Vjeruj
### Waiting
### Receive Key
### Register Device
@@ -125,6 +127,7 @@ hub.registerSuccess.unlockBtn=Otključaj
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -421,4 +424,4 @@ quit.lockAndQuitBtn=Zaključaj i napusti
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+234 -114
View File
@@ -18,11 +18,16 @@ generic.button.print=Nyomtatás
generic.button.remove=Eltávolítás
## Vault state
vault.state.locked=Zárolva
vault.state.unlocked=Feloldva
vault.state.missing=Hiányzó
vault.state.migrationNeeded=Migráció szükséges
vault.state.processing=Feldolgozás
vault.state.error=Hiba
# Error
error.message=Hiba: %s
error.description=Upsz! A Cryptomator nem számított rá, hogy ez megtörténik. Keressen meglévő megoldást erre a hibára. Vagy ha még nem jelentették, bátran tegye ezt meg.
error.description=A Cryptomator nem számított rá, hogy ez megtörténik. Keressen meglévő megoldást erre a hibára. Vagy ha még nem jelentették, bátran tegye ezt meg.
error.hyperlink.lookup=Hiba okának keresése
error.hyperlink.report=Hiba jelentése
error.technicalDetails=Részletek:
@@ -33,7 +38,7 @@ error.dismiss=Elvet
error.lookUpSolution=Megoldás keresése
# Defaults
defaults.vault.vaultName=Széf
defaults.vault.vaultName=Titkosított tároló
# Tray Menu
traymenu.showMainWindow=Megmutatás
@@ -45,30 +50,30 @@ traymenu.vault.lock=Zárolás
traymenu.vault.reveal=Megmutatás
# Add Vault Wizard
addvaultwizard.title=Széf hozzáadása
addvaultwizard.title=Titkosított tároló hozzáadása
## New
addvaultwizard.new.title=Széf hozzáadása
addvaultwizard.new.title=Titkosított tároló hozzáadása
### Name
addvaultwizard.new.nameInstruction=Válasszon egy nevet az új széf számára
addvaultwizard.new.namePrompt=A széf neve
addvaultwizard.new.nameInstruction=Válasszon egy nevet a tároló számára
addvaultwizard.new.namePrompt=Titkosított tároló neve
### Location
addvaultwizard.new.locationInstruction=Hova mentse a Cryptomator a széf titkosított fájljait?
addvaultwizard.new.locationInstruction=Hova mentse a tároló titkosított fájljait?
addvaultwizard.new.locationLoading=Helyi fájlrendszer ellenőrzése alapértelmezett felhő tárolási könyvtárakra…
addvaultwizard.new.locationLabel=Tárolási hely
addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerLabel=Egyedi hely
addvaultwizard.new.directoryPickerButton=Választás…
addvaultwizard.new.directoryPickerTitle=Könyvtár kiválasztása
addvaultwizard.new.fileAlreadyExists=Már létezik fájl/könyvtár ezzel a trezornévvel
addvaultwizard.new.fileAlreadyExists=Már létezik fájl/könyvtár ezzel a tárolónévvel
addvaultwizard.new.locationDoesNotExist=A megadott elérési úton lévő könyvtár nem létezik, vagy nem érhető el
addvaultwizard.new.locationIsNotWritable=Nincs írási hozzáférés a megadott elérési úthoz
addvaultwizard.new.locationIsOk=Megfelelő hely a trezornak
addvaultwizard.new.invalidName=Érvénytelen vault név
addvaultwizard.new.validName=Érvényes vault név
addvaultwizard.new.validCharacters.message=A vault neve a következő karaktereket tartalmazhatja:
addvaultwizard.new.validCharacters.chars=Szókarakterek (pl. a, ж vagy 수)
addvaultwizard.new.locationIsOk=Megfelelő hely a titkosított tárolónak
addvaultwizard.new.invalidName=Érvénytelen tárolónév
addvaultwizard.new.validName=Érvényes tárolónév
addvaultwizard.new.validCharacters.message=A titkosított tároló neve a következő karaktereket tartalmazhatja:
addvaultwizard.new.validCharacters.chars=Szókarakterek (pl. a, ж vagy 수)
addvaultwizard.new.validCharacters.numbers=Számok
addvaultwizard.new.validCharacters.dashes=Kötőjel (%s) vagy alulvonás (%s)
addvaultwizard.new.validCharacters.dashes=Kötőjel (%s) vagy alvonás (%s)
### Expert Settings
addvaultwizard.new.expertSettings.enableExpertSettingsCheckbox=Haladó beállítások engedélyezése
addvaultwizard.new.expertSettings.shorteningThreshold.invalid=Írjon be egy értéket 36 és 220 között (alapértelmezett: 220)
@@ -76,41 +81,49 @@ addvaultwizard.new.expertSettings.shorteningThreshold.tooltip=További informác
addvaultwizard.new.expertSettings.shorteningThreshold.title=A kódolt fájlnevek maximális hosszúsága
addvaultwizard.new.expertSettings.shorteningThreshold.valid=Érvényes
### Password
addvaultwizard.new.createVaultBtn=Új széf létrehozása
addvaultwizard.new.createVaultBtn=Új titkosított tároló létrehozása
addvaultwizard.new.generateRecoveryKeyChoice=Nem fog tudni hozzáférni az adataihoz a jelszó nélkül. Akar egy visszaállítási kulcsot arra az esetre, ha elveszíti a jelszavát?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Igen kérem, jobb félni, mint megijedni.
addvaultwizard.new.generateRecoveryKeyChoice.no=Nem köszönöm, nem fogom elveszíteni a jelszavam.
addvaultwizard.new.generateRecoveryKeyChoice.yes=Igen kérem, jobb félni, mint megijedni
addvaultwizard.new.generateRecoveryKeyChoice.no=Nem köszönöm, nem fogom elveszíteni a jelszavam
### Information
addvault.new.readme.storageLocation.fileName=FONTOS.rtf
addvault.new.readme.storageLocation.1=⚠️ SZÉF FÁJLOK ⚠️
addvault.new.readme.storageLocation.2=Ez a széfjének a tárolási helye.
addvault.new.readme.storageLocation.1=⚠️ TITKOSÍTOTT FÁJLOK ⚠️
addvault.new.readme.storageLocation.2=Ez a titkosított tárolójának helye.
addvault.new.readme.storageLocation.3=NE
addvault.new.readme.storageLocation.4=• ne módosítson semmilyen fájlt ebbe a könyvtárba
addvault.new.readme.storageLocation.5=• ne tegyen titkosítani való fájlokat ebbe a könyvtárba
addvault.new.readme.storageLocation.6=Ha fájlokat akr titkosítani és a széf tartalmát akarja szerkeszteni akkor tegye a következőt:
addvault.new.readme.storageLocation.7=1. Adja hozzá a széfet a Cryptomator-hoz.
addvault.new.readme.storageLocation.8=2. Nyissa meg a széfet a Cryptomator-ban.
addvault.new.readme.storageLocation.4=• ne módosítson semmilyen fájlt ebben a könyvtárba
addvault.new.readme.storageLocation.5=• ne tegyen titkosítani való fájlokat ebbe a könyvtárba.
addvault.new.readme.storageLocation.6=Ha fájlokat akar titkosítani és a tároló tartalmát akarja szerkeszteni akkor tegye a következőt:
addvault.new.readme.storageLocation.7=1. Adja hozzá a tárolót a Cryptomator felületén.
addvault.new.readme.storageLocation.8=2. Nyissa meg a tárolót a Cryptomator felületén.
addvault.new.readme.storageLocation.9=3. Nyissa meg a hozzáférési helyet a "Megjelenítés" gombra való kattintással.
addvault.new.readme.storageLocation.10=Ha segítségre van szüksége, akkor látogasson el a dokumentáció oldalára: %s
addvault.new.readme.accessLocation.fileName=ÜDVÖZÖLJÜK.rtf
addvault.new.readme.accessLocation.1=🔐️ TITKOSÍTOTT KÖTET 🔐️
addvault.new.readme.accessLocation.2=Ez a széf hozzáférési helye.
addvault.new.readme.accessLocation.3=Bármilyen, a kötethez hozzáadott fájl titkosításra kerül a Cryptomator által. Úgy dolgozhat vele, mint minden más meghajtóval/mappával. Ez az egyetlen dekódolt tartalmi nézet. A fájlai folyamatosan titkosítva maradnak a merevlemezén.
addvault.new.readme.accessLocation.2=Ez a tároló hozzáférési helye.
addvault.new.readme.accessLocation.3=Bármilyen, a kötethez hozzáadott fájl titkosításra kerül a Cryptomator által. Úgy dolgozhat vele, mint minden más meghajtóval/mappával. Ez az egyetlen dekódolt tartalmi nézet. A fájljai folyamatosan titkosítva maradnak a merevlemezén.
addvault.new.readme.accessLocation.4=Bátran eltávolíthatja ezt a fájlt.
## Existing
addvaultwizard.existing.title=Meglévő széf hozzáadása
addvaultwizard.existing.instruction=Válassza ki a "vault.cryptomatotor" fájlt a meglévő tárolóhoz. Ha csak egy "masterkey.cryptomatotor" nevű fájl létezik, válassza azt.
addvaultwizard.existing.title=Meglévő tároló hozzáadása
addvaultwizard.existing.instruction=Válassza ki a "vault.cryptomator" fájlt a meglévő tárolóban. Ha csak egy "masterkey.cryptomator" nevű fájl létezik, válassza azt.
addvaultwizard.existing.restore=Visszaállítás…
addvaultwizard.existing.chooseBtn=Kiválaszt…
addvaultwizard.existing.filePickerTitle=Trezor fájl kiválasztása
addvaultwizard.existing.filePickerMimeDesc=Cryptomator széf
addvaultwizard.existing.filePickerTitle=Titkosított tároló fájl kiválasztása
addvaultwizard.existing.filePickerMimeDesc=Cryptomator tároló
addvaultwizard.existing.notAVault.title=Nem titkosított tároló
addvaultwizard.existing.notAVault.message=A kiválasztott könyvtár nem Cryptomator titkosított tároló
addvaultwizard.existing.notAVault.description.missingDataDir=A következő mappában hiányzik a szükséges "d" almappa: "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=A következő mappában található "d" bejegyzés nem könyvtár: "%s".
addvaultwizard.existing.notAVault.description.missingVaultConfig=A szükséges "vault.cryptomator" fájl hiányzik a következő mappából: "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=A "%s" mappában található "vault.cryptomator" fájl nem olvasható el, mert nincs megfelelő hozzáférési jogosultság.
addvaultwizard.existing.notAVault.description.unsupportedStructure=A következő mappa könyvtárstruktúrája nem támogatott: "%s".
## Success
addvaultwizard.success.nextStepsInstructions=Széf létrehozva "%s".\nA tartalom eléréséhez, vagy hozzáadásához fel kell oldania a széfet. Alternatív megoldásként később bármikor feloldhatja.
addvaultwizard.success.nextStepsInstructions=Titkosított tároló létrehozva "%s".\nA tartalom eléréséhez, vagy hozzáadásához fel kell oldania a tárolót. Alternatív megoldásként később is bármikor feloldhatja.
addvaultwizard.success.unlockNow=Azonnali feloldás
# Remove Vault
removeVault.title=Széf eltávolitása
removeVault.message=Vault eltávolitása?
removeVault.description=Ez kizárolag a Cryptomator-ból távolitja el ezt a széfet. Később hozzáadhatja újra. A titkosított fájlokat nem törli a merevlemezről.
removeVault.title="%s" tároló eltávolítása
removeVault.message=Titkosított tároló eltávolítása?
removeVault.description=Ez kizárólag a Cryptomator listájából távolítja el a tárolót. Később hozzáadhatja újra. A titkosított fájlokat nem törli a merevlemezről.
# Change Password
changepassword.title=Jelszó megváltoztatása
@@ -120,7 +133,7 @@ changepassword.finalConfirmation=Megértettem, hogy nem fogok hozzáférni az ad
# Forget Password
forgetPassword.title=Jelszó elfelejtése
forgetPassword.message=Elfelejtette az elmentett jelszót?
forgetPassword.description=Eltávolítja a széf mentett jelszavát a rendszere kulcstartójából.
forgetPassword.description=Eltávolítja a tároló mentett jelszavát a rendszere kulcstartójából.
forgetPassword.confirmBtn=Jelszó elfelejtése
# Unlock
@@ -130,30 +143,37 @@ unlock.savePassword=Jelszó megjegyzése
unlock.unlockBtn=Feloldás
## Select
unlock.chooseMasterkey.message=Mesterkulcs fájl nem található
unlock.chooseMasterkey.description=Nem található a tároló kulcsfájlja a várt helyen. Kérjük válassza ki a kulcsfájlt manuálisan.
unlock.chooseMasterkey.description=Nem található kulcsfájl ehhez a titkosított tárolóhoz: "%s". Kérjük válassza ki a kulcsfájlt manuálisan.
unlock.chooseMasterkey.restoreInstead=Inkább mesterkulcs fájl helyreállítása
unlock.chooseMasterkey.filePickerTitle=Mesterkulcs fájl kiválasztása
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Mesterkulcs
## Success
unlock.success.message=Sikeres feloldás
unlock.success.description="%s" sikreresen feloldásra került! Mostmár hozzáférhet a virtuális trezorhoz.
unlock.success.description=Mostantól elérhető a csatolási pontján keresztül a következő tároló tartalma: "%s".
unlock.success.rememberChoice=Jegyezze meg a választást és ne mutassa többet
unlock.success.revealBtn=Széf megjelenítése
## Failure
unlock.error.customPath.message=Nem lehet csatolni a széfet az egyéni útvonalhoz
unlock.error.customPath.description.notSupported=Ha szeretné továbbra is az egyéni útvonalat használni, kérem, menjen a beállításokba és válasszon egy kötet típust, amely támogatja azt. Máskülönben, menjen a széf opciókhoz és válasszon egy támogatott csatoláspontot.
unlock.error.customPath.description.notExists=Az egyéni csatolás útvonal nem létezik. Hozza létre a helyi fájlrendszerében vagy változtassa meg a széf opciókban.
unlock.error.customPath.message=Nem lehet csatolni a tárolót az egyéni útvonalhoz
unlock.error.customPath.description.notSupported=Ha szeretné továbbra is az egyéni útvonalat használni, kérem, menjen a beállításokba és válasszon egy kötet típust, amely támogatja azt. Máskülönben, menjen a tároló beállításaihoz és válasszon egy támogatott csatoláspontot.
unlock.error.customPath.description.notExists=Az egyéni csatolás útvonal nem létezik. Hozza létre a helyi fájlrendszerében vagy változtassa meg a tároló beállításaiban.
unlock.error.customPath.description.inUse=A meghajtó betűjele vagy a csatolási útvonal: "%s" már foglalt.
unlock.error.customPath.description.hideawayNotDir=A feloldáshoz használt, "%3$s" nevű ideiglenes, rejtett fájlt nem lehet eltávolítani. Kérjük, ellenőrizze a fájlt, majd törölje manuálisan.
unlock.error.customPath.description.couldNotBeCleaned=A széfet nem lehetett a "%s" elérési útvonalra csatlakoztatni. Kérjük, próbálja meg újra, vagy válasszon másik elérési útvonalat.
unlock.error.customPath.description.couldNotBeCleaned=A tárolót nem lehetett a "%s" elérési útvonalra csatlakoztatni. Kérjük, próbálja meg újra, vagy válasszon másik elérési útvonalat.
unlock.error.customPath.description.notEmptyDir=A megadott "%s" elérési útvonal nem egy üres mappa. Kérjük, válasszon egy üres mappát, és próbálja meg újra.
unlock.error.customPath.description.generic=Egyéni csatolási útvonalat választott ehhez a széfhez, de használatakor ez a hibaüzenet érkezett: %2$s
unlock.error.restartRequired.message=Nem lehet feloldani a széfet
unlock.error.restartRequired.description=Módosítsa a kötet típusát a széf beállításaiban, vagy indítsa újra a Cryptomator-t.
unlock.error.customPath.description.generic=Egyéni csatolási útvonalat választott ehhez a tárolóhoz, de használatakor ez a hibaüzenet érkezett: %2$s
unlock.error.restartRequired.message=Nem lehet feloldani a titkosított tárolót
unlock.error.restartRequired.description=Módosítsa a kötet típusát a tároló beállításaiban, vagy indítsa újra a Cryptomator-t.
unlock.error.title=A(z) „%s” feloldása sikertelen
## Hub
hub.noKeychain.message=Nem lehet az eszközkulcshoz hozzáférni
hub.noKeychain.description=Hogy feloldja a Hub széfeket, egy eszközkulcs szükséges, mely egy kulcslánccal van biztosítva. A folytatáshoz engedélyezze a következőt: “%s” és válasszon egy kulcsláncot a beállításokban.
hub.noKeychain.description=Hogy feloldja a Hub-tárolókat, egy eszközkulcs szükséges, mely egy kulcslánccal van biztosítva. A folytatáshoz engedélyezze a következőt: “%s” és válasszon egy kulcsláncot a beállításokban.
hub.noKeychain.openBtn=Beállítások megnyitása
### Check Host Authenticity
hub.checkHostTrust.message.check=Konfiguráció ellenőrzése…
hub.checkHostTrust.message.ask=Megbízik ebben a gépben?
hub.checkHostTrust.message.ask.plural=Megbízik ezekben a gépben?
hub.checkHostTrust.trustBtn=Megbízható
hub.checkHostTrust.denyBtn=Elutasít
### Waiting
hub.auth.message=Várakozás a hitelesítésre…
hub.auth.description=Automatikusan átirányítjuk a bejelentkezési oldalra.
@@ -172,17 +192,22 @@ hub.register.legacy.occupiedMsg=Név már használatban van
hub.register.legacy.description=Ez az első Hub hozzáférés erről az eszközről. Kérem, regisztrálja.
### Registration Success
hub.registerSuccess.message=Az eszköz regisztrálva
hub.registerSuccess.description=Az eszköze sikeresen regisztrálva. Most már folytathatja a széf feloldását.
hub.registerSuccess.description=Az eszköze sikeresen regisztrálva. Most már folytathatja a titkosított tároló feloldását.
hub.registerSuccess.unlockBtn=Feloldás
hub.registerSuccess.legacy.description=A széfhez való hozzáféréshez az eszközének a széf tulajdonosától további engedélyt kell kapnia.
hub.registerSuccess.legacy.description=A titkosított tárolóhoz való hozzáféréshez az eszközének a tároló tulajdonosától további engedélyt kell kapnia.
### Registration Failed
hub.registerFailed.message=Az eszköz regisztrációja sikertelen
hub.registerFailed.description.generic=Hiba történt a regisztrációs folyamat során. További részletekért nézze meg az alkalmazás naplóját.
hub.registerFailed.description.deviceAlreadyExists=Ez az eszköz már egy másik felhasználóhoz van regisztrálva. Próbáljon meg felhasználói fiókot váltani, vagy használjon egy másik eszközt.
### Archived
hub.archived.message=Titkosított tároló archiválva
hub.archived.description=Ez a tároló archivált és már nem érhető el. Kérjük, vegye fel a kapcsolatot a tárhely tulajdonosával.
### Unauthorized
hub.unauthorized.message=Hozzáférés megtagadva
hub.unauthorized.description=Nincs hozzáférésed a széf megnyitásához. Vedd fel a kapcsolatot a széf tulajdonosával és kérj hozzáférést.
hub.unauthorized.description=Nincs hozzáférésed a titkosított tároló megnyitásához. Vedd fel a kapcsolatot a tároló tulajdonosával és kérj hozzáférést.
### Untrusted Host
hub.untrustedHost.message=A kiszolgáló nem megbízható
hub.untrustedHost.description=A Hubhoz való csatlakozás biztonsági okokból blokkolva lett. Ha úgy gondolja, hogy a Hub-szerver biztonságos, lépjen kapcsolatba a Hub rendszergazdájával, vagy próbálja meg újra.
### Requires Account Initialization
hub.requireAccountInit.message=Beavatkozás szükséges
hub.requireAccountInit.description.0=A folytatáshoz kérlek töltsd ki a szükséges lépéseket a te
@@ -199,49 +224,49 @@ lock.forced.description=A „%s” zárolását függőben lévő műveletek vag
lock.forced.retryBtn=Újra
lock.forced.forceBtn=Lezárás kényszerítése
## Failure
lock.fail.message=Zárolás sikertelen.
lock.fail.description=A "%s" tárolót nem lehetett zárolni. Győződjön meg arról, hogy a nem mentett munkát máshová menti, és a fontos olvasási/írási műveletek befejeződtek. A trezor bezárásához szakítsa meg a Cryptomator folyamatot.
lock.fail.message=Zárolás sikertelen
lock.fail.description=A "%s" tárolót nem lehetett zárolni. Győződjön meg arról, hogy a nem mentett munkát máshová menti, és a fontos olvasási/írási műveletek befejeződtek. A tároló bezárásához szakítsa meg a Cryptomator folyamatot.
# Migration
migration.title=Széf frissítése
migration.title=Titkosított tároló frissítése
## Start
migration.start.header=Széf frissítése
migration.start.text=Hogy megnyissa a "%s" nevű széfét a Cryptomator ezen új verziójában, a széfet frissíteni kell egy újabb formátumra. Mielőtt ezt megteszi, az alábbiakat érdemes figyelembe vennie:
migration.start.header=Titkosított tároló frissítése
migration.start.text=Hogy megnyissa a "%s" nevű titkosított tárolót a Cryptomator ezen új verziójában, a tárolót frissíteni kell egy újabb formátumra. Mielőtt ezt megteszi, az alábbiakat érdemes figyelembe vennie:
migration.start.remarkUndone=Ezt a módosítást nem lehet visszafordítani.
migration.start.remarkVersions=A Cryptomator régebbi verziói nem fogják tudni megnyitni a frissített széfet.
migration.start.remarkCanRun=Meg kell győződnie arról, hogy minden eszköz, amelyről eléri ezt a széfet képes futtatni a Cryptomator ezen verzióját.
migration.start.remarkSynced=Meg kell győződnie arról, hogy a széfe teljesen szinkronizálva van ezen és az összes többi eszközön a frissítés előtt.
migration.start.remarkVersions=A Cryptomator régebbi verziói nem fogják tudni megnyitni a frissített tárolót.
migration.start.remarkCanRun=Meg kell győződnie arról, hogy minden eszköz, amelyről eléri ezt a titkosított tárolót, képes futtatni a Cryptomator ezen verzióját.
migration.start.remarkSynced=Meg kell győződnie arról, hogy a tároló teljesen szinkronizálva van ezen és az összes többi eszközön a frissítés előtt.
migration.start.confirm=Elolvastam és megértettem a fenti információkat
## Run
migration.run.enterPassword=Írja be a jelszót a következőhöz Enter the password for "%s"
migration.run.startMigrationBtn=Széf frissítése
migration.run.startMigrationBtn=Tároló frissítése
migration.run.progressHint=Ez eltarthat egy darabig…
## Success
migration.success.nextStepsInstructions=A "%s" sikeresen migrálva. \nMost már feloldhatja a széfet.
migration.success.nextStepsInstructions=A "%s" sikeresen migrálva. \nMost már feloldhatja a titkosított tárolót.
migration.success.unlockNow=Azonnali feloldás
## Missing file system capabilities
migration.error.missingFileSystemCapabilities.title=Nem támogatott fájlrendszer
migration.error.missingFileSystemCapabilities.description=A migráció nem kezdődött el, mert a széf nem megfelelő fájlrendszeren található.
migration.error.missingFileSystemCapabilities.description=A migráció nem kezdődött el, mert a tároló nem megfelelő fájlrendszeren található.
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=A fájlrendszer nem támogatja a hosszú fájlneveket.
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=A fájlrendszer nem támogatja a hosszú útvonalakat.
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=A fájlrendszer nem teszi lehetővé az olvasást.
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=A fájlrendszer nem teszi lehetővé az írást.
## Impossible
migration.impossible.heading=A széf frissítése sikertelen
migration.impossible.reason=A széfet nem lehet automatikusan frissíteni, mert a tárolási helye vagy a hozzáférési pontja nem kompatibilis.
migration.impossible.moreInfo=A széf továbbra is megnyitható marad egy régebbi verzióval. A széf kézi frissítésével kapcsolatos utasításokért keresse fel a következő címet:
migration.impossible.heading=A titkosított tároló frissítése sikertelen
migration.impossible.reason=A tárolót nem lehet automatikusan frissíteni, mert a tárolási helye vagy a hozzáférési pontja nem kompatibilis.
migration.impossible.moreInfo=A tároló továbbra is megnyitható marad egy régebbi verzióval. A titkosított tároló kézi frissítésével kapcsolatos utasításokért keresse fel a következő címet
# Health Check
## Start
health.title="%s" állapotellenőrzése
health.intro.header=Állapotfelmérés
health.intro.text=Az állapotfelmérés olyan ellenőrzéscsomag, amely felderíti és esetlegesen kijavítja a trezor belső szerkezetében fellépő problémákat. Kérjük, ne feledje:
health.intro.text=Az állapotfelmérés olyan ellenőrzéscsomag, amely felderíti és esetlegesen kijavítja a titkosított tároló belső szerkezetében fellépő problémákat. Kérjük, ne feledje:
health.intro.remarkSync=Győződjön meg arról, hogy minden eszköz teljesen szinkronizálva van, ez megoldja a legtöbb problémát.
health.intro.remarkFix=Nem minden probléma javítható.
health.intro.remarkBackup=Ha az adatok sérültek, csak a biztonsági mentés segíthet.
health.intro.affirmation=Elolvastam és megértettem a fenti információkat
## Start Failure
health.fail.header=Hiba a Trezor konfiguráció betöltésekor
health.fail.header=Hiba a tároló konfigurációjának betöltésekor
health.fail.ioError=Hiba történt a konfigurációs fájl elérése és olvasása közben.
health.fail.parseError=Hiba történt a tároló konfigurációjának elemzése közben.
health.fail.moreInfo=További infó
@@ -260,6 +285,8 @@ health.check.detail.checkFinishedAndFound=Az ellenőrzés véget ért. Kérem el
health.check.detail.checkFailed=Az ellenőrzés egy hiba miatt megszakadt.
health.check.detail.checkCancelled=Az ellenőrzés meg lett szakítva.
health.check.detail.listFilters.label=Szűrő
health.check.detail.filterSeverity=Szűrés súlyosság szerint
health.check.detail.filterFixState=Szűrés állapot szerint
health.check.detail.fixAllSpecificBtn=Az összes ilyen javítása
health.check.exportBtn=Jelentés exportálása
## Result view
@@ -268,10 +295,10 @@ health.result.severityFilter.good=Rendben
health.result.severityFilter.info=Infó
health.result.severityFilter.warn=Figyelmeztetés
health.result.severityFilter.crit=Kritikus
health.result.severityTip.good=Súlyosság: Jó\nNormális séf struktúra.
health.result.severityTip.info=Súlyosság: Info\nA széf struktúrája ép, javítás ajánlott.
health.result.severityTip.warn=Súlyosság: Figyelmeztetés\nA széf struktúrája sérült, javítás erősen ajánlott.
health.result.severityTip.crit=Súlyosság: Kritikus\nA széf struktúrája sérült, adatvesztés áll fönt.
health.result.severityTip.good=Súlyosság: Jó\nNormális tároló struktúra.
health.result.severityTip.info=Súlyosság: Infó\nA tároló struktúrája ép, javítás ajánlott.
health.result.severityTip.warn=Súlyosság: Figyelmeztetés\nA tároló struktúrája sérült, javítás erősen ajánlott.
health.result.severityTip.crit=Súlyosság: Kritikus\nA tároló struktúrája sérült, adatvesztés veszélye áll fenn.
health.result.fixStateFilter.all=Javítás státusz - Mind
health.result.fixStateFilter.fixable=Javítható
health.result.fixStateFilter.notFixable=Nem javítható
@@ -288,12 +315,13 @@ preferences.title=Beállítások
## General
preferences.general=Általános
preferences.general.startHidden=Az ablak elrejtése a Cryptomator indítása után
preferences.general.autoCloseVaults=Széfek lezárása megerősítés nélkül az alkalmazás bezárásakor
preferences.general.autoCloseVaults=Titkosított tárolók lezárása megerősítés nélkül az alkalmazás bezárásakor
preferences.general.debugLogging=Hibakeresési naplózás engedélyezése
preferences.general.debugDirectory=Naplófájlok megjelenítése
preferences.general.autoStart=Cryptomator indítása a rendszerrel együtt
preferences.general.keychainBackend=Itt tárolja a jelszavakat
preferences.general.quickAccessService=Adja a feloldott széfeket a gyors elérési területhez
preferences.general.quickAccessService=A feloldott tárolókat a Gyors elérési területhez adja
preferences.general.resetTrustedHosts=A megbízható kiszolgálók visszaállítása
## Interface
preferences.interface=Kezelőfelület
preferences.interface.theme=Megjelenés
@@ -307,7 +335,7 @@ preferences.interface.interfaceOrientation=Felhasználói felület tájolása
preferences.interface.interfaceOrientation.ltr=Balról jobbra
preferences.interface.interfaceOrientation.rtl=Jobbról balra
preferences.interface.showTrayIcon=Tálca ikon megjelenítése (újraindítás szükséges)
preferences.interface.compactMode=Kompakt széflista engedélyezése
preferences.interface.compactMode=Kompakt tárolólista engedélyezése
## Volume
preferences.volume=Virtuális meghajtó
preferences.volume.type=Alapértelmezett kötet típus
@@ -332,8 +360,13 @@ preferences.updates.lastUpdateCheck.never=soha
preferences.updates.lastUpdateCheck.recently=mostanában
preferences.updates.lastUpdateCheck.daysAgo=%s nappal ezelőtt
preferences.updates.lastUpdateCheck.hoursAgo=%s órával ezelőtt
preferences.updates.prohibitedDueToUnlockedVaults.1=Kérem
preferences.updates.prohibitedDueToUnlockedVaults.2=zárolja tárolóit
preferences.updates.prohibitedDueToUnlockedVaults.3=a frissítés telepítéséhez.
preferences.updates.checkFailed=A frissítések keresése sikertelen. Kérem, ellenőrizze az internetkapcsolatát, vagy próbálja meg később újra.
preferences.updates.updateFailed=A frissítés nem sikerült. Kérjük, telepítse a frissítést manuálisan.
preferences.updates.upToDate=A Cryptomator naprakész.
preferences.updates.visitDownloadPage=Látogasson el a letöltési oldalra
## Contribution
preferences.contribute=Támogasson bennünket
@@ -344,15 +377,17 @@ preferences.contribute.promptText=Ide illessze be támogatói igazolása kódjá
preferences.contribute.thankYou=Köszönjük, hogy támogatja a Cryptomator nyílt forráskódú fejlesztését!
preferences.contribute.donate=Támogatás
preferences.contribute.sponsor=Szponzor
preferences.contribute.removeCert.tooltip=Tanúsítvány eltávolítása
### Remove License Key Dialog
removeCert.title=Tanúsítvány eltávolítása
removeCert.message=Eltávolítja a támogatói tanúsítványt?
removeCert.description=A Cryptomator alapvető funkcióit ez nem érinti. Sem a széfekhez való hozzáférés nem korlátozott, sem a biztonsági szint nem csökken.
removeCert.description=A Cryptomator alapvető funkcióit ez nem érinti. Sem a titkosított tárolókhoz való hozzáférés nem korlátozott, sem a biztonsági szint nem csökken.
#<-- Add entries for donations and code/translation/documentation contribution -->
## About
preferences.about=Rólunk
preferences.about.thirdPartyLicenses=Harmadik felek által kiadott licencek
# Vault Statistics
stats.title=Statisztika ehhez %s
@@ -392,32 +427,40 @@ stats.access.total=Összes hozzáférés: %d
# Main Window
## Vault List
main.vaultlist=Széfek
main.vaultlist.emptyList.onboardingInstruction=Kattintson ide egy széf hozzáadásához
main.vaultlist.listEntry=Titkosított tároló %s (%s)
main.vaultlist.emptyList.onboardingInstruction=Kattintson ide egy titkosított tároló hozzáadásához
main.vaultlist.contextMenu.remove=Eltávolítás…
main.vaultlist.contextMenu.lock=Zárolás
main.vaultlist.contextMenu.unlock=Feloldás…
main.vaultlist.contextMenu.unlockNow=Azonnali feloldás
main.vaultlist.contextMenu.vaultoptions=Széf beállítások
main.vaultlist.contextMenu.reveal=Széf megjelenítése
main.vaultlist.contextMenu.vaultoptions=Titkosított tároló beállításai
main.vaultlist.contextMenu.reveal=Tároló megjelenítése
main.vaultlist.contextMenu.share=Megosztás…
main.vaultlist.addVaultBtn.menuItemNew=Új titkosított tároló létrehozása…
main.vaultlist.addVaultBtn.menuItemExisting=Titkosított tároló megnyitása…
main.vaultlist.addVaultBtn.menuItemRecover=Titkosított tároló visszaállítása…
main.vaultlist.addVaultButton.tooltip=Széf hozzáadása
main.vaultlist.showEventsButton.tooltip=Eseménynapló megnyitása
main.vaultlist.showPreferencesButton.tooltip=Beállítások megnyitása
##Notification
main.notification.updateAvailable=Frissítés elérhető.
main.notification.support=Cryptomator támogatása.
main.notification.closeButton.tooltip=Az információs sáv bezárása
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Köszönjük, hogy a Cryptomator programot választotta a fájlai védelmére. Ha segítségre van szüksége, akkor olvassa el a kezdő útmutatónk lépéseit:
main.vaultDetail.welcomeOnboarding=Köszönjük, hogy a Cryptomator programot választotta a fájljai védelmére. Ha segítségre van szüksége, akkor olvassa el a kezdő útmutatónk lépéseit:
main.vaultDetail.storageLocation=Titkosított tároló helye
### Locked
main.vaultDetail.lockedStatus=ZÁROLVA
main.vaultDetail.unlockBtn=Feloldás…
main.vaultDetail.unlockNowBtn=Azonnali feloldás
main.vaultDetail.optionsBtn=Széf beállítások
main.vaultDetail.optionsBtn=Titkosított tároló beállításai
main.vaultDetail.passwordSavedInKeychain=Jelszó mentve
main.vaultDetail.share=Megosztás…
### Unlocked
main.vaultDetail.unlockedStatus=FELOLDVA
main.vaultDetail.accessLocation=A széf tartalma itt érhető el:
main.vaultDetail.revealBtn=Széf megjelenítése
main.vaultDetail.accessLocation=A tároló tartalma itt érhető el:
main.vaultDetail.revealBtn=Tároló megjelenítése
main.vaultDetail.copyUri=URI másolása
main.vaultDetail.lockBtn=Zárolás
main.vaultDetail.bytesPerSecondRead=Olvasás:
@@ -425,21 +468,26 @@ main.vaultDetail.bytesPerSecondWritten=Írás:
main.vaultDetail.throughput.idle=tétlen
main.vaultDetail.throughput.kbps=%.1f KiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Széf statisztika
main.vaultDetail.stats=Tároló statisztika
main.vaultDetail.locateEncryptedFileBtn=Titkosított fájl megkeresése
main.vaultDetail.locateEncryptedFileBtn.tooltip=Válasszon a széfből egy fájlt a titkosított megfelelőjének megkereséséhez
main.vaultDetail.locateEncryptedFileBtn.tooltip=Válasszon a tárolóból egy fájlt a titkosított megfelelőjének megkereséséhez
main.vaultDetail.encryptedPathsCopied=Az útvonal a vágólapra került!
main.vaultDetail.locateEncrypted.filePickerTitle=Fájl kiválasztása a tárolóból
main.vaultDetail.decryptName.buttonLabel=Fájlnevek visszafejtése
main.vaultDetail.decryptName.tooltip=Válasszon ki egy fájlt a titkosított tárolóból, hogy visszafejtse a nevét
### Missing
main.vaultDetail.missing.info=A Cryptomator nem talált széfet ezen az útvonalon.
main.vaultDetail.missing.info=A Cryptomator nem talált titkosított tárolót ezen az útvonalon.
main.vaultDetail.missing.recheck=Ellenőrizze újra
main.vaultDetail.missing.remove=A széf eltávolítása a listából…
main.vaultDetail.missing.changeLocation=A széf helyének megváltoztatása…
main.vaultDetail.missing.remove=A tároló eltávolítása a listából…
main.vaultDetail.missing.changeLocation=A titkosított tároló helyének megváltoztatása…
### Missing Vault Config
main.vaultDetail.missingVaultConfig.info=A tároló konfigurációja hiányzik.
main.vaultDetail.missingVaultConfig.restore=Tároló konfiguráció helyreállítása
### Needs Migration
main.vaultDetail.migrateButton=Széf frissítése
main.vaultDetail.migratePrompt=A széfet új formátumra kell frissíteni, mielőtt hozzáférhet
main.vaultDetail.migrateButton=Tároló frissítése
main.vaultDetail.migratePrompt=A titkosított tárolót új formátumra kell frissíteni, mielőtt hozzáférhet
### Error
main.vaultDetail.error.info=Hiba történt a széf merevlemezről való betöltése során.
main.vaultDetail.error.info=Hiba történt a titkosított tároló merevlemezről való betöltése során.
main.vaultDetail.error.reload=Újratöltés
main.vaultDetail.error.windowTitle=Hiba az adatok betöltése közben
@@ -448,7 +496,7 @@ wrongFileAlert.title=Hogyan lehet fájlokat titkosítani
wrongFileAlert.message=Próbálta ezeket a fájlokat titkosítani?
wrongFileAlert.description=Erre a célra a Cryptomator egy kötetet biztosít a rendszer fájlkezelőjében.
wrongFileAlert.instruction.0=Hogy titkosítsa a fájlokat kövesse a következő lépéseket:
wrongFileAlert.instruction.1=1. Oldja fel a széfet.
wrongFileAlert.instruction.1=1. Oldja fel a titkosított tárolót.
wrongFileAlert.instruction.2=2. Kattintson a "Megjelenítés" gombra, hogy megnyissa a kötetet a fájlkezelőjében.
wrongFileAlert.instruction.3=3. Adjon hozzá fájlokat a kötethez.
wrongFileAlert.link=További segítségért látogasson el ide
@@ -456,10 +504,11 @@ wrongFileAlert.link=További segítségért látogasson el ide
# Vault Options
## General
vaultOptions.general=Általános
vaultOptions.general.vaultName=A széf neve
vaultOptions.general.vaultName=A tároló neve
vaultOptions.general.autoLock.lockAfterTimePart1=Lezárás, ha tétlen
vaultOptions.general.autoLock.lockAfterTimePart2=perc
vaultOptions.general.unlockAfterStartup=A széf feloldása a Cryptomator indításakor
vaultOptions.general.autoLock.accessibleText=Zárolási időkorlát percben
vaultOptions.general.unlockAfterStartup=A titkosított tároló feloldása a Cryptomator indításakor
vaultOptions.general.actionAfterUnlock=Sikeres feloldás után
vaultOptions.general.actionAfterUnlock.ignore=Ne tegyen semmit
vaultOptions.general.actionAfterUnlock.reveal=Jelenítse meg a kötetet
@@ -486,19 +535,21 @@ vaultOptions.mount.volume.type=Kötet típus
vaultOptions.masterkey=Jelszó
vaultOptions.masterkey.changePasswordBtn=Jelszó megváltoztatása
vaultOptions.masterkey.forgetSavedPasswordBtn=Mentett jelszó törlése
vaultOptions.masterkey.recoveryKeyExplanation=A helyreállítási kulcs az egyetlen módja annak, hogy visszaállítsa a széfhez való hozzáférést, ha elveíti a jelszavát.
vaultOptions.masterkey.recoveryKeyExplanation=A helyreállítási kulcs az egyetlen módja annak, hogy visszaállítsa a tárolóhoz való hozzáférést, ha elveszíti a jelszavát.
vaultOptions.masterkey.showRecoveryKeyBtn=Visszaállítási kulcs megjelenítése
vaultOptions.masterkey.recoverPasswordBtn=Jelszó visszaállítása
vaultOptions.masterkey.missingMasterkeyFile=Ezek az beállítások csak akkor érhetők el, ha a masterkey fájl megtalálható a tároló könyvtárában.
## Hub
vaultOptions.hub=Helyreállítás
vaultOptions.hub.convertInfo=Ezen visszaállítási kulcs segítségével átváltoztathatja ezt a Hub széfet egy jelszó-alapú széffé vészhelyzet esetén.
vaultOptions.hub.convertBtn=Jelszó-alapú széffé alakítás
vaultOptions.hub.convertInfo=Ezen visszaállítási kulcs segítségével átváltoztathatja ezt a Hub-tárolót egy jelszó-alapú titkosított tárolóvá vészhelyzet esetén.
vaultOptions.hub.convertBtn=Jelszó-alapú tárolóvá alakítás
# Recovery Key
## Display Recovery Key
recoveryKey.display.title=Visszaállítási kulcs mutatása
recoveryKey.create.message=Jelszó szükséges
recoveryKey.create.description=Írja be a jelszavát a "%s" visszaállítási kulcsának megjelenítéséhez:
recoveryKey.recover.description=Adja meg a jelszót a "%s" tárolóhoz, hogy helyreállítsa a tároló konfigurációját.
recoveryKey.display.description=A következő helyreállítási kulcs használható a "%s" hozzáférésének visszaállítására:
recoveryKey.display.StorageHints=Tartsa nagyon biztonságos helyen. pl.:\n •Tárolja egy jelszókezelővel\n •Mentse el egy USB meghajtóra\n •Nyomtassa egy papírra
## Reset Password
@@ -506,41 +557,71 @@ recoveryKey.display.StorageHints=Tartsa nagyon biztonságos helyen. pl.:\n •T
recoveryKey.recover.title=Jelszó visszaállítása
recoveryKey.recover.prompt=Írja be a visszaállítási kulcsot a következőhöz "%s":
recoveryKey.recover.correctKey=Ez a visszaállítási kulcs érvényes
recoveryKey.recover.wrongKey=Ez a visszaállítási kulcs egy másik széfhez tartozik
recoveryKey.recover.wrongKey=Ez a visszaállítási kulcs egy másik titkosított tárolóhóz tartozik
recoveryKey.recover.invalidKey=Ez a visszaállítási kulcs nem érvényes
recoveryKey.printout.heading=Cryptomator visszaállítási kulcs\n"%s"\n
### Reset Password
recoveryKey.recover.resetBtn=Visszaállítás
recoveryKey.recover.recoverBtn=Helyreállítás
### Recovery Key Password Reset Success
recoveryKey.recover.resetSuccess.message=A jelszó alaphelyzetbe állítása sikeresen megtörtént
recoveryKey.recover.resetSuccess.description=Feloldhatja a széfet az új jelszóval.
recoveryKey.recover.resetSuccess.description=Feloldhatja a titkosított tárolót az új jelszóval.
### Recovery Key Vault Config Reset Success
recoveryKey.recover.resetVaultConfigSuccess.message=Tároló konfiguráció helyreállítva
recoveryKey.recover.resetMasterkeyFileSuccess.message=A mesterkulcsfájl helyreállítva
recoveryKey.recover.resetMasterkeyFileSuccess.description=Mostantól a jelszavával oldhatja fel a titkosított tárolót.
# Recover Vault Config File and/or Masterkey
##Add Existing Vault without recovery - Dialog
recover.existing.title=Titkosított tároló hozzáadva
recover.existing.message=A tároló sikeresen hozzáadva
recover.existing.description=A "%s" titkosított tároló hozzáadásra került a tárolók listájára. Helyreállítási műveletre nem volt szükség.
##Vault Already Exists - Dialog
recover.alreadyExists.title=A titkosított tároló már létezik
recover.alreadyExists.message=Ez a tároló már hozzá lett adva
recover.alreadyExists.description="%s" nevű titkosított tároló már hozzá volt adva a tárolók listájához, ezért nem került újból hozzáadásra.
##Invalid Selection - Dialog
recover.invalidSelection.title=Érvénytelen kiválasztás
recover.invalidSelection.message=A kiválasztott elem nem titkosított tároló
recover.invalidSelection.description=A kiválasztott mappának érvényes Cryptomator tárolónak kell lennie.
## Contact Hub Vault Owner - Dialog
contactHubVaultOwner.title=Hub széf
contactHubVaultOwner.message=Ezt a titkosító tárolót a Cryptomator Hub segítségével hozták létre
contactHubVaultOwner.description=Kérjük, vegye fel a kapcsolatot a tároló tulajdonosával a hiányzó fájl helyreállítása érdekében. A tároló-sablont a Cryptomator Hubról töltheti le.
##Dialog Title
recover.recoverVaultConfig.title=Titkosított tároló konfiguráció helyreállítása
recover.recoverMasterkey.title=Mesterkulcsfájl helyreállítása
## OnBoarding
recover.onBoarding.chooseMethod=Válasszon helyreállítási módszer:
recover.onBoarding.useRecoveryKey=Helyreállítási kulcs használata
recover.onBoarding.usePassword=Jelszó használata
recover.onBoarding.intro=Ellenőrizze a következőket:
recover.onBoarding.pleaseConfirm=Továbblépés előtt ellenőrizze a következőket:
recover.onBoarding.otherwisePleaseConfirm=Egyébként erősítse meg:
recover.onBoarding.allMissing.intro=Ha ezt a titkosított tárolót a Cryptomator Hub kezeli, akkor a könyvtár tulajdonosának kell helyreállítania az Ön számára.
recover.onBoarding.intro.ensure=Minden fájl teljes mértékben szinkronizálva van.
recover.onBoarding.affirmation=Elolvastam és megértettem ezeket a követelményeket
###Vault Config Missing
recover.onBoarding.intro.recoveryKey=Birtokában van a tároló helyreállítási kulcsa és tudja milyen haladó beállításokat használtak.
recover.onBoarding.intro.password=Birtokában van a tároló jelszava és tudja milyen haladó beállításokat használtak.
###Masterkey Missing
recover.onBoarding.intro.masterkey.recoveryKey=Birtokában van a tároló helyreállítási kulcsa.
## Expert Settings
recover.expertSettings.shorteningThreshold.title=Ennek az értéknek meg kell egyeznie a helyreállítás előtt használt értékkel, hogy biztosítva legyen a korábban titkosított adatokkal való kompatibilitás.
# Convert Vault
convertVault.title=Széf átalakítása
convertVault.title=Titkosított tároló átalakítása
convertVault.convert.convertBtn.before=Átalakítás
convertVault.convert.convertBtn.processing=Átalakítás…
convertVault.success.message=Sikeres átalakítás
convertVault.hubToPassword.success.description=Feloldhatja a széfet a kiválasztott jelszóval Hub hozzáférés nélkül.
convertVault.hubToPassword.success.description=Feloldhatja a titkosított tárolót a kiválasztott jelszóval Hub hozzáférés nélkül.
# New Password
newPassword.promptText=Adjon meg egy új jelszót
@@ -556,13 +637,13 @@ passwordStrength.messageLabel.4=Nagyon erős
# Quit
quit.title=Alkalmazás bezárása
quit.message=Vannak feloldott széfek
quit.description=Kérem, erősítse meg a kilépési szándékát. A Cryptomator lezárja az összes feloldott széfet az adatvesztés elkerülése érdekében.
quit.message=Vannak feloldott titkosított tárolók
quit.description=Kérem, erősítse meg a kilépési szándékát. A Cryptomator lezárja az összes feloldott titkosított tárolót az adatvesztés elkerülése érdekében.
quit.lockAndQuitBtn=Zárolás és kilépés
# Forced Quit
quit.forced.message=Egyes széfeket nem lehetett lezárni
quit.forced.description=A széfek zárolását függőbben lévő műveletek vagy megnyitott fájlok blokkolták. Kényszerítheti a maradék széfek zárolását, de az I/O megszakítása nem mentett adatok elvesztéséhez vezethet.
quit.forced.message=Egyes tárolókat nem lehetett lezárni
quit.forced.description=A titkosított tárolók zárolását függőbben lévő műveletek vagy megnyitott fájlok blokkolták. Kényszerítheti a maradék tárolók zárolását, de az I/O megszakítása nem mentett adatok elvesztéséhez vezethet.
quit.forced.forceAndQuitBtn=Kényszerítés és Kilépés
# Update Reminder
@@ -580,37 +661,76 @@ dokanySupportEnd.description=A Cryptomator nem támogatja tovább a Dokany köte
dokanySupportEnd.preferencesBtn=Beállítások megnyitása
#Retry If Readonly
retryIfReadonly.title=Korlátozott Széf Hozzáférés
retryIfReadonly.message=Nincs írási jogod a széf könyvtárához
retryIfReadonly.description=A Cryptomator nem tud a széf könyvtárába írni. Átrakhatod a széfet írásvédettre és megpróbálhatod újra. Ezt az opciót kikapcsolhatod a széf beállításaiban.
retryIfReadonly.title=Korlátozott tároló hozzáférés
retryIfReadonly.message=Nincs írási jogod a tároló könyvtárához
retryIfReadonly.description=A Cryptomator nem tud a tároló könyvtárába írni. Átrakhatod a tárolót írásvédettre és megpróbálhatod újra. Ezt az opciót kikapcsolhatod a titkosított tároló beállításaiban.
retryIfReadonly.retry=Változtatás és Újrapróbálás
# Share Vault
shareVault.title=Széf megosztása
shareVault.message=Szeretné megosztani a széfét másokkal?
shareVault.description=Mindig legyen óvatos, amikor másokkal osztja meg a széfét. Röviden, kövesse az alábbi lépéseket:
shareVault.instruction.1=Ossza meg a titkosított széf mappájának hozzáférését felhőalapú tárolón keresztül.
shareVault.instruction.2=2. Ossza meg a széf jelszavát biztonságos módon.
shareVault.title=Titkosított tároló megosztása
shareVault.message=Szeretné megosztani a titkosított tárolóját másokkal?
shareVault.description=Mindig legyen óvatos, amikor másokkal osztja meg a tárolóit. Röviden, kövesse az alábbi lépéseket:
shareVault.instruction.1=1. Ossza meg a titkosított tároló mappájának hozzáférését felhőalapú tárolón keresztül.
shareVault.instruction.2=2. Ossza meg a titkosított tároló jelszavát biztonságos módon.
shareVault.remarkBestPractices=További információkért tekintse meg a legjobb gyakorlatokra vonatkozó javaslatokat a dokumentációnkban.
shareVault.docsTooltip=Nyissa meg a dokumentációt, hogy többet megtudjon a széfek megosztásáról.
shareVault.docsTooltip=Nyissa meg a dokumentációt, hogy többet megtudjon a titkosított tárolók megosztásáról.
shareVault.hubAd.description=A biztonságos mód csapatokban való munkavégzéshez
shareVault.hubAd.keyManagement=Nullaismeretű (Zero-knowledge) kulcskezelés
shareVault.hubAd.keyManagement=• Zero-knowledge kulcskezelés
shareVault.hubAd.authentication=• Erős hitelesítés
shareVault.hubAd.encryption=• Végponttól végpontig terjedő titkosítás
shareVault.visitHub=Látogassa meg a Cryptomator Hubot
shareVault.hub.message=Hogyan osszon meg egy Hub széfet
shareVault.hub.description=Ahhoz, hogy megossza a széf tartalmát egy másik csapattaggal, két lépést kell végrehajtania:
shareVault.hub.message=Hogyan osszon meg egy Hub-tárolót
shareVault.hub.description=Ahhoz, hogy megossza a tároló tartalmát egy másik csapattaggal, két lépést kell végrehajtania:
shareVault.hub.instruction.1=Ossza meg a titkosított széf mappájának hozzáférését felhőalapú tárolón keresztül.
shareVault.hub.instruction.2=2. Adjon hozzáférést a csapattagnak a Cryptomator Hubban.
shareVault.hub.openHub=Nyissa meg a Cryptomator Hubot
# Decrypt File Names
decryptNames.title=Fájlnevek visszafejtése
decryptNames.filePicker.title=Titkosított fájl kiválasztása
decryptNames.filePicker.extensionDescription=Cryptomator titkosított fájl
decryptNames.copyTable.tooltip=Táblázat másolása
decryptNames.clearTable.tooltip=Táblázat törlése
decryptNames.column.encrypted=Titkosított
decryptNames.column.decrypted=Visszafejtett
decryptNames.copyHint=A cella tartalmának másolása a következővel: %s
decryptNames.dropZone.message=Húzza ide a fájlokat, vagy kattintson a kiválasztáshoz
decryptNames.dropZone.error.vaultInternalFiles=A titkosított tároló belső fájljai nem visszafejthető névvel lettek kiválasztva
decryptNames.dropZone.error.foreignFiles=A kiválasztott fájlok nem a "%s" titkosított tárolóhoz tartoznak
decryptNames.dropZone.error.noDirIdBackup=A kiválasztott könyvtár nem tartalmaz dird.c9r fájlt
decryptNames.dropZone.error.generic=A fájlnevek visszafejtése nem sikerült
# Event View
eventView.title=Események
eventView.filter.allVaults=Mind
eventView.clearListButton.tooltip=Lista törlése
eventView.filterVaults=Szűrés tároló szerint
eventView.cell.actionsButton.tooltip=Eseményműveletek
## event list entries
eventView.entry.vaultLocked.description="%s" megnyitása a részletekért
eventView.entry.conflictResolved.message=Megoldott ütközések
eventView.entry.conflictResolved.showDecrypted=Titkosított fájlok megjelenítése
eventView.entry.conflict.message=Ütközés feloldása sikertelen
eventView.entry.conflict.showDecrypted=A visszafejtett, eredeti fájl megjelenítése
eventView.entry.conflict.showEncrypted=Az ütköző, titkosított fájl megjelenítése
eventView.entry.decryptionFailed.message=A visszafejtés sikertelen
eventView.entry.decryptionFailed.showEncrypted=Titkosított fájl megjelenítése
eventView.entry.brokenDirFile.message=Törött könyvtárhivatkozás
eventView.entry.brokenDirFile.showEncrypted=Törött, titkosított hivatkozás megjelenítése
eventView.entry.brokenFileNode.message=Meghibásodott fájlrendszer-csomópont
eventView.entry.brokenFileNode.showEncrypted=Meghibásodott, titkosított csomópont megjelenítése
eventView.entry.brokenFileNode.copyDecrypted=A visszafejtett elérési út másolása
eventView.entry.inUse.message=A fájl használatban van
eventView.entry.inUse.showDecrypted=Titkosított fájlok megjelenítése
eventView.entry.inUse.showEncrypted=Titkosított fájl megjelenítése
eventView.entry.inUse.copyUserAndDevice=A zároló felhasználó és eszköznév másolása
eventView.entry.inUse.ignoreLock=Használati állapot figyelmen kívül hagyása
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
notification.inUse.message=A fájlt egy másik eszközön használják
notification.inUse.description=A fájlt %s használja ezen a rendszeren: %s. Kérje meg, hogy zárja be a fájlt, és várja meg a szinkronizálás befejezését. Az állapot figyelmen kívül hagyásával most is megnyithatja, de ez ütközéseket okozhat, vagy felülírhatja az újabb módosításokat.
notification.inUse.action=Használati állapot figyelmen kívül hagyása
@@ -154,6 +154,8 @@ unlock.error.title=Gagal membuka kunci "%s"
hub.noKeychain.message=Tidak dapat mengakses perangkat kunci
hub.noKeychain.description=Untuk membuka kunci Hub vault, diperlukan perangkat kunci, yang diamankan menggunakan keychain. Untuk melanjutkan, aktifkan “%s” dan pilih keychain di preferensi.
hub.noKeychain.openBtn=Buka Preferensi
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Percayai
### Waiting
hub.auth.message=Menunggu otentikasi…
hub.auth.description=Anda secara otomatis akan diarahkan ke halaman login.
@@ -183,6 +185,7 @@ hub.registerFailed.description.deviceAlreadyExists=Perangkat ini sudah terdaftar
### Unauthorized
hub.unauthorized.message=Akses ditolak
hub.unauthorized.description=Anda tidak punya otorisasi untuk membuka brankas ini. Hubungi pemilik brankas untuk meminta akses.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Tindakan diperlukan
hub.requireAccountInit.description.0=Untuk melanjutkan, silakan lengkapi langkah-langkah yang diperlukan dalam
@@ -614,4 +617,4 @@ eventView.filter.allVaults=Semua
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+18 -1
View File
@@ -109,6 +109,13 @@ addvaultwizard.existing.restore=Ripristina…
addvaultwizard.existing.chooseBtn=Scegli…
addvaultwizard.existing.filePickerTitle=Seleziona file cassaforte
addvaultwizard.existing.filePickerMimeDesc=Cassaforte di Cryptomator
addvaultwizard.existing.notAVault.title=Non è una cassaforte
addvaultwizard.existing.notAVault.message=La cartella selezionata non è una cassaforte Cryptomator
addvaultwizard.existing.notAVault.description.missingDataDir=Manca la necessaria sottodirectory "d" all'interno di "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=La voce "d" all'interno di "%s" non è una directory.
addvaultwizard.existing.notAVault.description.missingVaultConfig=Manca il file necessario "vault.cryptomator" all'interno di "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=Il file "vault.cryptomator" che si trova dentro "%s" non può essere letto a causa di diritti di accesso insufficienti.
addvaultwizard.existing.notAVault.description.unsupportedStructure=La struttura della directory di "%s" non è supportata.
## Success
addvaultwizard.success.nextStepsInstructions=Cassaforte "%s" aggiunta.\nDevi sbloccare questa cassaforte per accedere o aggiungere contenuti. Altrimenti, puoi sbloccarla in qualsiasi momento successivo.
addvaultwizard.success.unlockNow=Sblocca Ora
@@ -161,6 +168,12 @@ unlock.error.title=Sblocco "%s" non riuscito
hub.noKeychain.message=Impossibile accedere alla chiave del dispositivo
hub.noKeychain.description=Per sbloccare le casseforti Hub, è necessaria una chiave del dispositivo, che è protetta tramite un portachiavi. Per procedere, abilita "%s" e seleziona un portachiavi nelle preferenze.
hub.noKeychain.openBtn=Apri Preferenze
### Check Host Authenticity
hub.checkHostTrust.message.check=Controllo Configurazione…
hub.checkHostTrust.message.ask=Ti fidi di questo host?
hub.checkHostTrust.message.ask.plural=Ti fidi di questi host?
hub.checkHostTrust.trustBtn=Fidati
hub.checkHostTrust.denyBtn=Rifiuta
### Waiting
hub.auth.message=In attesa di autenticazione…
hub.auth.description=Dovresti essere reindirizzato automaticamente alla pagina di login.
@@ -192,6 +205,9 @@ hub.archived.description=Questa cassaforte è stata archiviata e non è più acc
### Unauthorized
hub.unauthorized.message=Accesso negato
hub.unauthorized.description=Non sei autorizzato ad aprire questa cassaforte. Chiedi l'accesso al proprietario.
### Untrusted Host
hub.untrustedHost.message=Host non affidabile
hub.untrustedHost.description=La connessione all'Hub è stata bloccata per la tua sicurezza. Se ritieni che l'host Hub sia sicuro, contatta l'amministratore dell'Hub o riprova.
### Requires Account Initialization
hub.requireAccountInit.message=Azione richiesta
hub.requireAccountInit.description.0=Per procedere, completa i passaggi richiesti nel tuo
@@ -305,6 +321,7 @@ preferences.general.debugDirectory=Rivela i file di registro
preferences.general.autoStart=Avvia Cryptomator all'avvio del sistema
preferences.general.keychainBackend=Memorizza le password con
preferences.general.quickAccessService=Aggiungi cassaforte sbloccata all'area di accesso rapido
preferences.general.resetTrustedHosts=Azzera gli host affidabili
## Interface
preferences.interface=Interfaccia
preferences.interface.theme=Aspetto
@@ -716,4 +733,4 @@ eventView.entry.inUse.ignoreLock=Ignora lo stato di utilizzo
## FileIsInUse Notification
notification.inUse.message=Il file è in uso su un altro dispositivo
notification.inUse.description=Il file è aperto da %s su %s. Chiedigli di chiudere il file e permettere che la sincronizzazione termini. È possibile ignorare lo stato ed aprirlo ora, ma questo può causare conflitti o la sovrascrittura delle modifiche più recenti.
notification.inUse.action=Ignora lo Stato di Utilizzo
notification.inUse.action=Ignora lo Stato di Utilizzo
@@ -154,6 +154,8 @@ unlock.error.title=ロック解除 "%s" に失敗しました。
hub.noKeychain.message=デバイス キーにアクセスできません
hub.noKeychain.description=ハブ金庫を解錠するには、キーチェーンが保護するデバイス キーが必要です。続行するには、"%s" を有効にし環境設定からキーチェーンを選択します。
hub.noKeychain.openBtn=環境設定を開く
### Check Host Authenticity
hub.checkHostTrust.trustBtn=信頼する
### Waiting
hub.auth.message=認証を待機中…
hub.auth.description=ログイン ページに自動的にリダイレクトされます。
@@ -183,6 +185,7 @@ hub.registerFailed.description.deviceAlreadyExists=このデバイスは既に
### Unauthorized
hub.unauthorized.message=アクセスが拒否されました
hub.unauthorized.description=この金庫を開く権限がありません。金庫の所有者からアクセス許可を貰って下さい。
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=アクションが必要です
hub.requireAccountInit.description.0=続行するには以下のサイトで必要な手順を完了してください
@@ -632,4 +635,4 @@ eventView.entry.inUse.copyUserAndDevice=ロックしているユーザーとデ
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+21 -4
View File
@@ -109,6 +109,13 @@ addvaultwizard.existing.restore=복구…
addvaultwizard.existing.chooseBtn=선택…
addvaultwizard.existing.filePickerTitle=Vault 파일 선택
addvaultwizard.existing.filePickerMimeDesc=Cryptomator Vault
addvaultwizard.existing.notAVault.title=Vault가 아님
addvaultwizard.existing.notAVault.message=선택한 폴더는 Cryptomator Vault가 아닙니다
addvaultwizard.existing.notAVault.description.missingDataDir="%s" 내부에 필수 "d" 하위 디렉터리가 누락되었습니다.
addvaultwizard.existing.notAVault.description.dataNotADirectory="%s" 내부의 "d" 항목은 디렉터리가 아닙니다.
addvaultwizard.existing.notAVault.description.missingVaultConfig="%s" 내부에 필수 "vault.cryptomator" 파일이 누락되었습니다.
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=접근 권한이 부족하여 "%s" 내부의 "vault.cryptomator" 파일을 읽을 수 없습니다.
addvaultwizard.existing.notAVault.description.unsupportedStructure="%s"의 디렉터리 구조는 지원되지 않습니다.
## Success
addvaultwizard.success.nextStepsInstructions="%s" Vault가 추가되었습니다.\n이 Vault를 접근하거나 컨텐츠를 추가하려면 잠금 해제가 필요합니다. 그렇지만 언제든지 잠금 해제가 가능합니다.
addvaultwizard.success.unlockNow=지금 잠금 해제
@@ -161,6 +168,12 @@ unlock.error.title="%s" 잠금 해제 실패
hub.noKeychain.message=기기 키에 액세스할 수 없습니다
hub.noKeychain.description=Hub Vaults를 잠금 해제하려면 키체인을 사용하여 보호되는 기기 키가 필요합니다. 계속하려면 "%s"을(를) 활성화하고 기본 설정에서 키체인을 선택하십시오.
hub.noKeychain.openBtn=설정 열기
### Check Host Authenticity
hub.checkHostTrust.message.check=구성 확인 중…
hub.checkHostTrust.message.ask=이 호스트를 신뢰하겠습니까?
hub.checkHostTrust.message.ask.plural=이 호스트를 신뢰하겠습니까?
hub.checkHostTrust.trustBtn=신뢰하기
hub.checkHostTrust.denyBtn=거부
### Waiting
hub.auth.message=인증 대기 중…
hub.auth.description=자동으로 로그인 페이지로 리다이렉트 될 것입니다.
@@ -192,6 +205,9 @@ hub.archived.description=이 Vault는 아카이브되어 더 이상 접근할
### Unauthorized
hub.unauthorized.message=액세스 거부됨
hub.unauthorized.description=해당 Vault에 접근하도록 허가되지 않았습니다. Vault의 소유자에게 권한을 요청하세요.
### Untrusted Host
hub.untrustedHost.message=호스트를 신뢰할 수 없음
hub.untrustedHost.description=보안상의 이유로 Hub 연결이 차단되었습니다. Hub 호스트가 안전하다고 판단되시면 Hub 관리자에게 문의하거나 다시 시도해 주세요.
### Requires Account Initialization
hub.requireAccountInit.message=조치가 필요함
hub.requireAccountInit.description.0=진행하려면 필요한 조치를 완료하십시오:
@@ -199,7 +215,7 @@ hub.requireAccountInit.description.1=Hub 사용자 프로필
hub.requireAccountInit.description.2=.
### License Exceeded
hub.invalidLicense.message=Hub 라이선스가 잘못되었습니다.
hub.invalidLicense.description=Cryptomator Hub 인스턴스에 잘못된 라이선스가 있습니다. 라이선스를 업그레이드하거나 갱신하려면 허브 관리자에게 알리십시오.
hub.invalidLicense.description=Cryptomator Hub 인스턴스에 잘못된 라이선스가 있습니다. 라이선스를 업그레이드하거나 갱신하려면 Hub 관리자에게 알리십시오.
# Lock
## Force
@@ -305,6 +321,7 @@ preferences.general.debugDirectory=로그 파일 표시
preferences.general.autoStart=시스템 시작 시 Cryptomator 실행
preferences.general.keychainBackend=다음 경로에 비밀번호 저장
preferences.general.quickAccessService=열린 Vault를 빠른 접근 위치에 추가하기
preferences.general.resetTrustedHosts=신뢰하는 호스트 목록 초기화
## Interface
preferences.interface=인터페이스
preferences.interface.theme=테마
@@ -581,7 +598,7 @@ recover.recoverMasterkey.title=마스터키 복구하기
## OnBoarding
recover.onBoarding.chooseMethod=복구 방법을 선택하세요:
recover.onBoarding.useRecoveryKey=복구키 사용하기
recover.onBoarding.useRecoveryKey=복구 키 사용하기
recover.onBoarding.usePassword=비밀번호 사용하기
recover.onBoarding.intro=아래 사항을 정확히 읽고 확인하세요:
recover.onBoarding.pleaseConfirm=진행하기 전, 다음 사항을 확인해 주십시오:
@@ -700,7 +717,7 @@ eventView.entry.conflict.showDecrypted=복호화된 원본 파일 보기
eventView.entry.conflict.showEncrypted=충돌하는 암호화된 파일 보기
eventView.entry.decryptionFailed.message=복호화 실패
eventView.entry.decryptionFailed.showEncrypted=암호화된 파일 보기
eventView.entry.brokenDirFile.message=망가진 디렉터리 링크
eventView.entry.brokenDirFile.message=잘못된 디렉터리 링크
eventView.entry.brokenDirFile.showEncrypted=망가진 암호화된 링크 보기
eventView.entry.brokenFileNode.message=망가진 파일 시스템 노드
eventView.entry.brokenFileNode.showEncrypted=망가진 암호화된 노드 보기
@@ -716,4 +733,4 @@ eventView.entry.inUse.ignoreLock=사용 여부 상태 무시
## FileIsInUse Notification
notification.inUse.message=다른 기기에서 파일 사용 중
notification.inUse.description=해당 파일은 %s이(가) %s의 컴퓨터에서 열어 놓은 상태입니다. 파일을 닫고 동기화가 완료될 때까지 기다리도록 요청하세요. 상태를 무시하고 지금 파일을 열 수도 있지만, 이렇게 하면 충돌이 발생하거나 최신 변경 사항이 덮어쓰여질 수 있습니다.
notification.inUse.action=사용 여부 상태 무시
notification.inUse.action=사용 여부 상태 무시
@@ -0,0 +1,326 @@
# Locale Specific CSS files such as CJK, RTL,...
# Generics
## Button
generic.button.apply=Taikyti
generic.button.back=Atgal
generic.button.cancel=Atsisakyti
generic.button.change=Keisti
generic.button.choose=Pasirinkti…
generic.button.close=Užverti
generic.button.copy=Kopijuoti
generic.button.copied=Nukopijuota!
generic.button.done=Atlikta
generic.button.previous=Ankstesnis
generic.button.next=Kitas
generic.button.print=Spausdinti
generic.button.remove=Šalinti
## Vault state
vault.state.error=Klaida
# Error
error.message=Įvyko klaida
error.technicalDetails=Išsamiau:
# Defaults
defaults.vault.vaultName=Slėptuvė
# Tray Menu
traymenu.vault.unlock=Atrakinti
traymenu.vault.lock=Užrakinti
# Add Vault Wizard
## New
### Name
### Location
addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerButton=Pasirinkti…
addvaultwizard.new.invalidName=Netinkamas slėptuvės pavadinimas
addvaultwizard.new.validName=Tinkamas slėptuvės pavadinimas
addvaultwizard.new.validCharacters.message=Slėptuvės pavadinime gali būti šie simboliai:
addvaultwizard.new.validCharacters.chars=Raidės (pvz., a, ж ar 수)
addvaultwizard.new.validCharacters.numbers=Skaitmenys
addvaultwizard.new.validCharacters.dashes=Brūkšnelis (%s) ar pabraukimo brūkšnys (%s)
### Expert Settings
addvaultwizard.new.expertSettings.shorteningThreshold.tooltip=Atverkite dokumentaciją norėdami sužinoti daugiau.
### Password
addvaultwizard.new.createVaultBtn=Sukurti slėptuvę
addvaultwizard.new.generateRecoveryKeyChoice=Be slaptažodžio nebegalėsite pasiekti savo duomenų. Ar norite sukurti atkūrimo raktą tam atvejui, jei prarasite slaptažodį?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Taip, geriau apsidrausti nei gailėtis
addvaultwizard.new.generateRecoveryKeyChoice.no=Ne, ačiū, aš neprarasiu slaptažodžio
### Information
addvault.new.readme.storageLocation.fileName=SVARBU.rtf
addvault.new.readme.accessLocation.1=🔐️ ŠIFRUOTAS TOMAS 🔐️
## Existing
addvaultwizard.existing.chooseBtn=Pasirinkti…
## Success
# Remove Vault
removeVault.title=Šalinti „%s“
removeVault.message=Šalinti slėptuvę?
# Change Password
changepassword.title=Keisti slaptažodį
# Forget Password
# Unlock
unlock.title=Atrakinti „%s“
unlock.unlockBtn=Atrakinti
## Select
## Success
## Failure
unlock.error.restartRequired.message=Nepavyko atrakinti slėptuvės
unlock.error.restartRequired.description=Pakeiskite slėptuvės parinktyse tomo tipą arba paleiskite Cryptomator iš naujo.
## Hub
### Check Host Authenticity
hub.checkHostTrust.message.check=Tikrinama konfigūracija…
### Waiting
hub.auth.message=Laukiama tapatybės nustatymo…
### Receive Key
### Register Device
hub.register.message=Naujas įrenginys
### Register Device Legacy
### Registration Success
hub.registerSuccess.unlockBtn=Atrakinti
### Registration Failed
### Archived
hub.archived.message=Slėptuvė archyvuota
hub.archived.description=Ši slėptuvė archyvuota ir daugiau nebepasiekiama. Susisiekite su slėptuvės savininku.
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
# Lock
## Force
## Failure
# Migration
## Start
migration.start.confirm=Аš perskaičiau ir supratau aukščiau pateiktą informaciją
## Run
## Success
migration.success.unlockNow=Atrakinti dabar
## Missing file system capabilities
migration.error.missingFileSystemCapabilities.title=Nepalaikoma failų sistema
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Failų sistema nepalaiko ilgų failo pavadinimų.
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Failų sistema nepalaiko ilgų kelių.
## Impossible
# Health Check
## Start
health.title=„%s“ būsenos patikrinimas
health.intro.header=Būsenos patikrinimas
health.intro.text=Būsenos patikrinimas tai patikrinimų, skirtų aptikti ir galimai išspręsti jūsų slėptuvės vidinėje struktūroje esančias problemas, rinkinys. Turėkite omenyje:
health.intro.remarkSync=Užtikrinkite, kad visi įrenginiai būtų visiškai sinchronizuoti, tai išsprendžia daugumą problemų.
health.intro.remarkFix=Ne visos problemos gali būti išspręstos.
health.intro.remarkBackup=Jei duomenys yra sugadinti, gali padėti tik atsarginė kopija.
health.intro.affirmation=Аš perskaičiau ir supratau aukščiau pateiktą informaciją
## Start Failure
health.fail.parseError=Nagrinėjant slėptuvės konfigūraciją įvyko klaida.
health.fail.moreInfo=Daugiau informacijos
## Check Selection
## Detail view
## Result view
health.result.severityFilter.info=Informacija
health.result.severityFilter.warn=Įspėjimas
## Fix Application
# Preferences
## General
## Interface
preferences.interface=Sąsaja
preferences.interface.theme=Išvaizda ir turinys
preferences.interface.language=Kalba (reikalauja paleidimo iš naujo)
preferences.interface.language.auto=Sistemos numatytoji
preferences.interface.interfaceOrientation=Sąsajos orientacija
preferences.interface.interfaceOrientation.ltr=Iš kairės į dešinę
preferences.interface.interfaceOrientation.rtl=Iš dešinės į kairę
preferences.interface.showTrayIcon=Rodyti dėklo piktogramą (reikalauja paleidimo iš naujo)
## Volume
preferences.volume.tcp.port=Numatytasis TCP prievadas
## Updates
preferences.updates.currentVersion=Dabartinė versija: %s
preferences.updates.checkNowBtn=Tikrinti dabar
preferences.updates.lastUpdateCheck.never=niekada
preferences.updates.lastUpdateCheck.recently=neseniai
preferences.updates.upToDate=Cryptomator yra naujausios versijos.
## Contribution
preferences.contribute.removeCert.tooltip=Šalinti liudijimą
### Remove License Key Dialog
removeCert.title=Šalinti liudijimą
#<-- Add entries for donations and code/translation/documentation contribution -->
## About
preferences.about=Apie
preferences.about.thirdPartyLicenses=Trečiųjų šalių licencijos
# Vault Statistics
stats.title=%s statistika
## Read
## Write
## Accesses
# Main Window
## Vault List
main.vaultlist=Slėptuvės
main.vaultlist.listEntry=Slėptuvė %s (%s)
main.vaultlist.emptyList.onboardingInstruction=Spustelėkite čia norėdami pridėti slėptuvę
main.vaultlist.contextMenu.remove=Šalinti…
main.vaultlist.contextMenu.lock=Užrakinti
main.vaultlist.contextMenu.unlock=Atrakinti…
main.vaultlist.contextMenu.unlockNow=Atrakinti dabar
main.vaultlist.contextMenu.vaultoptions=Rodyti slėptuvės parinktis
main.vaultlist.contextMenu.share=Bendrinti…
main.vaultlist.addVaultBtn.menuItemNew=Sukurti naują slėptuvę…
main.vaultlist.addVaultBtn.menuItemExisting=Atverti esamą slėptuvę…
main.vaultlist.addVaultButton.tooltip=Pridėti slėptuvę
main.vaultlist.showPreferencesButton.tooltip=Rodyti nuostatas
##Notification
main.notification.updateAvailable=Prieinamas atnaujinimas.
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Dėkojame, kad failų apsaugai pasirinkote Cryptomator. Jei prireiks pagalbos, peržiūrėkite darbo pradžios gaires:
### Locked
main.vaultDetail.lockedStatus=UŽRAKINTA
main.vaultDetail.unlockBtn=Atrakinti…
main.vaultDetail.unlockNowBtn=Atrakinti dabar
main.vaultDetail.optionsBtn=Slėptuvės parinktys
### Unlocked
main.vaultDetail.unlockedStatus=ATRAKINTA
main.vaultDetail.accessLocation=Jūsų slėptuvės turinys yra pasiekiamas štai čia:
main.vaultDetail.copyUri=Kopijuoti URI
main.vaultDetail.lockBtn=Užrakinti
main.vaultDetail.bytesPerSecondRead=Skaitymas:
main.vaultDetail.bytesPerSecondWritten=Rašymas:
main.vaultDetail.throughput.idle=neveiklus
main.vaultDetail.stats=Slėptuvės statistika
main.vaultDetail.encryptedPathsCopied=Keliai nukopijuoti į iškarpinę!
### Missing
main.vaultDetail.missing.remove=Šalinti iš slėptuvių sąrašo…
### Missing Vault Config
main.vaultDetail.missingVaultConfig.info=Trūksta slėptuvės konfigūracijos.
main.vaultDetail.missingVaultConfig.restore=Atkurti slėptuvės konfigūraciją
### Needs Migration
main.vaultDetail.migrateButton=Naujinti slėptuvę
### Error
main.vaultDetail.error.info=Įkeliant slėptuvę iš disko įvyko klaida.
main.vaultDetail.error.reload=Įkelti iš naujo
main.vaultDetail.error.windowTitle=Klaida įkeliant slėptuvę
# Wrong File Alert
wrongFileAlert.title=Kaip šifruoti failus
wrongFileAlert.message=Ar mėginote šifruoti šiuos failus?
# Vault Options
## General
vaultOptions.general.vaultName=Slėptuvės pavadinimas
vaultOptions.general.actionAfterUnlock=Po sėkmingo atrakinimo
vaultOptions.general.actionAfterUnlock.ignore=Nieko nedaryti
vaultOptions.general.actionAfterUnlock.ask=Klausti
## Mount
vaultOptions.mount=Prijungimas
vaultOptions.mount.customMountFlags=Tinkintos prijungimo vėliavėlės
vaultOptions.mount.mountPoint=Prijungimo taškas
vaultOptions.mount.mountPoint.auto=Automatiškai parinkti tinkamą vietą
vaultOptions.mount.mountPoint.custom=Naudoti pasirinktą katalogą
vaultOptions.mount.mountPoint.directoryPickerButton=Pasirinkti…
vaultOptions.mount.mountPoint.directoryPickerTitle=Parinkti katalogą
vaultOptions.mount.volume.tcp.port=TCP prievadas
vaultOptions.mount.volume.type=Tomo tipas
## Master Key
vaultOptions.masterkey=Slaptažodis
vaultOptions.masterkey.changePasswordBtn=Keisti slaptažodį
vaultOptions.masterkey.recoverPasswordBtn=Atstatyti slaptažodį
## Hub
# Recovery Key
## Display Recovery Key
## Reset Password
### Enter Recovery Key
recoveryKey.recover.title=Atstatyti slaptažodį
### Reset Password
recoveryKey.recover.resetBtn=Atstatyti
### Recovery Key Password Reset Success
### Recovery Key Vault Config Reset Success
# Recover Vault Config File and/or Masterkey
##Add Existing Vault without recovery - Dialog
##Vault Already Exists - Dialog
##Invalid Selection - Dialog
## Contact Hub Vault Owner - Dialog
##Dialog Title
## OnBoarding
recover.onBoarding.intro.ensure=Visi failai yra visiškai sinchronizuoti.
###Vault Config Missing
###Masterkey Missing
## Expert Settings
# Convert Vault
# New Password
newPassword.passwordsMatch=Slaptažodžiai sutampa!
newPassword.passwordsDoNotMatch=Slaptažodžiai nesutampa
passwordStrength.messageLabel.tooShort=Naudokite bent %d simbolius
passwordStrength.messageLabel.0=Labai silpnas
passwordStrength.messageLabel.1=Silpnas
passwordStrength.messageLabel.2=Vidutinis
passwordStrength.messageLabel.3=Stiprus
passwordStrength.messageLabel.4=Labai stiprus
# Quit
quit.title=Išjungti programą
quit.message=Yra neužrakintų slėptuvių
quit.lockAndQuitBtn=Užrakinti ir išjungti
# Forced Quit
quit.forced.message=Kai kurių slėptuvių nepavyko užrakinti
# Update Reminder
updateReminder.message=Tikrinti, ar yra atnaujinimų?
updateReminder.notNow=Ne dabar
updateReminder.yesOnce=Taip, vieną kartą
updateReminder.yesAutomatically=Taip, automatiškai
#Dokany Support End
#Retry If Readonly
# Share Vault
shareVault.message=Ar norėtumėte bendrinti slėptuvę su kitais?
shareVault.docsTooltip=Norėdami daugiau sužinoti apie slėptuvių bendrinimą atverkite dokumentaciją.
# Decrypt File Names
decryptNames.filePicker.extensionDescription=Cryptomator šifruotas failas
decryptNames.column.encrypted=Šifruotas
decryptNames.column.decrypted=Iššifruotas
decryptNames.dropZone.error.noDirIdBackup=Pasirinktų failų kataloge nėra dirId.c9r failo
decryptNames.dropZone.error.generic=Nepavyko iššifruoti failų pavadinimų
# Event View
## event list entries
eventView.entry.conflictResolved.showDecrypted=Rodyti iššifruotą failą
eventView.entry.decryptionFailed.showEncrypted=Rodyti šifruotą failą
eventView.entry.inUse.showDecrypted=Rodyti iššifruotą failą
eventView.entry.inUse.showEncrypted=Rodyti šifruotą failą
# Notifications
## FileIsInUse Notification
notification.inUse.message=Failas yra naudojamas kitame įrenginyje
@@ -161,6 +161,10 @@ unlock.error.title="%s" atslēgšana neizdevās
hub.noKeychain.message=Nebija iespējams piekļūt ierīces atslēgai
hub.noKeychain.description=Lai atslēgtu Hub glabātavas, ir nepieciešama ierīces atslēga, kas tiek droši uzglabāta atslēgu saišķī. Lai tuprinātu, iestatījumos jāiespējo "%s" un jāatlasa atslēgu saišķis.
hub.noKeychain.openBtn=Atvērt iestatījumus
### Check Host Authenticity
hub.checkHostTrust.message.check=Pārbauda konfigurāciju…
hub.checkHostTrust.trustBtn=Uzticēties
hub.checkHostTrust.denyBtn=Noraidīt
### Waiting
hub.auth.message=Gaida autentificēšanu…
hub.auth.description=Vajadzētu notikt automātiskai pārvirzīšanai uz pieteikšanās lapu.
@@ -192,6 +196,7 @@ hub.archived.description=Glabātava tika arhivēta un vairs nav pieejama. Lūgum
### Unauthorized
hub.unauthorized.message=Piekļuve atteikta
hub.unauthorized.description=Nav pilnvaras atvērt šo glabātavu. Jāsazinās ar glabātavas īpašnieku, lai pieprasītu piekļuvi.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Nepieciešama darbība
hub.requireAccountInit.description.0=Lai turpinātu, lūgums pabeigt nepieciešamos soļus savā
@@ -715,4 +720,4 @@ eventView.entry.inUse.ignoreLock=Neņemt vēra izmantošanas stāvokli
## FileIsInUse Notification
notification.inUse.message=Datne tiek izmantota citā ierīcē
notification.inUse.description=Datni atvēra %s ierīcē %s. Jāvaicā aizvērt datni un ļaut pabeigties sinhronizēšanai. Stāvokli tagad var neņemt vērā, lai atvērtu datni, bet tas var radīt nesaderības vai pārrakstīt jaunākas izmaiņas.
notification.inUse.action=Neņemt vēra izmantošanas stāvokli
notification.inUse.action=Neņemt vēra izmantošanas stāvokli
@@ -77,6 +77,7 @@ unlock.unlockBtn=Отклучи
## Success
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -86,6 +87,7 @@ hub.registerSuccess.unlockBtn=Отклучи
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -206,4 +208,4 @@ vaultOptions.mount.mountPoint.directoryPickerButton=Избор…
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -32,6 +32,7 @@
## Success
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -40,6 +41,7 @@
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -154,4 +156,4 @@
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -159,6 +159,8 @@ unlock.error.title=Lås opp "%s" mislyktes
hub.noKeychain.message=Får ikke tilgang til enhetsnøkkel
hub.noKeychain.description=For å låse opp Hub-hvelv er det nødvendig med en enhetsnøkkel som er sikret med en nøkkelring. For å fortsette, aktiver "%s" og velg en nøkkelring i innstillingene.
hub.noKeychain.openBtn=Åpne innstillinger
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Stol på
### Waiting
hub.auth.message=Venter på autentisering…
hub.auth.description=Du burde bli automatisk videresendt til innloggingssiden.
@@ -188,6 +190,7 @@ hub.registerFailed.description.deviceAlreadyExists=Denne enheten er allerede reg
hub.archived.message=Hvelvet er arkivert
### Unauthorized
hub.unauthorized.message=Ingen tilgang
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Påkrevd handling
hub.requireAccountInit.description.0=For å fortsette, fullfør trinnene som kreves i din
@@ -613,4 +616,4 @@ shareVault.hub.openHub=Åpne Cryptomator hub
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+18 -1
View File
@@ -109,6 +109,13 @@ addvaultwizard.existing.restore=Herstel…
addvaultwizard.existing.chooseBtn=Kies…
addvaultwizard.existing.filePickerTitle=Kies kluisbestand
addvaultwizard.existing.filePickerMimeDesc=Cryptomator kluis
addvaultwizard.existing.notAVault.title=Geen kluis
addvaultwizard.existing.notAVault.message=De geselecteerde map is geen Cryptomatorkluis
addvaultwizard.existing.notAVault.description.missingDataDir=De vereiste "d" submap ontbreekt binnen "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=De "d" invoer binnen "%s" is geen map.
addvaultwizard.existing.notAVault.description.missingVaultConfig=Het vereiste "vault.cryptomator" bestand ontbreekt in "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=Bestand "vault.cryptomator" binnen "%s" kan niet worden gelezen omdat er onvoldoende toegangsrechten zijn.
addvaultwizard.existing.notAVault.description.unsupportedStructure=De mapstructuur van "%s" wordt niet ondersteund.
## Success
addvaultwizard.success.nextStepsInstructions=Toegevoegde kluis "%s".\nOntgrendel deze kluis om toegang te krijgen tot of om inhoud toe te voegen. Optioneel kunt u deze op elk later tijdstip ontgrendelen.
addvaultwizard.success.unlockNow=Nu Ontgrendelen
@@ -161,6 +168,12 @@ unlock.error.title=Ontgrendelen "%s" mislukt
hub.noKeychain.message=Geen toegang tot de apparaatsleutel
hub.noKeychain.description=Om Hub kluizen te ontgrendelen is een apparaatsleutel vereist, die met een sleutelhanger wordt beveiligd. Om verder te gaan, schakel "%s" in en selecteer een sleutelhanger in de voorkeursinstellingen.
hub.noKeychain.openBtn=Open Voorkeuren
### Check Host Authenticity
hub.checkHostTrust.message.check=Configuratie controleren…
hub.checkHostTrust.message.ask=Deze hosts vertrouwen?
hub.checkHostTrust.message.ask.plural=Deze hosts vertrouwen?
hub.checkHostTrust.trustBtn=Vertrouwen
hub.checkHostTrust.denyBtn=Weigeren
### Waiting
hub.auth.message=Wachten op authenticatie…
hub.auth.description=U zal automatisch worden doorgestuurd naar de inlogpagina.
@@ -192,6 +205,9 @@ hub.archived.description=Deze kluis is gearchiveerd en is niet meer toegankelijk
### Unauthorized
hub.unauthorized.message=Toegang geweigerd
hub.unauthorized.description=U bent niet geautoriseerd om deze kluis te openen. Neem contact op met de eigenaar van de kluis om toegang aan te vragen.
### Untrusted Host
hub.untrustedHost.message=Host niet vertrouwd
hub.untrustedHost.description=Verbinding met Hub werd geblokkeerd voor je veiligheid. Als je gelooft dat de Hub host veilig is, neem dan contact op met je Hub administrator of probeer het opnieuw.
### Requires Account Initialization
hub.requireAccountInit.message=Actie vereist
hub.requireAccountInit.description.0=Om verder te gaan, gelieve de stappen te voltooien in uw
@@ -305,6 +321,7 @@ preferences.general.debugDirectory=Logboekbestanden bekijken
preferences.general.autoStart=Start Cryptomator als het systeem opstart
preferences.general.keychainBackend=Bewaar wachtwoorden met
preferences.general.quickAccessService=Voeg ontgrendelde kluizen toe aan snelle toegang
preferences.general.resetTrustedHosts=Vertrouwde hosts vrijgegeven
## Interface
preferences.interface=Uiterlijk
preferences.interface.theme=Uiterlijk
@@ -716,4 +733,4 @@ eventView.entry.inUse.ignoreLock=Gebruiksstatus negeren
## FileIsInUse Notification
notification.inUse.message=Bestand is op een ander apparaat in gebruik
notification.inUse.description=Het bestand is geopend door %s op %s. Vraag ze om het bestand te sluiten en laat de synchronisatie eindigen. Je kunt de status negeren om het nu te openen, maar dit kan conflicten veroorzaken of nieuwere wijzigingen overschrijven.
notification.inUse.action=Gebruiksstatus negeren
notification.inUse.action=Gebruiksstatus negeren
@@ -95,6 +95,7 @@ unlock.success.rememberChoice=Hugs valet - ikkje vis dette igjen
unlock.success.revealBtn=Gjer eininga synleg
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -104,6 +105,7 @@ hub.registerSuccess.unlockBtn=Låse opp
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -315,4 +317,4 @@ quit.lockAndQuitBtn=Lås og avslutt
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -32,6 +32,7 @@
## Success
## Failure
## Hub
### Check Host Authenticity
### Waiting
### Receive Key
### Register Device
@@ -40,6 +41,7 @@
### Registration Failed
### Archived
### Unauthorized
### Untrusted Host
### Requires Account Initialization
### License Exceeded
@@ -154,4 +156,4 @@
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -138,6 +138,8 @@ unlock.error.restartRequired.message=ਵਾਲਟ ਨੂੰ ਅਣ-ਲਾਕ ਕ
unlock.error.title="%s" ਨੂੰ ਅਣ-ਲਾਕ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ
## Hub
hub.noKeychain.openBtn=ਪਸੰਦਾਂ ਨੂੰ ਖੋਲ੍ਹੋ
### Check Host Authenticity
hub.checkHostTrust.trustBtn=ਭਰੋਸਾ ਕਰੋ
### Waiting
hub.auth.message=ਪਰਮਾਣਕਿਤਾ ਦੀ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…
hub.auth.description=ਤੁਹਾਨੂੰ ਆਪਣੇ-ਆਪ ਲਾਗਇਨ ਸਫ਼ੇ ਲਈ ਰੀ-ਡਿਰੈਕਟ ਕੀਤਾ ਜਾਵੇਗਾ।
@@ -157,6 +159,7 @@ hub.registerFailed.message=ਡਿਵਾਈਸ ਰਜਿਸਟਰ ਕਰਨਾ
### Archived
### Unauthorized
hub.unauthorized.message=ਪਹੁੰਚ ਤੋਂ ਇਨਾਕਰ
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=ਕਾਰਵਾਈ ਦੀ ਲੋੜ ਹੈ
hub.requireAccountInit.description.1=ਹੱਬ ਵਰਤੋਂਕਾਰ ਪਰੋਫਾਇਲ
@@ -583,4 +586,4 @@ eventView.entry.inUse.showEncrypted=ਇੰਕ੍ਰਿਪਟ ਕੀਤੀ ਫ਼ਾ
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
@@ -161,6 +161,8 @@ unlock.error.title=Błąd odblokowywania "%s"
hub.noKeychain.message=Brak dostępu do klucza urządzenia
hub.noKeychain.description=Aby odblokować sejfy na Hubie, wymagany jest klucz urządzenia zabezpieczony za pomocą pęku kluczy. Aby kontynuować, włącz "%s" i wybierz Pęk kluczy w ustawieniach.
hub.noKeychain.openBtn=Otwórz ustawienia
### Check Host Authenticity
hub.checkHostTrust.trustBtn=Zaufany
### Waiting
hub.auth.message=Oczekiwanie na autoryzację…
hub.auth.description=Przekierowanie na stronę logowania nastąpi automatycznie.
@@ -192,6 +194,7 @@ hub.archived.description=Ten sejf został zarchiwizowany i nie jest już dostęp
### Unauthorized
hub.unauthorized.message=Brak dostępu
hub.unauthorized.description=Nie masz uprawnień do otwierania tego sejfu. Skontaktuj się z właścicielem sejfu i poproś o dostęp.
### Untrusted Host
### Requires Account Initialization
hub.requireAccountInit.message=Wymagane działanie
hub.requireAccountInit.description.0=Aby kontynuować, wykonaj wymagane kroki w Twoim
@@ -711,4 +714,4 @@ eventView.entry.inUse.copyUserAndDevice=Kopiowanie blokady użytkownika i nazwy
# Notifications
## FileIsInUse Notification
## FileIsInUse Notification
+18 -1
View File
@@ -109,6 +109,13 @@ addvaultwizard.existing.restore=Restaurar…
addvaultwizard.existing.chooseBtn=Escolher…
addvaultwizard.existing.filePickerTitle=Selecionar o ficheiro do cofre
addvaultwizard.existing.filePickerMimeDesc=Cofre Cryptomator
addvaultwizard.existing.notAVault.title=Não é um cofre
addvaultwizard.existing.notAVault.message=A pasta selecionada não é um cofre do Cryptomator
addvaultwizard.existing.notAVault.description.missingDataDir=O subdiretório "d" obrigatório está em falta dentro de "%s".
addvaultwizard.existing.notAVault.description.dataNotADirectory=A entrada "d" dentro de "%s" não é um directório.
addvaultwizard.existing.notAVault.description.missingVaultConfig=O ficheiro "vault.cryptomator" necessário está em falta dentro de "%s".
addvaultwizard.existing.notAVault.description.vaultConfigAccessDenied=O ficheiro "vault.cryptomator" dentro de "%s" não pode ser lido devido a direitos de acesso insuficientes.
addvaultwizard.existing.notAVault.description.unsupportedStructure=A estrutura de diretórios "%s" não é suportada.
## Success
addvaultwizard.success.nextStepsInstructions=Adicionado cofre "%s".\nPrecisa de desbloquear este cofre para aceder ou adicionar conteúdo. Como alternativa, pode desbloquear a qualquer momento mais tarde.
addvaultwizard.success.unlockNow=Desbloquear agora
@@ -161,6 +168,12 @@ unlock.error.title=Desbloqueio "%s" falhou
hub.noKeychain.message=Não foi possível aceder à chave do dispositivo
hub.noKeychain.description=Para desbloquear os cofres do Hub, é necessária uma chave do dispositivo, que é protegida usando um porta-chaves. Para continuar, ative “%s” e selecione um porta-chaves nas preferências.
hub.noKeychain.openBtn=Abrir preferências
### Check Host Authenticity
hub.checkHostTrust.message.check=Verificando a configuração…
hub.checkHostTrust.message.ask=Confiar neste anfitrião?
hub.checkHostTrust.message.ask.plural=Confiar nestes anfitriões?
hub.checkHostTrust.trustBtn=Confiar
hub.checkHostTrust.denyBtn=Negar
### Waiting
hub.auth.message=A aguardar autenticação…
hub.auth.description=Vai ser redirecionado automaticamente para a página de início de sessão.
@@ -192,6 +205,9 @@ hub.archived.description=Este cofre foi arquivado e não está mais acessível.
### Unauthorized
hub.unauthorized.message=Acesso negado
hub.unauthorized.description=Não está autorizado a abrir este cofre. Contacte o proprietário do cofre para solicitar o acesso.
### Untrusted Host
hub.untrustedHost.message=Host não fiável
hub.untrustedHost.description=A ligação ao Hub foi bloqueada por motivos de segurança. Se acredita que o host do Hub é seguro, contacte o administrador do Hub ou tente novamente.
### Requires Account Initialization
hub.requireAccountInit.message=Ação requerida
hub.requireAccountInit.description.0=Para continuar, conclua as etapas necessárias no seu
@@ -305,6 +321,7 @@ preferences.general.debugDirectory=Mostrar ficheiros de registo
preferences.general.autoStart=Iniciar o Cryptomator no início do sistema
preferences.general.keychainBackend=Guardar palavras-passe com
preferences.general.quickAccessService=Adicionar cofres desbloqueados à área de acesso rápido
preferences.general.resetTrustedHosts=Redefinir hosts fidedignos
## Interface
preferences.interface=Interface
preferences.interface.theme=Aspecto e Ambiente
@@ -716,4 +733,4 @@ eventView.entry.inUse.ignoreLock=Ignorar estado de utilização
## FileIsInUse Notification
notification.inUse.message=O ficheiro está em utilização noutro dispositivo
notification.inUse.description=O ficheiro está aberto por %s em %s. Peça-lhes que fechem o ficheiro e deixem a sincronização terminar. Pode ignorar o estado para o abrir agora, mas isso pode causar conflitos ou sobrescrever alterações mais recentes.
notification.inUse.action=Ignorar estado de utilização
notification.inUse.action=Ignorar estado de utilização

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