From c56d0b7d4adecfbb27327afabd10c4e2b3066680 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 26 Jan 2016 20:17:33 +0100 Subject: [PATCH] first compile-clean attempt to integrate the layered I/O subsystem with the existing UI --- .../crypto/CryptoFileSystemComponent.java | 4 +- .../crypto/CryptoFileSystemFactory.java | 3 +- .../crypto/CryptoFileSystemModule.java | 10 ++ main/frontend-api/.gitignore | 1 + main/frontend-api/pom.xml | 27 ++++ .../org/cryptomator/frontend/Frontend.java | 18 +++ .../FrontendCreationFailedException.java | 9 ++ .../cryptomator/frontend/FrontendFactory.java | 17 ++ .../cryptomator/frontend/package-info.java | 12 ++ main/frontend-webdav/pom.xml | 6 +- .../webdav}/WebDavComponent.java | 2 +- .../frontend/webdav/WebDavFrontend.java | 72 +++++++++ .../webdav}/WebDavServer.java | 32 +++- .../webdav}/WebDavServletContextFactory.java | 2 +- .../webdav}/mount/AbstractWebDavMount.java | 2 +- .../webdav}/mount/CommandFailedException.java | 2 +- .../webdav}/mount/FallbackWebDavMounter.java | 4 +- .../webdav}/mount/LinuxGvfsWebDavMounter.java | 35 ++--- .../webdav}/mount/MacOsXWebDavMounter.java | 29 ++-- .../webdav}/mount/MountStrategies.java | 2 +- .../frontend/webdav}/mount/WebDavMount.java | 2 +- .../frontend/webdav}/mount/WebDavMounter.java | 6 +- .../webdav}/mount/WebDavMounterProvider.java | 11 +- .../webdav}/mount/WebDavMounterStrategy.java | 2 +- .../webdav}/mount/WindowsDriveLetters.java | 2 +- .../webdav}/mount/WindowsWebDavMounter.java | 26 +-- .../webdav/mount}/command/CommandResult.java | 4 +- .../webdav/mount}/command/CommandRunner.java | 4 +- .../mount}/command/FutureCommandResult.java | 4 +- .../webdav/mount}/command/Script.java | 4 +- .../webdav}/InMemoryWebDavServer.java | 5 +- .../webdav}/NioWebDavServer.java | 5 +- .../webdav}/WebDavServerTest.java | 5 +- main/pom.xml | 43 +++-- main/ui/pom.xml | 16 +- .../org/cryptomator/ui/CryptomatorModule.java | 22 +-- .../controllers/ChangePasswordController.java | 148 +++++++++--------- .../ui/controllers/InitializeController.java | 24 +-- .../ui/controllers/UnlockController.java | 79 +++------- .../ui/controllers/UnlockedController.java | 104 ++++++------ .../java/org/cryptomator/ui/model/Vault.java | 140 ++++++++--------- .../cryptomator/ui/model/VaultFactory.java | 24 ++- 42 files changed, 539 insertions(+), 430 deletions(-) create mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemModule.java create mode 100644 main/frontend-api/.gitignore create mode 100644 main/frontend-api/pom.xml create mode 100644 main/frontend-api/src/main/java/org/cryptomator/frontend/Frontend.java create mode 100644 main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendCreationFailedException.java create mode 100644 main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendFactory.java create mode 100644 main/frontend-api/src/main/java/org/cryptomator/frontend/package-info.java rename main/frontend-webdav/src/main/java/org/cryptomator/{webdav/server => frontend/webdav}/WebDavComponent.java (77%) create mode 100644 main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java rename main/frontend-webdav/src/main/java/org/cryptomator/{webdav/server => frontend/webdav}/WebDavServer.java (72%) rename main/frontend-webdav/src/main/java/org/cryptomator/{webdav/server => frontend/webdav}/WebDavServletContextFactory.java (98%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/AbstractWebDavMount.java (74%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/CommandFailedException.java (93%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/FallbackWebDavMounter.java (94%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/LinuxGvfsWebDavMounter.java (80%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/MacOsXWebDavMounter.java (82%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/MountStrategies.java (97%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/WebDavMount.java (94%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/WebDavMounter.java (91%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/WebDavMounterProvider.java (78%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/WebDavMounterStrategy.java (95%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/WindowsDriveLetters.java (96%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav}/mount/WindowsWebDavMounter.java (90%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount}/command/CommandResult.java (96%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount}/command/CommandRunner.java (96%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount}/command/FutureCommandResult.java (95%) rename main/{ui/src/main/java/org/cryptomator/ui/util => frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount}/command/Script.java (92%) rename main/frontend-webdav/src/test/java/org/cryptomator/{webdav/server => frontend/webdav}/InMemoryWebDavServer.java (94%) rename main/frontend-webdav/src/test/java/org/cryptomator/{webdav/server => frontend/webdav}/NioWebDavServer.java (96%) rename main/frontend-webdav/src/test/java/org/cryptomator/{webdav/server => frontend/webdav}/WebDavServerTest.java (95%) diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java index c75864fc2..4ad66a20a 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java @@ -2,12 +2,10 @@ package org.cryptomator.filesystem.crypto; import javax.inject.Singleton; -import org.cryptomator.crypto.engine.impl.CryptoEngineModule; - import dagger.Component; @Singleton -@Component(modules = CryptoEngineModule.class) +@Component(modules = CryptoFileSystemModule.class) interface CryptoFileSystemComponent { CryptoFileSystemFactory cryptoFileSystemFactory(); diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java index 5e732e8c0..56cd965c4 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java @@ -5,6 +5,7 @@ import javax.inject.Provider; import javax.inject.Singleton; import org.cryptomator.crypto.engine.Cryptor; +import org.cryptomator.crypto.engine.InvalidPassphraseException; import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; import org.cryptomator.filesystem.blockaligned.BlockAlignedFileSystemFactory; @@ -24,7 +25,7 @@ public class CryptoFileSystemFactory { this.blockAlignedFileSystemFactory = blockAlignedFileSystemFactory; } - public FileSystem get(Folder root, CharSequence passphrase, CryptoFileSystemDelegate delegate) { + public FileSystem get(Folder root, CharSequence passphrase, CryptoFileSystemDelegate delegate) throws InvalidPassphraseException { final FileSystem nameShorteningFs = shorteningFileSystemFactory.get(root); final FileSystem cryptoFs = new CryptoFileSystem(nameShorteningFs, cryptorProvider.get(), delegate, passphrase); return blockAlignedFileSystemFactory.get(cryptoFs); diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemModule.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemModule.java new file mode 100644 index 000000000..9519bb91c --- /dev/null +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemModule.java @@ -0,0 +1,10 @@ +package org.cryptomator.filesystem.crypto; + +import org.cryptomator.crypto.engine.impl.CryptoEngineModule; + +import dagger.Module; + +@Module(includes = CryptoEngineModule.class) +public class CryptoFileSystemModule { + +} diff --git a/main/frontend-api/.gitignore b/main/frontend-api/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/main/frontend-api/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/main/frontend-api/pom.xml b/main/frontend-api/pom.xml new file mode 100644 index 000000000..44c480425 --- /dev/null +++ b/main/frontend-api/pom.xml @@ -0,0 +1,27 @@ + + + + 4.0.0 + + org.cryptomator + main + 0.11.0-SNAPSHOT + + frontend-api + Cryptomator frontend: API + API for filesystem frontends + + + + org.cryptomator + filesystem-api + + + \ No newline at end of file diff --git a/main/frontend-api/src/main/java/org/cryptomator/frontend/Frontend.java b/main/frontend-api/src/main/java/org/cryptomator/frontend/Frontend.java new file mode 100644 index 000000000..8acbeb060 --- /dev/null +++ b/main/frontend-api/src/main/java/org/cryptomator/frontend/Frontend.java @@ -0,0 +1,18 @@ +package org.cryptomator.frontend; + +import java.util.Map; +import java.util.Optional; + +public interface Frontend extends AutoCloseable { + + public enum MountParam { + MOUNT_NAME, WIN_DRIVE_LETTER + } + + boolean mount(Map> map); + + void unmount(); + + void reveal(); + +} diff --git a/main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendCreationFailedException.java b/main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendCreationFailedException.java new file mode 100644 index 000000000..b16a959bf --- /dev/null +++ b/main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendCreationFailedException.java @@ -0,0 +1,9 @@ +package org.cryptomator.frontend; + +public class FrontendCreationFailedException extends Exception { + + public FrontendCreationFailedException(Throwable cause) { + super(cause); + } + +} diff --git a/main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendFactory.java b/main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendFactory.java new file mode 100644 index 000000000..ba5aa1bbe --- /dev/null +++ b/main/frontend-api/src/main/java/org/cryptomator/frontend/FrontendFactory.java @@ -0,0 +1,17 @@ +package org.cryptomator.frontend; + +import org.cryptomator.filesystem.Folder; + +public interface FrontendFactory { + + /** + * Provides a new frontend to access the given folder. + * + * @param root Root resource accessible through this frontend. + * @param uniqueName Name of the frontend, i.e. used to create subresources for the different frontends inside of a common virtual drive. + * @return A new frontend + * @throws FrontendCreationFailedException If creation was not possible. + */ + Frontend create(Folder root, String uniqueName) throws FrontendCreationFailedException; + +} diff --git a/main/frontend-api/src/main/java/org/cryptomator/frontend/package-info.java b/main/frontend-api/src/main/java/org/cryptomator/frontend/package-info.java new file mode 100644 index 000000000..5115d8e04 --- /dev/null +++ b/main/frontend-api/src/main/java/org/cryptomator/frontend/package-info.java @@ -0,0 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2015 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation + *******************************************************************************/ +/** + * Provides frontends for {@link org.cryptomator.filesystem.FileSystem FileSystems}. + */ +package org.cryptomator.frontend; \ No newline at end of file diff --git a/main/frontend-webdav/pom.xml b/main/frontend-webdav/pom.xml index f936103ed..2a89be18c 100644 --- a/main/frontend-webdav/pom.xml +++ b/main/frontend-webdav/pom.xml @@ -15,7 +15,7 @@ 0.11.0-SNAPSHOT frontend-webdav - Jackrabbit-based WebDAV filesystem frontend + Cryptomator frontend: WebDAV frontend Provides access via WebDAV to filesystems @@ -32,6 +32,10 @@ org.cryptomator commons + + org.cryptomator + frontend-api + diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java similarity index 77% rename from main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java index 5923f4652..0dcb931e0 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java @@ -1,4 +1,4 @@ -package org.cryptomator.webdav.server; +package org.cryptomator.frontend.webdav; import javax.inject.Singleton; diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java new file mode 100644 index 000000000..c54738162 --- /dev/null +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java @@ -0,0 +1,72 @@ +package org.cryptomator.frontend.webdav; + +import java.net.URI; +import java.util.Map; +import java.util.Optional; + +import org.cryptomator.frontend.Frontend; +import org.cryptomator.frontend.FrontendCreationFailedException; +import org.cryptomator.frontend.webdav.mount.CommandFailedException; +import org.cryptomator.frontend.webdav.mount.WebDavMount; +import org.cryptomator.frontend.webdav.mount.WebDavMounterProvider; +import org.eclipse.jetty.servlet.ServletContextHandler; + +class WebDavFrontend implements Frontend { + + private final WebDavMounterProvider webdavMounterProvider; + private final ServletContextHandler handler; + private final URI uri; + private WebDavMount mount; + + public WebDavFrontend(WebDavMounterProvider webdavMounterProvider, ServletContextHandler handler, URI uri) throws FrontendCreationFailedException { + this.webdavMounterProvider = webdavMounterProvider; + this.handler = handler; + this.uri = uri; + try { + handler.start(); + } catch (Exception e) { + throw new FrontendCreationFailedException(e); + } + } + + @Override + public void close() throws Exception { + unmount(); + handler.stop(); + } + + @Override + public boolean mount(Map> mountParams) { + try { + mount = webdavMounterProvider.get().mount(uri, mountParams); + return true; + } catch (CommandFailedException e) { + return false; + } + } + + @Override + public void unmount() { + if (mount != null) { + try { + mount.unmount(); + } catch (CommandFailedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + @Override + public void reveal() { + if (mount != null) { + try { + mount.reveal(); + } catch (CommandFailedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + +} \ No newline at end of file diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java similarity index 72% rename from main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java index a909ccb54..138b3ab4c 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java @@ -1,4 +1,4 @@ -package org.cryptomator.webdav.server; +package org.cryptomator.frontend.webdav; import java.net.URI; import java.net.URISyntaxException; @@ -10,6 +10,10 @@ import javax.inject.Singleton; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.filesystem.Folder; +import org.cryptomator.frontend.Frontend; +import org.cryptomator.frontend.FrontendCreationFailedException; +import org.cryptomator.frontend.FrontendFactory; +import org.cryptomator.frontend.webdav.mount.WebDavMounterProvider; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -21,7 +25,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton -public class WebDavServer { +public class WebDavServer implements FrontendFactory { private static final Logger LOG = LoggerFactory.getLogger(WebDavServer.class); private static final String LOCALHOST = SystemUtils.IS_OS_WINDOWS ? "::1" : "localhost"; @@ -34,15 +38,17 @@ public class WebDavServer { private final ServerConnector localConnector; private final ContextHandlerCollection servletCollection; private final WebDavServletContextFactory servletContextFactory; + private final WebDavMounterProvider webdavMounterProvider; @Inject - WebDavServer(WebDavServletContextFactory servletContextFactory) { + WebDavServer(WebDavServletContextFactory servletContextFactory, WebDavMounterProvider webdavMounterProvider) { final BlockingQueue queue = new LinkedBlockingQueue<>(MAX_PENDING_REQUESTS); final ThreadPool tp = new QueuedThreadPool(MAX_THREADS, MIN_THREADS, THREAD_IDLE_SECONDS, queue); this.server = new Server(tp); this.localConnector = new ServerConnector(server); this.servletCollection = new ContextHandlerCollection(); this.servletContextFactory = servletContextFactory; + this.webdavMounterProvider = webdavMounterProvider; localConnector.setHost(LOCALHOST); server.setConnectors(new Connector[] {localConnector}); @@ -82,17 +88,27 @@ public class WebDavServer { } } - public ServletContextHandler addServlet(Folder root, String contextPath) { + // visible for testing + ServletContextHandler addServlet(Folder root, URI contextRoot) { + ServletContextHandler handler = servletContextFactory.create(contextRoot, root); + servletCollection.addHandler(handler); + servletCollection.mapContexts(); + return handler; + } + + @Override + public Frontend create(Folder root, String contextPath) throws FrontendCreationFailedException { + if (!contextPath.startsWith("/")) { + throw new IllegalArgumentException("contextPath must begin with '/'"); + } final URI uri; try { uri = new URI("http", null, LOCALHOST, getPort(), contextPath, null, null); } catch (URISyntaxException e) { throw new IllegalStateException(e); } - ServletContextHandler handler = servletContextFactory.create(uri, root); - servletCollection.addHandler(handler); - servletCollection.mapContexts(); - return handler; + final ServletContextHandler handler = addServlet(root, uri); + return new WebDavFrontend(webdavMounterProvider, handler, uri); } } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServletContextFactory.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServletContextFactory.java similarity index 98% rename from main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServletContextFactory.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServletContextFactory.java index 1cce68a1a..868d6d0be 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServletContextFactory.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServletContextFactory.java @@ -6,7 +6,7 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.webdav.server; +package org.cryptomator.frontend.webdav; import java.net.URI; import java.util.EnumSet; diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/AbstractWebDavMount.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/AbstractWebDavMount.java similarity index 74% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/AbstractWebDavMount.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/AbstractWebDavMount.java index 6ff446117..061bd100f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/AbstractWebDavMount.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/AbstractWebDavMount.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; abstract class AbstractWebDavMount implements WebDavMount { diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/CommandFailedException.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/CommandFailedException.java similarity index 93% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/CommandFailedException.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/CommandFailedException.java index dacf5a0fb..6599f19a7 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/CommandFailedException.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/CommandFailedException.java @@ -7,7 +7,7 @@ * Sebastian Stenzel - initial API and implementation * Markus Kreusch - Refactored WebDavMounter to use strategy pattern ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; public class CommandFailedException extends Exception { diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/FallbackWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/FallbackWebDavMounter.java similarity index 94% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/FallbackWebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/FallbackWebDavMounter.java index 21b8bc454..778037c4b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/FallbackWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/FallbackWebDavMounter.java @@ -6,12 +6,14 @@ * Contributors: * Markus Kreusch - Refactored WebDavMounter to use strategy pattern ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import java.net.URI; import java.util.Map; import java.util.Optional; +import org.cryptomator.frontend.Frontend.MountParam; + /** * A WebDavMounter acting as fallback if no other mounter works. * diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/LinuxGvfsWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsWebDavMounter.java similarity index 80% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/LinuxGvfsWebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsWebDavMounter.java index ed7aa3f96..685e95dc2 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/LinuxGvfsWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsWebDavMounter.java @@ -8,7 +8,7 @@ * Markus Kreusch - Refactored WebDavMounter to use strategy pattern * Mohit Raju - Added fallback schema-name "webdav" when opening file managers ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import java.net.URI; import java.util.Map; @@ -18,13 +18,15 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.util.command.Script; +import org.cryptomator.frontend.Frontend.MountParam; +import org.cryptomator.frontend.webdav.mount.command.Script; @Singleton final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy { - + @Inject - LinuxGvfsWebDavMounter() {} + LinuxGvfsWebDavMounter() { + } @Override public boolean shouldWork() { @@ -40,7 +42,7 @@ final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy { return false; } } - + @Override public void warmUp(int serverPort) { // no-op @@ -48,32 +50,29 @@ final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy { @Override public WebDavMount mount(URI uri, Map> mountParams) throws CommandFailedException { - final Script mountScript = Script.fromLines( - "set -x", - "gvfs-mount \"dav:$DAV_SSP\"") - .addEnv("DAV_SSP", uri.getRawSchemeSpecificPart()); + final Script mountScript = Script.fromLines("set -x", "gvfs-mount \"dav:$DAV_SSP\"").addEnv("DAV_SSP", uri.getRawSchemeSpecificPart()); mountScript.execute(); return new LinuxGvfsWebDavMount(uri); } - + private static class LinuxGvfsWebDavMount extends AbstractWebDavMount { private final URI webDavUri; private final Script testMountStillExistsScript; private final Script unmountScript; - + private LinuxGvfsWebDavMount(URI webDavUri) { this.webDavUri = webDavUri; this.testMountStillExistsScript = Script.fromLines("set -x", "test `gvfs-mount --list | grep \"$DAV_SSP\" | wc -l` -eq 1").addEnv("DAV_SSP", webDavUri.getRawSchemeSpecificPart()); this.unmountScript = Script.fromLines("set -x", "gvfs-mount -u \"dav:$DAV_SSP\"").addEnv("DAV_SSP", webDavUri.getRawSchemeSpecificPart()); } - + @Override public void unmount() throws CommandFailedException { boolean mountStillExists; try { testMountStillExistsScript.execute(); mountStillExists = true; - } catch(CommandFailedException e) { + } catch (CommandFailedException e) { mountStillExists = false; } // only attempt unmount if user didn't unmount manually: @@ -85,16 +84,16 @@ final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy { @Override public void reveal() throws CommandFailedException { try { - openMountWithWebdavUri("dav:"+webDavUri.getRawSchemeSpecificPart()).execute(); + openMountWithWebdavUri("dav:" + webDavUri.getRawSchemeSpecificPart()).execute(); } catch (CommandFailedException exception) { - openMountWithWebdavUri("webdav:"+webDavUri.getRawSchemeSpecificPart()).execute(); + openMountWithWebdavUri("webdav:" + webDavUri.getRawSchemeSpecificPart()).execute(); } } - - private Script openMountWithWebdavUri(String webdavUri){ + + private Script openMountWithWebdavUri(String webdavUri) { return Script.fromLines("set -x", "xdg-open \"$DAV_URI\"").addEnv("DAV_URI", webdavUri); } - + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/MacOsXWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java similarity index 82% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/MacOsXWebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java index 22b33ec59..a0c46b9ee 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/MacOsXWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java @@ -7,7 +7,7 @@ * Sebastian Stenzel - initial API and implementation, strategy fine tuning * Markus Kreusch - Refactored WebDavMounter to use strategy pattern ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import java.net.URI; import java.nio.file.FileSystems; @@ -20,13 +20,15 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.util.command.Script; +import org.cryptomator.frontend.Frontend.MountParam; +import org.cryptomator.frontend.webdav.mount.command.Script; @Singleton final class MacOsXWebDavMounter implements WebDavMounterStrategy { - + @Inject - MacOsXWebDavMounter() {} + MacOsXWebDavMounter() { + } @Override public boolean shouldWork() { @@ -43,31 +45,26 @@ final class MacOsXWebDavMounter implements WebDavMounterStrategy { final String mountName = mountParams.get(MountParam.MOUNT_NAME).orElseThrow(() -> { return new IllegalArgumentException("Missing mount parameter MOUNT_NAME."); }); - + // we don't use the uri to derive a path, as it *could* be longer than 255 chars. final String path = "/Volumes/Cryptomator_" + UUID.randomUUID().toString(); - final Script mountScript = Script.fromLines( - "mkdir \"$MOUNT_PATH\"", - "mount_webdav -S -v $MOUNT_NAME \"$DAV_AUTHORITY$DAV_PATH\" \"$MOUNT_PATH\"") - .addEnv("DAV_AUTHORITY", uri.getRawAuthority()) - .addEnv("DAV_PATH", uri.getRawPath()) - .addEnv("MOUNT_PATH", path) - .addEnv("MOUNT_NAME", mountName); + final Script mountScript = Script.fromLines("mkdir \"$MOUNT_PATH\"", "mount_webdav -S -v $MOUNT_NAME \"$DAV_AUTHORITY$DAV_PATH\" \"$MOUNT_PATH\"").addEnv("DAV_AUTHORITY", uri.getRawAuthority()) + .addEnv("DAV_PATH", uri.getRawPath()).addEnv("MOUNT_PATH", path).addEnv("MOUNT_NAME", mountName); mountScript.execute(); return new MacWebDavMount(path); } - + private static class MacWebDavMount extends AbstractWebDavMount { private final String mountPath; private final Script revealScript; private final Script unmountScript; - + private MacWebDavMount(String mountPath) { this.mountPath = mountPath; this.revealScript = Script.fromLines("open \"$MOUNT_PATH\"").addEnv("MOUNT_PATH", mountPath); this.unmountScript = Script.fromLines("diskutil umount $MOUNT_PATH").addEnv("MOUNT_PATH", mountPath); } - + @Override public void unmount() throws CommandFailedException { // only attempt unmount if user didn't unmount manually: @@ -80,7 +77,7 @@ final class MacOsXWebDavMounter implements WebDavMounterStrategy { public void reveal() throws CommandFailedException { revealScript.execute(); } - + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/MountStrategies.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java similarity index 97% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/MountStrategies.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java index 5bf74b54a..0c0d74956 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/MountStrategies.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import static java.util.Arrays.asList; import static java.util.Collections.unmodifiableList; diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMount.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMount.java similarity index 94% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMount.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMount.java index 46abfe83d..9908c3317 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMount.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMount.java @@ -6,7 +6,7 @@ * Contributors: * Markus Kreusch - Refactored WebDavMounter to use strategy pattern ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; /** * A mounted webdav share. diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounter.java similarity index 91% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounter.java index ce58ed6e8..78f0d9aec 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounter.java @@ -7,15 +7,15 @@ * Sebastian Stenzel - initial API and implementation * Markus Kreusch - Refactored to use strategy pattern ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import java.net.URI; import java.util.Map; import java.util.Optional; +import org.cryptomator.frontend.Frontend.MountParam; + public interface WebDavMounter { - - public static enum MountParam {MOUNT_NAME, WIN_DRIVE_LETTER} /** * Tries to mount a given webdav share. diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterProvider.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterProvider.java similarity index 78% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterProvider.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterProvider.java index 64745d69b..be27b5347 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterProvider.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterProvider.java @@ -7,16 +7,14 @@ * Markus Kreusch - Refactored to use strategy pattern * Sebastian Stenzel - Refactored to use Guice provider, added warmup-phase for windows mounts. ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import java.util.Collection; -import java.util.concurrent.ExecutorService; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; -import org.cryptomator.webdav.WebDavServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,15 +25,12 @@ public class WebDavMounterProvider implements Provider { private final WebDavMounterStrategy choosenStrategy; @Inject - public WebDavMounterProvider(WebDavServer server, ExecutorService executorService, MountStrategies availableStrategies) { + public WebDavMounterProvider(MountStrategies availableStrategies) { this.choosenStrategy = getStrategyWhichShouldWork(availableStrategies); - executorService.execute(() -> { - this.choosenStrategy.warmUp(server.getPort()); - }); } @Override - public WebDavMounterStrategy get() { + public WebDavMounter get() { return this.choosenStrategy; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterStrategy.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterStrategy.java similarity index 95% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterStrategy.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterStrategy.java index deff797ee..1e129a14a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterStrategy.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterStrategy.java @@ -7,7 +7,7 @@ * Markus Kreusch - Refactored WebDavMounter to use strategy pattern * Sebastian Stenzel - minor strategy fine tuning ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; /** * A strategy able to mount a webdav share and display it to the user. diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsDriveLetters.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsDriveLetters.java similarity index 96% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsDriveLetters.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsDriveLetters.java index 03b01e446..41247fe9d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsDriveLetters.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsDriveLetters.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; import static java.util.stream.Collectors.toSet; import static java.util.stream.IntStream.rangeClosed; diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java similarity index 90% rename from main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsWebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java index e30ca707d..45e22987e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java @@ -7,9 +7,9 @@ * Sebastian Stenzel - initial API and implementation, strategy fine tuning * Markus Kreusch - Refactored WebDavMounter to use strategy pattern ******************************************************************************/ -package org.cryptomator.ui.util.mount; +package org.cryptomator.frontend.webdav.mount; -import static org.cryptomator.ui.util.command.Script.fromLines; +import static org.cryptomator.frontend.webdav.mount.command.Script.fromLines; import java.net.URI; import java.util.Map; @@ -23,8 +23,9 @@ import javax.inject.Singleton; import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.util.command.CommandResult; -import org.cryptomator.ui.util.command.Script; +import org.cryptomator.frontend.Frontend.MountParam; +import org.cryptomator.frontend.webdav.mount.command.CommandResult; +import org.cryptomator.frontend.webdav.mount.command.Script; /** * A {@link WebDavMounterStrategy} utilizing the "net use" command. @@ -38,7 +39,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { private static final int MAX_MOUNT_ATTEMPTS = 8; private static final char AUTO_ASSIGN_DRIVE_LETTER = '*'; private final WindowsDriveLetters driveLetters; - + @Inject WindowsWebDavMounter(WindowsDriveLetters driveLetters) { this.driveLetters = driveLetters; @@ -60,7 +61,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { if (driveLetters.getOccupiedDriveLetters().contains(driveLetter)) { throw new CommandFailedException("Drive letter occupied."); } - + final String driveLetterStr = driveLetter.charValue() == AUTO_ASSIGN_DRIVE_LETTER ? CharUtils.toString(AUTO_ASSIGN_DRIVE_LETTER) : driveLetter + ":"; final Script localhostMountScript = fromLines("net use %DRIVE_LETTER% \\\\localhost@%DAV_PORT%\\DavWWWRoot%DAV_UNC_PATH% /persistent:no"); localhostMountScript.addEnv("DRIVE_LETTER", driveLetterStr); @@ -74,13 +75,14 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { ipv6literaltMountScript.addEnv("DRIVE_LETTER", driveLetterStr); ipv6literaltMountScript.addEnv("DAV_PORT", String.valueOf(uri.getPort())); ipv6literaltMountScript.addEnv("DAV_UNC_PATH", uri.getRawPath().replace('/', '\\')); - final Script proxyBypassScript = fromLines("reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";0--1.ipv6-literal.net;0--1.ipv6-literal.net:%DAV_PORT%\" /f"); + final Script proxyBypassScript = fromLines( + "reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";0--1.ipv6-literal.net;0--1.ipv6-literal.net:%DAV_PORT%\" /f"); proxyBypassScript.addEnv("DAV_PORT", String.valueOf(uri.getPort())); mountResult = bypassProxyAndRetryMount(localhostMountScript, ipv6literaltMountScript, proxyBypassScript); } return new WindowsWebDavMount(driveLetter.charValue() == AUTO_ASSIGN_DRIVE_LETTER ? getDriveLetter(mountResult.getStdOut()) : driveLetter); } - + private CommandResult bypassProxyAndRetryMount(Script localhostMountScript, Script ipv6literalMountScript, Script proxyBypassScript) throws CommandFailedException { CommandFailedException latestException = null; for (int i = 0; i < MAX_MOUNT_ATTEMPTS; i++) { @@ -109,18 +111,18 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { throw new CommandFailedException("Failed to get a drive letter from net use output."); } } - + private class WindowsWebDavMount extends AbstractWebDavMount { private final Character driveLetter; private final Script openExplorerScript; private final Script unmountScript; - + private WindowsWebDavMount(Character driveLetter) { this.driveLetter = driveLetter; this.openExplorerScript = fromLines("start explorer.exe " + driveLetter + ":"); this.unmountScript = fromLines("net use " + driveLetter + ": /delete").addEnv("DRIVE_LETTER", Character.toString(driveLetter)); } - + @Override public void unmount() throws CommandFailedException { // only attempt unmount if user didn't unmount manually: @@ -133,7 +135,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { public void reveal() throws CommandFailedException { openExplorerScript.execute(); } - + private boolean isVolumeMounted() { return driveLetters.getOccupiedDriveLetters().contains(driveLetter); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/command/CommandResult.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/CommandResult.java similarity index 96% rename from main/ui/src/main/java/org/cryptomator/ui/util/command/CommandResult.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/CommandResult.java index 466fab057..e5cbb6253 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/command/CommandResult.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/CommandResult.java @@ -7,7 +7,7 @@ * Markus Kreusch * Sebastian Stenzel - using Futures, lazy loading for out/err. ******************************************************************************/ -package org.cryptomator.ui.util.command; +package org.cryptomator.frontend.webdav.mount.command; import static java.lang.String.format; @@ -15,7 +15,7 @@ import java.io.IOException; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.util.Strings; -import org.cryptomator.ui.util.mount.CommandFailedException; +import org.cryptomator.frontend.webdav.mount.CommandFailedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/command/CommandRunner.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/CommandRunner.java similarity index 96% rename from main/ui/src/main/java/org/cryptomator/ui/util/command/CommandRunner.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/CommandRunner.java index 2c5cb69b0..d8e1af65b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/command/CommandRunner.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/CommandRunner.java @@ -7,7 +7,7 @@ * Markus Kreusch * Sebastian Stenzel - Refactoring ******************************************************************************/ -package org.cryptomator.ui.util.command; +package org.cryptomator.frontend.webdav.mount.command; import static java.lang.String.format; import static org.apache.commons.lang3.SystemUtils.IS_OS_UNIX; @@ -24,7 +24,7 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.util.mount.CommandFailedException; +import org.cryptomator.frontend.webdav.mount.CommandFailedException; /** *

diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/command/FutureCommandResult.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/FutureCommandResult.java similarity index 95% rename from main/ui/src/main/java/org/cryptomator/ui/util/command/FutureCommandResult.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/FutureCommandResult.java index 6f907b4b6..6b0baff70 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/command/FutureCommandResult.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/FutureCommandResult.java @@ -6,7 +6,7 @@ * Contributors: * Sebastian Stenzel ******************************************************************************/ -package org.cryptomator.ui.util.command; +package org.cryptomator.frontend.webdav.mount.command; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -17,7 +17,7 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import org.cryptomator.ui.util.mount.CommandFailedException; +import org.cryptomator.frontend.webdav.mount.CommandFailedException; final class FutureCommandResult implements Future, Runnable { diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/command/Script.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/Script.java similarity index 92% rename from main/ui/src/main/java/org/cryptomator/ui/util/command/Script.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/Script.java index 0fb1c78c1..dc3c2724c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/command/Script.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/command/Script.java @@ -6,13 +6,13 @@ * Contributors: * Markus Kreusch ******************************************************************************/ -package org.cryptomator.ui.util.command; +package org.cryptomator.frontend.webdav.mount.command; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.cryptomator.ui.util.mount.CommandFailedException; +import org.cryptomator.frontend.webdav.mount.CommandFailedException; public final class Script { diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/InMemoryWebDavServer.java b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/InMemoryWebDavServer.java similarity index 94% rename from main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/InMemoryWebDavServer.java rename to main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/InMemoryWebDavServer.java index 4f0cf64ff..e8c197868 100644 --- a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/InMemoryWebDavServer.java +++ b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/InMemoryWebDavServer.java @@ -6,8 +6,9 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.webdav.server; +package org.cryptomator.frontend.webdav; +import java.net.URI; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -27,7 +28,7 @@ public class InMemoryWebDavServer { server.start(); FileSystem fileSystem = setupFilesystem(); - ServletContextHandler servlet = server.addServlet(fileSystem, "/foo"); + ServletContextHandler servlet = server.addServlet(fileSystem, URI.create("http://localhost:8080/foo")); servlet.addFilter(LoggingHttpFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); servlet.start(); diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/NioWebDavServer.java b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/NioWebDavServer.java similarity index 96% rename from main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/NioWebDavServer.java rename to main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/NioWebDavServer.java index 0ae5c837e..95ea25713 100644 --- a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/NioWebDavServer.java +++ b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/NioWebDavServer.java @@ -6,12 +6,13 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.webdav.server; +package org.cryptomator.frontend.webdav; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UncheckedIOException; +import java.net.URI; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; @@ -36,7 +37,7 @@ public class NioWebDavServer { server.start(); FileSystem fileSystem = setupFilesystem(); - ServletContextHandler servlet = server.addServlet(fileSystem, "/foo"); + ServletContextHandler servlet = server.addServlet(fileSystem, URI.create("http://localhost:8080/foo")); servlet.addFilter(LoggingHttpFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); servlet.start(); diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/WebDavServerTest.java b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java similarity index 95% rename from main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/WebDavServerTest.java rename to main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java index dd8385016..9287ea057 100644 --- a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/WebDavServerTest.java +++ b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java @@ -1,9 +1,10 @@ -package org.cryptomator.webdav.server; +package org.cryptomator.frontend.webdav; import static org.hamcrest.collection.IsArrayContaining.hasItemInArray; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; @@ -49,7 +50,7 @@ public class WebDavServerTest { @Before public void startServlet() throws Exception { fs = new InMemoryFileSystem(); - servlet = SERVER.addServlet(fs, "/test"); + servlet = SERVER.addServlet(fs, URI.create("http://localhost:" + SERVER.getPort() + "/test")); servlet.start(); servletRoot = "http://localhost:" + SERVER.getPort() + "/test"; } diff --git a/main/pom.xml b/main/pom.xml index e96527d02..8a701a90d 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -52,19 +52,18 @@ + + org.cryptomator + commons + ${project.version} + org.cryptomator commons-test ${project.version} test - - - - org.cryptomator - commons - ${project.version} - + org.cryptomator filesystem-api @@ -91,22 +90,18 @@ filesystem-crypto ${project.version} + + + org.cryptomator + frontend-api + ${project.version} + + + org.cryptomator + frontend-webdav + ${project.version} + - - org.cryptomator - core - ${project.version} - - - org.cryptomator - crypto-api - ${project.version} - - - org.cryptomator - crypto-aes - ${project.version} - org.cryptomator ui @@ -259,10 +254,8 @@ filesystem-nameshortening filesystem-crypto filesystem-invariants-tests + frontend-api frontend-webdav - crypto-api - crypto-aes - core ui diff --git a/main/ui/pom.xml b/main/ui/pom.xml index a7951aab3..4d8d263af 100644 --- a/main/ui/pom.xml +++ b/main/ui/pom.xml @@ -20,11 +20,23 @@ org.cryptomator - core + filesystem-api org.cryptomator - crypto-aes + filesystem-nio + + + org.cryptomator + filesystem-crypto + + + org.cryptomator + frontend-api + + + org.cryptomator + frontend-webdav diff --git a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java index 34299fd2f..6afe035cb 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java @@ -7,18 +7,17 @@ import java.util.concurrent.Executors; import javax.inject.Named; import javax.inject.Singleton; -import org.cryptomator.crypto.Cryptor; -import org.cryptomator.crypto.SamplingCryptorDecorator; -import org.cryptomator.crypto.aes256.CryptoModule; +import org.cryptomator.filesystem.crypto.CryptoFileSystemModule; +import org.cryptomator.frontend.FrontendFactory; +import org.cryptomator.frontend.webdav.WebDavServer; +import org.cryptomator.frontend.webdav.mount.WebDavMounter; +import org.cryptomator.frontend.webdav.mount.WebDavMounterProvider; import org.cryptomator.ui.model.VaultObjectMapperProvider; import org.cryptomator.ui.settings.Settings; import org.cryptomator.ui.settings.SettingsProvider; import org.cryptomator.ui.util.DeferredCloser; import org.cryptomator.ui.util.DeferredCloser.Closer; import org.cryptomator.ui.util.SemVerComparator; -import org.cryptomator.ui.util.mount.WebDavMounter; -import org.cryptomator.ui.util.mount.WebDavMounterProvider; -import org.cryptomator.webdav.WebDavServer; import com.fasterxml.jackson.databind.ObjectMapper; @@ -26,7 +25,7 @@ import dagger.Module; import dagger.Provides; import javafx.application.Application; -@Module(includes = CryptoModule.class) +@Module(includes = CryptoFileSystemModule.class) class CryptomatorModule { private final Application application; @@ -83,18 +82,11 @@ class CryptomatorModule { @Provides @Singleton - WebDavServer provideWebDavServer() { - final WebDavServer webDavServer = new WebDavServer(); + FrontendFactory provideFrontendFactory(WebDavServer webDavServer) { webDavServer.start(); return closeLater(webDavServer, WebDavServer::stop); } - @Provides - @Named("SamplingCryptor") - Cryptor provideCryptor(Cryptor cryptor) { - return SamplingCryptorDecorator.decorate(cryptor); - } - private T closeLater(T object, Closer closer) { return deferredCloser.closeLater(object, closer).get().get(); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java index 97c6d8426..1673a49aa 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java @@ -1,28 +1,17 @@ package org.cryptomator.ui.controllers; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; import java.util.ResourceBundle; import javax.inject.Inject; import javax.inject.Singleton; -import org.cryptomator.crypto.exceptions.UnsupportedKeyLengthException; -import org.cryptomator.crypto.exceptions.UnsupportedVaultException; -import org.cryptomator.crypto.exceptions.WrongPasswordException; import org.cryptomator.ui.controls.SecPasswordField; import org.cryptomator.ui.model.Vault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javafx.application.Application; -import javafx.application.Platform; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -107,75 +96,80 @@ public class ChangePasswordController extends AbstractFXMLViewController { @FXML private void didClickChangePasswordButton(ActionEvent event) { - downloadsPageLink.setVisible(false); - final Path masterKeyPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_FILE); - final Path masterKeyBackupPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_BACKUP_FILE); - - // decrypt with old password: - final CharSequence oldPassword = oldPasswordField.getCharacters(); - try (final InputStream masterKeyInputStream = Files.newInputStream(masterKeyPath, StandardOpenOption.READ)) { - vault.getCryptor().decryptMasterKey(masterKeyInputStream, oldPassword); - Files.copy(masterKeyPath, masterKeyBackupPath, StandardCopyOption.REPLACE_EXISTING); - } catch (IOException ex) { - messageText.setText(resourceBundle.getString("changePassword.errorMessage.decryptionFailed")); - LOG.error("Decryption failed for technical reasons.", ex); - newPasswordField.swipe(); - retypePasswordField.swipe(); - return; - } catch (WrongPasswordException e) { - messageText.setText(resourceBundle.getString("changePassword.errorMessage.wrongPassword")); - newPasswordField.swipe(); - retypePasswordField.swipe(); - Platform.runLater(oldPasswordField::requestFocus); - return; - } catch (UnsupportedKeyLengthException ex) { - messageText.setText(resourceBundle.getString("changePassword.errorMessage.unsupportedKeyLengthInstallJCE")); - LOG.warn("Unsupported Key-Length. Please install Oracle Java Cryptography Extension (JCE).", ex); - newPasswordField.swipe(); - retypePasswordField.swipe(); - return; - } catch (UnsupportedVaultException e) { - downloadsPageLink.setVisible(true); - if (e.isVaultOlderThanSoftware()) { - messageText.setText(resourceBundle.getString("changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware") + " "); - } else if (e.isSoftwareOlderThanVault()) { - messageText.setText(resourceBundle.getString("changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault") + " "); - } - newPasswordField.swipe(); - retypePasswordField.swipe(); - return; - } finally { - oldPasswordField.swipe(); - } - - // when we reach this line, decryption was successful. - - // encrypt with new password: - final CharSequence newPassword = newPasswordField.getCharacters(); - try (final OutputStream masterKeyOutputStream = Files.newOutputStream(masterKeyPath, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.SYNC)) { - vault.getCryptor().encryptMasterKey(masterKeyOutputStream, newPassword); - messageText.setText(resourceBundle.getString("changePassword.infoMessage.success")); - Platform.runLater(this::didChangePassword); - // At this point the backup is still using the old password. - // It will be changed as soon as the user unlocks the vault the next time. - // This way he can still restore the old password, if he doesn't remember the new one. - } catch (IOException ex) { - LOG.error("Re-encryption failed for technical reasons. Restoring Backup.", ex); - this.restoreBackupQuietly(); - } finally { - newPasswordField.swipe(); - retypePasswordField.swipe(); - } + throw new UnsupportedOperationException("TODO"); + /* + * downloadsPageLink.setVisible(false); + * final Path masterKeyPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_FILE); + * final Path masterKeyBackupPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_BACKUP_FILE); + * + * // decrypt with old password: + * final CharSequence oldPassword = oldPasswordField.getCharacters(); + * try (final InputStream masterKeyInputStream = Files.newInputStream(masterKeyPath, StandardOpenOption.READ)) { + * vault.getCryptor().decryptMasterKey(masterKeyInputStream, oldPassword); + * Files.copy(masterKeyPath, masterKeyBackupPath, StandardCopyOption.REPLACE_EXISTING); + * } catch (IOException ex) { + * messageText.setText(resourceBundle.getString("changePassword.errorMessage.decryptionFailed")); + * LOG.error("Decryption failed for technical reasons.", ex); + * newPasswordField.swipe(); + * retypePasswordField.swipe(); + * return; + * } catch (WrongPasswordException e) { + * messageText.setText(resourceBundle.getString("changePassword.errorMessage.wrongPassword")); + * newPasswordField.swipe(); + * retypePasswordField.swipe(); + * Platform.runLater(oldPasswordField::requestFocus); + * return; + * } catch (UnsupportedKeyLengthException ex) { + * messageText.setText(resourceBundle.getString("changePassword.errorMessage.unsupportedKeyLengthInstallJCE")); + * LOG.warn("Unsupported Key-Length. Please install Oracle Java Cryptography Extension (JCE).", ex); + * newPasswordField.swipe(); + * retypePasswordField.swipe(); + * return; + * } catch (UnsupportedVaultException e) { + * downloadsPageLink.setVisible(true); + * if (e.isVaultOlderThanSoftware()) { + * messageText.setText(resourceBundle.getString("changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware") + " "); + * } else if (e.isSoftwareOlderThanVault()) { + * messageText.setText(resourceBundle.getString("changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault") + " "); + * } + * newPasswordField.swipe(); + * retypePasswordField.swipe(); + * return; + * } finally { + * oldPasswordField.swipe(); + * } + * + * // when we reach this line, decryption was successful. + * + * // encrypt with new password: + * final CharSequence newPassword = newPasswordField.getCharacters(); + * try (final OutputStream masterKeyOutputStream = Files.newOutputStream(masterKeyPath, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.SYNC)) { + * vault.getCryptor().encryptMasterKey(masterKeyOutputStream, newPassword); + * messageText.setText(resourceBundle.getString("changePassword.infoMessage.success")); + * Platform.runLater(this::didChangePassword); + * // At this point the backup is still using the old password. + * // It will be changed as soon as the user unlocks the vault the next time. + * // This way he can still restore the old password, if he doesn't remember the new one. + * } catch (IOException ex) { + * LOG.error("Re-encryption failed for technical reasons. Restoring Backup.", ex); + * this.restoreBackupQuietly(); + * } finally { + * newPasswordField.swipe(); + * retypePasswordField.swipe(); + * } + */ } private void restoreBackupQuietly() { - final Path masterKeyPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_FILE); - final Path masterKeyBackupPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_BACKUP_FILE); - try { - Files.copy(masterKeyBackupPath, masterKeyPath, StandardCopyOption.REPLACE_EXISTING); - } catch (IOException ex) { - LOG.error("Restoring Backup failed.", ex); - } + /* + * final Path masterKeyPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_FILE); + * final Path masterKeyBackupPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_BACKUP_FILE); + * try { + * Files.copy(masterKeyBackupPath, masterKeyPath, StandardCopyOption.REPLACE_EXISTING); + * } catch (IOException ex) { + * LOG.error("Restoring Backup failed.", ex); + * } + */ } private void didChangePassword() { diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java index cdb297f1d..df135ce0c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java @@ -9,14 +9,8 @@ package org.cryptomator.ui.controllers; import java.io.IOException; -import java.io.OutputStream; import java.net.URL; import java.nio.file.FileAlreadyExistsException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.InvalidPathException; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; import java.util.ResourceBundle; import javax.inject.Inject; @@ -90,23 +84,11 @@ public class InitializeController extends AbstractFXMLViewController { @FXML protected void initializeVault(ActionEvent event) { setControlsDisabled(true); - final Path masterKeyPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_FILE); - final CharSequence password = passwordField.getCharacters(); - try (OutputStream masterKeyOutputStream = Files.newOutputStream(masterKeyPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)) { - vault.getCryptor().randomizeMasterKey(); - vault.getCryptor().encryptMasterKey(masterKeyOutputStream, password); - final String dataRootDir = vault.getCryptor().encryptDirectoryPath("", FileSystems.getDefault().getSeparator()); - final Path dataRootPath = vault.getPath().resolve("d").resolve(dataRootDir); - final Path metadataPath = vault.getPath().resolve("m"); - Files.createDirectories(dataRootPath); - Files.createDirectories(metadataPath); - if (listener != null) { - listener.didInitialize(this); - } + final CharSequence passphrase = passwordField.getCharacters(); + try { + vault.create(passphrase); } catch (FileAlreadyExistsException ex) { messageLabel.setText(resourceBundle.getString("initialize.messageLabel.alreadyInitialized")); - } catch (InvalidPathException ex) { - messageLabel.setText(resourceBundle.getString("initialize.messageLabel.invalidPath")); } catch (IOException ex) { LOG.error("I/O Exception", ex); } finally { 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 616f96a8c..2dc2e270c 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 @@ -8,31 +8,22 @@ ******************************************************************************/ package org.cryptomator.ui.controllers; -import java.io.IOException; -import java.io.InputStream; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; import java.util.Comparator; import java.util.ResourceBundle; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import javax.inject.Inject; -import javax.security.auth.DestroyFailedException; import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.crypto.exceptions.UnsupportedKeyLengthException; -import org.cryptomator.crypto.exceptions.UnsupportedVaultException; -import org.cryptomator.crypto.exceptions.WrongPasswordException; +import org.cryptomator.crypto.engine.InvalidPassphraseException; +import org.cryptomator.frontend.FrontendCreationFailedException; +import org.cryptomator.frontend.webdav.mount.WindowsDriveLetters; import org.cryptomator.ui.controls.SecPasswordField; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.util.FXThreads; -import org.cryptomator.ui.util.mount.CommandFailedException; -import org.cryptomator.ui.util.mount.WindowsDriveLetters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -258,49 +249,30 @@ public class UnlockController extends AbstractFXMLViewController { setControlsDisabled(true); progressIndicator.setVisible(true); downloadsPageLink.setVisible(false); - final Path masterKeyPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_FILE); - final Path masterKeyBackupPath = vault.getPath().resolve(Vault.VAULT_MASTERKEY_BACKUP_FILE); final CharSequence password = passwordField.getCharacters(); - try (final InputStream masterKeyInputStream = Files.newInputStream(masterKeyPath, StandardOpenOption.READ)) { - vault.getCryptor().decryptMasterKey(masterKeyInputStream, password); - if (!vault.startServer()) { - messageText.setText(resourceBundle.getString("unlock.messageLabel.startServerFailed")); - vault.getCryptor().destroy(); - return; - } - // at this point we know for sure, that the masterkey can be decrypted, so lets make a backup: - Files.copy(masterKeyPath, masterKeyBackupPath, StandardCopyOption.REPLACE_EXISTING); - vault.setUnlocked(true); - final Future futureMount = exec.submit(vault::mount); + try { + vault.activateFrontend(password); + Future futureMount = exec.submit(vault::mount); FXThreads.runOnMainThreadWhenFinished(exec, futureMount, this::unlockAndMountFinished); - } catch (IOException ex) { - setControlsDisabled(false); - progressIndicator.setVisible(false); - messageText.setText(resourceBundle.getString("unlock.errorMessage.decryptionFailed")); - LOG.error("Decryption failed for technical reasons.", ex); - } catch (WrongPasswordException e) { + } catch (InvalidPassphraseException e) { setControlsDisabled(false); progressIndicator.setVisible(false); messageText.setText(resourceBundle.getString("unlock.errorMessage.wrongPassword")); Platform.runLater(passwordField::requestFocus); - } catch (UnsupportedKeyLengthException ex) { + } catch (FrontendCreationFailedException ex) { setControlsDisabled(false); progressIndicator.setVisible(false); - messageText.setText(resourceBundle.getString("unlock.errorMessage.unsupportedKeyLengthInstallJCE")); - LOG.warn("Unsupported Key-Length. Please install Oracle Java Cryptography Extension (JCE).", ex); - } catch (UnsupportedVaultException e) { - setControlsDisabled(false); - progressIndicator.setVisible(false); - downloadsPageLink.setVisible(true); - if (e.isVaultOlderThanSoftware()) { - messageText.setText(resourceBundle.getString("unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware") + " "); - } else if (e.isSoftwareOlderThanVault()) { - messageText.setText(resourceBundle.getString("unlock.errorMessage.unsupportedVersion.softwareOlderThanVault") + " "); - } - } catch (DestroyFailedException e) { - setControlsDisabled(false); - progressIndicator.setVisible(false); - LOG.error("Destruction of cryptor threw an exception.", e); + messageText.setText(resourceBundle.getString("unlock.errorMessage.decryptionFailed")); + LOG.error("Decryption failed for technical reasons.", ex); + // } catch (UnsupportedVaultException e) { + // setControlsDisabled(false); + // progressIndicator.setVisible(false); + // downloadsPageLink.setVisible(true); + // if (e.isVaultOlderThanSoftware()) { + // messageText.setText(resourceBundle.getString("unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware") + " "); + // } else if (e.isSoftwareOlderThanVault()) { + // messageText.setText(resourceBundle.getString("unlock.errorMessage.unsupportedVersion.softwareOlderThanVault") + " "); + // } } finally { passwordField.swipe(); } @@ -317,18 +289,9 @@ public class UnlockController extends AbstractFXMLViewController { progressIndicator.setVisible(false); setControlsDisabled(false); if (vault.isUnlocked() && !mountSuccess) { - exec.submit(() -> { - vault.stopServer(); - vault.setUnlocked(false); - }); + exec.submit(vault::deactivateFrontend); } else if (vault.isUnlocked() && mountSuccess) { - exec.submit(() -> { - try { - vault.reveal(); - } catch (CommandFailedException e) { - LOG.error("Failed to reveal mounted vault", e); - } - }); + exec.submit(vault::reveal); } if (mountSuccess && listener != null) { listener.didUnlock(this); diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java index 2bed56759..34c2e1826 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java @@ -15,10 +15,8 @@ import java.util.concurrent.ExecutorService; import javax.inject.Inject; import javax.inject.Provider; -import org.cryptomator.crypto.CryptorIOSampling; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.util.ActiveWindowStyleSupport; -import org.cryptomator.ui.util.mount.CommandFailedException; import javafx.animation.Animation; import javafx.animation.KeyFrame; @@ -30,7 +28,6 @@ import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; -import javafx.scene.chart.XYChart.Data; import javafx.scene.chart.XYChart.Series; import javafx.scene.control.Label; import javafx.stage.Stage; @@ -81,30 +78,21 @@ public class UnlockedController extends AbstractFXMLViewController { @FXML private void didClickRevealVault(ActionEvent event) { - exec.submit(() -> { - try { - vault.reveal(); - } catch (CommandFailedException e) { - Platform.runLater(() -> { - messageLabel.setText(resourceBundle.getString("unlocked.label.revealFailed")); - }); - } - }); + exec.submit(vault::reveal); } @FXML private void didClickCloseVault(ActionEvent event) { exec.submit(() -> { - try { - vault.unmount(); - } catch (CommandFailedException e) { - Platform.runLater(() -> { - messageLabel.setText(resourceBundle.getString("unlocked.label.unmountFailed")); - }); - return; - } - vault.stopServer(); - vault.setUnlocked(false); + // try { + vault.unmount(); + // } catch (CommandFailedException e) { + // Platform.runLater(() -> { + // messageLabel.setText(resourceBundle.getString("unlocked.label.unmountFailed")); + // }); + // return; + // } + vault.deactivateFrontend(); if (listener != null) { Platform.runLater(() -> { listener.didLock(this); @@ -129,7 +117,7 @@ public class UnlockedController extends AbstractFXMLViewController { // IO Graph // **************************************** - private void startIoSampling(final CryptorIOSampling sampler) { + private void startIoSampling(final Object sampler) { final Series decryptedBytes = new Series<>(); decryptedBytes.setName("decrypted"); final Series encryptedBytes = new Series<>(); @@ -156,14 +144,14 @@ public class UnlockedController extends AbstractFXMLViewController { private static final double BYTES_TO_MEGABYTES_FACTOR = 1.0 / IO_SAMPLING_INTERVAL / 1024.0 / 1024.0; private static final double SMOOTHING_FACTOR = 0.3; private static final long EFFECTIVELY_ZERO = 100000; // 100kb - private final CryptorIOSampling sampler; + private final Object sampler; private final Series decryptedBytes; private final Series encryptedBytes; - private int step = 0; - private long oldDecBytes = 0; - private long oldEncBytes = 0; + private final int step = 0; + private final long oldDecBytes = 0; + private final long oldEncBytes = 0; - public IoSamplingAnimationHandler(CryptorIOSampling sampler, Series decryptedBytes, Series encryptedBytes) { + public IoSamplingAnimationHandler(Object sampler, Series decryptedBytes, Series encryptedBytes) { this.sampler = sampler; this.decryptedBytes = decryptedBytes; this.encryptedBytes = encryptedBytes; @@ -171,28 +159,30 @@ public class UnlockedController extends AbstractFXMLViewController { @Override public void handle(ActionEvent event) { - step++; - - final long decBytes = sampler.pollDecryptedBytes(true); - final double smoothedDecBytes = oldDecBytes + SMOOTHING_FACTOR * (decBytes - oldDecBytes); - final double smoothedDecMb = smoothedDecBytes * BYTES_TO_MEGABYTES_FACTOR; - oldDecBytes = smoothedDecBytes > EFFECTIVELY_ZERO ? (long) smoothedDecBytes : 0l; - decryptedBytes.getData().add(new Data(step, smoothedDecMb)); - if (decryptedBytes.getData().size() > IO_SAMPLING_STEPS) { - decryptedBytes.getData().remove(0); - } - - final long encBytes = sampler.pollEncryptedBytes(true); - final double smoothedEncBytes = oldEncBytes + SMOOTHING_FACTOR * (encBytes - oldEncBytes); - final double smoothedEncMb = smoothedEncBytes * BYTES_TO_MEGABYTES_FACTOR; - oldEncBytes = smoothedEncBytes > EFFECTIVELY_ZERO ? (long) smoothedEncBytes : 0l; - encryptedBytes.getData().add(new Data(step, smoothedEncMb)); - if (encryptedBytes.getData().size() > IO_SAMPLING_STEPS) { - encryptedBytes.getData().remove(0); - } - - xAxis.setLowerBound(step - IO_SAMPLING_STEPS); - xAxis.setUpperBound(step); + /* + * step++; + * + * final long decBytes = sampler.pollDecryptedBytes(true); + * final double smoothedDecBytes = oldDecBytes + SMOOTHING_FACTOR * (decBytes - oldDecBytes); + * final double smoothedDecMb = smoothedDecBytes * BYTES_TO_MEGABYTES_FACTOR; + * oldDecBytes = smoothedDecBytes > EFFECTIVELY_ZERO ? (long) smoothedDecBytes : 0l; + * decryptedBytes.getData().add(new Data(step, smoothedDecMb)); + * if (decryptedBytes.getData().size() > IO_SAMPLING_STEPS) { + * decryptedBytes.getData().remove(0); + * } + * + * final long encBytes = sampler.pollEncryptedBytes(true); + * final double smoothedEncBytes = oldEncBytes + SMOOTHING_FACTOR * (encBytes - oldEncBytes); + * final double smoothedEncMb = smoothedEncBytes * BYTES_TO_MEGABYTES_FACTOR; + * oldEncBytes = smoothedEncBytes > EFFECTIVELY_ZERO ? (long) smoothedEncBytes : 0l; + * encryptedBytes.getData().add(new Data(step, smoothedEncMb)); + * if (encryptedBytes.getData().size() > IO_SAMPLING_STEPS) { + * encryptedBytes.getData().remove(0); + * } + * + * xAxis.setLowerBound(step - IO_SAMPLING_STEPS); + * xAxis.setUpperBound(step); + */ } } @@ -216,12 +206,14 @@ public class UnlockedController extends AbstractFXMLViewController { }); // sample crypto-throughput: - stopIoSampling(); - if (vault.getCryptor() instanceof CryptorIOSampling) { - startIoSampling((CryptorIOSampling) vault.getCryptor()); - } else { - ioGraph.setVisible(false); - } + /* + * stopIoSampling(); + * if (vault.getCryptor() instanceof CryptorIOSampling) { + * startIoSampling((CryptorIOSampling) vault.getCryptor()); + * } else { + * ioGraph.setVisible(false); + * } + */ } public LockListener getListener() { 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 455a58a66..f3361e5f9 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 @@ -2,6 +2,8 @@ package org.cryptomator.ui.model; import java.io.IOException; import java.io.Serializable; +import java.io.UncheckedIOException; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Path; import java.text.Normalizer; @@ -11,62 +13,58 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import javax.security.auth.DestroyFailedException; - import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.StringUtils; -import org.cryptomator.crypto.Cryptor; +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.crypto.CryptoFileSystemDelegate; +import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory; +import org.cryptomator.filesystem.nio.NioFileSystem; +import org.cryptomator.frontend.Frontend; +import org.cryptomator.frontend.Frontend.MountParam; +import org.cryptomator.frontend.FrontendCreationFailedException; +import org.cryptomator.frontend.FrontendFactory; import org.cryptomator.ui.util.DeferredClosable; import org.cryptomator.ui.util.DeferredCloser; import org.cryptomator.ui.util.FXThreads; -import org.cryptomator.ui.util.mount.CommandFailedException; -import org.cryptomator.ui.util.mount.WebDavMount; -import org.cryptomator.ui.util.mount.WebDavMounter; -import org.cryptomator.ui.util.mount.WebDavMounter.MountParam; -import org.cryptomator.webdav.WebDavServer; -import org.cryptomator.webdav.WebDavServer.ServletLifeCycleAdapter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; +import dagger.Lazy; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -public class Vault implements Serializable { +public class Vault implements Serializable, CryptoFileSystemDelegate { private static final long serialVersionUID = 3754487289683599469L; - private static final Logger LOG = LoggerFactory.getLogger(Vault.class); + @Deprecated public static final String VAULT_FILE_EXTENSION = ".cryptomator"; + + @Deprecated public static final String VAULT_MASTERKEY_FILE = "masterkey.cryptomator"; - public static final String VAULT_MASTERKEY_BACKUP_FILE = "masterkey.cryptomator.bkup"; private final Path path; - private final WebDavServer server; - private final Cryptor cryptor; - private final WebDavMounter mounter; + private final Lazy frontendFactory; private final DeferredCloser closer; + private final CryptoFileSystemFactory cryptoFileSystemFactory; private final ObjectProperty unlocked = new SimpleObjectProperty(this, "unlocked", Boolean.FALSE); private final ObservableList namesOfResourcesWithInvalidMac = FXThreads.observableListOnMainThread(FXCollections.observableArrayList()); private final Set whitelistedResourcesWithInvalidMac = new HashSet<>(); private String mountName; private Character winDriveLetter; - private DeferredClosable webDavServlet = DeferredClosable.empty(); - private DeferredClosable webDavMount = DeferredClosable.empty(); + private DeferredClosable filesystemFrontend = DeferredClosable.empty(); /** * Package private constructor, use {@link VaultFactory}. */ - Vault(final Path vaultDirectoryPath, final WebDavServer server, final Cryptor cryptor, final WebDavMounter mounter, final DeferredCloser closer) { + Vault(Path vaultDirectoryPath, Lazy frontendFactory, CryptoFileSystemFactory cryptoFileSystemFactory, DeferredCloser closer) { this.path = vaultDirectoryPath; - this.server = server; - this.cryptor = cryptor; - this.mounter = mounter; + this.frontendFactory = frontendFactory; this.closer = closer; + this.cryptoFileSystemFactory = cryptoFileSystemFactory; try { setMountName(getName()); @@ -84,35 +82,34 @@ public class Vault implements Serializable { return Files.isRegularFile(masterKeyPath); } - public synchronized boolean startServer() { - namesOfResourcesWithInvalidMac.clear(); - whitelistedResourcesWithInvalidMac.clear(); - Optional o = webDavServlet.get(); - if (o.isPresent() && o.get().isRunning()) { - return false; + public void create(CharSequence passphrase) throws IOException { + try { + FileSystem fs = NioFileSystem.rootedAt(path); + if (fs.children().count() > 0) { + throw new FileAlreadyExistsException(null, null, "Vault location not empty."); + } + cryptoFileSystemFactory.get(fs, passphrase, this); + } catch (UncheckedIOException e) { + throw new IOException(e); } - ServletLifeCycleAdapter servlet = server.createServlet(path, cryptor, namesOfResourcesWithInvalidMac, whitelistedResourcesWithInvalidMac, mountName); - if (servlet.start()) { - webDavServlet = closer.closeLater(servlet); - return true; - } - return false; } - public void stopServer() { + public synchronized void activateFrontend(CharSequence passphrase) throws FrontendCreationFailedException { try { - unmount(); - } catch (CommandFailedException e) { - LOG.warn("Unmounting failed. Locking anyway...", e); + FileSystem fs = NioFileSystem.rootedAt(path); + FileSystem cryptoFs = cryptoFileSystemFactory.get(fs, passphrase, this); + String contextPath = StringUtils.prependIfMissing(mountName, "/"); + Frontend frontend = frontendFactory.get().create(cryptoFs, contextPath); + filesystemFrontend = closer.closeLater(frontend); + setUnlocked(true); + } catch (UncheckedIOException e) { + throw new FrontendCreationFailedException(e); } - webDavServlet.close(); - try { - cryptor.destroy(); - } catch (DestroyFailedException e) { - LOG.error("Destruction of cryptor throw an exception.", e); - } - whitelistedResourcesWithInvalidMac.clear(); - namesOfResourcesWithInvalidMac.clear(); + } + + public synchronized void deactivateFrontend() { + filesystemFrontend.close(); + setUnlocked(false); } private Map> getMountParams() { @@ -123,32 +120,35 @@ public class Vault implements Serializable { } public Boolean mount() { - final ServletLifeCycleAdapter servlet = webDavServlet.get().orElse(null); - if (servlet == null || !servlet.isRunning()) { - return false; - } - try { - webDavMount = closer.closeLater(mounter.mount(servlet.getServletUri(), getMountParams())); - return true; - } catch (CommandFailedException e) { - LOG.warn("mount failed", e); + // TODO exception handling + Frontend frontend = filesystemFrontend.get().orElse(null); + if (frontend == null) { return false; + } else { + return frontend.mount(getMountParams()); } } - public void reveal() throws CommandFailedException { - final WebDavMount mnt = webDavMount.get().orElse(null); - if (mnt != null) { - mnt.reveal(); - } + public void reveal() { + // TODO exception handling + filesystemFrontend.get().ifPresent(Frontend::reveal); } - public void unmount() throws CommandFailedException { - final WebDavMount mnt = webDavMount.get().orElse(null); - if (mnt != null) { - mnt.unmount(); - } - webDavMount = DeferredClosable.empty(); + public void unmount() { + // TODO exception handling + filesystemFrontend.get().ifPresent(Frontend::unmount); + } + + /* Delegate Methods */ + + @Override + public void authenticationFailed(String cleartextPath) { + namesOfResourcesWithInvalidMac.add(cleartextPath); + } + + @Override + public boolean shouldSkipAuthentication(String cleartextPath) { + return namesOfResourcesWithInvalidMac.contains(cleartextPath); } /* Getter/Setter */ @@ -164,9 +164,9 @@ public class Vault implements Serializable { return StringUtils.removeEnd(path.getFileName().toString(), VAULT_FILE_EXTENSION); } - public Cryptor getCryptor() { - return cryptor; - } + // public Cryptor getCryptor() { + // return cryptor; + // } public ObjectProperty unlockedProperty() { return unlocked; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java index 17ee6f891..9f050b02f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java @@ -3,33 +3,31 @@ package org.cryptomator.ui.model; import java.nio.file.Path; import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Singleton; -import org.cryptomator.crypto.Cryptor; +import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory; +import org.cryptomator.frontend.FrontendFactory; +import org.cryptomator.frontend.webdav.mount.WebDavMounter; import org.cryptomator.ui.util.DeferredCloser; -import org.cryptomator.ui.util.mount.WebDavMounter; -import org.cryptomator.webdav.WebDavServer; + +import dagger.Lazy; @Singleton public class VaultFactory { - private final WebDavServer server; - private final Provider cryptorProvider; - private final WebDavMounter mounter; + private final Lazy frontendFactory; + private final CryptoFileSystemFactory cryptoFileSystemFactory; private final DeferredCloser closer; @Inject - public VaultFactory(WebDavServer server, @Named("SamplingCryptor") Provider cryptorProvider, WebDavMounter mounter, DeferredCloser closer) { - this.server = server; - this.cryptorProvider = cryptorProvider; - this.mounter = mounter; + public VaultFactory(Lazy frontendFactory, CryptoFileSystemFactory cryptoFileSystemFactory, WebDavMounter mounter, DeferredCloser closer) { + this.frontendFactory = frontendFactory; + this.cryptoFileSystemFactory = cryptoFileSystemFactory; this.closer = closer; } public Vault createVault(Path path) { - return new Vault(path, server, cryptorProvider.get(), mounter, closer); + return new Vault(path, frontendFactory, cryptoFileSystemFactory, closer); } }