diff --git a/main/core/pom.xml b/main/core/pom.xml
index cfd19cab9..d23e756e7 100644
--- a/main/core/pom.xml
+++ b/main/core/pom.xml
@@ -12,7 +12,7 @@
org.cryptomator
main
- 0.1.0-SNAPSHOT
+ 0.1.0
core
Cryptomator core I/O module
@@ -28,7 +28,6 @@
org.cryptomator
crypto-api
- ${project.parent.version}
diff --git a/main/core/src/main/java/org/cryptomator/webdav/WebDAVServer.java b/main/core/src/main/java/org/cryptomator/webdav/WebDAVServer.java
index da4d85322..69ec48815 100644
--- a/main/core/src/main/java/org/cryptomator/webdav/WebDAVServer.java
+++ b/main/core/src/main/java/org/cryptomator/webdav/WebDAVServer.java
@@ -22,6 +22,7 @@ public final class WebDAVServer {
private static final Logger LOG = LoggerFactory.getLogger(WebDAVServer.class);
private static final WebDAVServer INSTANCE = new WebDAVServer();
+ private static final String LOCALHOST = "127.0.0.1";
private final Server server = new Server();
private WebDAVServer() {
@@ -32,11 +33,14 @@ public final class WebDAVServer {
return INSTANCE;
}
- public boolean start(final String workDir, final int port, final Cryptor cryptor) {
+ /**
+ * @param workDir Path of encrypted folder.
+ * @param cryptor A fully initialized cryptor instance ready to en- or decrypt streams.
+ * @return port, on which the server did start
+ */
+ public int start(final String workDir, final Cryptor cryptor) {
final ServerConnector connector = new ServerConnector(server);
- connector.setHost("127.0.0.1");
- connector.setPort(port);
- server.setConnectors(new Connector[] {connector});
+ connector.setHost(LOCALHOST);
final String contextPath = "/";
@@ -46,12 +50,13 @@ public final class WebDAVServer {
server.setHandler(context);
try {
+ server.setConnectors(new Connector[] {connector});
server.start();
} catch (Exception ex) {
LOG.error("Server couldn't be started", ex);
}
- return server.isStarted();
+ return connector.getLocalPort();
}
public boolean isRunning() {
@@ -68,7 +73,7 @@ public final class WebDAVServer {
}
private ServletHolder getMiltonServletHolder(final String workDir, final String contextPath, final Cryptor cryptor) {
- final ServletHolder result = new ServletHolder("OCE-WebDAV-Servlet", new WebDavServlet(cryptor));
+ final ServletHolder result = new ServletHolder("Cryptomator-WebDAV-Servlet", new WebDavServlet(cryptor));
result.setInitParameter(WebDavServlet.CFG_FS_ROOT, workDir);
result.setInitParameter(WebDavServlet.CFG_HTTP_ROOT, contextPath);
return result;
diff --git a/main/crypto-aes/pom.xml b/main/crypto-aes/pom.xml
index 1f09c76f2..c05dee070 100644
--- a/main/crypto-aes/pom.xml
+++ b/main/crypto-aes/pom.xml
@@ -12,7 +12,7 @@
org.cryptomator
main
- 0.1.0-SNAPSHOT
+ 0.1.0
crypto-aes
Cryptomator cryptographic module (AES)
@@ -22,7 +22,6 @@
org.cryptomator
crypto-api
- ${project.parent.version}
diff --git a/main/crypto-api/pom.xml b/main/crypto-api/pom.xml
index 072fa335e..894471358 100644
--- a/main/crypto-api/pom.xml
+++ b/main/crypto-api/pom.xml
@@ -12,7 +12,7 @@
org.cryptomator
main
- 0.1.0-SNAPSHOT
+ 0.1.0
crypto-api
Cryptomator cryptographic module API
diff --git a/main/pom.xml b/main/pom.xml
index ed50f873c..3c66b30fb 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -11,12 +11,22 @@
4.0.0
org.cryptomator
main
- 0.1.0-SNAPSHOT
+ 0.1.0
pom
Cryptomator
+
cryptomator.org
+ http://cryptomator.org
+
+
+
+ Sebastian Stenzel
+ sebastian.stenzel@gmail.com
+ +1
+
+
UTF-8
@@ -31,15 +41,30 @@
1.9
-
-
- Sebastian Stenzel
- sebastian.stenzel@gmail.com
-
-
-
+
+
+ org.cryptomator
+ core
+ ${project.version}
+
+
+ org.cryptomator
+ crypto-api
+ ${project.version}
+
+
+ org.cryptomator
+ crypto-aes
+ ${project.version}
+
+
+ org.cryptomator
+ ui
+ ${project.version}
+
+
log4j
diff --git a/main/ui/pom.xml b/main/ui/pom.xml
index 3cc4baff0..ac5a0ab03 100644
--- a/main/ui/pom.xml
+++ b/main/ui/pom.xml
@@ -1,16 +1,24 @@
-
+
4.0.0
org.cryptomator
main
- 0.1.0-SNAPSHOT
+ 0.1.0
ui
Cryptomator GUI
+ Cryptomator
org.cryptomator.ui.MainApplication
${java.home}/../lib/ant-javafx.jar
@@ -19,12 +27,10 @@
org.cryptomator
core
- ${project.parent.version}
org.cryptomator
crypto-aes
- ${project.parent.version}
@@ -91,7 +97,7 @@
-
+
@@ -102,9 +108,9 @@
-
-
-
+
+
+
diff --git a/main/ui/src/main/java/org/cryptomator/ui/AccessController.java b/main/ui/src/main/java/org/cryptomator/ui/AccessController.java
index 07243d78a..47dc60504 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/AccessController.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/AccessController.java
@@ -43,6 +43,8 @@ import org.cryptomator.crypto.exceptions.WrongPasswordException;
import org.cryptomator.ui.controls.SecPasswordField;
import org.cryptomator.ui.settings.Settings;
import org.cryptomator.ui.util.MasterKeyFilter;
+import org.cryptomator.ui.util.WebDavMounter;
+import org.cryptomator.ui.util.WebDavMounter.CommandFailedException;
import org.cryptomator.webdav.WebDAVServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -197,21 +199,29 @@ public class AccessController implements Initializable {
}
private void tryStart() {
- try {
- final Settings settings = Settings.load();
- if (WebDAVServer.getInstance().start(settings.getWebdavWorkDir(), settings.getPort(), cryptor)) {
- startServerButton.setText(localization.getString("access.button.stopServer"));
- passwordField.setDisable(true);
+ final Settings settings = Settings.load();
+ final int webdavPort = WebDAVServer.getInstance().start(settings.getWebdavWorkDir(), cryptor);
+ if (webdavPort > 0) {
+ startServerButton.setText(localization.getString("access.button.stopServer"));
+ passwordField.setDisable(true);
+ try {
+ WebDavMounter.mount(webdavPort);
+ } catch (CommandFailedException e) {
+ messageLabel.setText(String.format(localization.getString("access.messageLabel.mountFailed"), webdavPort));
+ LOG.error("Mounting WebDAV share failed.", e);
}
- } catch (NumberFormatException ex) {
- LOG.error("Invalid port", ex);
}
}
private void tryStop() {
- if (WebDAVServer.getInstance().stop()) {
- startServerButton.setText(localization.getString("access.button.startServer"));
- passwordField.setDisable(false);
+ try {
+ WebDavMounter.unmount(5);
+ if (WebDAVServer.getInstance().stop()) {
+ startServerButton.setText(localization.getString("access.button.startServer"));
+ passwordField.setDisable(false);
+ }
+ } catch (CommandFailedException e) {
+ LOG.warn("Unmounting WebDAV share failed.", e);
}
}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/AdvancedController.java b/main/ui/src/main/java/org/cryptomator/ui/AdvancedController.java
deleted file mode 100644
index d1eb684cf..000000000
--- a/main/ui/src/main/java/org/cryptomator/ui/AdvancedController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014 Sebastian Stenzel
- * 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
- ******************************************************************************/
-package org.cryptomator.ui;
-
-import java.net.URL;
-import java.util.ResourceBundle;
-
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-import javafx.event.EventHandler;
-import javafx.fxml.FXML;
-import javafx.fxml.Initializable;
-import javafx.scene.control.TextField;
-import javafx.scene.input.KeyEvent;
-import javafx.scene.layout.GridPane;
-
-import org.apache.commons.lang3.CharUtils;
-import org.cryptomator.ui.settings.Settings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class AdvancedController implements Initializable {
-
- private static final Logger LOG = LoggerFactory.getLogger(AdvancedController.class);
-
- @FXML
- private GridPane rootGridPane;
-
- @FXML
- private TextField portTextField;
-
- @Override
- public void initialize(URL url, ResourceBundle rb) {
- portTextField.setText(String.valueOf(Settings.load().getPort()));
- portTextField.addEventFilter(KeyEvent.KEY_TYPED, new NumericKeyTypeEventFilter());
- portTextField.focusedProperty().addListener(new PortTextFieldFocusListener());
- }
-
- /**
- * Consumes key events, if typed key is not 0-9.
- */
- private static final class NumericKeyTypeEventFilter implements EventHandler {
- @Override
- public void handle(KeyEvent t) {
- if (t.getCharacter() == null || t.getCharacter().length() == 0) {
- return;
- }
- char c = t.getCharacter().charAt(0);
- if (!CharUtils.isAsciiNumeric(c)) {
- t.consume();
- }
- }
- }
-
- /**
- * Saves port settings, when textfield loses focus.
- */
- private class PortTextFieldFocusListener implements ChangeListener {
- @Override
- public void changed(ObservableValue extends Boolean> property, Boolean wasFocused, Boolean isFocused) {
- final Settings settings = Settings.load();
- try {
- int port = Integer.valueOf(portTextField.getText());
- settings.setPort(port);
- } catch (NumberFormatException ex) {
- LOG.warn("Invalid port " + portTextField.getText());
- portTextField.setText(String.valueOf(settings.getPort()));
- }
- }
- }
-
-}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java b/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java
index 1e978775b..f1d914ee0 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java
@@ -18,10 +18,16 @@ import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.settings.Settings;
+import org.cryptomator.ui.util.WebDavMounter;
+import org.cryptomator.ui.util.WebDavMounter.CommandFailedException;
import org.cryptomator.webdav.WebDAVServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class MainApplication extends Application {
+ private static final Logger LOG = LoggerFactory.getLogger(MainApplication.class);
+
public static void main(String[] args) {
launch(args);
}
@@ -40,6 +46,11 @@ public class MainApplication extends Application {
@Override
public void stop() throws Exception {
+ try {
+ WebDavMounter.unmount(5);
+ } catch (CommandFailedException e) {
+ LOG.warn("Unmounting WebDAV share failed.", e);
+ }
WebDAVServer.getInstance().stop();
Settings.save();
super.stop();
diff --git a/main/ui/src/main/java/org/cryptomator/ui/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/MainController.java
index 94ec34438..e417f1c53 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/MainController.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/MainController.java
@@ -10,38 +10,42 @@ package org.cryptomator.ui;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
+import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
public class MainController {
-
+
+ @FXML
+ private ToggleGroup toolbarButtonGroup;
+
@FXML
private VBox rootVBox;
-
+
@FXML
private Pane initializePanel;
-
+
@FXML
private Pane accessPanel;
-
+
@FXML
private Pane advancedPanel;
-
+
@FXML
protected void showInitializePane(ActionEvent event) {
showPanel(initializePanel);
}
-
+
@FXML
protected void showAccessPane(ActionEvent event) {
showPanel(accessPanel);
}
-
+
@FXML
protected void showAdvancedPane(ActionEvent event) {
showPanel(advancedPanel);
}
-
+
private void showPanel(Pane panel) {
rootVBox.getChildren().remove(1);
rootVBox.getChildren().add(panel);
diff --git a/main/ui/src/main/java/org/cryptomator/ui/controls/ClearOnDisableListener.java b/main/ui/src/main/java/org/cryptomator/ui/controls/ClearOnDisableListener.java
index 38e8655f0..b5bf8f68a 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/controls/ClearOnDisableListener.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/controls/ClearOnDisableListener.java
@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Sebastian Stenzel
+ * 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
+ ******************************************************************************/
package org.cryptomator.ui.controls;
import javafx.beans.value.ChangeListener;
diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java
index f470bd310..0d095ec86 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java
@@ -18,6 +18,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
+import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,20 +36,18 @@ public class Settings implements Serializable {
private static Settings INSTANCE = null;
static {
- final String home = System.getProperty("user.home", ".");
final String appdata = System.getenv("APPDATA");
- final String os = System.getProperty("os.name").toLowerCase();
final FileSystem fs = FileSystems.getDefault();
- if (os.contains("win") && appdata != null) {
+ if (SystemUtils.IS_OS_WINDOWS && appdata != null) {
SETTINGS_DIR = fs.getPath(appdata, "opencloudencryptor");
- } else if (os.contains("win") && appdata == null) {
- SETTINGS_DIR = fs.getPath(home, ".opencloudencryptor");
- } else if (os.contains("mac")) {
- SETTINGS_DIR = fs.getPath(home, "Library/Application Support/opencloudencryptor");
+ } else if (SystemUtils.IS_OS_WINDOWS && appdata == null) {
+ SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, ".opencloudencryptor");
+ } else if (SystemUtils.IS_OS_MAC_OSX) {
+ SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, "Library/Application Support/opencloudencryptor");
} else {
// (os.contains("solaris") || os.contains("sunos") || os.contains("linux") || os.contains("unix"))
- SETTINGS_DIR = fs.getPath(home, ".opencloudencryptor");
+ SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, ".opencloudencryptor");
}
}
@@ -113,10 +112,12 @@ public class Settings implements Serializable {
this.username = username;
}
+ @Deprecated
public int getPort() {
return port;
}
+ @Deprecated
public void setPort(int port) {
this.port = port;
}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/MasterKeyFilter.java b/main/ui/src/main/java/org/cryptomator/ui/util/MasterKeyFilter.java
index c747c749e..844f42acc 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/util/MasterKeyFilter.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/util/MasterKeyFilter.java
@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Sebastian Stenzel
+ * 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
+ ******************************************************************************/
package org.cryptomator.ui.util;
import java.io.IOException;
diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/WebDavMounter.java b/main/ui/src/main/java/org/cryptomator/ui/util/WebDavMounter.java
new file mode 100644
index 000000000..72c39e757
--- /dev/null
+++ b/main/ui/src/main/java/org/cryptomator/ui/util/WebDavMounter.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Sebastian Stenzel
+ * 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
+ ******************************************************************************/
+package org.cryptomator.ui.util;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
+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 WebDavMounter() {
+ throw new IllegalStateException("not instantiable.");
+ }
+
+ public static void mount(int localPort) throws CommandFailedException {
+ if (SystemUtils.IS_OS_MAC_OSX) {
+ exec("mkdir /Volumes/Cryptomator", CMD_DEFAULT_TIMEOUT);
+ exec("mount_webdav -S -v Cryptomator localhost:" + localPort + " /Volumes/Cryptomator", CMD_DEFAULT_TIMEOUT);
+ exec("open /Volumes/Cryptomator", CMD_DEFAULT_TIMEOUT);
+ }
+ }
+
+ public static void unmount(int timeout) throws CommandFailedException {
+ if (SystemUtils.IS_OS_MAC_OSX) {
+ exec("umount /Volumes/Cryptomator", timeout);
+ }
+ }
+
+ private static void exec(String cmd, int timoutSeconds) throws CommandFailedException {
+ try {
+ final Process 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()));
+ }
+ } catch (IOException | InterruptedException | IllegalThreadStateException e) {
+ LOG.error("Command execution failed.", e);
+ throw new CommandFailedException(e);
+ }
+
+ }
+
+ public static class CommandFailedException extends Exception {
+
+ private static final long serialVersionUID = 5784853630182321479L;
+
+ private CommandFailedException(String message) {
+ super(message);
+ }
+
+ private CommandFailedException(Throwable cause) {
+ super(cause);
+ }
+
+ }
+
+}
diff --git a/main/ui/src/main/resources/advanced.fxml b/main/ui/src/main/resources/advanced.fxml
deleted file mode 100644
index 0bcc1c537..000000000
--- a/main/ui/src/main/resources/advanced.fxml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/main/ui/src/main/resources/localization.properties b/main/ui/src/main/resources/localization.properties
index 280b284b6..2394ed932 100644
--- a/main/ui/src/main/resources/localization.properties
+++ b/main/ui/src/main/resources/localization.properties
@@ -9,7 +9,6 @@
# main.fxml
toolbarbutton.initialize=Initialize Vault
toolbarbutton.access=Access Vault
-toolbarbutton.advanced=Advanced Settings
# initialize.fxml
initialize.label.workDir=New vault location
@@ -32,6 +31,4 @@ access.messageLabel.wrongPassword=Wrong password.
access.messageLabel.invalidStorageLocation=Vault directory invalid.
access.messageLabel.decryptionFailed=Decryption failed.
access.messageLabel.unsupportedKeyLengthInstallJCE=Decryption failed. Please install Oracle JCE.
-
-# advanced.fxml
-advanced.label.port=WebDAV Port
+access.messageLabel.mountFailed=Mounting WebDAV share (Port %d) failed.
diff --git a/main/ui/src/main/resources/logo.icns b/main/ui/src/main/resources/logo.icns
new file mode 100644
index 000000000..f2eb85138
Binary files /dev/null and b/main/ui/src/main/resources/logo.icns differ
diff --git a/main/ui/src/main/resources/main.fxml b/main/ui/src/main/resources/main.fxml
index 2b08770b0..f1fe478a3 100644
--- a/main/ui/src/main/resources/main.fxml
+++ b/main/ui/src/main/resources/main.fxml
@@ -21,7 +21,6 @@
-
@@ -32,7 +31,6 @@
-