mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-14 00:31:27 +00:00
webdav mounting on windows
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
******************************************************************************/
|
||||
package org.cryptomator.webdav;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.webdav.jackrabbit.WebDavServlet;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
@@ -15,6 +18,8 @@ import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -22,7 +27,17 @@ public final class WebDAVServer {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WebDAVServer.class);
|
||||
private static final String LOCALHOST = "127.0.0.1";
|
||||
private final Server server = new Server();
|
||||
private static final int MAX_PENDING_REQUESTS = 200;
|
||||
private static final int MAX_THREADS = 4;
|
||||
private static final int MIN_THREADS = 2;
|
||||
private static final int THREAD_IDLE_SECONDS = 20;
|
||||
private final Server server;
|
||||
|
||||
public WebDAVServer() {
|
||||
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(MAX_PENDING_REQUESTS);
|
||||
final ThreadPool tp = new QueuedThreadPool(MAX_THREADS, MIN_THREADS, THREAD_IDLE_SECONDS, queue);
|
||||
server = new Server(tp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param workDir Path of encrypted folder.
|
||||
|
||||
@@ -15,7 +15,6 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
@@ -39,12 +38,11 @@ import org.slf4j.LoggerFactory;
|
||||
public class AccessController implements Initializable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AccessController.class);
|
||||
private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
|
||||
|
||||
private final Aes256Cryptor cryptor = new Aes256Cryptor();
|
||||
private final WebDAVServer server = new WebDAVServer();
|
||||
private final int id = ID_GENERATOR.getAndIncrement();
|
||||
private ResourceBundle rb;
|
||||
private String unmountCmd;
|
||||
|
||||
@FXML
|
||||
private GridPane rootPane;
|
||||
@@ -91,7 +89,7 @@ public class AccessController implements Initializable {
|
||||
final int webdavPort = server.start(settings.getWebdavWorkDir(), cryptor);
|
||||
if (webdavPort > 0) {
|
||||
try {
|
||||
WebDavMounter.mount(webdavPort, id);
|
||||
unmountCmd = WebDavMounter.mount(webdavPort);
|
||||
MainApplication.addShutdownTask(this::tryStop);
|
||||
} catch (CommandFailedException e) {
|
||||
messageLabel.setText(String.format(rb.getString("access.messageLabel.mountFailed"), webdavPort));
|
||||
@@ -101,14 +99,13 @@ public class AccessController implements Initializable {
|
||||
}
|
||||
|
||||
public void tryStop() {
|
||||
try {
|
||||
if (server != null && server.isRunning()) {
|
||||
WebDavMounter.unmount(id, 5);
|
||||
server.stop();
|
||||
if (server != null && server.isRunning()) {
|
||||
try {
|
||||
WebDavMounter.unmount(unmountCmd);
|
||||
} catch (CommandFailedException e) {
|
||||
LOG.warn("Unmounting WebDAV share failed.", e);
|
||||
}
|
||||
} catch (CommandFailedException e) {
|
||||
LOG.warn("Unmounting WebDAV share failed.", e);
|
||||
} finally {
|
||||
server.stop();
|
||||
cryptor.swipeSensitiveData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ package org.cryptomator.ui.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
@@ -19,35 +21,54 @@ import org.slf4j.LoggerFactory;
|
||||
public final class WebDavMounter {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WebDavMounter.class);
|
||||
private static final int CMD_DEFAULT_TIMEOUT = 1;
|
||||
private static final int CMD_DEFAULT_TIMEOUT = 3;
|
||||
private static final Pattern WIN_MOUNT_DRIVELETTER_PATTERN = Pattern.compile("\\s*[A-Z]:\\s*");
|
||||
|
||||
private WebDavMounter() {
|
||||
throw new IllegalStateException("not instantiable.");
|
||||
}
|
||||
|
||||
public static synchronized void mount(int localPort, int uniqueId) throws CommandFailedException {
|
||||
|
||||
/**
|
||||
* @return Unmount Command
|
||||
*/
|
||||
public static synchronized String mount(int localPort) throws CommandFailedException {
|
||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||
exec("mkdir /Volumes/Cryptomator" + uniqueId, CMD_DEFAULT_TIMEOUT);
|
||||
exec("mount_webdav -S -v Cryptomator localhost:" + localPort + " /Volumes/Cryptomator" + uniqueId, CMD_DEFAULT_TIMEOUT);
|
||||
exec("open /Volumes/Cryptomator" + uniqueId, CMD_DEFAULT_TIMEOUT);
|
||||
exec("mkdir /Volumes/Cryptomator" + localPort, CMD_DEFAULT_TIMEOUT);
|
||||
exec("mount_webdav -S -v Cryptomator localhost:" + localPort + " /Volumes/Cryptomator" + localPort, CMD_DEFAULT_TIMEOUT);
|
||||
exec("open /Volumes/Cryptomator" + localPort, CMD_DEFAULT_TIMEOUT);
|
||||
return "umount /Volumes/Cryptomator" + localPort;
|
||||
} else if (SystemUtils.IS_OS_WINDOWS) {
|
||||
final String result = exec("net use * http://127.0.0.1:" + localPort + " /persistent:no", CMD_DEFAULT_TIMEOUT);
|
||||
final Matcher matcher = WIN_MOUNT_DRIVELETTER_PATTERN.matcher(result);
|
||||
if (matcher.find()) {
|
||||
final String driveLetter = matcher.group();
|
||||
return "net use " + driveLetter + " /delete";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void unmount(String command) throws CommandFailedException {
|
||||
if (command != null) {
|
||||
exec(command, CMD_DEFAULT_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void unmount(int uniqueId, int timeout) throws CommandFailedException {
|
||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||
exec("umount /Volumes/Cryptomator" + uniqueId, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private static void exec(String cmd, int timoutSeconds) throws CommandFailedException {
|
||||
private static String exec(String cmd, int timoutSeconds) throws CommandFailedException {
|
||||
try {
|
||||
final Process proc = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd});
|
||||
final Process proc;
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
proc = Runtime.getRuntime().exec(new String[]{"cmd", "/C", cmd});
|
||||
} else {
|
||||
proc = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd});
|
||||
}
|
||||
if (proc.waitFor(timoutSeconds, TimeUnit.SECONDS)) {
|
||||
proc.destroy();
|
||||
}
|
||||
if (proc.exitValue() != 0) {
|
||||
throw new CommandFailedException(IOUtils.toString(proc.getErrorStream()));
|
||||
}
|
||||
return IOUtils.toString(proc.getInputStream());
|
||||
} catch (IOException | InterruptedException | IllegalThreadStateException e) {
|
||||
LOG.error("Command execution failed.", e);
|
||||
throw new CommandFailedException(e);
|
||||
|
||||
Reference in New Issue
Block a user