From e35c7a699175994a0dfcb9d5344654df21635c54 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 23 May 2019 12:50:40 +0200 Subject: [PATCH 01/35] Updated issue templates [ci skip] --- .github/ISSUE_TEMPLATE.md | 31 ----------- .github/ISSUE_TEMPLATE/1.4.0-beta-testing.md | 15 ------ .github/ISSUE_TEMPLATE/bug.md | 56 ++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature.md | 32 +++++++++++ SUPPORT.md | 16 ++++-- 5 files changed, 100 insertions(+), 50 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .github/ISSUE_TEMPLATE/1.4.0-beta-testing.md create mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/feature.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 3808d9c0d..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,31 +0,0 @@ -## Issue Checklist - -Before creating a new issue make sure that you -- searched existing (and closed) issues: https://github.com/cryptomator/cryptomator/issues -- searched the knowledge base: https://community.cryptomator.org/c/kb -- have read the support guide: https://github.com/cryptomator/cryptomator/blob/develop/SUPPORT.md -- have read the contribution guide: https://github.com/cryptomator/cryptomator/blob/develop/.github/CONTRIBUTING.md -- have read the code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md - -## Basic Info - -I'm using Windows / macOS / Linux / … in version: … - -I'm running Cryptomator in version: … -(You can check the version in the Cryptomator settings.) - -## Description - -… -(Please describe in detail what you did, what you expected, and what really happened.) - -## Attachments (optional) - -If you want to add the log file or screenshots, please add them as attachments. If your log file seems empty and doesn't show any errors, you may enable the debug mode first. Here is how to do that: https://community.cryptomator.org/t/how-do-i-enable-debug-mode/36 - -Then reproduce the problem to ensure all important information is contained in there. You may use test data or redact sensitive information from the log file. - -You can find the log file -- on Windows: %appdata%/Cryptomator/cryptomator.log -- on macOS: ~/Library/Logs/Cryptomator/cryptomator.log -- on Linux: ~/.Cryptomator/cryptomator.log diff --git a/.github/ISSUE_TEMPLATE/1.4.0-beta-testing.md b/.github/ISSUE_TEMPLATE/1.4.0-beta-testing.md deleted file mode 100644 index c78c19e22..000000000 --- a/.github/ISSUE_TEMPLATE/1.4.0-beta-testing.md +++ /dev/null @@ -1,15 +0,0 @@ -## 1.4.0 Beta Issue Checklist -- Existing 1.4.0 Beta Issues: https://github.com/cryptomator/cryptomator/milestone/27 -- Contribution Guide: https://github.com/cryptomator/cryptomator/blob/develop/.github/CONTRIBUTING.md -- Code of Conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md - -## Software Used During the Test -- Cryptomator 1.4.0 Beta 1 -- Ubuntu 16.04 / macOS 10.11.6 / etc -- Linux Kernel x.y.z -- Gnome x.y.z -- OpenOffice x.y.z -- ... - -## Description -What doesn't work? What did you do? How can the bug be reproduced? diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 000000000..0a2bd6c0a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,56 @@ +--- +name: "Bug Report" +about: "Create a report to help us improve" +labels: type:bug +--- + + + +### Description + +[Summarize your problem] + +### System Setup + +* Operating system and version: +* Cryptomator version (shown in the settings): +* Drive (FUSE/Dokany/WebDAV): + +### Steps to Reproduce + +1. [First Step] +2. [Second Step] +3. [and so on...] + +#### Expected behavior: +[What you expect to happen] + +#### Actual behavior +[What actually happens] + +#### Reproduces how often: +[What percentage of the time does it reproduce?] + +### Additional Information + +Any additional information, log files, screenshots, configuration or data that might be necessary to reproduce the issue. + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 000000000..a27cc1f5f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,32 @@ +--- +name: "Feature Request" +about: "Suggest an idea for this project" +labels: type:feature-request +--- + + + +### Summary + +One paragraph explanation of the feature. + +### Motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? + +### Describe alternatives you've considered + +A clear and concise description of the alternative solutions you've considered. Be sure to explain why Atom's existing customizability isn't suitable for this feature. + +### Additional context + +Add any other context or screenshots about the feature request here. diff --git a/SUPPORT.md b/SUPPORT.md index cdbc8ff88..c7dc14547 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -4,7 +4,15 @@ For development-related topics, GitHub is the right place. For _everything else_, please visit our official [Cryptomator Community](https://community.cryptomator.org) (we are there, too :wink:). Amongst others, you will find: -- Installation manuals -- Usage guides -- Help with problems -- Tips & tricks +- [Knowledge Base](https://community.cryptomator.org/c/kb) + - Installation manuals + - Usage guides + - FAQ +- [Help with problems](https://community.cryptomator.org/c/help) + - Assistance with the setup + - Known issues and workarounds + - Discussions about the apps +- [Development discussions](https://community.cryptomator.org/c/development) + - General questions + - Discussions regarding our design decissions + - Our roadmap From bcbf53a6066f167ca09a3b5ba333c9d8781050bf Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 23 May 2019 16:01:12 +0200 Subject: [PATCH 02/35] Create FUNDING.yml [ci skip] --- .github/FUNDING.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..0af73f145 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,8 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +custom: https://cryptomator.org/sponsors/ From c31212a73a5a44fa19d6c7035d9db2af9b9c3f3b Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Thu, 23 May 2019 16:12:53 +0200 Subject: [PATCH 03/35] Create SECURITY.md --- SECURITY.md | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..7cc13ff3c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,124 @@ +# Security Policy + +## Reporting a Vulnerability + +For reporting security-related vulnerabilities or exploits that [haven't been reported yet](https://github.com/cryptomator/cryptomator/labels/type%3Asecurity-issue), contact us at: security@cryptomator.org + +
+PGP Key + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: GPGTools - https://gpgtools.org + +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 +=W1Ri +-----END PGP PUBLIC KEY BLOCK----- +``` +
From 8db856855ebd51ffe983245bffd5dfac7a735a86 Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Fri, 24 May 2019 14:51:48 +0200 Subject: [PATCH 04/35] Updated issue templates, code of conduct, and contributing [ci skip] --- .github/CODE_OF_CONDUCT.md | 28 ++++++++++--------- .github/CONTRIBUTING.md | 4 +-- .github/ISSUE_TEMPLATE/bug.md | 45 +++++++++++++++++-------------- .github/ISSUE_TEMPLATE/feature.md | 16 +++++------ 4 files changed, 50 insertions(+), 43 deletions(-) diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index ad3196738..3a7337fe3 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -5,9 +5,9 @@ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. ## Our Standards @@ -23,7 +23,7 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or -advances + advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic @@ -45,12 +45,12 @@ threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. ## Enforcement @@ -68,7 +68,9 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index bb48037de..4547fb8df 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -5,7 +5,7 @@ - Ensure you're running the latest version of Cryptomator. - Ensure the bug is related to the desktop version of Cryptomator. Bugs concerning the Cryptomator iOS and Android app can be reported on the [Cryptomator for iOS issues list](https://github.com/cryptomator/cryptomator-ios/issues) and [Cryptomator for Android issues list](https://github.com/cryptomator/cryptomator-android/issues) respectively. - Ensure the bug was not [already reported](https://github.com/cryptomator/cryptomator/issues). You can also check out our [FAQ](https://community.cryptomator.org/c/kb/faq). -- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator/issues/new). +- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator/issues/new/choose). ## Did you write a patch that fixes a bug? @@ -14,7 +14,7 @@ ## Do you intend to add a new feature or change an existing one? -- Suggest your change by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new) and start writing code. +- Suggest your change by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new/choose) and start writing code. ## Code of Conduct diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 0a2bd6c0a..0504eebce 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -1,6 +1,6 @@ --- name: "Bug Report" -about: "Create a report to help us improve" +about: "Create a report to help us improve" labels: type:bug --- @@ -11,46 +11,51 @@ We're happy to help you via our support channels! Please read: https://github.co By filing an issue, you are expected to comply with our code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md -Of course we also expect you to search for existing similar issues, first! ;) https://github.com/cryptomator/cryptomator/issues?q= +Of course, we also expect you to search for existing similar issues first! ;) https://github.com/cryptomator/cryptomator/issues?q= --> ### Description -[Summarize your problem] +[Summarize your problem.] ### System Setup -* Operating system and version: -* Cryptomator version (shown in the settings): -* Drive (FUSE/Dokany/WebDAV): +* Operating system and version: [Windows/macOS/Linux + Version] +* Cryptomator version: [Shown in the settings] +* Drive: [Dokany/FUSE/WebDAV] ### Steps to Reproduce -1. [First Step] -2. [Second Step] -3. [and so on...] +1. [First step] +2. [Second step] +3. [and so on…] -#### Expected behavior: -[What you expect to happen] +#### Expected Behavior -#### Actual behavior -[What actually happens] +[What you expect to happen.] -#### Reproduces how often: -[What percentage of the time does it reproduce?] +#### Actual Behavior + +[What actually happens.] + +#### Reproducibility + +[Always/Intermittent/Only once] ### Additional Information -Any additional information, log files, screenshots, configuration or data that might be necessary to reproduce the issue. +[Any additional information, log files, screenshots, configuration, or data that might be necessary to reproduce the issue.] \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index a27cc1f5f..869d4d4b9 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -1,6 +1,6 @@ --- name: "Feature Request" -about: "Suggest an idea for this project" +about: "Suggest an idea for this project" labels: type:feature-request --- @@ -11,22 +11,22 @@ We're happy to help you via our support channels! Please read: https://github.co By filing a feature request, you are expected to comply with our code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md -Of course we also expect you to search for existing similar feature requests, first! ;) +Of course, we also expect you to search for existing similar feature requests first! ;) --> ### Summary -One paragraph explanation of the feature. +[One paragraph explanation of the feature.] ### Motivation -Why are we doing this? What use cases does it support? What is the expected outcome? +[Why are we doing this? What use cases does it support? What is the expected outcome?] -### Describe alternatives you've considered +### Considered Alternatives -A clear and concise description of the alternative solutions you've considered. Be sure to explain why Atom's existing customizability isn't suitable for this feature. +[A clear and concise description of the alternative solutions you've considered.] -### Additional context +### Additional Context -Add any other context or screenshots about the feature request here. +[Add any other context or screenshots about the feature request here.] \ No newline at end of file From f53f2d2ca4b7eb0bde642eb82cca0a88041b0a22 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 17 Jun 2019 13:55:31 +0200 Subject: [PATCH 05/35] allow to store custom mount flags in the vault settings (required for #802) [ci skip] --- .../common/settings/VaultSettings.java | 6 ++++ .../settings/VaultSettingsJsonAdapter.java | 30 ++++++++++++++++++- .../VaultSettingsJsonAdapterTest.java | 28 ++++++++++++++++- main/pom.xml | 2 +- .../org/cryptomator/ui/model/FuseVolume.java | 18 +++++++++-- 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 41c91efcf..8f30fd70f 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -20,6 +20,7 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Base64; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -44,6 +45,7 @@ public class VaultSettings { private final BooleanProperty usesIndividualMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH); private final StringProperty individualMountPath = new SimpleStringProperty(); private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE); + private final ObjectProperty> mountFlags = new SimpleObjectProperty<>(List.of()); public VaultSettings(String id) { this.id = Objects.requireNonNull(id); @@ -147,6 +149,10 @@ public class VaultSettings { return usesReadOnlyMode; } + public ObjectProperty> mountFlags() { + return mountFlags; + } + /* Hashcode/Equals */ @Override diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 7a3f03b39..484e91e1c 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -6,12 +6,15 @@ package org.cryptomator.common.settings; import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; class VaultSettingsJsonAdapter { @@ -26,8 +29,10 @@ class VaultSettingsJsonAdapter { out.name("unlockAfterStartup").value(value.unlockAfterStartup().get()); out.name("revealAfterMount").value(value.revealAfterMount().get()); out.name("usesIndividualMountPath").value(value.usesIndividualMountPath().get()); - out.name("individualMountPath").value(value.individualMountPath().get()); //TODO: should this always be written? ( because it could contain metadata, which the user may not want to save!) + out.name("individualMountPath").value(value.individualMountPath().get()); out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get()); + out.name("mountFlags"); + writeMountFlags(out, value.mountFlags().get()); out.endObject(); } @@ -41,6 +46,7 @@ class VaultSettingsJsonAdapter { boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT; boolean usesIndividualMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH; boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE; + List mountFlags = null; in.beginObject(); while (in.hasNext()) { @@ -73,6 +79,9 @@ class VaultSettingsJsonAdapter { case "usesReadOnlyMode": usesReadOnlyMode = in.nextBoolean(); break; + case "mountFlags": + mountFlags = readMountFlags(in); + break; default: LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); @@ -90,7 +99,26 @@ class VaultSettingsJsonAdapter { vaultSettings.usesIndividualMountPath().set(usesIndividualMountPath); vaultSettings.individualMountPath().set(individualMountPath); vaultSettings.usesReadOnlyMode().set(usesReadOnlyMode); + vaultSettings.mountFlags().set(mountFlags); return vaultSettings; } + private List readMountFlags(JsonReader in) throws IOException { + List result = new ArrayList<>(); + in.beginArray(); + while (!JsonToken.END_ARRAY.equals(in.peek())) { + result.add(in.nextString()); + } + in.endArray(); + return result; + } + + private void writeMountFlags(JsonWriter out, List flags) throws IOException { + out.beginArray(); + for (String flag : flags) { + out.value(flag); + } + out.endArray(); + } + } diff --git a/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java b/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java index 32f393842..eb3bb1582 100644 --- a/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java @@ -6,12 +6,17 @@ package org.cryptomator.common.settings; import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import org.hamcrest.CoreMatchers; +import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.StringReader; +import java.io.StringWriter; import java.nio.file.Paths; +import java.util.Arrays; public class VaultSettingsJsonAdapterTest { @@ -19,7 +24,7 @@ public class VaultSettingsJsonAdapterTest { @Test public void testDeserialize() throws IOException { - String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\"}"; + String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\", \"mountFlags\":[\"--foo\", \"--bar\"]}"; JsonReader jsonReader = new JsonReader(new StringReader(json)); VaultSettings vaultSettings = adapter.read(jsonReader); @@ -28,6 +33,27 @@ public class VaultSettingsJsonAdapterTest { Assertions.assertEquals("test", vaultSettings.mountName().get()); Assertions.assertEquals("X", vaultSettings.winDriveLetter().get()); Assertions.assertEquals("/home/test/crypto", vaultSettings.individualMountPath().get()); + MatcherAssert.assertThat(vaultSettings.mountFlags().get(), CoreMatchers.hasItems("--foo", "--bar")); + + + } + + @Test + public void testSerialize() throws IOException { + VaultSettings vaultSettings = new VaultSettings("test"); + vaultSettings.path().set(Paths.get("/foo/bar")); + vaultSettings.mountName().set("mountyMcMountFace"); + vaultSettings.mountFlags().set(Arrays.asList("--foo", "--bar")); + + StringWriter buf = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(buf); + adapter.write(jsonWriter, vaultSettings); + String result = buf.toString(); + + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"id\":\"test\"")); + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"/foo/bar\"")); + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountName\":\"mountyMcMountFace\"")); + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountFlags\":[\"--foo\",\"--bar\"]")); } } diff --git a/main/pom.xml b/main/pom.xml index ffe4cb6c5..6a4dd6e33 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -27,7 +27,7 @@ 1.2.1 1.8.5 2.0.0 - 1.1.3 + 1.2.0-SNAPSHOT 1.1.8 1.0.10 diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java b/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java index fcd69493d..dbce4eccb 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java @@ -9,6 +9,7 @@ import org.cryptomator.frontend.fuse.mount.EnvironmentVariables; import org.cryptomator.frontend.fuse.mount.FuseMountFactory; import org.cryptomator.frontend.fuse.mount.FuseNotSupportedException; import org.cryptomator.frontend.fuse.mount.Mount; +import org.cryptomator.frontend.fuse.mount.Mounter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,6 +21,7 @@ import java.nio.file.Files; import java.nio.file.NotDirectoryException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import java.util.Optional; public class FuseVolume implements Volume { @@ -96,16 +98,26 @@ public class FuseVolume implements Volume { private void mount(Path root) throws VolumeException { try { + Mounter mounter = FuseMountFactory.getMounter(); EnvironmentVariables envVars = EnvironmentVariables.create() // - .withMountName(vaultSettings.mountName().getValue()) // - .withMountPath(mountPoint) // + .withFlags(mountFlags(mounter)) + .withMountPoint(mountPoint) // .build(); - this.fuseMnt = FuseMountFactory.getMounter().mount(root, envVars); + this.fuseMnt = mounter.mount(root, envVars); } catch (CommandFailedException e) { throw new VolumeException("Unable to mount Filesystem", e); } } + private String[] mountFlags(Mounter mounter) { + List mountFlags = vaultSettings.mountFlags().get(); + if (mountFlags.isEmpty()) { + return mounter.defaultMountFlags(); + } else { + return mountFlags.toArray(String[]::new); + } + } + @Override public void reveal() throws VolumeException { try { From 367281fccb3a8a1bfbf8e27ece6a1fd6f1804123 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Jun 2019 14:45:43 +0200 Subject: [PATCH 06/35] overwrite settings atomically --- .../cryptomator/common/settings/SettingsProvider.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java b/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java index 732b66fef..92efe5e1f 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java @@ -29,6 +29,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.util.Optional; import java.util.concurrent.Executors; @@ -109,11 +110,13 @@ public class SettingsProvider implements Provider { LOG.debug("Attempting to save settings to {}", settingsPath); try { Files.createDirectories(settingsPath.getParent()); - try (OutputStream out = Files.newOutputStream(settingsPath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); // - Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8)) { + Path tmpPath = settingsPath.resolveSibling(settingsPath.getFileName().toString() + ".tmp"); + try (OutputStream out = Files.newOutputStream(tmpPath, StandardOpenOption.CREATE_NEW); // + Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8)) { gson.toJson(settings, writer); - LOG.info("Settings saved to {}", settingsPath); } + Files.move(tmpPath, settingsPath, StandardCopyOption.REPLACE_EXISTING); + LOG.info("Settings saved to {}", settingsPath); } catch (IOException e) { LOG.error("Failed to save settings.", e); } From f909f384be8520816f9d5b25dc568781e95ed3cd Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Jun 2019 15:00:25 +0200 Subject: [PATCH 07/35] improved error logging --- .../java/org/cryptomator/common/settings/SettingsProvider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java b/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java index 92efe5e1f..0aae9a541 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java @@ -10,6 +10,7 @@ package org.cryptomator.common.settings; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; import org.cryptomator.common.Environment; import org.cryptomator.common.LazyInitializer; import org.slf4j.Logger; @@ -117,7 +118,7 @@ public class SettingsProvider implements Provider { } Files.move(tmpPath, settingsPath, StandardCopyOption.REPLACE_EXISTING); LOG.info("Settings saved to {}", settingsPath); - } catch (IOException e) { + } catch (IOException | JsonParseException e) { LOG.error("Failed to save settings.", e); } } From 06abbf2dd1ccc854be10ba84c3c0d541807d2865 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Jun 2019 15:00:54 +0200 Subject: [PATCH 08/35] custom mount flags default to empty flags --- .../java/org/cryptomator/common/settings/VaultSettings.java | 5 +++-- .../common/settings/VaultSettingsJsonAdapter.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 8f30fd70f..67b010556 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -35,9 +35,10 @@ public class VaultSettings { public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true; public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false; public static final boolean DEFAULT_USES_READONLY_MODE = false; + public static final List DEFAULT_MOUNT_FLAGS = List.of(); private final String id; - private final ObjectProperty path = new SimpleObjectProperty<>(); + private final ObjectProperty path = new SimpleObjectProperty(); private final StringProperty mountName = new SimpleStringProperty(); private final StringProperty winDriveLetter = new SimpleStringProperty(); private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP); @@ -45,7 +46,7 @@ public class VaultSettings { private final BooleanProperty usesIndividualMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH); private final StringProperty individualMountPath = new SimpleStringProperty(); private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE); - private final ObjectProperty> mountFlags = new SimpleObjectProperty<>(List.of()); + private final ObjectProperty> mountFlags = new SimpleObjectProperty(DEFAULT_MOUNT_FLAGS); public VaultSettings(String id) { this.id = Objects.requireNonNull(id); diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 484e91e1c..11d94dd44 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -46,7 +46,7 @@ class VaultSettingsJsonAdapter { boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT; boolean usesIndividualMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH; boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE; - List mountFlags = null; + List mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; in.beginObject(); while (in.hasNext()) { From ed9adab9b437117de4baeb20a5164faaeb3af366 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Jun 2019 16:31:10 +0200 Subject: [PATCH 09/35] store custom mount flags in settings.json as string instead of string array --- .../common/settings/VaultSettings.java | 8 +++--- .../settings/VaultSettingsJsonAdapter.java | 28 ++----------------- .../VaultSettingsJsonAdapterTest.java | 8 +++--- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 67b010556..0a0301266 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -35,7 +35,7 @@ public class VaultSettings { public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true; public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false; public static final boolean DEFAULT_USES_READONLY_MODE = false; - public static final List DEFAULT_MOUNT_FLAGS = List.of(); + public static final String DEFAULT_MOUNT_FLAGS = ""; private final String id; private final ObjectProperty path = new SimpleObjectProperty(); @@ -46,7 +46,7 @@ public class VaultSettings { private final BooleanProperty usesIndividualMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH); private final StringProperty individualMountPath = new SimpleStringProperty(); private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE); - private final ObjectProperty> mountFlags = new SimpleObjectProperty(DEFAULT_MOUNT_FLAGS); + private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS); public VaultSettings(String id) { this.id = Objects.requireNonNull(id); @@ -55,7 +55,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, usesIndividualMountPath, individualMountPath, usesReadOnlyMode}; + return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, usesIndividualMountPath, individualMountPath, usesReadOnlyMode, mountFlags}; } private void deriveMountNameFromPath(Path path) { @@ -150,7 +150,7 @@ public class VaultSettings { return usesReadOnlyMode; } - public ObjectProperty> mountFlags() { + public StringProperty mountFlags() { return mountFlags; } diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 11d94dd44..e5130cdb0 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -6,15 +6,12 @@ package org.cryptomator.common.settings; import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; class VaultSettingsJsonAdapter { @@ -31,8 +28,7 @@ class VaultSettingsJsonAdapter { out.name("usesIndividualMountPath").value(value.usesIndividualMountPath().get()); out.name("individualMountPath").value(value.individualMountPath().get()); out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get()); - out.name("mountFlags"); - writeMountFlags(out, value.mountFlags().get()); + out.name("mountFlags").value(value.mountFlags().get()); out.endObject(); } @@ -46,7 +42,7 @@ class VaultSettingsJsonAdapter { boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT; boolean usesIndividualMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH; boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE; - List mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; + String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; in.beginObject(); while (in.hasNext()) { @@ -80,7 +76,7 @@ class VaultSettingsJsonAdapter { usesReadOnlyMode = in.nextBoolean(); break; case "mountFlags": - mountFlags = readMountFlags(in); + mountFlags = in.nextString(); break; default: LOG.warn("Unsupported vault setting found in JSON: " + name); @@ -103,22 +99,4 @@ class VaultSettingsJsonAdapter { return vaultSettings; } - private List readMountFlags(JsonReader in) throws IOException { - List result = new ArrayList<>(); - in.beginArray(); - while (!JsonToken.END_ARRAY.equals(in.peek())) { - result.add(in.nextString()); - } - in.endArray(); - return result; - } - - private void writeMountFlags(JsonWriter out, List flags) throws IOException { - out.beginArray(); - for (String flag : flags) { - out.value(flag); - } - out.endArray(); - } - } diff --git a/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java b/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java index eb3bb1582..62a37a5c2 100644 --- a/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java @@ -24,7 +24,7 @@ public class VaultSettingsJsonAdapterTest { @Test public void testDeserialize() throws IOException { - String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\", \"mountFlags\":[\"--foo\", \"--bar\"]}"; + String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\", \"mountFlags\":\"--foo --bar\"}"; JsonReader jsonReader = new JsonReader(new StringReader(json)); VaultSettings vaultSettings = adapter.read(jsonReader); @@ -33,7 +33,7 @@ public class VaultSettingsJsonAdapterTest { Assertions.assertEquals("test", vaultSettings.mountName().get()); Assertions.assertEquals("X", vaultSettings.winDriveLetter().get()); Assertions.assertEquals("/home/test/crypto", vaultSettings.individualMountPath().get()); - MatcherAssert.assertThat(vaultSettings.mountFlags().get(), CoreMatchers.hasItems("--foo", "--bar")); + Assertions.assertEquals("--foo --bar", vaultSettings.mountFlags().get()); } @@ -43,7 +43,7 @@ public class VaultSettingsJsonAdapterTest { VaultSettings vaultSettings = new VaultSettings("test"); vaultSettings.path().set(Paths.get("/foo/bar")); vaultSettings.mountName().set("mountyMcMountFace"); - vaultSettings.mountFlags().set(Arrays.asList("--foo", "--bar")); + vaultSettings.mountFlags().set("--foo --bar"); StringWriter buf = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(buf); @@ -53,7 +53,7 @@ public class VaultSettingsJsonAdapterTest { MatcherAssert.assertThat(result, CoreMatchers.containsString("\"id\":\"test\"")); MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"/foo/bar\"")); MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountName\":\"mountyMcMountFace\"")); - MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountFlags\":[\"--foo\",\"--bar\"]")); + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountFlags\":\"--foo --bar\"")); } } From b15d410378db19d06be0e1bfe8e9cabff0455cea Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Jun 2019 16:39:56 +0200 Subject: [PATCH 10/35] Re-layouted unlock UI and added textfield for custom mount flags (atm only supported for FUSE - see #802) --- .../ui/controllers/UnlockController.java | 41 +++-- .../ui/model/DefaultMountFlags.java | 13 ++ .../cryptomator/ui/model/DokanyVolume.java | 2 +- .../org/cryptomator/ui/model/FuseVolume.java | 19 +-- .../org/cryptomator/ui/model/PerVault.java | 13 ++ .../java/org/cryptomator/ui/model/Vault.java | 33 +++- .../cryptomator/ui/model/VaultComponent.java | 1 - .../org/cryptomator/ui/model/VaultModule.java | 79 ++++++++-- .../java/org/cryptomator/ui/model/Volume.java | 2 +- .../cryptomator/ui/model/WebDavVolume.java | 3 +- main/ui/src/main/resources/fxml/unlock.fxml | 145 ++++++++---------- .../ui/src/main/resources/localization/en.txt | 5 +- 12 files changed, 226 insertions(+), 130 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/model/DefaultMountFlags.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/model/PerVault.java diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java index 3d90c689f..dd9808070 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java @@ -11,6 +11,7 @@ package org.cryptomator.ui.controllers; import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import javafx.application.Application; +import javafx.beans.Observable; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; @@ -27,6 +28,7 @@ import javafx.scene.control.TextField; import javafx.scene.input.KeyEvent; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; import javafx.scene.text.Text; import javafx.stage.DirectoryChooser; import javafx.stage.Stage; @@ -113,6 +115,12 @@ public class UnlockController implements ViewController { @FXML private TextField mountName; + @FXML + private CheckBox useCustomMountFlags; + + @FXML + private TextField mountFlags; + @FXML private CheckBox revealAfterMount; @@ -134,17 +142,14 @@ public class UnlockController implements ViewController { @FXML private ProgressIndicator progressIndicator; - @FXML - private Text progressText; - @FXML private Hyperlink downloadsPageLink; @FXML - private GridPane advancedOptions; + private VBox advancedOptions; @FXML - private GridPane root; + private VBox root; @FXML private CheckBox unlockAfterStartup; @@ -158,6 +163,9 @@ public class UnlockController implements ViewController { unlockButton.disableProperty().bind(passwordField.textProperty().isEmpty()); mountName.addEventFilter(KeyEvent.KEY_TYPED, this::filterAlphanumericKeyEvents); mountName.textProperty().addListener(this::mountNameDidChange); + useCustomMountFlags.selectedProperty().addListener(this::useCustomMountFlagsDidChange); + mountFlags.disableProperty().bind(useCustomMountFlags.selectedProperty().not()); + mountFlags.textProperty().addListener(this::mountFlagsDidChange); savePassword.setDisable(!keychainAccess.isPresent()); unlockAfterStartup.disableProperty().bind(savePassword.disabledProperty().or(savePassword.selectedProperty().not())); @@ -173,7 +181,6 @@ public class UnlockController implements ViewController { } } - @Override public Parent getRoot() { return root; @@ -199,7 +206,6 @@ public class UnlockController implements ViewController { advancedOptions.setVisible(false); advancedOptionsButton.setText(localization.getString("unlock.button.advancedOptions.show")); progressIndicator.setVisible(false); - progressText.setText(null); state.successMessage().map(localization::getString).ifPresent(messageText::setText); if (SystemUtils.IS_OS_WINDOWS) { winDriveLetter.valueProperty().removeListener(driveLetterChangeListener); @@ -212,6 +218,8 @@ public class UnlockController implements ViewController { } downloadsPageLink.setVisible(false); mountName.setText(vault.getMountName()); + useCustomMountFlags.setSelected(vault.isHavingCustomMountFlags()); + mountFlags.setText(vault.getMountFlags()); savePassword.setSelected(false); // auto-fill pw from keychain: if (keychainAccess.isPresent()) { @@ -318,6 +326,23 @@ public class UnlockController implements ViewController { } else { vault.setMountName(newValue); } + if (!useCustomMountFlags.isSelected()) { + mountFlags.setText(vault.getMountFlags()); // flags might depend on the volume name + } + } + + + private void useCustomMountFlagsDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused")Boolean oldValue, Boolean newValue) { + if (!newValue) { + vault.setMountFlags(VaultSettings.DEFAULT_MOUNT_FLAGS); + mountFlags.setText(vault.getMountFlags()); + } + } + + private void mountFlagsDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused")String oldValue, String newValue) { + if (useCustomMountFlags.isSelected()) { + vault.setMountFlags(newValue); + } } @FXML @@ -435,7 +460,6 @@ public class UnlockController implements ViewController { CharSequence password = passwordField.getCharacters(); Tasks.create(() -> { - progressText.setText(localization.getString("unlock.pendingMessage.unlocking")); vault.unlock(password); if (keychainAccess.isPresent() && savePassword.isSelected()) { keychainAccess.get().storePassphrase(vault.getId(), password); @@ -476,7 +500,6 @@ public class UnlockController implements ViewController { }).andFinally(() -> { advancedOptions.setDisable(false); progressIndicator.setVisible(false); - progressText.setText(null); }).runOnce(executor); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/DefaultMountFlags.java b/main/ui/src/main/java/org/cryptomator/ui/model/DefaultMountFlags.java new file mode 100644 index 000000000..50943a34f --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/model/DefaultMountFlags.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.model; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Qualifier +@Documented +@Retention(RUNTIME) +public @interface DefaultMountFlags { +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/DokanyVolume.java b/main/ui/src/main/java/org/cryptomator/ui/model/DokanyVolume.java index b9200a981..1c419830e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/DokanyVolume.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/DokanyVolume.java @@ -44,7 +44,7 @@ public class DokanyVolume implements Volume { } @Override - public void mount(CryptoFileSystem fs) throws VolumeException, IOException { + public void mount(CryptoFileSystem fs, String mountFlags) throws VolumeException, IOException { Path mountPath = getMountPoint(); String mountName = vaultSettings.mountName().get(); try { diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java b/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java index dbce4eccb..b740dfcbd 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/FuseVolume.java @@ -1,5 +1,6 @@ package org.cryptomator.ui.model; +import com.google.common.base.Splitter; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.Environment; import org.cryptomator.common.settings.VaultSettings; @@ -21,7 +22,6 @@ import java.nio.file.Files; import java.nio.file.NotDirectoryException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.List; import java.util.Optional; public class FuseVolume implements Volume { @@ -44,7 +44,7 @@ public class FuseVolume implements Volume { } @Override - public void mount(CryptoFileSystem fs) throws IOException, FuseNotSupportedException, VolumeException { + public void mount(CryptoFileSystem fs, String mountFlags) throws IOException, FuseNotSupportedException, VolumeException { Optional optionalCustomMountPoint = vaultSettings.getIndividualMountPath(); if (optionalCustomMountPoint.isPresent()) { Path customMountPoint = Paths.get(optionalCustomMountPoint.get()); @@ -55,7 +55,7 @@ public class FuseVolume implements Volume { this.mountPoint = prepareTemporaryMountPoint(); LOG.debug("Successfully created mount point: {}", mountPoint); } - mount(fs.getPath("/")); + mount(fs.getPath("/"), mountFlags); } private void checkProvidedMountPoint(Path mountPoint) throws IOException { @@ -96,11 +96,11 @@ public class FuseVolume implements Volume { throw new VolumeException("Did not find feasible mount point."); } - private void mount(Path root) throws VolumeException { + private void mount(Path root, String mountFlags) throws VolumeException { try { Mounter mounter = FuseMountFactory.getMounter(); EnvironmentVariables envVars = EnvironmentVariables.create() // - .withFlags(mountFlags(mounter)) + .withFlags(splitFlags(mountFlags)) .withMountPoint(mountPoint) // .build(); this.fuseMnt = mounter.mount(root, envVars); @@ -109,13 +109,8 @@ public class FuseVolume implements Volume { } } - private String[] mountFlags(Mounter mounter) { - List mountFlags = vaultSettings.mountFlags().get(); - if (mountFlags.isEmpty()) { - return mounter.defaultMountFlags(); - } else { - return mountFlags.toArray(String[]::new); - } + private String[] splitFlags(String str) { + return Splitter.on(' ').splitToList(str).toArray(String[]::new); } @Override diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/PerVault.java b/main/ui/src/main/java/org/cryptomator/ui/model/PerVault.java new file mode 100644 index 000000000..3172beec0 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/model/PerVault.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.model; + +import javax.inject.Scope; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +@interface PerVault { + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java index bd48150fc..325f6ba97 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java @@ -25,7 +25,6 @@ import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags; import org.cryptomator.cryptofs.CryptoFileSystemProvider; import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.InvalidPassphraseException; -import org.cryptomator.ui.model.VaultModule.PerVault; import org.fxmisc.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +43,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; +import java.util.function.Supplier; @PerVault public class Vault { @@ -54,6 +54,7 @@ public class Vault { private final VaultSettings vaultSettings; private final Provider volumeProvider; + private final Supplier defaultMountFlags; private final AtomicReference cryptoFileSystem = new AtomicReference<>(); private final ObjectProperty state = new SimpleObjectProperty(State.LOCKED); @@ -64,9 +65,10 @@ public class Vault { } @Inject - Vault(VaultSettings vaultSettings, Provider volumeProvider) { + Vault(VaultSettings vaultSettings, Provider volumeProvider, @DefaultMountFlags Supplier defaultMountFlags) { this.vaultSettings = vaultSettings; this.volumeProvider = volumeProvider; + this.defaultMountFlags = defaultMountFlags; } // ****************************************************************************** @@ -110,7 +112,7 @@ public class Vault { } CryptoFileSystem fs = getCryptoFileSystem(passphrase); volume = volumeProvider.get(); - volume.mount(fs); + volume.mount(fs, getMountFlags()); Platform.runLater(() -> { state.set(State.UNLOCKED); }); @@ -241,10 +243,6 @@ public class Vault { } } - public String getMountName() { - return vaultSettings.mountName().get(); - } - public String getCustomMountPath() { return vaultSettings.individualMountPath().getValueSafe(); } @@ -253,6 +251,10 @@ public class Vault { vaultSettings.individualMountPath().set(mountPath); } + public String getMountName() { + return vaultSettings.mountName().get(); + } + public void setMountName(String mountName) throws IllegalArgumentException { if (StringUtils.isBlank(mountName)) { throw new IllegalArgumentException("mount name is empty"); @@ -261,6 +263,23 @@ public class Vault { } } + public boolean isHavingCustomMountFlags() { + return !Strings.isNullOrEmpty(vaultSettings.mountFlags().get()); + } + + public String getMountFlags() { + String mountFlags = vaultSettings.mountFlags().get(); + if (Strings.isNullOrEmpty(mountFlags)) { + return defaultMountFlags.get(); + } else { + return mountFlags; + } + } + + public void setMountFlags(String mountFlags) { + vaultSettings.mountFlags().set(mountFlags); + } + public Character getWinDriveLetter() { if (vaultSettings.winDriveLetter().get() == null) { return null; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultComponent.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultComponent.java index 6fafed661..bca3dab63 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/VaultComponent.java @@ -7,7 +7,6 @@ package org.cryptomator.ui.model; import dagger.BindsInstance; import org.cryptomator.common.settings.VaultSettings; -import org.cryptomator.ui.model.VaultModule.PerVault; import dagger.Subcomponent; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultModule.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultModule.java index 100137f6f..8ca71d692 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/VaultModule.java @@ -7,28 +7,24 @@ package org.cryptomator.ui.model; import dagger.Module; import dagger.Provides; +import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.settings.Settings; +import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.settings.VolumeImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.inject.Scope; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.function.Supplier; @Module public class VaultModule { private static final Logger LOG = LoggerFactory.getLogger(VaultModule.class); - @Scope - @Documented - @Retention(RetentionPolicy.RUNTIME) - @interface PerVault { - - } - @Provides public Volume provideVolume(Settings settings, WebDavVolume webDavVolume, FuseVolume fuseVolume, DokanyVolume dokanyVolume) { VolumeImpl preferredImpl = settings.preferredVolumeImpl().get(); @@ -45,4 +41,65 @@ public class VaultModule { } } + @Provides + @PerVault + @DefaultMountFlags + public Supplier provideDefaultMountFlags(Settings settings, VaultSettings vaultSettings) { + VolumeImpl preferredImpl = settings.preferredVolumeImpl().get(); + switch (preferredImpl) { + case FUSE: + if (SystemUtils.IS_OS_MAC_OSX) { + return () -> getMacFuseDefaultMountFlags(settings, vaultSettings); + } else if (SystemUtils.IS_OS_LINUX) { + return () -> getLinuxFuseDefaultMountFlags(settings, vaultSettings); + } + case DOKANY: + return () -> getDokanyDefaultMountFlags(settings, vaultSettings); + default: + return () -> "--flags-supported-on-FUSE-or-DOKANY-only"; + } + } + + private String getMacFuseDefaultMountFlags(Settings settings, VaultSettings vaultSettings) { + assert SystemUtils.IS_OS_MAC_OSX; + // see: https://github.com/osxfuse/osxfuse/wiki/Mount-options + try { + Path userHome = Paths.get(System.getProperty("user.home")); + int uid = (int) Files.getAttribute(userHome, "unix:uid"); + int gid = (int) Files.getAttribute(userHome, "unix:gid"); + return "-ovolname=" + vaultSettings.mountName().get() // volume name + + " -ouid=" + uid // + + " -ogid=" + gid // + + " -oatomic_o_trunc" // + + " -oauto_xattr" // + + " -oauto_cache" // + + " -omodules=iconv,from_code=UTF-8,to_code=UTF-8-MAC" // show files names in Unicode NFD encoding + + " -onoappledouble" // vastly impacts performance for some reason... + + " -odefault_permissions"; // let the kernel assume permissions based on file attributes etc + } catch (IOException e) { + LOG.error("Could not read uid/gid from USER_HOME", e); + return ""; + } + } + + private String getLinuxFuseDefaultMountFlags(Settings settings, VaultSettings vaultSettings) { + assert SystemUtils.IS_OS_LINUX; + try { + Path userHome = Paths.get(System.getProperty("user.home")); + int uid = (int) Files.getAttribute(userHome, "unix:uid"); + int gid = (int) Files.getAttribute(userHome, "unix:gid"); + return "-oauto_unmount" // + + " -ouid=" + uid // + + " -ogid=" + gid; + } catch (IOException e) { + LOG.error("Could not read uid/gid from USER_HOME", e); + return ""; + } + } + + private String getDokanyDefaultMountFlags(Settings settings, VaultSettings vaultSettings) { + // TODO + return "--not-yet-supported"; + } + } diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Volume.java b/main/ui/src/main/java/org/cryptomator/ui/model/Volume.java index 73f8d666b..dc1aae0cd 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Volume.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Volume.java @@ -22,7 +22,7 @@ public interface Volume { * @param fs * @throws IOException */ - void mount(CryptoFileSystem fs) throws IOException, VolumeException; + void mount(CryptoFileSystem fs, String mountFlags) throws IOException, VolumeException; void reveal() throws VolumeException; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java b/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java index 2161e388d..118e3a368 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java @@ -11,7 +11,6 @@ import org.cryptomator.frontend.webdav.servlet.WebDavServletController; import javax.inject.Inject; import javax.inject.Provider; - import java.net.InetAddress; import java.net.UnknownHostException; @@ -35,7 +34,7 @@ public class WebDavVolume implements Volume { } @Override - public void mount(CryptoFileSystem fs) throws VolumeException { + public void mount(CryptoFileSystem fs, String mountFlags) throws VolumeException { if (server == null) { server = serverProvider.get(); } diff --git a/main/ui/src/main/resources/fxml/unlock.fxml b/main/ui/src/main/resources/fxml/unlock.fxml index 585b60b50..29a9b82e3 100644 --- a/main/ui/src/main/resources/fxml/unlock.fxml +++ b/main/ui/src/main/resources/fxml/unlock.fxml @@ -17,102 +17,81 @@ - + + - + + - + - - - - + + + - - -