|
@@ -9,25 +9,18 @@
|
|
|
package org.cryptomator.ui.model;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
-import java.net.InetAddress;
|
|
|
-import java.net.UnknownHostException;
|
|
|
import java.nio.file.FileAlreadyExistsException;
|
|
|
-import java.nio.file.FileSystem;
|
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.NoSuchFileException;
|
|
|
import java.nio.file.Path;
|
|
|
import java.nio.file.Paths;
|
|
|
import java.util.Objects;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
-import java.util.function.Function;
|
|
|
import java.util.function.Predicate;
|
|
|
|
|
|
import javax.inject.Inject;
|
|
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.apache.commons.lang3.SystemUtils;
|
|
|
import org.cryptomator.common.LazyInitializer;
|
|
|
-import org.cryptomator.common.Optionals;
|
|
|
import org.cryptomator.common.settings.Settings;
|
|
|
import org.cryptomator.common.settings.VaultSettings;
|
|
|
import org.cryptomator.cryptofs.CryptoFileSystem;
|
|
@@ -35,24 +28,21 @@ import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
|
|
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
|
|
import org.cryptomator.cryptolib.api.CryptoException;
|
|
|
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
|
|
-import org.cryptomator.frontend.webdav.ServerLifecycleException;
|
|
|
-import org.cryptomator.frontend.webdav.WebDavServer;
|
|
|
-import org.cryptomator.frontend.webdav.mount.MountParams;
|
|
|
-import org.cryptomator.frontend.webdav.mount.Mounter.CommandFailedException;
|
|
|
-import org.cryptomator.frontend.webdav.mount.Mounter.Mount;
|
|
|
-import org.cryptomator.frontend.webdav.mount.Mounter.UnmountOperation;
|
|
|
-import org.cryptomator.frontend.webdav.servlet.WebDavServletController;
|
|
|
import org.cryptomator.ui.model.VaultModule.PerVault;
|
|
|
-import org.fxmisc.easybind.EasyBind;
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
|
|
|
+import com.google.common.base.Strings;
|
|
|
import javafx.application.Platform;
|
|
|
import javafx.beans.Observable;
|
|
|
import javafx.beans.binding.Binding;
|
|
|
import javafx.beans.property.ObjectProperty;
|
|
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
|
|
import javafx.beans.property.SimpleObjectProperty;
|
|
|
+import javafx.beans.property.StringProperty;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.commons.lang3.SystemUtils;
|
|
|
+import org.fxmisc.easybind.EasyBind;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
|
@PerVault
|
|
|
public class Vault {
|
|
@@ -64,22 +54,24 @@ public class Vault {
|
|
|
|
|
|
private final Settings settings;
|
|
|
private final VaultSettings vaultSettings;
|
|
|
- private final WebDavServer server;
|
|
|
private final AtomicReference<CryptoFileSystem> cryptoFileSystem = new AtomicReference<>();
|
|
|
private final ObjectProperty<State> state = new SimpleObjectProperty<State>(State.LOCKED);
|
|
|
|
|
|
- private WebDavServletController servlet;
|
|
|
- private Mount mount;
|
|
|
+ private NioAdapter nioAdapter;
|
|
|
|
|
|
public enum State {
|
|
|
LOCKED, UNLOCKED, MOUNTING, MOUNTED, UNMOUNTING
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
@Inject
|
|
|
- Vault(Settings settings, VaultSettings vaultSettings, WebDavServer server) {
|
|
|
+ Vault(Settings settings, VaultSettings vaultSettings, NioAdapter nioAdapter) {
|
|
|
this.settings = settings;
|
|
|
this.vaultSettings = vaultSettings;
|
|
|
- this.server = server;
|
|
|
+ this.nioAdapter = nioAdapter;
|
|
|
+
|
|
|
+ if (Strings.isNullOrEmpty(vaultSettings.mountPath().get())) {
|
|
|
+ vaultSettings.mountPath().set(settings.defaultMountDir().get() + "/" + vaultSettings.mountName().get());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// ******************************************************************************
|
|
@@ -111,80 +103,48 @@ public class Vault {
|
|
|
CryptoFileSystemProvider.changePassphrase(getPath(), MASTERKEY_FILENAME, oldPassphrase, newPassphrase);
|
|
|
}
|
|
|
|
|
|
- public synchronized void unlock(CharSequence passphrase) throws ServerLifecycleException, CryptoException, IOException {
|
|
|
- FileSystem fs = getCryptoFileSystem(passphrase);
|
|
|
- if (!server.isRunning()) {
|
|
|
- server.start();
|
|
|
- }
|
|
|
- servlet = server.createWebDavServlet(fs.getPath("/"), vaultSettings.getId() + "/" + vaultSettings.mountName().get());
|
|
|
- servlet.start();
|
|
|
+ public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException {
|
|
|
+ CryptoFileSystem fs = getCryptoFileSystem(passphrase);
|
|
|
+ nioAdapter.unlock(fs);
|
|
|
Platform.runLater(() -> {
|
|
|
state.set(State.UNLOCKED);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
public synchronized void mount() throws CommandFailedException {
|
|
|
- if (servlet == null) {
|
|
|
- throw new IllegalStateException("Mounting requires unlocked WebDAV servlet.");
|
|
|
- }
|
|
|
-
|
|
|
- MountParams mountParams = MountParams.create() //
|
|
|
- .withWindowsDriveLetter(vaultSettings.winDriveLetter().get()) //
|
|
|
- .withPreferredGvfsScheme(settings.preferredGvfsScheme().get()) //
|
|
|
- .withWebdavHostname(getLocalhostAliasOrNull()) //
|
|
|
- .build();
|
|
|
-
|
|
|
Platform.runLater(() -> {
|
|
|
state.set(State.MOUNTING);
|
|
|
});
|
|
|
- mount = servlet.mount(mountParams); // might block this thread for a while
|
|
|
+ nioAdapter.mount();
|
|
|
Platform.runLater(() -> {
|
|
|
state.set(State.MOUNTED);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- private String getLocalhostAliasOrNull() {
|
|
|
- try {
|
|
|
- InetAddress alias = InetAddress.getByName(LOCALHOST_ALIAS);
|
|
|
- if (alias.getHostAddress().equals("127.0.0.1")) {
|
|
|
- return LOCALHOST_ALIAS;
|
|
|
- } else {
|
|
|
- return null;
|
|
|
- }
|
|
|
- } catch (UnknownHostException e) {
|
|
|
- return null;
|
|
|
- }
|
|
|
+ public synchronized void unmountForced() throws CommandFailedException {
|
|
|
+ unmount(true);
|
|
|
}
|
|
|
|
|
|
public synchronized void unmount() throws CommandFailedException {
|
|
|
- unmount(Function.identity());
|
|
|
+ unmount(false);
|
|
|
}
|
|
|
|
|
|
- public synchronized void unmountForced() throws CommandFailedException {
|
|
|
- unmount(Optionals.unwrap(Mount::forced));
|
|
|
- }
|
|
|
-
|
|
|
- private synchronized void unmount(Function<Mount, ? extends UnmountOperation> unmountOperationChooser) throws CommandFailedException {
|
|
|
+ private synchronized void unmount(boolean forced) throws CommandFailedException {
|
|
|
Platform.runLater(() -> {
|
|
|
state.set(State.UNMOUNTING);
|
|
|
});
|
|
|
- if (mount != null) {
|
|
|
- unmountOperationChooser.apply(mount).unmount();
|
|
|
- mount = null;
|
|
|
+ if (forced && nioAdapter.supportsForcedUnmount()) {
|
|
|
+ nioAdapter.unmountForced();
|
|
|
+ } else {
|
|
|
+ nioAdapter.unmount();
|
|
|
}
|
|
|
Platform.runLater(() -> {
|
|
|
state.set(State.UNLOCKED);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- public boolean supportsForcedUnmount() {
|
|
|
- return mount != null && mount.forced().isPresent();
|
|
|
- }
|
|
|
-
|
|
|
- public synchronized void lock() throws ServerLifecycleException, IOException {
|
|
|
- if (servlet != null) {
|
|
|
- servlet.stop();
|
|
|
- }
|
|
|
+ public synchronized void lock() throws IOException {
|
|
|
+ nioAdapter.stop();
|
|
|
CryptoFileSystem fs = cryptoFileSystem.getAndSet(null);
|
|
|
if (fs != null) {
|
|
|
fs.close();
|
|
@@ -201,7 +161,7 @@ public class Vault {
|
|
|
try {
|
|
|
unmount();
|
|
|
} catch (CommandFailedException e) {
|
|
|
- if (supportsForcedUnmount()) {
|
|
|
+ if (nioAdapter.supportsForcedUnmount()) {
|
|
|
try {
|
|
|
unmountForced();
|
|
|
} catch (CommandFailedException e1) {
|
|
@@ -218,10 +178,11 @@ public class Vault {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * TODO: implement it again
|
|
|
+ */
|
|
|
public void reveal() throws CommandFailedException {
|
|
|
- if (mount != null) {
|
|
|
- mount.reveal();
|
|
|
- }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// ******************************************************************************
|
|
@@ -243,17 +204,13 @@ public class Vault {
|
|
|
}
|
|
|
|
|
|
public Observable[] observables() {
|
|
|
- return new Observable[] {state};
|
|
|
+ return new Observable[]{state};
|
|
|
}
|
|
|
|
|
|
public VaultSettings getVaultSettings() {
|
|
|
return vaultSettings;
|
|
|
}
|
|
|
|
|
|
- public synchronized String getWebDavUrl() {
|
|
|
- return servlet.getServletRootUri().toString();
|
|
|
- }
|
|
|
-
|
|
|
public Path getPath() {
|
|
|
return vaultSettings.path().getValue();
|
|
|
}
|
|
@@ -308,6 +265,18 @@ public class Vault {
|
|
|
return vaultSettings.mountName().get();
|
|
|
}
|
|
|
|
|
|
+ public StringProperty getMountPathProperty() {
|
|
|
+ return vaultSettings.mountPath();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setMountPath(String mountPath) {
|
|
|
+ if (mountPath.isEmpty()) {
|
|
|
+ vaultSettings.mountPath().set(settings.defaultMountDir().get());
|
|
|
+ } else {
|
|
|
+ vaultSettings.mountPath().set(mountPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void setMountName(String mountName) throws IllegalArgumentException {
|
|
|
if (StringUtils.isBlank(mountName)) {
|
|
|
throw new IllegalArgumentException("mount name is empty");
|
|
@@ -332,6 +301,10 @@ public class Vault {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public String getFilesystemRootUrl() {
|
|
|
+ return nioAdapter.getFilesystemRootUrl();
|
|
|
+ }
|
|
|
+
|
|
|
public String getId() {
|
|
|
return vaultSettings.getId();
|
|
|
}
|
|
@@ -355,4 +328,7 @@ public class Vault {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public boolean supportsForcedUnmount() {
|
|
|
+ return nioAdapter.supportsForcedUnmount();
|
|
|
+ }
|
|
|
}
|